void CallChainRoot::AddCallChain(const std::vector<SampleEntry*>& callchain, uint64_t period) { children_period += period; CallChainNode* p = FindMatchingNode(children, callchain[0]); if (p == nullptr) { std::unique_ptr<CallChainNode> new_node = AllocateNode(callchain, 0, period, 0); children.push_back(std::move(new_node)); return; } size_t callchain_pos = 0; while (true) { size_t match_length = GetMatchingLengthInNode(p, callchain, callchain_pos); CHECK_GT(match_length, 0u); callchain_pos += match_length; bool find_child = true; if (match_length < p->chain.size()) { SplitNode(p, match_length); find_child = false; // No need to find matching node in p->children. } if (callchain_pos == callchain.size()) { p->period += period; return; } p->children_period += period; if (find_child) { CallChainNode* np = FindMatchingNode(p->children, callchain[callchain_pos]); if (np != nullptr) { p = np; continue; } } std::unique_ptr<CallChainNode> new_node = AllocateNode(callchain, callchain_pos, period, 0); p->children.push_back(std::move(new_node)); break; } }
// Create a proxy in the tree as a leaf node. We return the index // of the node instead of a pointer so that we can grow // the node pool. int32 b2DynamicTree::CreateProxy(const b2AABB& aabb, void* userData) { int32 proxyId = AllocateNode(); // Fatten the aabb. b2Vec2 r(b2_aabbExtension, b2_aabbExtension); m_nodes[proxyId].aabb.lowerBound = aabb.lowerBound - r; m_nodes[proxyId].aabb.upperBound = aabb.upperBound + r; m_nodes[proxyId].userData = userData; InsertLeaf(proxyId); // Rebalance if necessary. int32 iterationCount = m_nodeCount >> 4; int32 tryCount = 0; int32 height = ComputeHeight(); while (height > 64 && tryCount < 10) { Rebalance(iterationCount); height = ComputeHeight(); ++tryCount; } return proxyId; }
static void SplitNode(CallChainNode* parent, size_t parent_length) { std::unique_ptr<CallChainNode> child = AllocateNode(parent->chain, parent_length, parent->period, parent->children_period); child->children = std::move(parent->children); parent->period = 0; parent->children_period = child->period + child->children_period; parent->chain.resize(parent_length); parent->children.clear(); parent->children.push_back(std::move(child)); }
void VDFilterFrameCache::Add(VDFilterFrameBuffer *buf, sint64 key) { VDFilterFrameBufferCacheNode *hnode = AllocateNode(); hnode->mKey = key; hnode->mpBuffer = buf; int htidx = (unsigned)hnode->mKey % (kBufferHashTableSize - 1); mHashTable[htidx].push_back(hnode); buf->AddCacheReference(hnode); }
// Create a proxy in the tree as a leaf node. We return the index // of the node instead of a pointer so that we can grow // the node pool. int32 b2DynamicTree::CreateProxy(const b2AABB& aabb, void* userData) { int32 proxyId = AllocateNode(); // Fatten the aabb. b2Vec2 r(b2_aabbExtension, b2_aabbExtension); m_nodes[proxyId].aabb.lowerBound = aabb.lowerBound - r; m_nodes[proxyId].aabb.upperBound = aabb.upperBound + r; m_nodes[proxyId].userData = userData; m_nodes[proxyId].height = 0; InsertLeaf(proxyId); return proxyId; }
// Create a proxy in the tree as a leaf node. We return the index // of the node instead of a pointer so that we can grow // the node pool. uint16 b2DynamicTree::CreateProxy(const b2AABB& aabb, void* userData) { uint16 node = AllocateNode(); // Fatten the aabb. b2Vec2 center = aabb.GetCenter(); b2Vec2 extents = b2_fatAABBFactor * aabb.GetExtents(); m_nodes[node].aabb.lowerBound = center - extents; m_nodes[node].aabb.upperBound = center + extents; m_nodes[node].userData = userData; InsertLeaf(node); return node; }
// Split the child of x at the specified index (that is already loaded and available at y) void DiskBTree::split(std::shared_ptr<BTreeNode> x, uint16_t i, std::shared_ptr<BTreeNode> y) { auto z = std::make_shared<BTreeNode>(AllocateNode(), TFactor, MaxKeySize); z->isLeaf = y->isLeaf; z->KeyCount = y->KeyCount = TFactor - 1; // Move the largest t – 1 keys and corresponding t children from y to z for(int64_t j = 0; j < TFactor - 1; j++) { z->Keys[j] = y->Keys[j + TFactor]; y->Keys[j + TFactor] = nullptr; } if(!y->isLeaf) { // Y isn't a leaf. Don't forget to move t child pointers for(auto j = 0; j < TFactor; j++) { z->Children[j] = y->Children[j + TFactor]; y->Children[j + TFactor] = 0; } } // insert z as a child of x for(int64_t j = x->KeyCount; j >= i; j--) { x->Children[j + 1] = x->Children[j]; } x->Children[i+1] = z->ID; // Make room for the median of the split for(int64_t j = x->KeyCount; j > i; j--) { x->Keys[j] = x->Keys[j-1]; } // Promote the median x->Keys[i] = y->Keys[TFactor-1]; y->Keys[TFactor - 1] = nullptr; // And update the key count of x x->KeyCount++; // Commit all the things commit(x); commit(y); commit(z, true); }
static void MakeExprNode( ExprTree &tree, char token, Kind kind, ExprTree left, ExprTree right ) { tree = AllocateNode(); tree->left = left; tree->right = right; tree->kind = kind; switch ( kind ) { case CONDITIONAL: tree->data.cond = token; break; case LITERAL: tree->data.value = g_pGetSymbolProc( mIdentifier ); break; case NOT: break; default: VPC_Error( "Error in ExpTree" ); } }
DiskBTree::DiskBTree(std::string path, uint16_t branchingFactor, uint16_t maxKeySize) : TreePath(path), TFactor(branchingFactor), MaxKeySize(maxKeySize) { // Ensure the directory the tree should be placed in exists utils::createDirectories(utils::parent(path)); FileHandle.open(path, std::ios::binary | std::ios::in | std::ios::out); readCount++; if(!FileHandle.good()) { // We have to do this dance to ensure the file gets created... FileHandle.close(); FileHandle.open(path, std::ios::out); FileHandle.close(); FileHandle.open(path, std::ios::binary | std::ios::in | std::ios::out); // Probably a new tree, try to commit the empty metadata auto x = std::make_shared<BTreeNode>(AllocateNode(), TFactor, MaxKeySize); x->isLeaf = true; RootID = x->ID; commit(x, true); } else { // Existing tree utils::read_binary(FileHandle, NextNode); utils::read_binary(FileHandle, RootID); utils::read_binary(FileHandle, TFactor); utils::read_binary(FileHandle, MaxKeySize); } FileHandle.flush(); FileHandle.close(); FileHandle.open(path, std::ios::binary | std::ios::in | std::ios::out); }
// Adds the word to the tree. If the word already exists, its occurrance count is incremeneted void DiskBTree::add(std::string key) { if (key.length() > MaxKeySize) throw std::runtime_error("Key to large. Try again with a larger max key size"); auto r = load(RootID); assert(r != nullptr); if(r->isFull()) { // If the root node is full, we have to push a new root out to the top auto s = std::make_shared<BTreeNode>(AllocateNode(), TFactor, MaxKeySize); RootID = s->ID; s->isLeaf = false; s->Children[s->KeyCount] = r->ID; commit(s, true); split(s, 0, r); insertNonFull(s, key); } else { insertNonFull(r, key); } }
void b2DynamicTree::RebuildBottomUp() { int32* nodes = (int32*)b2Alloc(m_nodeCount * sizeof(int32)); int32 count = 0; // Build array of leaves. Free the rest. for (int32 i = 0; i < m_nodeCapacity; ++i) { if (m_nodes[i].height < 0) { // free node in pool continue; } if (m_nodes[i].IsLeaf()) { m_nodes[i].parent = b2_nullNode; nodes[count] = i; ++count; } else { FreeNode(i); } } while (count > 1) { float32 minCost = b2_maxFloat; int32 iMin = -1, jMin = -1; for (int32 i = 0; i < count; ++i) { b2AABB aabbi = m_nodes[nodes[i]].aabb; for (int32 j = i + 1; j < count; ++j) { b2AABB aabbj = m_nodes[nodes[j]].aabb; b2AABB b; b.Combine(aabbi, aabbj); float32 cost = b.GetPerimeter(); if (cost < minCost) { iMin = i; jMin = j; minCost = cost; } } } int32 index1 = nodes[iMin]; int32 index2 = nodes[jMin]; b2TreeNode* child1 = m_nodes + index1; b2TreeNode* child2 = m_nodes + index2; int32 parentIndex = AllocateNode(); b2TreeNode* parent = m_nodes + parentIndex; parent->child1 = index1; parent->child2 = index2; parent->height = 1 + b2Max(child1->height, child2->height); parent->aabb.Combine(child1->aabb, child2->aabb); parent->parent = b2_nullNode; child1->parent = parentIndex; child2->parent = parentIndex; nodes[jMin] = nodes[count-1]; nodes[iMin] = parentIndex; --count; } m_root = nodes[0]; b2Free(nodes); Validate(); }
void b2DynamicTree::InsertLeaf(int32 leaf) { ++m_insertionCount; if (m_root == b2_nullNode) { m_root = leaf; m_nodes[m_root].parent = b2_nullNode; return; } // Find the best sibling for this node b2AABB leafAABB = m_nodes[leaf].aabb; int32 index = m_root; while (m_nodes[index].IsLeaf() == false) { int32 child1 = m_nodes[index].child1; int32 child2 = m_nodes[index].child2; float32 area = m_nodes[index].aabb.GetPerimeter(); b2AABB combinedAABB; combinedAABB.Combine(m_nodes[index].aabb, leafAABB); float32 combinedArea = combinedAABB.GetPerimeter(); // Cost of creating a new parent for this node and the new leaf float32 cost = 2.0f * combinedArea; // Minimum cost of pushing the leaf further down the tree float32 inheritanceCost = 2.0f * (combinedArea - area); // Cost of descending into child1 float32 cost1; if (m_nodes[child1].IsLeaf()) { b2AABB aabb; aabb.Combine(leafAABB, m_nodes[child1].aabb); cost1 = aabb.GetPerimeter() + inheritanceCost; } else { b2AABB aabb; aabb.Combine(leafAABB, m_nodes[child1].aabb); float32 oldArea = m_nodes[child1].aabb.GetPerimeter(); float32 newArea = aabb.GetPerimeter(); cost1 = (newArea - oldArea) + inheritanceCost; } // Cost of descending into child2 float32 cost2; if (m_nodes[child2].IsLeaf()) { b2AABB aabb; aabb.Combine(leafAABB, m_nodes[child2].aabb); cost2 = aabb.GetPerimeter() + inheritanceCost; } else { b2AABB aabb; aabb.Combine(leafAABB, m_nodes[child2].aabb); float32 oldArea = m_nodes[child2].aabb.GetPerimeter(); float32 newArea = aabb.GetPerimeter(); cost2 = newArea - oldArea + inheritanceCost; } // Descend according to the minimum cost. if (cost < cost1 && cost < cost2) { break; } // Descend if (cost1 < cost2) { index = child1; } else { index = child2; } } int32 sibling = index; // Create a new parent. int32 oldParent = m_nodes[sibling].parent; int32 newParent = AllocateNode(); m_nodes[newParent].parent = oldParent; m_nodes[newParent].userData = NULL; m_nodes[newParent].aabb.Combine(leafAABB, m_nodes[sibling].aabb); m_nodes[newParent].height = m_nodes[sibling].height + 1; if (oldParent != b2_nullNode) { // The sibling was not the root. if (m_nodes[oldParent].child1 == sibling) { m_nodes[oldParent].child1 = newParent; } else { m_nodes[oldParent].child2 = newParent; } m_nodes[newParent].child1 = sibling; m_nodes[newParent].child2 = leaf; m_nodes[sibling].parent = newParent; m_nodes[leaf].parent = newParent; } else { // The sibling was the root. m_nodes[newParent].child1 = sibling; m_nodes[newParent].child2 = leaf; m_nodes[sibling].parent = newParent; m_nodes[leaf].parent = newParent; m_root = newParent; } // Walk back up the tree fixing heights and AABBs index = m_nodes[leaf].parent; while (index != b2_nullNode) { index = Balance(index); int32 child1 = m_nodes[index].child1; int32 child2 = m_nodes[index].child2; b2Assert(child1 != b2_nullNode); b2Assert(child2 != b2_nullNode); m_nodes[index].height = 1 + b2Max(m_nodes[child1].height, m_nodes[child2].height); m_nodes[index].aabb.Combine(m_nodes[child1].aabb, m_nodes[child2].aabb); index = m_nodes[index].parent; } //Validate(); }
void b2DynamicTree::InsertLeaf(int32 leaf) { ++m_insertionCount; if (m_root == b2_nullNode) { m_root = leaf; m_nodes[m_root].parent = b2_nullNode; return; } // Find the best sibling for this node. b2Vec2 center = m_nodes[leaf].aabb.GetCenter(); int32 sibling = m_root; if (m_nodes[sibling].IsLeaf() == false) { do { int32 child1 = m_nodes[sibling].child1; int32 child2 = m_nodes[sibling].child2; b2Vec2 delta1 = b2Abs(m_nodes[child1].aabb.GetCenter() - center); b2Vec2 delta2 = b2Abs(m_nodes[child2].aabb.GetCenter() - center); float32 norm1 = delta1.x + delta1.y; float32 norm2 = delta2.x + delta2.y; if (norm1 < norm2) { sibling = child1; } else { sibling = child2; } } while(m_nodes[sibling].IsLeaf() == false); } // Create a parent for the siblings. int32 node1 = m_nodes[sibling].parent; int32 node2 = AllocateNode(); m_nodes[node2].parent = node1; m_nodes[node2].userData = NULL; m_nodes[node2].aabb.Combine(m_nodes[leaf].aabb, m_nodes[sibling].aabb); if (node1 != b2_nullNode) { if (m_nodes[m_nodes[sibling].parent].child1 == sibling) { m_nodes[node1].child1 = node2; } else { m_nodes[node1].child2 = node2; } m_nodes[node2].child1 = sibling; m_nodes[node2].child2 = leaf; m_nodes[sibling].parent = node2; m_nodes[leaf].parent = node2; do { if (m_nodes[node1].aabb.Contains(m_nodes[node2].aabb)) { break; } m_nodes[node1].aabb.Combine(m_nodes[m_nodes[node1].child1].aabb, m_nodes[m_nodes[node1].child2].aabb); node2 = node1; node1 = m_nodes[node1].parent; } while(node1 != b2_nullNode); } else { m_nodes[node2].child1 = sibling; m_nodes[node2].child2 = leaf; m_nodes[sibling].parent = node2; m_nodes[leaf].parent = node2; m_root = node2; } }