private void tryGetNext() {
      ICachedMNode node;
      CacheEntry cacheEntry;
      while (bufferedNodeIterator.hasNext() || status == ITERATE_NEW_BUFFER) {
        if (!bufferedNodeIterator.hasNext()) {
          // flushingBuffer of NewChildBuffer has been traversed, and the flushingBuffer of
          // UpdateChildBuffer needs to be traversed.
          bufferedNodeIterator = container.getUpdatedChildFlushingBuffer().values().iterator();
          status = ITERATE_UPDATE_BUFFER;
          if (!bufferedNodeIterator.hasNext()) {
            return;
          }
        }
        node = bufferedNodeIterator.next();

        // prevent this node being added buffer during the following check and potential flush
        // unlock in PBTreeFlushExecutor
        lockManager.writeLock(node);

        boolean unlockImmediately = true;

        try {
          // update cache status after persist
          // when process one node, all of its buffered child should be moved to cache
          // except those with volatile children
          cacheEntry = getCacheEntry(node);

          synchronized (cacheEntry) {
            if (status == ITERATE_UPDATE_BUFFER
                && container.getUpdatedChildReceivingBuffer().containsKey(node.getName())) {
              if (cacheEntry.hasVolatileDescendant()
                  && getCachedMNodeContainer(node).hasChildrenInBuffer()) {
                // these two factor judgement is not redundant because the #hasVolatileDescendant is
                // on a higher priority than #container.hasChildren

                // nodes with volatile children should be treated as root of volatile subtree and
                // return for flush
                nextSubtree = node;
                unlockImmediately = false;
                return;
              } else {
                continue;
              }
            }

            cacheEntry.setVolatile(false);
            memoryStatistics.removeVolatileNode();
            if (status == ITERATE_UPDATE_BUFFER) {
              container.moveMNodeFromUpdateChildBufferToCache(node.getName());
            } else {
              container.moveMNodeFromNewChildBufferToCache(node.getName());
            }

            if (cacheEntry.hasVolatileDescendant()
                && getCachedMNodeContainer(node).hasChildrenInBuffer()) {
              // these two factor judgement is not redundant because the #hasVolatileDescendant is
              // on a higher priority than #container.hasChildren

              // nodes with volatile children should be treated as root of volatile subtree and
              // return for flush
              nextSubtree = node;
              unlockImmediately = false;
              return;
            }

            // there's no direct volatile subtree under this node, thus there's no need to flush it
            // add the node and its ancestors to cache
            nodeCache.addToNodeCache(cacheEntry, node);
            addAncestorsToCache(node);
          }
        } finally {
          if (unlockImmediately) {
            lockManager.writeUnlock(node);
          }
        }
      }
    }
Collect updated storage group node.

@return null if not exist
iotdb-core/datanode/src/main/java/org/apache/iotdb/db/schemaengine/schemaregion/mtree/impl/pbtree/memory/MemoryManager.java