Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -2574,4 +2574,6 @@ private DataNodePipeMessages() {}
"Topic metadata for %s is unavailable during consensus subscription setup";
public static final String EXCEPTION_TOPIC_CONFIG_FOR_ARG_IS_UNAVAILABLE_DURING_CONSENSUS_SUBSCRIPTION_SETUP_B94404EE =
"Topic config for %s is unavailable during consensus subscription setup";
public static final String LOG_FAILED_TO_RELEASE_TSFILE_PARSER_MEMORY_FOR_PIPE_ARG_CREATION_TIME_ARG_IN_DATAREGION_ARG_BECAUSE_NO_RESERVATION_EXISTS_BB8321C0 =
"Failed to release TsFile parser memory for Pipe {} (creation time {}) in DataRegion {} because no reservation exists.";
}
Original file line number Diff line number Diff line change
Expand Up @@ -2403,4 +2403,6 @@ private DataNodePipeMessages() {}
"共识订阅设置期间 topic %s 的元数据不可用";
public static final String EXCEPTION_TOPIC_CONFIG_FOR_ARG_IS_UNAVAILABLE_DURING_CONSENSUS_SUBSCRIPTION_SETUP_B94404EE =
"共识订阅设置期间 topic %s 的配置不可用";
public static final String LOG_FAILED_TO_RELEASE_TSFILE_PARSER_MEMORY_FOR_PIPE_ARG_CREATION_TIME_ARG_IN_DATAREGION_ARG_BECAUSE_NO_RESERVATION_EXISTS_BB8321C0 =
"无法释放 Pipe {}(创建时间 {})在 DataRegion {} 中的 TsFile 解析器内存,因为不存在对应的预留。";
}
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
import org.apache.iotdb.consensus.config.IoTConsensusV2Config;
import org.apache.iotdb.db.consensus.DataRegionConsensusImpl;
import org.apache.iotdb.db.i18n.DataNodeMiscMessages;
import org.apache.iotdb.db.pipe.resource.PipeDataNodeResourceManager;
import org.apache.iotdb.db.queryengine.plan.relational.metadata.fetcher.cache.LastCacheLoadStrategy;
import org.apache.iotdb.db.service.metrics.IoTDBInternalLocalReporter;
import org.apache.iotdb.db.storageengine.StorageEngine;
Expand Down Expand Up @@ -2761,6 +2762,7 @@ private void loadLoadTsFileHotModifiedProp(TrimProperties properties) throws IOE

private void loadPipeHotModifiedProp(TrimProperties properties) throws IOException {
PipeDescriptor.loadPipeProps(commonDescriptor.getConfig(), properties, true);
PipeDataNodeResourceManager.memory().notifyNextTsFileParserMemoryReservation();
LoggerPeriodicalLogReducer.update();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
import org.apache.iotdb.db.pipe.metric.overview.PipeDataNodeSinglePipeMetrics;
import org.apache.iotdb.db.pipe.resource.PipeDataNodeResourceManager;
import org.apache.iotdb.db.pipe.resource.memory.PipeMemoryManager;
import org.apache.iotdb.db.pipe.resource.memory.PipeMemoryManager.TsFileParserMemoryReservation;
import org.apache.iotdb.db.pipe.resource.tsfile.PipeTsFileResourceManager;
import org.apache.iotdb.db.pipe.source.dataregion.realtime.assigner.PipeTsFileEpochProgressIndexKeeper;
import org.apache.iotdb.db.storageengine.dataregion.memtable.TsFileProcessor;
Expand Down Expand Up @@ -80,6 +81,7 @@ public class PipeTsFileInsertionEvent extends PipeInsertionEvent
private static final Logger LOGGER = LoggerFactory.getLogger(PipeTsFileInsertionEvent.class);

private final TsFileResource resource;
private final String dataRegionId;
private File tsFile;
private long extractTime = 0;

Expand All @@ -98,6 +100,8 @@ public class PipeTsFileInsertionEvent extends PipeInsertionEvent
private final AtomicBoolean isClosed;
private final AtomicReference<TsFileInsertionEventParser> eventParser;
private final AtomicBoolean isTsFileParserMemoryReserved = new AtomicBoolean(false);
private final TsFileParserMemoryReservation tsFileParserMemoryReservationKey =
new TsFileParserMemoryReservation();

// The point count of the TsFile. Used for metrics on IoTConsensusV2' receiver side.
// May be updated after it is flushed. Should be negative if not set.
Expand Down Expand Up @@ -221,6 +225,7 @@ private PipeTsFileInsertionEvent(
databaseNameFromDataRegion);

this.resource = resource;
this.dataRegionId = resource.getDataRegionId();

// For events created at assigner or historical extractor, the tsFile is get from the resource
// For events created for source, the tsFile is inherited from the assigner, because the
Expand Down Expand Up @@ -879,15 +884,12 @@ private void waitForResourceEnough4Parsing(final long timeoutMs) throws Interrup
final long startTime = System.currentTimeMillis();
long lastRecordTime = startTime;

final long memoryCheckIntervalMs =
PipeConfig.getInstance().getPipeCheckMemoryEnoughIntervalMs();
while (!tryReserveTsFileParserMemory(memoryManager)) {
Thread.sleep(memoryCheckIntervalMs);

final long currentTime = System.currentTimeMillis();
final double elapsedRecordTimeSeconds = (currentTime - lastRecordTime) / 1000.0;
final double waitTimeSeconds = (currentTime - startTime) / 1000.0;
if (elapsedRecordTimeSeconds > 10.0) {
final long elapsedRecordTimeInMs = currentTime - lastRecordTime;
final long waitTimeInMs = currentTime - startTime;
final double waitTimeSeconds = waitTimeInMs / 1000.0;
if (elapsedRecordTimeInMs > 10_000) {
LOGGER.info(
DataNodePipeMessages.WAIT_FOR_MEMORY_ENOUGH_FOR_PARSING_FOR,
resource != null ? resource.getTsFilePath() : "tsfile",
Expand All @@ -900,14 +902,20 @@ private void waitForResourceEnough4Parsing(final long timeoutMs) throws Interrup
waitTimeSeconds);
}

if (waitTimeSeconds * 1000 > timeoutMs) {
if (waitTimeInMs > timeoutMs) {
// should contain 'TimeoutException' in exception message
throw new PipeRuntimeOutOfMemoryCriticalException(
String.format(
DataNodePipeMessages
.PIPE_EXCEPTION_TIMEOUTEXCEPTION_WAITED_S_SECONDS_FOR_MEMORY_TO_PARSE_TSFILE_0E4EF8FD,
waitTimeSeconds));
}

tsFileParserMemoryReservationKey.await(
Math.max(
1,
Math.min(
timeoutMs - waitTimeInMs, 10_000 - Math.min(10_000, elapsedRecordTimeInMs))));
}

final long currentTime = System.currentTimeMillis();
Expand All @@ -924,7 +932,8 @@ private boolean tryReserveTsFileParserMemory(final PipeMemoryManager memoryManag
return true;
}

if (!memoryManager.tryReserveTsFileParserMemory()) {
if (!memoryManager.tryReserveTsFileParserMemory(
pipeName, creationTime, dataRegionId, tsFileParserMemoryReservationKey)) {
return false;
}

Expand All @@ -936,11 +945,20 @@ private boolean tryReserveTsFileParserMemory(final PipeMemoryManager memoryManag
private void releaseTsFileParserMemoryIfReserved() {
synchronized (isTsFileParserMemoryReserved) {
if (isTsFileParserMemoryReserved.compareAndSet(true, false)) {
PipeDataNodeResourceManager.memory().releaseTsFileParserMemory();
PipeDataNodeResourceManager.memory()
.releaseTsFileParserMemory(pipeName, creationTime, dataRegionId);
}
}
}

private void cancelTsFileParserMemoryReservationIfPending() {
if (!isTsFileParserMemoryReserved.get()) {
PipeDataNodeResourceManager.memory()
.cancelTsFileParserMemoryReservation(
pipeName, creationTime, dataRegionId, tsFileParserMemoryReservationKey);
}
}

/** The method is used to prevent circular replication in IoTConsensusV2 */
public boolean isGeneratedByIoTConsensusV2() {
return isGeneratedByIoTConsensusV2;
Expand Down Expand Up @@ -1009,6 +1027,7 @@ public long count(final boolean skipReportOnCommit) throws Exception {
/** Release the resource of {@link TsFileInsertionEventParser}. */
@Override
public void close() {
cancelTsFileParserMemoryReservationIfPending();
eventParser.getAndUpdate(
parser -> {
if (Objects.nonNull(parser)) {
Expand Down Expand Up @@ -1053,12 +1072,14 @@ public PipeEventResource eventResourceBuilder() {
this.referenceCount,
this.pipeName,
this.creationTime,
this.dataRegionId,
this.tsFile,
this.isWithMod,
this.modFile,
this.sharedModFile,
this.eventParser,
this.isTsFileParserMemoryReserved);
this.isTsFileParserMemoryReserved,
this.tsFileParserMemoryReservationKey);
}

private static class PipeTsFileInsertionEventResource extends PipeEventResource {
Expand All @@ -1070,33 +1091,42 @@ private static class PipeTsFileInsertionEventResource extends PipeEventResource
private final AtomicReference<TsFileInsertionEventParser> eventParser;
private final String pipeName;
private final long creationTime;
private final String dataRegionId;
private final AtomicBoolean isTsFileParserMemoryReserved;
private final TsFileParserMemoryReservation tsFileParserMemoryReservationKey;

private PipeTsFileInsertionEventResource(
final AtomicBoolean isReleased,
final AtomicInteger referenceCount,
final String pipeName,
final long creationTime,
final String dataRegionId,
final File tsFile,
final boolean isWithMod,
final File modFile,
final File sharedModFile,
final AtomicReference<TsFileInsertionEventParser> eventParser,
final AtomicBoolean isTsFileParserMemoryReserved) {
final AtomicBoolean isTsFileParserMemoryReserved,
final TsFileParserMemoryReservation tsFileParserMemoryReservationKey) {
super(isReleased, referenceCount);
this.pipeName = pipeName;
this.creationTime = creationTime;
this.dataRegionId = dataRegionId;
this.tsFile = tsFile;
this.isWithMod = isWithMod;
this.modFile = modFile;
this.sharedModFile = sharedModFile;
this.eventParser = eventParser;
this.isTsFileParserMemoryReserved = isTsFileParserMemoryReserved;
this.tsFileParserMemoryReservationKey = tsFileParserMemoryReservationKey;
}

@Override
protected void finalizeResource() {
try {
PipeDataNodeResourceManager.memory()
.cancelTsFileParserMemoryReservation(
pipeName, creationTime, dataRegionId, tsFileParserMemoryReservationKey);
final String pipeTsFileResourcePipeName =
PipeTsFileResourceManager.getPipeTsFileResourcePipeName(pipeName, creationTime);
// decrease reference count
Expand All @@ -1117,7 +1147,8 @@ protected void finalizeResource() {
});
synchronized (isTsFileParserMemoryReserved) {
if (isTsFileParserMemoryReserved.compareAndSet(true, false)) {
PipeDataNodeResourceManager.memory().releaseTsFileParserMemory();
PipeDataNodeResourceManager.memory()
.releaseTsFileParserMemory(pipeName, creationTime, dataRegionId);
}
}
} catch (final Exception e) {
Expand Down
Loading
Loading