SERVER-111641 Update SBE open()/close() behavior documentation (#53972)

GitOrigin-RevId: 73ca58a2e60ea1220e249f3094f338f1da60b806
This commit is contained in:
Ian Boros 2026-05-20 10:27:14 -04:00 committed by MongoDB Bot
parent d00374ee45
commit e028d6213a
2 changed files with 23 additions and 3 deletions

View File

@ -227,8 +227,18 @@ acquired during `open()`. Acquiring resources for query execution can include ac
needs to sort all of the values produced by its children (either in memory or on disk) before it
can produce results in sorted order.
It is only legal to call `close()` on PlanStages that have called `open()`, and to call `open()` on
PlanStages that are closed. In some cases (such as in
`close()` may be called at any time after `prepare()` — it is idempotent, so calling it multiple
times is always safe. Callers are not required to call `close()` before destroying the plan tree,
but are encouraged to do so as soon as execution is complete and the plan tree is only needed for
its accumulated statistics (for example, call `close()` before collecting `explain` output to
release runtime resources while keeping the plan tree alive for inspection).
`open()` is not all-or-nothing. If `open()` throws an exception, the plan tree may be left in a
partially open state: some child stages may have already acquired resources while others have not.
In that case, the only legal operations are to destroy the plan or to call `close()` followed by
destruction.
In some cases (such as in
[`LoopJoinStage`](https://github.com/mongodb/mongo/blob/06a931ffadd7ce62c32288d03e5a38933bd522d3/src/mongo/db/exec/sbe/stages/loop_join.cpp#L158)),
a parent stage may `open()` and `close()` a child stage repeatedly. However, doing so may be
expensive and ultimately redundant. This is where the `reOpen` parameter of `open()` comes in: when

View File

@ -732,6 +732,10 @@ public:
* When reOpen flag is true then the plan stage should reinitizalize already acquired resources
* (e.g. re-hash, re-sort, re-seek, etc), but it can avoid reinitializing things that do not
* contain state and are not destroyed by close(), since close() is not called before a reopen.
*
* open() is not all-or-nothing. If open() throws, the plan stage may be left in a "partially
* open" state. The only legal operations on a partially-open stage are to destroy it (let the
* destructor run), or to call close() and then destroy it.
*/
virtual void open(bool reOpen) = 0;
@ -757,7 +761,13 @@ public:
virtual PlanState getNext() = 0;
/**
* The mirror method to open(). It releases any acquired resources.
* Releases any resources acquired by open(). This method is idempotent: it is safe to call
* close() multiple times, and safe to call close() on a stage that was never opened. Callers
* are not required to call close() before destroying a plan stage, but are encouraged to do so
* whenever they have a plan that is no longer actively executing and want to release runtime
* resources (e.g. storage-engine cursors, memory buffers) without destroying the plan tree
* itself (for example, call close() before collecting explain output so that runtime resources
* are released while the plan tree remains available for inspection).
*/
virtual void close() = 0;