HTTP2PriorityQueue::Handle HTTP2PriorityQueue::addTransaction()

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;
}