2424import org .apache .iotdb .commons .exception .IoTDBRuntimeException ;
2525import org .apache .iotdb .commons .path .AlignedFullPath ;
2626import org .apache .iotdb .commons .path .IFullPath ;
27+ import org .apache .iotdb .commons .path .PatternTreeMap ;
2728import org .apache .iotdb .commons .utils .TestOnly ;
29+ import org .apache .iotdb .db .conf .IoTDBConfig ;
30+ import org .apache .iotdb .db .conf .IoTDBDescriptor ;
2831import org .apache .iotdb .db .exception .query .QueryProcessException ;
2932import org .apache .iotdb .db .queryengine .common .DeviceContext ;
3033import org .apache .iotdb .db .queryengine .common .FragmentInstanceId ;
3942import org .apache .iotdb .db .storageengine .StorageEngine ;
4043import org .apache .iotdb .db .storageengine .dataregion .DataRegion ;
4144import org .apache .iotdb .db .storageengine .dataregion .IDataRegionForQuery ;
45+ import org .apache .iotdb .db .storageengine .dataregion .modification .ModEntry ;
4246import org .apache .iotdb .db .storageengine .dataregion .read .IQueryDataSource ;
4347import org .apache .iotdb .db .storageengine .dataregion .read .QueryDataSource ;
4448import org .apache .iotdb .db .storageengine .dataregion .read .QueryDataSourceForRegionScan ;
4549import org .apache .iotdb .db .storageengine .dataregion .read .QueryDataSourceType ;
4650import org .apache .iotdb .db .storageengine .dataregion .read .control .FileReaderManager ;
4751import org .apache .iotdb .db .storageengine .dataregion .tsfile .TsFileResource ;
4852import org .apache .iotdb .db .utils .TimestampPrecisionUtils ;
53+ import org .apache .iotdb .db .utils .datastructure .PatternTreeMapFactory ;
4954import org .apache .iotdb .db .utils .datastructure .TVList ;
5055import org .apache .iotdb .mpp .rpc .thrift .TFetchFragmentInstanceStatisticsResp ;
5156
5257import org .apache .tsfile .file .metadata .IDeviceID ;
5358import org .apache .tsfile .read .filter .basic .Filter ;
5459import org .apache .tsfile .read .filter .factory .FilterFactory ;
60+ import org .apache .tsfile .utils .RamUsageEstimator ;
5561import org .slf4j .Logger ;
5662import org .slf4j .LoggerFactory ;
5763
7884public class FragmentInstanceContext extends QueryContext {
7985
8086 private static final Logger LOGGER = LoggerFactory .getLogger (FragmentInstanceContext .class );
87+ private static final IoTDBConfig config = IoTDBDescriptor .getInstance ().getConfig ();
8188 private static final long END_TIME_INITIAL_VALUE = -1L ;
8289 // wait over 5s for driver to close is abnormal
8390 private static final long LONG_WAIT_DURATION = 5_000_000_000L ;
@@ -93,6 +100,8 @@ public class FragmentInstanceContext extends QueryContext {
93100 // it will only be used once, after sharedQueryDataSource being inited, it will be set to null
94101 private List <IFullPath > sourcePaths ;
95102
103+ private boolean singleSourcePath = false ;
104+
96105 // Used for region scan, relating methods are to be added.
97106 private Map <IDeviceID , DeviceContext > devicePathsToContext ;
98107
@@ -320,6 +329,44 @@ public void start() {
320329 lastExecutionStartTime .set (now );
321330 }
322331
332+ @ Override
333+ protected PatternTreeMap <ModEntry , PatternTreeMapFactory .ModsSerializer > getAllModifications (
334+ TsFileResource resource ) {
335+ if (isSingleSourcePath () || memoryReservationManager == null ) {
336+ return loadAllModificationsFromDisk (resource );
337+ }
338+
339+ AtomicReference <PatternTreeMap <ModEntry , PatternTreeMapFactory .ModsSerializer >>
340+ atomicReference = new AtomicReference <>();
341+ PatternTreeMap <ModEntry , PatternTreeMapFactory .ModsSerializer > cachedResult =
342+ fileModCache .computeIfAbsent (
343+ resource .getTsFileID (),
344+ k -> {
345+ PatternTreeMap <ModEntry , PatternTreeMapFactory .ModsSerializer > allMods =
346+ loadAllModificationsFromDisk (resource );
347+ atomicReference .set (allMods );
348+ if (cachedModEntriesSize .get () >= config .getModsCacheSizeLimitPerFI ()) {
349+ return null ;
350+ }
351+ long memCost =
352+ RamUsageEstimator .sizeOfObject (allMods )
353+ + RamUsageEstimator .SHALLOW_SIZE_OF_CONCURRENT_HASHMAP_ENTRY ;
354+ long alreadyUsedMemoryForCachedModEntries = cachedModEntriesSize .get ();
355+ while (alreadyUsedMemoryForCachedModEntries + memCost
356+ < config .getModsCacheSizeLimitPerFI ()) {
357+ if (cachedModEntriesSize .compareAndSet (
358+ alreadyUsedMemoryForCachedModEntries ,
359+ alreadyUsedMemoryForCachedModEntries + memCost )) {
360+ memoryReservationManager .reserveMemoryCumulatively (memCost );
361+ return allMods ;
362+ }
363+ alreadyUsedMemoryForCachedModEntries = cachedModEntriesSize .get ();
364+ }
365+ return null ;
366+ });
367+ return cachedResult == null ? atomicReference .get () : cachedResult ;
368+ }
369+
323370 // the state change listener is added here in a separate initialize() method
324371 // instead of the constructor to prevent leaking the "this" reference to
325372 // another thread, which will cause unsafe publication of this instance.
@@ -479,12 +526,25 @@ public void setTimeFilterForTableModel(Filter timeFilter) {
479526 }
480527 }
481528
529+ @ Override
530+ public boolean collectTable (String table ) {
531+ boolean added = super .collectTable (table );
532+ if (added && memoryReservationManager != null ) {
533+ memoryReservationManager .reserveMemoryCumulatively (
534+ RamUsageEstimator .sizeOf (table ) + RamUsageEstimator .SHALLOW_SIZE_OF_HASHMAP_ENTRY );
535+ }
536+ return added ;
537+ }
538+
482539 public IDataRegionForQuery getDataRegion () {
483540 return dataRegion ;
484541 }
485542
486543 public void setSourcePaths (List <IFullPath > sourcePaths ) {
487544 this .sourcePaths = sourcePaths ;
545+ if (sourcePaths != null && sourcePaths .size () == 1 ) {
546+ singleSourcePath = true ;
547+ }
488548 }
489549
490550 public void setDevicePathsToContext (Map <IDeviceID , DeviceContext > devicePathsToContext ) {
@@ -791,6 +851,8 @@ public synchronized void releaseResource() {
791851 // release TVList/AlignedTVList owned by current query
792852 releaseTVListOwnedByQuery ();
793853
854+ fileModCache = null ;
855+ tables = null ;
794856 dataRegion = null ;
795857 globalTimeFilter = null ;
796858 sharedQueryDataSource = null ;
@@ -967,4 +1029,8 @@ public long getUnclosedSeqFileNum() {
9671029 public boolean ignoreNotExistsDevice () {
9681030 return ignoreNotExistsDevice ;
9691031 }
1032+
1033+ public boolean isSingleSourcePath () {
1034+ return singleSourcePath ;
1035+ }
9701036}
0 commit comments