This is an automated email from the ASF dual-hosted git repository.
zyk pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/iotdb.git
The following commit(s) were added to refs/heads/master by this push:
new 811f019a6e4 PBTree mode support logical view (#11401)
811f019a6e4 is described below
commit 811f019a6e40461a9f115282c7cf054fc7de2073
Author: Chen YZ <[email protected]>
AuthorDate: Mon Oct 30 14:48:36 2023 +0800
PBTree mode support logical view (#11401)
---
.../schema/mnode/factory/ConfigMNodeFactory.java | 3 +-
.../schemaregion/impl/SchemaRegionPBTreeImpl.java | 74 +++++++++-
.../mtree/impl/mem/MTreeBelowSGMemoryImpl.java | 5 +-
.../impl/mem/mnode/factory/MemMNodeFactory.java | 3 +-
.../impl/mem/snapshot/MemMTreeSnapshotUtil.java | 3 +-
.../mtree/impl/pbtree/MTreeBelowSGCachedImpl.java | 164 ++++++++++++++++++++-
.../mnode/container/ICachedMNodeContainer.java | 2 +-
.../pbtree/mnode/factory/CacheMNodeFactory.java | 3 +-
.../mtree/impl/pbtree/schemafile/RecordUtils.java | 97 ++++++++++--
.../commons/schema/node/utils/IMNodeFactory.java | 3 +-
10 files changed, 319 insertions(+), 38 deletions(-)
diff --git
a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/persistence/schema/mnode/factory/ConfigMNodeFactory.java
b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/persistence/schema/mnode/factory/ConfigMNodeFactory.java
index 362c39321d7..cd19f87d180 100644
---
a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/persistence/schema/mnode/factory/ConfigMNodeFactory.java
+++
b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/persistence/schema/mnode/factory/ConfigMNodeFactory.java
@@ -18,7 +18,6 @@
*/
package org.apache.iotdb.confignode.persistence.schema.mnode.factory;
-import org.apache.iotdb.commons.schema.node.info.IMeasurementInfo;
import org.apache.iotdb.commons.schema.node.role.IDatabaseMNode;
import org.apache.iotdb.commons.schema.node.role.IDeviceMNode;
import org.apache.iotdb.commons.schema.node.role.IMeasurementMNode;
@@ -84,7 +83,7 @@ public class ConfigMNodeFactory implements
IMNodeFactory<IConfigMNode> {
@Override
public IMeasurementMNode<IConfigMNode> createLogicalViewMNode(
- IDeviceMNode<IConfigMNode> parent, String name, IMeasurementInfo
measurementInfo) {
+ IDeviceMNode<IConfigMNode> parent, String name, IMeasurementSchema
measurementSchema) {
throw new UnsupportedOperationException("View is not supported.");
}
}
diff --git
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/schemaengine/schemaregion/impl/SchemaRegionPBTreeImpl.java
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/schemaengine/schemaregion/impl/SchemaRegionPBTreeImpl.java
index 8e43a1c85b7..e6df581b29f 100644
---
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/schemaengine/schemaregion/impl/SchemaRegionPBTreeImpl.java
+++
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/schemaengine/schemaregion/impl/SchemaRegionPBTreeImpl.java
@@ -30,6 +30,7 @@ import org.apache.iotdb.commons.schema.SchemaConstant;
import org.apache.iotdb.commons.schema.filter.SchemaFilterType;
import org.apache.iotdb.commons.schema.node.role.IDeviceMNode;
import org.apache.iotdb.commons.schema.node.role.IMeasurementMNode;
+import org.apache.iotdb.commons.schema.view.viewExpression.ViewExpression;
import org.apache.iotdb.consensus.ConsensusFactory;
import org.apache.iotdb.db.conf.IoTDBConfig;
import org.apache.iotdb.db.conf.IoTDBDescriptor;
@@ -837,30 +838,89 @@ public class SchemaRegionPBTreeImpl implements
ISchemaRegion {
}
@Override
- public void createLogicalView(ICreateLogicalViewPlan createLogicalViewPlan)
- throws MetadataException {
- throw new UnsupportedOperationException("createLogicalView is
unsupported.");
+ public void createLogicalView(ICreateLogicalViewPlan plan) throws
MetadataException {
+ while (!regionStatistics.isAllowToCreateNewSeries()) {
+ CacheMemoryManager.getInstance().waitIfReleasing();
+ }
+ try {
+ List<PartialPath> pathList = plan.getViewPathList();
+ Map<PartialPath, ViewExpression> viewPathToSourceMap =
+ plan.getViewPathToSourceExpressionMap();
+ for (PartialPath path : pathList) {
+ ViewExpression viewExpression = viewPathToSourceMap.get(path);
+ mtree.createLogicalView(path, viewExpression);
+ // write log
+ if (!isRecovering) {
+
writeToMLog(SchemaRegionWritePlanFactory.getCreateLogicalViewPlan(path,
viewExpression));
+ }
+ regionStatistics.addTimeseries(1L);
+ }
+ } catch (IOException e) {
+ throw new MetadataException(e);
+ }
}
@Override
public long constructLogicalViewBlackList(PathPatternTree patternTree)
throws MetadataException {
- throw new UnsupportedOperationException();
+ long preDeletedNum = 0;
+ for (PartialPath pathPattern : patternTree.getAllPathPatterns()) {
+ // Given pathPatterns may match one logical view multi times, which may
results in the
+ // preDeletedNum larger than the actual num of logical view. It doesn't
matter since the main
+ // purpose is to check whether there's logical view to be deleted.
+ List<PartialPath> paths =
mtree.constructLogicalViewBlackList(pathPattern);
+ preDeletedNum += paths.size();
+ for (PartialPath path : paths) {
+ try {
+
writeToMLog(SchemaRegionWritePlanFactory.getPreDeleteLogicalViewPlan(path));
+ } catch (IOException e) {
+ throw new MetadataException(e);
+ }
+ }
+ }
+ return preDeletedNum;
}
@Override
public void rollbackLogicalViewBlackList(PathPatternTree patternTree) throws
MetadataException {
- throw new UnsupportedOperationException();
+ for (PartialPath pathPattern : patternTree.getAllPathPatterns()) {
+ List<PartialPath> paths =
mtree.rollbackLogicalViewBlackList(pathPattern);
+ for (PartialPath path : paths) {
+ try {
+
writeToMLog(SchemaRegionWritePlanFactory.getRollbackPreDeleteLogicalViewPlan(path));
+ } catch (IOException e) {
+ throw new MetadataException(e);
+ }
+ }
+ }
}
@Override
public void deleteLogicalView(PathPatternTree patternTree) throws
MetadataException {
- throw new UnsupportedOperationException();
+ for (PartialPath pathPattern : patternTree.getAllPathPatterns()) {
+ for (PartialPath path : mtree.getPreDeletedLogicalView(pathPattern)) {
+ try {
+ deleteSingleTimeseriesInBlackList(path);
+
writeToMLog(SchemaRegionWritePlanFactory.getDeleteLogicalViewPlan(path));
+ } catch (IOException e) {
+ throw new MetadataException(e);
+ }
+ }
+ }
}
@Override
public void alterLogicalView(IAlterLogicalViewPlan alterLogicalViewPlan)
throws MetadataException {
- throw new UnsupportedOperationException();
+ mtree.alterLogicalView(
+ alterLogicalViewPlan.getViewPath(),
alterLogicalViewPlan.getSourceExpression());
+ // write log
+ if (!isRecovering) {
+ try {
+ writeToMLog(alterLogicalViewPlan);
+ } catch (IOException e) {
+ throw new MetadataException(e);
+ }
+ }
}
private void deleteSingleTimeseriesInBlackList(PartialPath path)
diff --git
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/schemaengine/schemaregion/mtree/impl/mem/MTreeBelowSGMemoryImpl.java
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/schemaengine/schemaregion/mtree/impl/mem/MTreeBelowSGMemoryImpl.java
index 2e5a2034fd6..7b9bae66af6 100644
---
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/schemaengine/schemaregion/mtree/impl/mem/MTreeBelowSGMemoryImpl.java
+++
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/schemaengine/schemaregion/mtree/impl/mem/MTreeBelowSGMemoryImpl.java
@@ -44,7 +44,6 @@ import
org.apache.iotdb.db.exception.metadata.template.TemplateIsInUseException;
import org.apache.iotdb.db.exception.quota.ExceedQuotaException;
import org.apache.iotdb.db.schemaengine.rescon.MemSchemaRegionStatistics;
import
org.apache.iotdb.db.schemaengine.schemaregion.mtree.impl.mem.mnode.IMemMNode;
-import
org.apache.iotdb.db.schemaengine.schemaregion.mtree.impl.mem.mnode.info.LogicalViewInfo;
import
org.apache.iotdb.db.schemaengine.schemaregion.mtree.loader.MNodeFactoryLoader;
import
org.apache.iotdb.db.schemaengine.schemaregion.mtree.traverser.collector.EntityCollector;
import
org.apache.iotdb.db.schemaengine.schemaregion.mtree.traverser.collector.MNodeCollector;
@@ -348,7 +347,7 @@ public class MTreeBelowSGMemoryImpl {
}
}
- // create a non-aligned timeseries
+ // create a aligned timeseries
if (entityMNode.isAlignedNullable() == null) {
entityMNode.setAligned(true);
}
@@ -1125,7 +1124,7 @@ public class MTreeBelowSGMemoryImpl {
String leafName = path.getMeasurement();
IMeasurementMNode<IMemMNode> measurementMNode =
nodeFactory.createLogicalViewMNode(
- null, leafName, new LogicalViewInfo(new
LogicalViewSchema(leafName, viewExpression)));
+ null, leafName, new LogicalViewSchema(leafName, viewExpression));
IMemMNode device =
checkAndAutoCreateDeviceNode(devicePath.getTailNode(), deviceParent);
// no need to check alias, because logical view has no alias
diff --git
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/schemaengine/schemaregion/mtree/impl/mem/mnode/factory/MemMNodeFactory.java
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/schemaengine/schemaregion/mtree/impl/mem/mnode/factory/MemMNodeFactory.java
index 62f700c398c..05c3e403506 100644
---
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/schemaengine/schemaregion/mtree/impl/mem/mnode/factory/MemMNodeFactory.java
+++
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/schemaengine/schemaregion/mtree/impl/mem/mnode/factory/MemMNodeFactory.java
@@ -18,7 +18,6 @@
*/
package
org.apache.iotdb.db.schemaengine.schemaregion.mtree.impl.mem.mnode.factory;
-import org.apache.iotdb.commons.schema.node.info.IMeasurementInfo;
import org.apache.iotdb.commons.schema.node.role.IDatabaseMNode;
import org.apache.iotdb.commons.schema.node.role.IDeviceMNode;
import org.apache.iotdb.commons.schema.node.role.IMeasurementMNode;
@@ -75,7 +74,7 @@ public class MemMNodeFactory implements
IMNodeFactory<IMemMNode> {
@Override
public IMeasurementMNode<IMemMNode> createLogicalViewMNode(
- IDeviceMNode<IMemMNode> parent, String name, IMeasurementInfo
measurementInfo) {
+ IDeviceMNode<IMemMNode> parent, String name, IMeasurementSchema
measurementSchema) {
throw new UnsupportedOperationException("View is not supported.");
}
}
diff --git
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/schemaengine/schemaregion/mtree/impl/mem/snapshot/MemMTreeSnapshotUtil.java
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/schemaengine/schemaregion/mtree/impl/mem/snapshot/MemMTreeSnapshotUtil.java
index a0a887ce9a9..7b337246e7e 100644
---
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/schemaengine/schemaregion/mtree/impl/mem/snapshot/MemMTreeSnapshotUtil.java
+++
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/schemaengine/schemaregion/mtree/impl/mem/snapshot/MemMTreeSnapshotUtil.java
@@ -36,7 +36,6 @@ import org.apache.iotdb.commons.utils.FileUtils;
import org.apache.iotdb.db.schemaengine.rescon.MemSchemaRegionStatistics;
import
org.apache.iotdb.db.schemaengine.schemaregion.mtree.impl.mem.MemMTreeStore;
import
org.apache.iotdb.db.schemaengine.schemaregion.mtree.impl.mem.mnode.IMemMNode;
-import
org.apache.iotdb.db.schemaengine.schemaregion.mtree.impl.mem.mnode.info.LogicalViewInfo;
import
org.apache.iotdb.db.schemaengine.schemaregion.mtree.loader.MNodeFactoryLoader;
import org.apache.iotdb.tsfile.utils.ReadWriteIOUtils;
import org.apache.iotdb.tsfile.write.schema.MeasurementSchema;
@@ -427,7 +426,7 @@ public class MemMTreeSnapshotUtil {
LogicalViewSchema logicalViewSchema =
LogicalViewSchema.deserializeFrom(inputStream);
long tagOffset = ReadWriteIOUtils.readLong(inputStream);
IMeasurementMNode<IMemMNode> node =
- nodeFactory.createLogicalViewMNode(null, name, new
LogicalViewInfo(logicalViewSchema));
+ nodeFactory.createLogicalViewMNode(null, name, logicalViewSchema);
node.setOffset(tagOffset);
node.setPreDeleted(ReadWriteIOUtils.readBool(inputStream));
return node.getAsMNode();
diff --git
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/schemaengine/schemaregion/mtree/impl/pbtree/MTreeBelowSGCachedImpl.java
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/schemaengine/schemaregion/mtree/impl/pbtree/MTreeBelowSGCachedImpl.java
index b7cd06744c8..138823eaf7b 100644
---
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/schemaengine/schemaregion/mtree/impl/pbtree/MTreeBelowSGCachedImpl.java
+++
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/schemaengine/schemaregion/mtree/impl/pbtree/MTreeBelowSGCachedImpl.java
@@ -29,6 +29,8 @@ import org.apache.iotdb.commons.schema.node.role.IDeviceMNode;
import org.apache.iotdb.commons.schema.node.role.IMeasurementMNode;
import org.apache.iotdb.commons.schema.node.utils.IMNodeFactory;
import org.apache.iotdb.commons.schema.node.utils.IMNodeIterator;
+import org.apache.iotdb.commons.schema.view.LogicalViewSchema;
+import org.apache.iotdb.commons.schema.view.viewExpression.ViewExpression;
import org.apache.iotdb.db.exception.metadata.AliasAlreadyExistException;
import org.apache.iotdb.db.exception.metadata.AlignedTimeseriesException;
import org.apache.iotdb.db.exception.metadata.MNodeTypeMismatchException;
@@ -300,7 +302,9 @@ public class MTreeBelowSGCachedImpl {
throw new PathAlreadyExistException(path.getFullPath());
}
- if (device.isDevice() && device.getAsDeviceMNode().isAligned()) {
+ if (device.isDevice()
+ && device.getAsDeviceMNode().isAlignedNullable() != null
+ && device.getAsDeviceMNode().isAligned()) {
throw new AlignedTimeseriesException(
"timeseries under this device is aligned, please use
createAlignedTimeseries or change device.",
device.getFullPath());
@@ -317,6 +321,11 @@ public class MTreeBelowSGCachedImpl {
device = entityMNode.getAsMNode();
}
+ // create a non-aligned timeseries
+ if (entityMNode.isAlignedNullable() == null) {
+ entityMNode.setAligned(false);
+ }
+
IMeasurementMNode<ICachedMNode> measurementMNode =
nodeFactory.createMeasurementMNode(
entityMNode,
@@ -382,7 +391,9 @@ public class MTreeBelowSGCachedImpl {
}
}
- if (device.isDevice() && !device.getAsDeviceMNode().isAligned()) {
+ if (device.isDevice()
+ && device.getAsDeviceMNode().isAlignedNullable() != null
+ && !device.getAsDeviceMNode().isAligned()) {
throw new AlignedTimeseriesException(
"Timeseries under this device is not aligned, please use
createTimeseries or change device.",
devicePath.getFullPath());
@@ -400,6 +411,11 @@ public class MTreeBelowSGCachedImpl {
device = entityMNode.getAsMNode();
}
+ // create a aligned timeseries
+ if (entityMNode.isAlignedNullable() == null) {
+ entityMNode.setAligned(true);
+ }
+
for (int i = 0; i < measurements.size(); i++) {
IMeasurementMNode<ICachedMNode> measurementMNode =
nodeFactory.createMeasurementMNode(
@@ -602,6 +618,7 @@ public class MTreeBelowSGCachedImpl {
ICachedMNode curNode = entityMNode.getAsMNode();
if (!entityMNode.isUseTemplate()) {
boolean hasMeasurement = false;
+ boolean hasNonViewMeasurement = false;
ICachedMNode child;
IMNodeIterator<ICachedMNode> iterator =
store.getChildrenIterator(curNode);
try {
@@ -610,7 +627,10 @@ public class MTreeBelowSGCachedImpl {
unPinMNode(child);
if (child.isMeasurement()) {
hasMeasurement = true;
- break;
+ if (!child.getAsMeasurementMNode().isLogicalView()) {
+ hasNonViewMeasurement = true;
+ break;
+ }
}
}
} finally {
@@ -624,6 +644,10 @@ public class MTreeBelowSGCachedImpl {
replaceStorageGroupMNode(curNode.getAsDatabaseMNode());
}
}
+ } else if (!hasNonViewMeasurement) {
+ // has some measurement but they are all logical view
+ entityMNode.setAligned(null);
+ updateMNode(entityMNode.getAsMNode());
}
}
@@ -863,6 +887,140 @@ public class MTreeBelowSGCachedImpl {
}
// endregion
+ // region Interfaces and Implementation for Logical View
+
+ public void createLogicalView(PartialPath path, ViewExpression
viewExpression)
+ throws MetadataException {
+ String[] nodeNames = path.getNodes();
+ if (nodeNames.length <= 2) {
+ throw new IllegalPathException(path.getFullPath());
+ }
+ MetaFormatUtils.checkTimeseries(path);
+ PartialPath devicePath = path.getDevicePath();
+ ICachedMNode deviceParent = checkAndAutoCreateInternalPath(devicePath);
+
+ try {
+ // synchronize check and add, we need addChild and add Alias become
atomic operation
+ // only write on mtree will be synchronized
+ synchronized (this) {
+ ICachedMNode device =
checkAndAutoCreateDeviceNode(devicePath.getTailNode(), deviceParent);
+ try {
+ String leafName = path.getMeasurement();
+ if (device.hasChild(leafName)) {
+ ICachedMNode node = device.getChild(leafName);
+ if (node.isMeasurement()) {
+ if (node.getAsMeasurementMNode().isPreDeleted()) {
+ throw new MeasurementInBlackListException(path);
+ } else {
+ throw new MeasurementAlreadyExistException(
+ path.getFullPath(),
node.getAsMeasurementMNode().getMeasurementPath());
+ }
+ } else {
+ throw new PathAlreadyExistException(path.getFullPath());
+ }
+ }
+
+ IDeviceMNode<ICachedMNode> entityMNode;
+ if (device.isDevice()) {
+ entityMNode = device.getAsDeviceMNode();
+ } else {
+ entityMNode = store.setToEntity(device);
+ if (entityMNode.isDatabase()) {
+ replaceStorageGroupMNode(entityMNode.getAsDatabaseMNode());
+ }
+ device = entityMNode.getAsMNode();
+ }
+
+ IMeasurementMNode<ICachedMNode> viewMNode =
+ nodeFactory.createLogicalViewMNode(
+ entityMNode, leafName, new LogicalViewSchema(leafName,
viewExpression));
+ store.addChild(entityMNode.getAsMNode(), leafName,
viewMNode.getAsMNode());
+ unPinMNode(viewMNode.getAsMNode());
+ } finally {
+ unPinMNode(device);
+ }
+ }
+ } finally {
+ if (deviceParent != null) {
+ unPinMNode(deviceParent);
+ }
+ }
+ }
+
+ public List<PartialPath> constructLogicalViewBlackList(PartialPath
pathPattern)
+ throws MetadataException {
+ List<PartialPath> result = new ArrayList<>();
+ try (MeasurementUpdater<ICachedMNode> updater =
+ new MeasurementUpdater<ICachedMNode>(
+ rootNode, pathPattern, store, false,
SchemaConstant.ALL_MATCH_SCOPE) {
+ protected void updateMeasurement(IMeasurementMNode<ICachedMNode>
node)
+ throws MetadataException {
+ if (node.isLogicalView()) {
+ node.setPreDeleted(true);
+ store.updateMNode(node.getAsMNode());
+ result.add(getPartialPathFromRootToNode(node.getAsMNode()));
+ }
+ }
+ }) {
+ updater.update();
+ }
+ return result;
+ }
+
+ public List<PartialPath> rollbackLogicalViewBlackList(PartialPath
pathPattern)
+ throws MetadataException {
+ List<PartialPath> result = new ArrayList<>();
+ try (MeasurementUpdater<ICachedMNode> updater =
+ new MeasurementUpdater<ICachedMNode>(
+ rootNode, pathPattern, store, false,
SchemaConstant.ALL_MATCH_SCOPE) {
+ protected void updateMeasurement(IMeasurementMNode<ICachedMNode>
node)
+ throws MetadataException {
+ if (node.isLogicalView()) {
+ node.setPreDeleted(false);
+ store.updateMNode(node.getAsMNode());
+ result.add(getPartialPathFromRootToNode(node.getAsMNode()));
+ }
+ }
+ }) {
+ updater.update();
+ }
+ return result;
+ }
+
+ public List<PartialPath> getPreDeletedLogicalView(PartialPath pathPattern)
+ throws MetadataException {
+ List<PartialPath> result = new LinkedList<>();
+ try (MeasurementCollector<Void, ICachedMNode> collector =
+ new MeasurementCollector<Void, ICachedMNode>(
+ rootNode, pathPattern, store, false,
SchemaConstant.ALL_MATCH_SCOPE) {
+ protected Void collectMeasurement(IMeasurementMNode<ICachedMNode>
node) {
+ if (node.isLogicalView() && node.isPreDeleted()) {
+ result.add(getPartialPathFromRootToNode(node.getAsMNode()));
+ }
+ return null;
+ }
+ }) {
+ collector.traverse();
+ }
+ return result;
+ }
+
+ public void alterLogicalView(PartialPath path, ViewExpression expression)
+ throws MetadataException {
+ IMeasurementMNode<ICachedMNode> leafMNode = getMeasurementMNode(path);
+ try {
+ if (!leafMNode.isLogicalView()) {
+ throw new MetadataException(String.format("[%s] is no view.", path));
+ }
+ leafMNode.setSchema(new LogicalViewSchema(leafMNode.getName(),
expression));
+ updateMNode(leafMNode.getAsMNode());
+ } finally {
+ unPinMNode(leafMNode.getAsMNode());
+ }
+ }
+
+ // endregion
+
// region Interfaces and Implementation for Template check and query
public void activateTemplate(PartialPath activatePath, Template template)
diff --git
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/schemaengine/schemaregion/mtree/impl/pbtree/mnode/container/ICachedMNodeContainer.java
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/schemaengine/schemaregion/mtree/impl/pbtree/mnode/container/ICachedMNodeContainer.java
index 5f48ea5d706..719ea62a7dd 100644
---
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/schemaengine/schemaregion/mtree/impl/pbtree/mnode/container/ICachedMNodeContainer.java
+++
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/schemaengine/schemaregion/mtree/impl/pbtree/mnode/container/ICachedMNodeContainer.java
@@ -74,6 +74,6 @@ public interface ICachedMNodeContainer extends
IMNodeContainer<ICachedMNode> {
}
static ICachedMNodeContainer getBelongedContainer(ICachedMNode node) {
- return (ICachedMNodeContainer) node.getParent().getChildren();
+ return getCachedMNodeContainer(node.getParent());
}
}
diff --git
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/schemaengine/schemaregion/mtree/impl/pbtree/mnode/factory/CacheMNodeFactory.java
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/schemaengine/schemaregion/mtree/impl/pbtree/mnode/factory/CacheMNodeFactory.java
index c6beaea4efd..faa19842007 100644
---
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/schemaengine/schemaregion/mtree/impl/pbtree/mnode/factory/CacheMNodeFactory.java
+++
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/schemaengine/schemaregion/mtree/impl/pbtree/mnode/factory/CacheMNodeFactory.java
@@ -18,7 +18,6 @@
*/
package
org.apache.iotdb.db.schemaengine.schemaregion.mtree.impl.pbtree.mnode.factory;
-import org.apache.iotdb.commons.schema.node.info.IMeasurementInfo;
import org.apache.iotdb.commons.schema.node.role.IDatabaseMNode;
import org.apache.iotdb.commons.schema.node.role.IDeviceMNode;
import org.apache.iotdb.commons.schema.node.role.IMeasurementMNode;
@@ -75,7 +74,7 @@ public class CacheMNodeFactory implements
IMNodeFactory<ICachedMNode> {
@Override
public IMeasurementMNode<ICachedMNode> createLogicalViewMNode(
- IDeviceMNode<ICachedMNode> parent, String name, IMeasurementInfo
measurementInfo) {
+ IDeviceMNode<ICachedMNode> parent, String name, IMeasurementSchema
measurementSchema) {
throw new UnsupportedOperationException("View is not supported.");
}
}
diff --git
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/schemaengine/schemaregion/mtree/impl/pbtree/schemafile/RecordUtils.java
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/schemaengine/schemaregion/mtree/impl/pbtree/schemafile/RecordUtils.java
index 6dd056291a4..ac2e2b8c6bb 100644
---
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/schemaengine/schemaregion/mtree/impl/pbtree/schemafile/RecordUtils.java
+++
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/schemaengine/schemaregion/mtree/impl/pbtree/schemafile/RecordUtils.java
@@ -22,6 +22,8 @@ import org.apache.iotdb.commons.exception.MetadataException;
import org.apache.iotdb.commons.schema.SchemaConstant;
import org.apache.iotdb.commons.schema.node.role.IMeasurementMNode;
import org.apache.iotdb.commons.schema.node.utils.IMNodeFactory;
+import org.apache.iotdb.commons.schema.view.LogicalViewSchema;
+import org.apache.iotdb.commons.schema.view.viewExpression.ViewExpression;
import org.apache.iotdb.commons.utils.TestOnly;
import
org.apache.iotdb.db.schemaengine.schemaregion.mtree.impl.pbtree.mnode.ICachedMNode;
import
org.apache.iotdb.db.schemaengine.schemaregion.mtree.impl.pbtree.mnode.container.ICachedMNodeContainer;
@@ -33,6 +35,8 @@ import org.apache.iotdb.tsfile.utils.ReadWriteIOUtils;
import org.apache.iotdb.tsfile.write.schema.IMeasurementSchema;
import org.apache.iotdb.tsfile.write.schema.MeasurementSchema;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.Map;
@@ -50,6 +54,7 @@ public class RecordUtils {
(short) 1 + 2 + 8 + 4 + 1; // always fixed length record
private static final short MEASUREMENT_BASIC_LENGTH =
(short) 1 + 2 + 8 + 8; // final length depends on its alias and props
+ private static final short VIEW_BASIC_LENGTH = (short) 1 + 2 + 8 + 1;
/** These offset rather than magic number may also be used to track usage of
related field. */
private static final short LENGTH_OFFSET = 1;
@@ -62,13 +67,19 @@ public class RecordUtils {
private static final byte INTERNAL_TYPE = 0;
private static final byte ENTITY_TYPE = 1;
private static final byte MEASUREMENT_TYPE = 4;
+ private static final byte VIEW_TYPE = 5;
private static final IMNodeFactory<ICachedMNode> nodeFactory =
MNodeFactoryLoader.getInstance().getCachedMNodeIMNodeFactory();
public static ByteBuffer node2Buffer(ICachedMNode node) {
if (node.isMeasurement()) {
- return measurement2Buffer(node.getAsMeasurementMNode());
+ IMeasurementMNode<ICachedMNode> measurementMNode =
node.getAsMeasurementMNode();
+ if (measurementMNode.isLogicalView()) {
+ return view2Buffer(measurementMNode);
+ } else {
+ return measurement2Buffer(measurementMNode);
+ }
} else {
return internal2Buffer(node);
}
@@ -90,7 +101,7 @@ public class RecordUtils {
*
* <ul>
* <li>1 bit : usingTemplate, whether using template
- * <li>1 bit : isAligned
+ * <li>2 bit : isAligned (00 for not aligned, 01 for aligned, 10 for null)
* </ul>
*
* @param node
@@ -98,13 +109,13 @@ public class RecordUtils {
*/
private static ByteBuffer internal2Buffer(ICachedMNode node) {
byte nodeType = INTERNAL_TYPE;
- boolean isAligned = false;
+ Boolean isAligned = null;
int schemaTemplateIdWithState = SchemaConstant.NON_TEMPLATE;
boolean isUseTemplate = false;
if (node.isDevice()) {
nodeType = ENTITY_TYPE;
- isAligned = node.getAsDeviceMNode().isAligned();
+ isAligned = node.getAsDeviceMNode().isAlignedNullable();
schemaTemplateIdWithState =
node.getAsDeviceMNode().getSchemaTemplateIdWithState();
isUseTemplate = node.getAsDeviceMNode().isUseTemplate();
}
@@ -154,9 +165,8 @@ public class RecordUtils {
bufferLength += 8 + e.getKey().getBytes().length +
e.getValue().length();
}
}
-
+ // normal measurement
ByteBuffer buffer = ByteBuffer.allocate(bufferLength);
-
ReadWriteIOUtils.write(MEASUREMENT_TYPE, buffer);
ReadWriteIOUtils.write((short) bufferLength, buffer);
ReadWriteIOUtils.write(convertTags2Long(node), buffer);
@@ -166,6 +176,41 @@ public class RecordUtils {
return buffer;
}
+ /**
+ * LogicalView MNode Record Structure: <br>
+ * (var length record, with length member)
+ *
+ * <ul>
+ * <li>1 byte: nodeType, as above
+ * <li>1 short (2 bytes): recLength, length of whole record
+ * <li>1 long (8 bytes): tagIndex, value of the offset within a measurement
+ * <li>1 boolean (1 bytes): statusBytes, isPreDeleted
+ * <li>var length ViewExpression
+ * </ul>
+ */
+ private static ByteBuffer view2Buffer(IMeasurementMNode<ICachedMNode> node) {
+ ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
+ try {
+ ViewExpression.serialize(
+ ((LogicalViewSchema) node.getSchema()).getExpression(),
byteArrayOutputStream);
+ } catch (IOException e) {
+ // ByteArrayOutputStream is a memory-based output stream that does not
involve disk IO and
+ // will not throw an IOException except for OOM.
+ throw new RuntimeException(e);
+ }
+ byte[] expressionData = byteArrayOutputStream.toByteArray();
+
+ int bufferLength = VIEW_BASIC_LENGTH + expressionData.length;
+
+ ByteBuffer buffer = ByteBuffer.allocate(bufferLength);
+ ReadWriteIOUtils.write(VIEW_TYPE, buffer);
+ ReadWriteIOUtils.write((short) bufferLength, buffer);
+ ReadWriteIOUtils.write(convertTags2Long(node), buffer);
+ ReadWriteIOUtils.write(node.isPreDeleted(), buffer);
+ buffer.put(expressionData);
+ return buffer;
+ }
+
/**
* NOTICE: Make sure that buffer has set its position and limit clearly
before pass to this
* method.<br>
@@ -193,7 +238,7 @@ public class RecordUtils {
byte bitFlag = ReadWriteIOUtils.readByte(buffer);
boolean usingTemplate = usingTemplate(bitFlag);
- boolean isAligned = isAligned(bitFlag);
+ Boolean isAligned = isAligned(bitFlag);
if (nodeType == 0) {
resNode = nodeFactory.createInternalMNode(null, nodeName);
@@ -207,16 +252,22 @@ public class RecordUtils {
ICachedMNodeContainer.getCachedMNodeContainer(resNode).setSegmentAddress(segAddr);
return resNode;
- } else {
+ } else if (nodeType == MEASUREMENT_TYPE) {
// measurement node
short recLenth = ReadWriteIOUtils.readShort(buffer);
long tagIndex = ReadWriteIOUtils.readLong(buffer);
long schemaByte = ReadWriteIOUtils.readLong(buffer);
String alias = ReadWriteIOUtils.readString(buffer);
Map<String, String> props = ReadWriteIOUtils.readMap(buffer);
-
return paddingMeasurement(nodeName, tagIndex, schemaByte, alias, props);
+ } else if (nodeType == VIEW_TYPE) {
+ short recLenth = ReadWriteIOUtils.readShort(buffer);
+ long tagIndex = ReadWriteIOUtils.readLong(buffer);
+ boolean isPreDeleted = ReadWriteIOUtils.readBool(buffer);
+ ViewExpression viewExpression = ViewExpression.deserialize(buffer);
+ return paddingLogicalView(nodeName, tagIndex, isPreDeleted,
viewExpression);
}
+ throw new MetadataException("Unrecognized node type: " + nodeType);
}
// region Getter and Setter to Record Buffer
@@ -314,7 +365,9 @@ public class RecordUtils {
} else if (node.isDevice()) {
builder.append("entityNode, ");
- if (node.getAsDeviceMNode().isAligned()) {
+ if (node.getAsDeviceMNode().isAlignedNullable() == null) {
+ builder.append("aligned is null, ");
+ } else if (node.getAsDeviceMNode().isAligned()) {
builder.append("aligned, ");
} else {
builder.append("not aligned, ");
@@ -375,23 +428,39 @@ public class RecordUtils {
return res;
}
+ private static ICachedMNode paddingLogicalView(
+ String nodeName, long tagIndex, boolean isPreDeleted, ViewExpression
viewExpression) {
+ IMeasurementSchema schema = new LogicalViewSchema(nodeName,
viewExpression);
+ IMeasurementMNode<ICachedMNode> res =
+ nodeFactory.createLogicalViewMNode(null, nodeName, schema);
+ res.setOffset(tagIndex);
+ res.setPreDeleted(isPreDeleted);
+ return res.getAsMNode();
+ }
+
// endregion
// region codex for bit flag
- private static byte encodeInternalStatus(boolean usingTemplate, boolean
isAligned) {
+ private static byte encodeInternalStatus(boolean usingTemplate, Boolean
isAligned) {
byte flag = 0;
if (usingTemplate) {
flag |= 0x01;
}
- if (isAligned) {
+ if (isAligned == null) {
+ flag |= 0x04;
+ } else if (isAligned) {
flag |= 0x02;
}
return flag;
}
- private static boolean isAligned(byte flag) {
- return (flag & 0x02) == 2;
+ private static Boolean isAligned(byte flag) {
+ if ((flag & 0x04) != 0) {
+ return null;
+ } else {
+ return (flag & 0x02) == 2;
+ }
}
private static boolean usingTemplate(byte flag) {
diff --git
a/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/schema/node/utils/IMNodeFactory.java
b/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/schema/node/utils/IMNodeFactory.java
index da7a3c1dc58..77645d3b9af 100644
---
a/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/schema/node/utils/IMNodeFactory.java
+++
b/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/schema/node/utils/IMNodeFactory.java
@@ -19,7 +19,6 @@
package org.apache.iotdb.commons.schema.node.utils;
import org.apache.iotdb.commons.schema.node.IMNode;
-import org.apache.iotdb.commons.schema.node.info.IMeasurementInfo;
import org.apache.iotdb.commons.schema.node.role.IDatabaseMNode;
import org.apache.iotdb.commons.schema.node.role.IDeviceMNode;
import org.apache.iotdb.commons.schema.node.role.IMeasurementMNode;
@@ -42,5 +41,5 @@ public interface IMNodeFactory<N extends IMNode<N>> {
N createInternalMNode(N parent, String name);
IMeasurementMNode<N> createLogicalViewMNode(
- IDeviceMNode<N> parent, String name, IMeasurementInfo measurementInfo);
+ IDeviceMNode<N> parent, String name, IMeasurementSchema
measurementSchema);
}