PcpNodeRef PcpPrimIndex_Graph::_InsertChildInStrengthOrder( size_t parentNodeIdx, size_t childNodeIdx) { TF_VERIFY(parentNodeIdx < _GetNumNodes()); TF_VERIFY(childNodeIdx < _GetNumNodes()); // Insert the child in the list of children, maintaining // the relative strength order. _Node& parentNode = _data->nodes[parentNodeIdx]; _Node& childNode = _data->nodes[childNodeIdx]; _ArcStrengthOrder comp(this); if (FIRST_CHILD(parentNode) == _Node::_invalidNodeIndex) { // No children yet so this is the first child. TF_VERIFY(LAST_CHILD(parentNode) == _Node::_invalidNodeIndex); FIRST_CHILD(parentNode) = LAST_CHILD(parentNode) = childNodeIdx; } else if (comp(childNodeIdx, FIRST_CHILD(parentNode))) { // New first child. TF_VERIFY(LAST_CHILD(parentNode) != _Node::_invalidNodeIndex); _Node& nextNode = _data->nodes[FIRST_CHILD(parentNode)]; NEXT_SIBLING(childNode) = FIRST_CHILD(parentNode); PREV_SIBLING(nextNode) = childNodeIdx; FIRST_CHILD(parentNode) = childNodeIdx; } else if (!comp(childNodeIdx, LAST_CHILD(parentNode))) { // New last child. _Node& prevNode = _data->nodes[LAST_CHILD(parentNode)]; PREV_SIBLING(childNode) = LAST_CHILD(parentNode); NEXT_SIBLING(prevNode) = childNodeIdx; LAST_CHILD(parentNode) = childNodeIdx; } else { // Child goes somewhere internal to the sibling linked list. for (size_t index = FIRST_CHILD(parentNode); index != _Node::_invalidNodeIndex; index = NEXT_SIBLING(_data->nodes[index])) { if (comp(childNodeIdx, index)) { _Node& nextNode = _data->nodes[index]; TF_VERIFY(PREV_SIBLING(nextNode) != _Node::_invalidNodeIndex); _Node& prevNode =_data->nodes[PREV_SIBLING(nextNode)]; PREV_SIBLING(childNode) = PREV_SIBLING(nextNode); NEXT_SIBLING(childNode) = index; PREV_SIBLING(nextNode) = childNodeIdx; NEXT_SIBLING(prevNode) = childNodeIdx; break; } } } return PcpNodeRef(this, childNodeIdx); }
size_t PcpPrimIndex_Graph::_CreateNodesForSubgraph( const PcpPrimIndex_Graph& subgraph, const PcpArc& arc) { // The subgraph's root should never have a parent or origin node; we // rely on this invariant below. TF_VERIFY(!subgraph.GetRootNode().GetParentNode() && !subgraph.GetRootNode().GetOriginNode()); // Insert a copy of all of the node data in the given subgraph into our // node pool. const size_t oldNumNodes = _GetNumNodes(); _data->finalized = false; _data->nodes.insert( _data->nodes.end(), subgraph._data->nodes.begin(), subgraph._data->nodes.end()); _nodeSitePaths.insert( _nodeSitePaths.end(), subgraph._nodeSitePaths.begin(), subgraph._nodeSitePaths.end()); _nodeHasSpecs.insert( _nodeHasSpecs.end(), subgraph._nodeHasSpecs.begin(), subgraph._nodeHasSpecs.end()); const size_t newNumNodes = _GetNumNodes(); const size_t subgraphRootNodeIndex = oldNumNodes; // Set the arc connecting the root of the subgraph to the rest of the // graph. _Node& subgraphRoot = _data->nodes[subgraphRootNodeIndex]; subgraphRoot.SetArc(arc); // XXX: This is very similar to code in _ApplyNodeIndexMapping that // adjust node references. There must be a good way to factor // all of that out... // Iterate over all of the newly-copied nodes and adjust references to // other nodes in the node pool. struct _ConvertOldToNewIndex { _ConvertOldToNewIndex(size_t base, size_t numNewNodes) : _base(base), _numNewNodes(numNewNodes) { } size_t operator()(size_t oldIndex) const { if (oldIndex != _Node::_invalidNodeIndex) { TF_VERIFY(oldIndex + _base < _numNewNodes); return oldIndex + _base; } else { return oldIndex; } } size_t _base; size_t _numNewNodes; }; const _ConvertOldToNewIndex convertToNewIndex(subgraphRootNodeIndex, newNumNodes); for (size_t i = oldNumNodes; i < newNumNodes; ++i) { _Node& newNode = _data->nodes[i]; // Update the node's mapToRoot since it is now part of a new graph. if (i != subgraphRootNodeIndex) { newNode.mapToRoot = subgraphRoot.mapToRoot.Compose(newNode.mapToRoot); } // The parent and origin of the root of the newly-inserted subgraph // don't need to be fixed up because it doesn't point to a node // within the subgraph. if (i != subgraphRootNodeIndex) { PARENT(newNode) = convertToNewIndex(PARENT(newNode)); ORIGIN(newNode) = convertToNewIndex(ORIGIN(newNode)); } FIRST_CHILD(newNode) = convertToNewIndex(FIRST_CHILD(newNode)); LAST_CHILD(newNode) = convertToNewIndex(LAST_CHILD(newNode)); PREV_SIBLING(newNode) = convertToNewIndex(PREV_SIBLING(newNode)); NEXT_SIBLING(newNode) = convertToNewIndex(NEXT_SIBLING(newNode)); } return subgraphRootNodeIndex; }
void PcpPrimIndex_Graph::_ApplyNodeIndexMapping( const std::vector<size_t>& nodeIndexMap) { _NodePool& oldNodes = _data->nodes; SdfPathVector& oldSitePaths = _nodeSitePaths; std::vector<bool>& oldHasSpecs = _nodeHasSpecs; TF_VERIFY(oldNodes.size() == oldSitePaths.size() && oldNodes.size() == oldHasSpecs.size()); TF_VERIFY(nodeIndexMap.size() == oldNodes.size()); const size_t numNodesToErase = std::count(nodeIndexMap.begin(), nodeIndexMap.end(), _Node::_invalidNodeIndex); const size_t oldNumNodes = oldNodes.size(); const size_t newNumNodes = oldNumNodes - numNodesToErase; TF_VERIFY(newNumNodes <= oldNumNodes); struct _ConvertOldToNewIndex { _ConvertOldToNewIndex(const std::vector<size_t>& table, size_t numNewNodes) : _table(table) { for (size_t i = 0, n = _table.size(); i != n; ++i) { TF_VERIFY(_table[i] < numNewNodes || _table[i] == _Node::_invalidNodeIndex); } } size_t operator()(size_t oldIndex) const { if (oldIndex != _Node::_invalidNodeIndex) { return _table[oldIndex]; } else { return oldIndex; } } const std::vector<size_t>& _table; }; const _ConvertOldToNewIndex convertToNewIndex(nodeIndexMap, newNumNodes); // If this mapping causes nodes to be erased, it's much more convenient // to fix up node indices to accommodate those erasures in the old node // pool before moving nodes to their new position. if (numNodesToErase > 0) { for (size_t i = 0; i < oldNumNodes; ++i) { const size_t oldNodeIndex = i; const size_t newNodeIndex = convertToNewIndex(oldNodeIndex); _Node& node = _data->nodes[oldNodeIndex]; // Sanity-check: If this node isn't going to be erased, its parent // can't be erased either. const bool nodeWillBeErased = (newNodeIndex == _Node::_invalidNodeIndex); if (!nodeWillBeErased) { const bool parentWillBeErased = PARENT(node) != _Node::_invalidNodeIndex && convertToNewIndex(PARENT(node)) == _Node::_invalidNodeIndex; TF_VERIFY(!parentWillBeErased); continue; } if (PREV_SIBLING(node) != _Node::_invalidNodeIndex) { _Node& prevNode = _data->nodes[PREV_SIBLING(node)]; NEXT_SIBLING(prevNode) = NEXT_SIBLING(node); } if (NEXT_SIBLING(node) != _Node::_invalidNodeIndex) { _Node& nextNode = _data->nodes[NEXT_SIBLING(node)]; PREV_SIBLING(nextNode) = PREV_SIBLING(node); } _Node& parentNode = _data->nodes[PARENT(node)]; if (FIRST_CHILD(parentNode) == oldNodeIndex) { FIRST_CHILD(parentNode) = NEXT_SIBLING(node); } if (LAST_CHILD(parentNode) == oldNodeIndex) { LAST_CHILD(parentNode) = PREV_SIBLING(node); } } } // Swap nodes into their new position. _NodePool nodesAfterMapping(newNumNodes); SdfPathVector nodeSitePathsAfterMapping(newNumNodes); std::vector<bool> nodeHasSpecsAfterMapping(newNumNodes); for (size_t i = 0; i < oldNumNodes; ++i) { const size_t oldNodeIndex = i; const size_t newNodeIndex = convertToNewIndex(oldNodeIndex); if (newNodeIndex == _Node::_invalidNodeIndex) { continue; } // Swap the node from the old node pool into the new node pool at // the desired location. _Node& oldNode = oldNodes[oldNodeIndex]; _Node& newNode = nodesAfterMapping[newNodeIndex]; newNode.Swap(oldNode); PARENT(newNode) = convertToNewIndex(PARENT(newNode)); ORIGIN(newNode) = convertToNewIndex(ORIGIN(newNode)); FIRST_CHILD(newNode) = convertToNewIndex(FIRST_CHILD(newNode)); LAST_CHILD(newNode) = convertToNewIndex(LAST_CHILD(newNode)); PREV_SIBLING(newNode) = convertToNewIndex(PREV_SIBLING(newNode)); NEXT_SIBLING(newNode) = convertToNewIndex(NEXT_SIBLING(newNode)); // Copy the corresponding node site path. nodeSitePathsAfterMapping[newNodeIndex] = oldSitePaths[oldNodeIndex]; nodeHasSpecsAfterMapping[newNodeIndex] = oldHasSpecs[oldNodeIndex]; } _data->nodes.swap(nodesAfterMapping); _nodeSitePaths.swap(nodeSitePathsAfterMapping); _nodeHasSpecs.swap(nodeHasSpecsAfterMapping); }
int32_t op_ret, int32_t op_errno, struct iatt *prebuf, struct iatt *postbuf, dict_t *xdata) { BARRIER_FOP_CBK (fsync, out, frame, this, op_ret, op_errno, prebuf, postbuf, xdata); out: return 0; } int32_t barrier_writev (call_frame_t *frame, xlator_t *this, fd_t *fd, struct iovec *vector, int32_t count, off_t off, uint32_t flags, struct iobref *iobref, dict_t *xdata) { if (!((flags | fd->flags) & (O_SYNC | O_DSYNC))) { STACK_WIND_TAIL (frame, FIRST_CHILD(this), FIRST_CHILD(this)->fops->writev, fd, vector, count, off, flags, iobref, xdata); return 0; } STACK_WIND (frame, barrier_writev_cbk, FIRST_CHILD(this), FIRST_CHILD(this)->fops->writev, fd, vector, count, off, flags, iobref, xdata); return 0; } int32_t barrier_fremovexattr (call_frame_t *frame, xlator_t *this, fd_t *fd, const char *name, dict_t *xdata)