3939import org .apache .iotdb .db .schemaengine .template .Template ;
4040
4141import org .apache .tsfile .utils .Pair ;
42+ import org .apache .tsfile .utils .RamUsageEstimator ;
4243import org .apache .tsfile .utils .ReadWriteIOUtils ;
4344import org .apache .tsfile .write .schema .IMeasurementSchema ;
4445
4950import java .util .ArrayList ;
5051import java .util .Deque ;
5152import java .util .HashMap ;
53+ import java .util .Iterator ;
5254import java .util .List ;
5355import java .util .Map ;
56+ import java .util .NoSuchElementException ;
5457import java .util .Set ;
5558
5659import static org .apache .iotdb .commons .conf .IoTDBConstant .PATH_ROOT ;
6063import static org .apache .iotdb .db .queryengine .common .schematree .node .SchemaNode .SCHEMA_MEASUREMENT_NODE ;
6164
6265public class ClusterSchemaTree implements ISchemaTree {
66+ private static final long SHALLOW_SIZE =
67+ RamUsageEstimator .shallowSizeOfInstance (ClusterSchemaTree .class );
6368 private static final ClusterTemplateManager templateManager =
6469 ClusterTemplateManager .getInstance ();
6570
@@ -75,6 +80,8 @@ public class ClusterSchemaTree implements ISchemaTree {
7580
7681 private Map <Integer , Template > templateMap = new HashMap <>();
7782
83+ private long ramBytesUsed ;
84+
7885 public ClusterSchemaTree () {
7986 root = new SchemaInternalNode (PATH_ROOT );
8087 }
@@ -484,59 +491,158 @@ public void serialize(OutputStream outputStream) throws IOException {
484491 root .serialize (outputStream );
485492 }
486493
487- public static ClusterSchemaTree deserialize (InputStream inputStream ) throws IOException {
494+ public Iterator <SchemaNode > getIteratorForSerialize () {
495+ return new SchemaNodePostOrderIterator (root );
496+ }
488497
489- byte nodeType ;
490- int childNum ;
491- Deque <SchemaNode > stack = new ArrayDeque <>();
492- SchemaNode child ;
493- boolean hasLogicalView = false ;
494- boolean hasNormalTimeSeries = false ;
495- Map <Integer , Template > templateMap = new HashMap <>();
496-
497- while (inputStream .available () > 0 ) {
498- nodeType = ReadWriteIOUtils .readByte (inputStream );
499- if (nodeType == SCHEMA_MEASUREMENT_NODE ) {
500- SchemaMeasurementNode measurementNode = SchemaMeasurementNode .deserialize (inputStream );
501- stack .push (measurementNode );
502- if (measurementNode .isLogicalView ()) {
503- hasLogicalView = true ;
498+ @ Override
499+ public long ramBytesUsed () {
500+ if (ramBytesUsed > 0 ) {
501+ return ramBytesUsed ;
502+ }
503+ ramBytesUsed =
504+ root .ramBytesUsed ()
505+ + SHALLOW_SIZE
506+ + RamUsageEstimator .sizeOfMapWithKnownShallowSize (
507+ templateMap ,
508+ RamUsageEstimator .SHALLOW_SIZE_OF_HASHMAP ,
509+ RamUsageEstimator .SHALLOW_SIZE_OF_HASHMAP_ENTRY );
510+ return ramBytesUsed ;
511+ }
512+
513+ public void setRamBytesUsed (long ramBytesUsed ) {
514+ this .ramBytesUsed = ramBytesUsed ;
515+ }
516+
517+ private static class SchemaNodePostOrderIterator implements Iterator <SchemaNode > {
518+ // This class is likely to be faster than Stack when used as a stack
519+ private final Deque <Pair <SchemaNode , Iterator <SchemaNode >>> stack = new ArrayDeque <>();
520+ private SchemaNode nextNode ;
521+
522+ public SchemaNodePostOrderIterator (SchemaNode root ) {
523+ stack .push (new Pair <>(root , root .getChildrenIterator ()));
524+ prepareNext ();
525+ }
526+
527+ @ Override
528+ public boolean hasNext () {
529+ return nextNode != null ;
530+ }
531+
532+ @ Override
533+ public SchemaNode next () {
534+ if (!hasNext ()) {
535+ throw new NoSuchElementException ();
536+ }
537+ SchemaNode result = nextNode ;
538+ prepareNext ();
539+ return result ;
540+ }
541+
542+ private void prepareNext () {
543+ nextNode = null ;
544+ while (!stack .isEmpty ()) {
545+ Pair <SchemaNode , Iterator <SchemaNode >> pair = stack .peek ();
546+ SchemaNode currentNode = pair .getLeft ();
547+ Iterator <SchemaNode > childrenIterator = pair .getRight ();
548+ if (childrenIterator .hasNext ()) {
549+ SchemaNode child = childrenIterator .next ();
550+ stack .push (new Pair <>(child , child .getChildrenIterator ()));
551+ } else {
552+ stack .pop ();
553+ nextNode = currentNode ;
554+ return ;
504555 }
505- hasNormalTimeSeries = true ;
506- } else {
507- SchemaInternalNode internalNode ;
508- if (nodeType == SCHEMA_ENTITY_NODE ) {
509- internalNode = SchemaEntityNode .deserialize (inputStream );
510- int templateId = internalNode .getAsEntityNode ().getTemplateId ();
511- if (templateId != NON_TEMPLATE ) {
512- templateMap .putIfAbsent (templateId , templateManager .getTemplate (templateId ));
556+ }
557+ }
558+ }
559+
560+ public static class SchemaNodeBatchDeserializer {
561+ private byte nodeType ;
562+ private int childNum ;
563+ // This class is likely to be faster than Stack when used as a stack
564+ private final Deque <SchemaNode > stack = new ArrayDeque <>();
565+ private SchemaNode child ;
566+ private boolean hasLogicalView = false ;
567+ private boolean hasNormalTimeSeries = false ;
568+ private Map <Integer , Template > templateMap = new HashMap <>();
569+ private boolean isFirstBatch = true ;
570+
571+ public boolean isFirstBatch () {
572+ return isFirstBatch ;
573+ }
574+
575+ public void deserializeFromBatch (InputStream inputStream ) throws IOException {
576+ isFirstBatch = false ;
577+ while (inputStream .available () > 0 ) {
578+ nodeType = ReadWriteIOUtils .readByte (inputStream );
579+ if (nodeType == SCHEMA_MEASUREMENT_NODE ) {
580+ SchemaMeasurementNode measurementNode = SchemaMeasurementNode .deserialize (inputStream );
581+ stack .push (measurementNode );
582+ if (measurementNode .isLogicalView ()) {
583+ hasLogicalView = true ;
513584 }
585+ hasNormalTimeSeries = true ;
514586 } else {
515- internalNode = SchemaInternalNode .deserialize (inputStream );
516- }
587+ SchemaInternalNode internalNode ;
588+ if (nodeType == SCHEMA_ENTITY_NODE ) {
589+ internalNode = SchemaEntityNode .deserialize (inputStream );
590+ int templateId = internalNode .getAsEntityNode ().getTemplateId ();
591+ if (templateId != NON_TEMPLATE ) {
592+ templateMap .putIfAbsent (templateId , templateManager .getTemplate (templateId ));
593+ }
594+ } else {
595+ internalNode = SchemaInternalNode .deserialize (inputStream );
596+ }
517597
518- childNum = ReadWriteIOUtils .readInt (inputStream );
519- while (childNum > 0 ) {
520- child = stack .pop ();
521- internalNode .addChild (child .getName (), child );
522- if (child .isMeasurement ()) {
523- SchemaMeasurementNode measurementNode = child .getAsMeasurementNode ();
524- if (measurementNode .getAlias () != null ) {
525- internalNode
526- .getAsEntityNode ()
527- .addAliasChild (measurementNode .getAlias (), measurementNode );
598+ childNum = ReadWriteIOUtils .readInt (inputStream );
599+ while (childNum > 0 ) {
600+ child = stack .pop ();
601+ internalNode .addChild (child .getName (), child );
602+ if (child .isMeasurement ()) {
603+ SchemaMeasurementNode measurementNode = child .getAsMeasurementNode ();
604+ if (measurementNode .getAlias () != null ) {
605+ internalNode
606+ .getAsEntityNode ()
607+ .addAliasChild (measurementNode .getAlias (), measurementNode );
608+ }
528609 }
610+ childNum --;
529611 }
530- childNum -- ;
612+ stack . push ( internalNode ) ;
531613 }
532- stack .push (internalNode );
533614 }
534615 }
535- ClusterSchemaTree result = new ClusterSchemaTree (stack .poll ());
536- result .templateMap = templateMap ;
537- result .hasLogicalMeasurementPath = hasLogicalView ;
538- result .hasNormalTimeSeries = hasNormalTimeSeries ;
539- return result ;
616+
617+ public ClusterSchemaTree finish () {
618+ try {
619+ ClusterSchemaTree result = new ClusterSchemaTree (stack .poll ());
620+ result .templateMap = templateMap ;
621+ result .hasLogicalMeasurementPath = hasLogicalView ;
622+ result .hasNormalTimeSeries = hasNormalTimeSeries ;
623+ return result ;
624+ } finally {
625+ reset ();
626+ }
627+ }
628+
629+ private void reset () {
630+ nodeType = 0 ;
631+ childNum = 0 ;
632+ stack .clear ();
633+ child = null ;
634+ hasLogicalView = false ;
635+ hasNormalTimeSeries = false ;
636+ // templateMap is set to the returned schema tree, so we should create a new one
637+ templateMap = new HashMap <>();
638+ isFirstBatch = true ;
639+ }
640+ }
641+
642+ public static ClusterSchemaTree deserialize (InputStream inputStream ) throws IOException {
643+ SchemaNodeBatchDeserializer schemaNodeBatchDeserializer = new SchemaNodeBatchDeserializer ();
644+ schemaNodeBatchDeserializer .deserializeFromBatch (inputStream );
645+ return schemaNodeBatchDeserializer .finish ();
540646 }
541647
542648 /**
0 commit comments