private void deleteAndUnpinEmptyInternalMNode(IDeviceMNode<ICachedMNode> entityMNode)
      throws MetadataException {
    ICachedMNode curNode = entityMNode.getAsMNode();
    if (!entityMNode.isUseTemplate()) {
      synchronized (this) {
        boolean hasMeasurement = false;
        boolean hasNonViewMeasurement = false;
        ICachedMNode child;
        IMNodeIterator<ICachedMNode> iterator = store.getChildrenIterator(curNode);
        try {
          while (iterator.hasNext()) {
            child = iterator.next();
            unPinMNode(child);
            if (child.isMeasurement()) {
              hasMeasurement = true;
              if (!child.getAsMeasurementMNode().isLogicalView()) {
                hasNonViewMeasurement = true;
                break;
              }
            }
          }
        } finally {
          iterator.close();
        }

        if (!hasMeasurement) {
          curNode = store.setToInternal(entityMNode);
        } else if (!hasNonViewMeasurement) {
          // has some measurement but they are all logical view
          store.updateMNode(entityMNode.getAsMNode(), o -> o.getAsDeviceMNode().setAligned(null));
        }
      }
    }

    // delete all empty ancestors except database and MeasurementMNode
    while (true) {
      // if current database has no time series, return the database name
      if (curNode.isDatabase()) {
        return;
      }

      synchronized (this) {
        if (!isEmptyInternalMNode(curNode)) {
          break;
        }
        store.deleteChild(curNode.getParent(), curNode.getName());
        curNode = curNode.getParent();
      }
    }
    unPinMNode(curNode);
  }
Used when delete timeseries or deactivate template. The last survived ancestor will be
unpinned.

@param entityMNode delete empty InternalMNode from entityMNode to storageGroupMNode
iotdb-core/datanode/src/main/java/org/apache/iotdb/db/schemaengine/schemaregion/mtree/impl/pbtree/MTreeBelowSGCachedImpl.java