Uploaded image for project: 'Core Server'
  1. Core Server
  2. SERVER-73307

Make `CurOpStack` always store a pointer to its `OpCtx`

    • Type: Icon: Improvement Improvement
    • Resolution: Fixed
    • Priority: Icon: Major - P3 Major - P3
    • 7.0.0-rc0
    • Affects Version/s: None
    • Component/s: Internal Code
    • Labels:
    • Service Arch
    • Fully Compatible
    • Service Arch 2023-02-06, Service Arch 2023-02-20
    • 155

      At the time of writing this ticket, CurOp is defined as a decoration on OperationContext, through CurOpStack which may contain a stack of CurOp objects:

      /**
       * This type decorates a Client object with a stack of active CurOp objects.
       *
       * It encapsulates the nesting logic for curops attached to a Client, along with
       * the notion that there is always a root CurOp attached to a Client.
       *
       * The stack itself is represented in the _parent pointers of the CurOp class.
       */
      class CurOp::CurOpStack {
      ...
      private:
          OperationContext* _opCtx = nullptr;
      
          // Top of the stack of CurOps for a Client.
          CurOp* _top = nullptr;
      
          // The bottom-most CurOp for a client.
          const CurOp _base;
      };
      

      CurOpStack holds a pointer to OperationContext, however, this pointer is not initialized until after the first CurOp is pushed to the stack:

      void CurOpStack::push(OperationContext* opCtx, CurOp* curOp) {
          invariant(opCtx);
          if (_opCtx) {
              invariant(_opCtx == opCtx);
          } else {
              _opCtx = opCtx;
          }
          stdx::lock_guard<Client> lk(*_opCtx->getClient());
          push_nolock(curOp);
      }
      

      We can use constructor actions (similar to the following example) to initialize the _opCtx member on CurOpStack during the construction of OperationContext, making sure _opCtx is always initialized and obviating the need to provide opCtx as an argument to CurOpStack and CurOp member functions. This also helps with simplifying the changes introduced by SERVER-70032.

      class CurOpClientObserver final : public ServiceContext::ClientObserver {
          void onCreateClient(Client*) {}
          void onDestroyClient(Client*) {}
          void onCreateOperationContext(OperationContext* opCtx) {
              _curopStack(opCtx).setOpCtx(opCtx);
          }
          void onDestroyOperationContext(OperationContext*) {}
      };
      
      ServiceContext::ConstructorActionRegisterer registerCurOpClientObserver{"CurOpClientObserver", [](ServiceContext* service) {
          service->registerClientObserver(std::make_unique<CurOpClientObserver>());
      }};
      

            Assignee:
            patrick.freed@mongodb.com Patrick Freed
            Reporter:
            amirsaman.memaripour@mongodb.com Amirsaman Memaripour
            Votes:
            0 Vote for this issue
            Watchers:
            3 Start watching this issue

              Created:
              Updated:
              Resolved: