Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,43 @@
}
}

private IDeviceMNode<IMemMNode> setToEntityAndUpdateFlags(final IMemMNode node) {
final boolean wasDevice = node.isDevice();
final IDeviceMNode<IMemMNode> deviceMNode = store.setToEntity(node);
if (!wasDevice) {
markAncestorsHavingDeviceDescendant(node);
}
return deviceMNode;
}

private void markAncestorsHavingDeviceDescendant(final IMemMNode deviceNode) {
IMemMNode current = deviceNode.getParent();
while (current != null && !current.hasDeviceDescendant()) {
current.setHasDeviceDescendant(true);
current = current.getParent();
}
}

private boolean hasDeviceDescendantInChildren(final IMemMNode node) {
try (final IMNodeIterator<IMemMNode> iterator = store.getChildrenIterator(node)) {
while (iterator.hasNext()) {
final IMemMNode child = iterator.next();
if (child.isDevice() || child.hasDeviceDescendant()) {
return true;
}
}
return false;
}
}

private void refreshAncestorsHavingDeviceDescendant(IMemMNode startNode) {
IMemMNode current = startNode;
while (current != null) {
current.setHasDeviceDescendant(hasDeviceDescendantInChildren(current));
current = current.getParent();
}
}

private long getTemplateMeasurementCount(final int templateId) {
final Template template = ClusterTemplateManager.getInstance().getTemplate(templateId);
return template == null ? 0L : template.getMeasurementNumber();
Expand Down Expand Up @@ -315,7 +352,7 @@
if (device.isDevice()) {
entityMNode = device.getAsDeviceMNode();
} else {
entityMNode = store.setToEntity(device);
entityMNode = setToEntityAndUpdateFlags(device);
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

setToEntityAndUpdateFlags marks ancestors when a node becomes a device. Please confirm refreshAncestorsHavingDeviceDescendant on deleteEmptyInternalMNode keeps flags correct when the last device under a prefix is removed.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Confirmed and covered with tests. The delete refresh recomputes ancestors from children, so when the last device under one prefix is removed, higher ancestors stay true if another sibling device subtree still exists and become false only after the last remaining device subtree is removed. I extended both memory and cached MTree tests for that case, and added memory-mode table-device drop coverage as well.

}

// create a non-aligned time series
Expand Down Expand Up @@ -353,7 +390,7 @@
* @param compressors compressor
*/
public List<IMeasurementMNode<IMemMNode>> createAlignedTimeSeries(
final PartialPath devicePath,

Check warning on line 393 in iotdb-core/datanode/src/main/java/org/apache/iotdb/db/schemaengine/schemaregion/mtree/impl/mem/MTreeBelowSGMemoryImpl.java

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

A "Brain Method" was detected. Refactor it to reduce at least one of the following metrics: LOC from 69 to 64, Complexity from 20 to 14, Nesting Level from 4 to 2, Number of Variables from 18 to 6.

See more on https://sonarcloud.io/project/issues?id=apache_iotdb&issues=AZ4mlnE8I-vGf32cLFKF&open=AZ4mlnE8I-vGf32cLFKF&pullRequest=17672
final List<String> measurements,
final List<TSDataType> dataTypes,
final List<TSEncoding> encodings,
Expand Down Expand Up @@ -409,7 +446,7 @@
if (device.isDevice()) {
entityMNode = device.getAsDeviceMNode();
} else {
entityMNode = store.setToEntity(device);
entityMNode = setToEntityAndUpdateFlags(device);
entityMNode.setAligned(true);
}

Expand Down Expand Up @@ -657,14 +694,15 @@
boolean hasMeasurement = false;
boolean hasNonViewMeasurement = false;
IMemMNode child;
IMNodeIterator<IMemMNode> iterator = store.getChildrenIterator(curNode);
while (iterator.hasNext()) {
child = iterator.next();
if (child.isMeasurement()) {
hasMeasurement = true;
if (!child.getAsMeasurementMNode().isLogicalView()) {
hasNonViewMeasurement = true;
break;
try (final IMNodeIterator<IMemMNode> iterator = store.getChildrenIterator(curNode)) {
while (iterator.hasNext()) {
child = iterator.next();
if (child.isMeasurement()) {
hasMeasurement = true;
if (!child.getAsMeasurementMNode().isLogicalView()) {
hasNonViewMeasurement = true;
break;
}
}
}
}
Expand All @@ -673,6 +711,7 @@
synchronized (this) {
curNode = store.setToInternal(entityMNode);
}
refreshAncestorsHavingDeviceDescendant(curNode.getParent());
} else if (!hasNonViewMeasurement) {
// has some measurement but they are all logical view
entityMNode.setAligned(null);
Expand Down Expand Up @@ -1033,7 +1072,7 @@
if (cur.isDevice()) {
entityMNode = cur.getAsDeviceMNode();
} else {
entityMNode = store.setToEntity(cur);
entityMNode = setToEntityAndUpdateFlags(cur);
}
}

Expand Down Expand Up @@ -1141,7 +1180,7 @@
if (cur.isDevice()) {
entityMNode = cur.getAsDeviceMNode();
} else {
entityMNode = store.setToEntity(cur);
entityMNode = setToEntityAndUpdateFlags(cur);
}

if (!entityMNode.isAligned()) {
Expand Down Expand Up @@ -1196,14 +1235,21 @@

private long rebuildSubtreeMeasurementCountFromNode(final IMemMNode node) {
long count = node.isMeasurement() ? 1L : 0L;
final IMNodeIterator<IMemMNode> iterator = store.getChildrenIterator(node);
while (iterator.hasNext()) {
count += rebuildSubtreeMeasurementCountFromNode(iterator.next());
boolean hasDeviceDescendant = false;
try (final IMNodeIterator<IMemMNode> iterator = store.getChildrenIterator(node)) {
while (iterator.hasNext()) {
final IMemMNode child = iterator.next();
count += rebuildSubtreeMeasurementCountFromNode(child);
if (child.isDevice() || child.hasDeviceDescendant()) {
hasDeviceDescendant = true;
}
}
}
if (node.isDevice() && node.getAsDeviceMNode().isUseTemplate()) {
count += getTemplateMeasurementCount(node.getAsDeviceMNode().getSchemaTemplateId());
}
node.setSubtreeMeasurementCount(count);
node.setHasDeviceDescendant(hasDeviceDescendant);
return count;
}

Expand Down Expand Up @@ -1786,7 +1832,7 @@
if (device.isDevice()) {
entityMNode = device.getAsDeviceMNode();
} else {
entityMNode = store.setToEntity(device);
entityMNode = setToEntityAndUpdateFlags(device);
// this parent has no measurement before. The leafName is his first child who is a logical
// view.
entityMNode.setAligned(null);
Expand Down Expand Up @@ -1923,7 +1969,7 @@
(TableDeviceInfo<IMemMNode>) entityMNode.getDeviceInfo();
attributeUpdater.accept(deviceInfo.getAttributePointer());
} else {
entityMNode = store.setToEntity(cur);
entityMNode = setToEntityAndUpdateFlags(cur);
final TableDeviceInfo<IMemMNode> deviceInfo = new TableDeviceInfo<>();
deviceInfo.setAttributePointer(attributePointerGetter.getAsInt());
entityMNode.getAsInternalMNode().setDeviceInfo(deviceInfo);
Expand Down Expand Up @@ -2040,6 +2086,7 @@
collector.traverse();
}
databaseMNode.deleteChild(tableName);
refreshAncestorsHavingDeviceDescendant(databaseMNode);
regionStatistics.resetTableDevice(tableName);
store.releaseMemory(memoryReleased.get());
return true;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,33 @@
package org.apache.iotdb.db.schemaengine.schemaregion.mtree.impl.mem.mnode;

import org.apache.iotdb.commons.schema.node.IMNode;
import org.apache.iotdb.db.schemaengine.schemaregion.mtree.impl.mem.mnode.basic.BasicMNode;

public interface IMemMNode extends IMNode<IMemMNode> {

BasicMNode getBasicMNode();

/**
* The count of measurement nodes contained in the subtree rooted at this node. The counter is
* maintained in memory only.
*/
long getSubtreeMeasurementCount();
default long getSubtreeMeasurementCount() {
return getBasicMNode().getSubtreeMeasurementCount();
}

default void setSubtreeMeasurementCount(final long subtreeMeasurementCount) {
getBasicMNode().setSubtreeMeasurementCount(subtreeMeasurementCount);
}

/**
* Whether there is any device node in the subtree rooted at this node, excluding the node itself.
* This flag is maintained in memory only.
*/
default boolean hasDeviceDescendant() {
return getBasicMNode().hasDeviceDescendant();
}

void setSubtreeMeasurementCount(long subtreeMeasurementCount);
default void setHasDeviceDescendant(final boolean hasDeviceDescendant) {
getBasicMNode().setHasDeviceDescendant(hasDeviceDescendant);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,9 @@ public class BasicMNode implements IMemMNode {
/** Cached count of measurements in this node's subtree, rebuilt on restart. */
private long subtreeMeasurementCount = 0L;

/** Cached flag showing whether there is any device in the subtree below this node. */
private boolean hasDeviceDescendant = false;

/** from root to this node, only be set when used once for InternalMNode */
private String fullPath;

Expand All @@ -58,6 +61,11 @@ public BasicMNode(IMemMNode parent, String name) {
this.basicMNodeInfo = new BasicMNodeInfo(name);
}

@Override
public BasicMNode getBasicMNode() {
return this;
}

@Override
public String getName() {
return basicMNodeInfo.getName();
Expand Down Expand Up @@ -112,6 +120,16 @@ public void setSubtreeMeasurementCount(final long subtreeMeasurementCount) {
this.subtreeMeasurementCount = subtreeMeasurementCount;
}

@Override
public boolean hasDeviceDescendant() {
return hasDeviceDescendant;
}

@Override
public void setHasDeviceDescendant(final boolean hasDeviceDescendant) {
this.hasDeviceDescendant = hasDeviceDescendant;
}

@Override
public PartialPath getPartialPath() {
final List<String> detachedPath = new ArrayList<>();
Expand Down Expand Up @@ -239,6 +257,7 @@ public <R, C> R accept(final MNodeVisitor<R, C> visitor, final C context) {
* <li>parent reference, 8B
* <li>fullPath reference, 8B
* <li>subtreeMeasurementCount, 8B
* <li>hasDeviceDescendant, 1B
* </ol>
* <li>MapEntry in parent
* <ol>
Expand All @@ -250,7 +269,7 @@ public <R, C> R accept(final MNodeVisitor<R, C> visitor, final C context) {
*/
@Override
public int estimateSize() {
return 8 + 8 + 8 + 8 + 8 + 8 + 8 + 28 + basicMNodeInfo.estimateSize();
return 8 + 8 + 8 + 8 + 8 + 1 + 8 + 8 + 28 + basicMNodeInfo.estimateSize();
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,14 +33,4 @@ public AboveDatabaseMNode(IMemMNode parent, String name) {
public IMemMNode getAsMNode() {
return this;
}

@Override
public long getSubtreeMeasurementCount() {
return basicMNode.getSubtreeMeasurementCount();
}

@Override
public void setSubtreeMeasurementCount(long subtreeMeasurementCount) {
basicMNode.setSubtreeMeasurementCount(subtreeMeasurementCount);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -45,14 +45,4 @@ public IDeviceInfo<IMemMNode> getDeviceInfo() {
public void setDeviceInfo(IDeviceInfo<IMemMNode> deviceInfo) {
basicMNode.setDeviceInfo(deviceInfo);
}

@Override
public long getSubtreeMeasurementCount() {
return basicMNode.getSubtreeMeasurementCount();
}

@Override
public void setSubtreeMeasurementCount(long subtreeMeasurementCount) {
basicMNode.setSubtreeMeasurementCount(subtreeMeasurementCount);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -52,14 +52,4 @@ public IMNodeContainer<IMemMNode> getChildren() {
public final boolean isLogicalView() {
return false;
}

@Override
public long getSubtreeMeasurementCount() {
return basicMNode.getSubtreeMeasurementCount();
}

@Override
public void setSubtreeMeasurementCount(long subtreeMeasurementCount) {
basicMNode.setSubtreeMeasurementCount(subtreeMeasurementCount);
}
}
Loading
Loading