@@ -174,6 +174,59 @@ public synchronized boolean createSnapshot(File snapshotDir) {
174174 return store .createSnapshot (snapshotDir );
175175 }
176176
177+ private void applySubtreeMeasurementDelta (IMemMNode startNode , final long delta ) {
178+ if (delta == 0 || startNode == null ) {
179+ return ;
180+ }
181+ IMemMNode current = startNode ;
182+ while (current != null ) {
183+ current .setSubtreeMeasurementCount (current .getSubtreeMeasurementCount () + delta );
184+ current = current .getParent ();
185+ }
186+ }
187+
188+ private IDeviceMNode <IMemMNode > setToEntityAndUpdateFlags (final IMemMNode node ) {
189+ final boolean wasDevice = node .isDevice ();
190+ final IDeviceMNode <IMemMNode > deviceMNode = store .setToEntity (node );
191+ if (!wasDevice ) {
192+ markAncestorsHavingDeviceDescendant (node );
193+ }
194+ return deviceMNode ;
195+ }
196+
197+ private void markAncestorsHavingDeviceDescendant (final IMemMNode deviceNode ) {
198+ IMemMNode current = deviceNode .getParent ();
199+ while (current != null && !current .hasDeviceDescendant ()) {
200+ current .setHasDeviceDescendant (true );
201+ current = current .getParent ();
202+ }
203+ }
204+
205+ private boolean hasDeviceDescendantInChildren (final IMemMNode node ) {
206+ try (final IMNodeIterator <IMemMNode > iterator = store .getChildrenIterator (node )) {
207+ while (iterator .hasNext ()) {
208+ final IMemMNode child = iterator .next ();
209+ if (child .isDevice () || child .hasDeviceDescendant ()) {
210+ return true ;
211+ }
212+ }
213+ return false ;
214+ }
215+ }
216+
217+ private void refreshAncestorsHavingDeviceDescendant (IMemMNode startNode ) {
218+ IMemMNode current = startNode ;
219+ while (current != null ) {
220+ current .setHasDeviceDescendant (hasDeviceDescendantInChildren (current ));
221+ current = current .getParent ();
222+ }
223+ }
224+
225+ private long getTemplateMeasurementCount (final int templateId ) {
226+ final Template template = ClusterTemplateManager .getInstance ().getTemplate (templateId );
227+ return template == null ? 0L : template .getMeasurementNumber ();
228+ }
229+
177230 public static MTreeBelowSGMemoryImpl loadFromSnapshot (
178231 File snapshotDir ,
179232 String storageGroupFullPath ,
@@ -184,13 +237,16 @@ public static MTreeBelowSGMemoryImpl loadFromSnapshot(
184237 Function <IMeasurementMNode <IMemMNode >, Map <String , String >> tagGetter ,
185238 Function <IMeasurementMNode <IMemMNode >, Map <String , String >> attributeGetter )
186239 throws IOException , IllegalPathException {
187- return new MTreeBelowSGMemoryImpl (
188- new PartialPath (storageGroupFullPath ),
189- MemMTreeStore .loadFromSnapshot (
190- snapshotDir , measurementProcess , deviceProcess , regionStatistics , metric ),
191- tagGetter ,
192- attributeGetter ,
193- regionStatistics );
240+ final MTreeBelowSGMemoryImpl mtree =
241+ new MTreeBelowSGMemoryImpl (
242+ new PartialPath (storageGroupFullPath ),
243+ MemMTreeStore .loadFromSnapshot (
244+ snapshotDir , measurementProcess , deviceProcess , regionStatistics , metric ),
245+ tagGetter ,
246+ attributeGetter ,
247+ regionStatistics );
248+ mtree .rebuildSubtreeMeasurementCount ();
249+ return mtree ;
194250 }
195251
196252 // endregion
@@ -268,7 +324,7 @@ public IMeasurementMNode<IMemMNode> createTimeSeries(
268324 if (device .isDevice ()) {
269325 entityMNode = device .getAsDeviceMNode ();
270326 } else {
271- entityMNode = store . setToEntity (device );
327+ entityMNode = setToEntityAndUpdateFlags (device );
272328 }
273329
274330 // create a non-aligned time series
@@ -290,6 +346,7 @@ public IMeasurementMNode<IMemMNode> createTimeSeries(
290346 entityMNode .addAlias (alias , measurementMNode );
291347 }
292348
349+ applySubtreeMeasurementDelta (measurementMNode .getAsMNode (), 1L );
293350 return measurementMNode ;
294351 }
295352 }
@@ -360,7 +417,7 @@ public List<IMeasurementMNode<IMemMNode>> createAlignedTimeSeries(
360417 if (device .isDevice ()) {
361418 entityMNode = device .getAsDeviceMNode ();
362419 } else {
363- entityMNode = store . setToEntity (device );
420+ entityMNode = setToEntityAndUpdateFlags (device );
364421 entityMNode .setAligned (true );
365422 }
366423
@@ -386,6 +443,7 @@ public List<IMeasurementMNode<IMemMNode>> createAlignedTimeSeries(
386443 if (aliasList != null && aliasList .get (i ) != null ) {
387444 entityMNode .addAlias (aliasList .get (i ), measurementMNode );
388445 }
446+ applySubtreeMeasurementDelta (measurementMNode .getAsMNode (), 1L );
389447 measurementMNodeList .add (measurementMNode );
390448 }
391449 return measurementMNodeList ;
@@ -539,6 +597,7 @@ public IMeasurementMNode<IMemMNode> deleteTimeseries(PartialPath path) throws Me
539597 if (deletedNode .getAlias () != null ) {
540598 parent .getAsDeviceMNode ().deleteAliasChild (deletedNode .getAlias ());
541599 }
600+ applySubtreeMeasurementDelta (parent , -1L );
542601 }
543602 deleteEmptyInternalMNode (parent .getAsDeviceMNode ());
544603 return deletedNode ;
@@ -551,14 +610,15 @@ public void deleteEmptyInternalMNode(IDeviceMNode<IMemMNode> entityMNode) {
551610 boolean hasMeasurement = false ;
552611 boolean hasNonViewMeasurement = false ;
553612 IMemMNode child ;
554- IMNodeIterator <IMemMNode > iterator = store .getChildrenIterator (curNode );
555- while (iterator .hasNext ()) {
556- child = iterator .next ();
557- if (child .isMeasurement ()) {
558- hasMeasurement = true ;
559- if (!child .getAsMeasurementMNode ().isLogicalView ()) {
560- hasNonViewMeasurement = true ;
561- break ;
613+ try (final IMNodeIterator <IMemMNode > iterator = store .getChildrenIterator (curNode )) {
614+ while (iterator .hasNext ()) {
615+ child = iterator .next ();
616+ if (child .isMeasurement ()) {
617+ hasMeasurement = true ;
618+ if (!child .getAsMeasurementMNode ().isLogicalView ()) {
619+ hasNonViewMeasurement = true ;
620+ break ;
621+ }
562622 }
563623 }
564624 }
@@ -567,6 +627,7 @@ public void deleteEmptyInternalMNode(IDeviceMNode<IMemMNode> entityMNode) {
567627 synchronized (this ) {
568628 curNode = store .setToInternal (entityMNode );
569629 }
630+ refreshAncestorsHavingDeviceDescendant (curNode .getParent ());
570631 } else if (!hasNonViewMeasurement ) {
571632 // has some measurement but they are all logical view
572633 entityMNode .setAligned (null );
@@ -889,7 +950,7 @@ public void activateTemplate(PartialPath activatePath, Template template)
889950 if (cur .isDevice ()) {
890951 entityMNode = cur .getAsDeviceMNode ();
891952 } else {
892- entityMNode = store . setToEntity (cur );
953+ entityMNode = setToEntityAndUpdateFlags (cur );
893954 }
894955 }
895956
@@ -907,6 +968,7 @@ public void activateTemplate(PartialPath activatePath, Template template)
907968 entityMNode .setUseTemplate (true );
908969 entityMNode .setSchemaTemplateId (template .getId ());
909970 regionStatistics .activateTemplate (template .getId ());
971+ applySubtreeMeasurementDelta (entityMNode .getAsMNode (), (long ) template .getMeasurementNumber ());
910972 }
911973
912974 public Map <PartialPath , List <Integer >> constructSchemaBlackListWithTemplate (
@@ -968,6 +1030,8 @@ protected void updateEntity(IDeviceMNode<IMemMNode> node) {
9681030 resultTemplateSetInfo .put (
9691031 node .getPartialPath (), Collections .singletonList (node .getSchemaTemplateId ()));
9701032 regionStatistics .deactivateTemplate (node .getSchemaTemplateId ());
1033+ applySubtreeMeasurementDelta (
1034+ node .getAsMNode (), -getTemplateMeasurementCount (node .getSchemaTemplateId ()));
9711035 node .deactivateTemplate ();
9721036 deleteEmptyInternalMNode (node );
9731037 }
@@ -991,7 +1055,7 @@ public void activateTemplateWithoutCheck(
9911055 if (cur .isDevice ()) {
9921056 entityMNode = cur .getAsDeviceMNode ();
9931057 } else {
994- entityMNode = store . setToEntity (cur );
1058+ entityMNode = setToEntityAndUpdateFlags (cur );
9951059 }
9961060
9971061 if (!entityMNode .isAligned ()) {
@@ -1000,6 +1064,7 @@ public void activateTemplateWithoutCheck(
10001064 entityMNode .setUseTemplate (true );
10011065 entityMNode .setSchemaTemplateId (templateId );
10021066 regionStatistics .activateTemplate (templateId );
1067+ applySubtreeMeasurementDelta (entityMNode .getAsMNode (), getTemplateMeasurementCount (templateId ));
10031068 }
10041069
10051070 public long countPathsUsingTemplate (PartialPath pathPattern , int templateId )
@@ -1011,6 +1076,30 @@ public long countPathsUsingTemplate(PartialPath pathPattern, int templateId)
10111076 }
10121077 }
10131078
1079+ public void rebuildSubtreeMeasurementCount () {
1080+ rebuildSubtreeMeasurementCountFromNode (rootNode );
1081+ }
1082+
1083+ private long rebuildSubtreeMeasurementCountFromNode (final IMemMNode node ) {
1084+ long count = node .isMeasurement () ? 1L : 0L ;
1085+ boolean hasDeviceDescendant = false ;
1086+ try (final IMNodeIterator <IMemMNode > iterator = store .getChildrenIterator (node )) {
1087+ while (iterator .hasNext ()) {
1088+ final IMemMNode child = iterator .next ();
1089+ count += rebuildSubtreeMeasurementCountFromNode (child );
1090+ if (child .isDevice () || child .hasDeviceDescendant ()) {
1091+ hasDeviceDescendant = true ;
1092+ }
1093+ }
1094+ }
1095+ if (node .isDevice () && node .getAsDeviceMNode ().isUseTemplate ()) {
1096+ count += getTemplateMeasurementCount (node .getAsDeviceMNode ().getSchemaTemplateId ());
1097+ }
1098+ node .setSubtreeMeasurementCount (count );
1099+ node .setHasDeviceDescendant (hasDeviceDescendant );
1100+ return count ;
1101+ }
1102+
10141103 // endregion
10151104
10161105 // region Interfaces for schema reader
@@ -1278,7 +1367,7 @@ public IMeasurementMNode<IMemMNode> createLogicalView(
12781367 if (device .isDevice ()) {
12791368 entityMNode = device .getAsDeviceMNode ();
12801369 } else {
1281- entityMNode = store . setToEntity (device );
1370+ entityMNode = setToEntityAndUpdateFlags (device );
12821371 // this parent has no measurement before. The leafName is his first child who is a logical
12831372 // view.
12841373 entityMNode .setAligned (null );
@@ -1287,6 +1376,7 @@ public IMeasurementMNode<IMemMNode> createLogicalView(
12871376 measurementMNode .setParent (entityMNode .getAsMNode ());
12881377 store .addChild (entityMNode .getAsMNode (), leafName , measurementMNode .getAsMNode ());
12891378
1379+ applySubtreeMeasurementDelta (measurementMNode .getAsMNode (), 1L );
12901380 return measurementMNode ;
12911381 }
12921382 }
0 commit comments