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