in proxygen/lib/http/session/HTTP2PriorityQueue.cpp [449:523]
HTTP2PriorityQueue::Handle HTTP2PriorityQueue::addTransaction(
HTTPCodec::StreamID id,
http2::PriorityUpdate pri,
HTTPTransaction* txn,
bool permanent,
uint64_t* depth) {
CHECK_NE(id, rootNodeId_);
CHECK_NE(id, pri.streamDependency) << "Tried to create a loop in the tree";
CHECK(!txn || !permanent);
if (largestId_ && id <= *largestId_) {
Node* existingNode = find(id, depth);
if (existingNode) {
CHECK(!permanent);
existingNode->convertVirtualNode(CHECK_NOTNULL(txn));
updatePriority(existingNode, pri);
return existingNode;
}
} else {
largestId_ = id;
}
if (!txn) {
if (numVirtualNodes_ >= maxVirtualNodes_) {
return nullptr;
}
numVirtualNodes_++;
}
Node* parent = &root_;
if (depth) {
*depth = 1;
}
if (pri.streamDependency != rootNodeId_) {
Node* dep = find(pri.streamDependency, depth);
if (dep == nullptr) {
// specified a missing parent (timed out an idle node)?
VLOG(4) << "assigning default priority to txn=" << id;
// No point to try to instantiate one more virtual node
// if we already reached the virtual node limit
if (numVirtualNodes_ < maxVirtualNodes_) {
// The parent node hasn't arrived yet. For now setting
// its priority fields to default.
parent =
nodeFromBaseNode(addTransaction(pri.streamDependency,
{rootNodeId_,
http2::DefaultPriority.exclusive,
http2::DefaultPriority.weight},
nullptr,
permanent,
depth));
if (depth) {
*depth += 1;
}
} else {
VLOG(4) << "Virtual node limit reached, ignoring stream dependency "
<< pri.streamDependency << " for new node ID " << id;
}
} else {
parent = dep;
if (depth) {
*depth += 1;
}
}
}
VLOG(4) << "Adding id=" << id << " with parent=" << parent->getID()
<< " and weight=" << ((uint16_t)pri.weight + 1);
auto node = std::make_unique<Node>(*this, parent, id, pri.weight, txn);
if (permanent) {
node->setPermanent();
} else if (!txn) {
scheduleNodeExpiration(node.get());
}
auto result = parent->emplaceNode(std::move(node), pri.exclusive);
pendingWeightChange_ = true;
return result;
}