Skip to content

Commit ef53e32

Browse files
authored
Fix active load cleanup lifecycle (#17947) (#17963)
(cherry picked from commit c4574b6)
1 parent 9442a1c commit ef53e32

10 files changed

Lines changed: 110 additions & 7 deletions

File tree

iotdb-core/datanode/src/main/java/org/apache/iotdb/db/conf/IoTDBConfig.java

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4259,7 +4259,17 @@ public void setLoadActiveListeningFailDir(String loadActiveListeningFailDir) {
42594259
}
42604260

42614261
public String getLoadActiveListeningPipeDir() {
4262-
return loadActiveListeningPipeDir;
4262+
return loadActiveListeningPipeDir == null || Objects.equals(loadActiveListeningPipeDir, "")
4263+
? extDir
4264+
+ File.separator
4265+
+ IoTDBConstant.LOAD_TSFILE_FOLDER_NAME
4266+
+ File.separator
4267+
+ IoTDBConstant.PIPE_FOLDER_NAME
4268+
: loadActiveListeningPipeDir;
4269+
}
4270+
4271+
public void setLoadActiveListeningPipeDir(String loadActiveListeningPipeDir) {
4272+
this.loadActiveListeningPipeDir = addDataHomeDir(loadActiveListeningPipeDir);
42634273
}
42644274

42654275
public String[] getLoadActiveListeningDirs() {

iotdb-core/datanode/src/main/java/org/apache/iotdb/db/conf/IoTDBDescriptor.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2484,6 +2484,9 @@ private void loadLoadTsFileProps(TrimProperties properties) throws IOException {
24842484
conf.setLoadActiveListeningFailDir(
24852485
properties.getProperty(
24862486
"load_active_listening_fail_dir", conf.getLoadActiveListeningFailDir()));
2487+
conf.setLoadActiveListeningPipeDir(
2488+
properties.getProperty(
2489+
"load_active_listening_pipe_dir", conf.getLoadActiveListeningPipeDir()));
24872490

24882491
final long loadActiveListeningCheckIntervalSeconds =
24892492
Long.parseLong(
@@ -2614,6 +2617,9 @@ private void loadLoadTsFileHotModifiedProp(TrimProperties properties) throws IOE
26142617
properties.getProperty(
26152618
"load_active_listening_fail_dir",
26162619
ConfigurationFileUtils.getConfigurationDefaultValue("load_active_listening_fail_dir")));
2620+
conf.setLoadActiveListeningPipeDir(
2621+
properties.getProperty(
2622+
"load_active_listening_pipe_dir", conf.getLoadActiveListeningPipeDir()));
26172623

26182624
conf.setLoadTsFileSpiltPartitionMaxSize(
26192625
Integer.parseInt(

iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/StorageEngine.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -310,6 +310,7 @@ public void start() throws StartupException {
310310
}
311311

312312
asyncRecoverTsFileResource();
313+
loadTsFileManager.start();
313314
}
314315

315316
private void startTimedService() {
@@ -394,6 +395,7 @@ private void asyncRecoverTsFileResource() {
394395

395396
@Override
396397
public void stop() {
398+
loadTsFileManager.stop();
397399
for (DataRegion dataRegion : dataRegionMap.values()) {
398400
if (dataRegion != null) {
399401
CompactionScheduleTaskManager.getInstance().unregisterDataRegion(dataRegion);
@@ -412,6 +414,7 @@ public void stop() {
412414

413415
@Override
414416
public void shutdown(long milliseconds) throws ShutdownException {
417+
loadTsFileManager.stop();
415418
try {
416419
for (DataRegion dataRegion : dataRegionMap.values()) {
417420
if (dataRegion != null) {

iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/load/LoadTsFileManager.java

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,9 +125,22 @@ public class LoadTsFileManager {
125125
public LoadTsFileManager() {
126126
registerCleanupTaskExecutor();
127127
recover();
128+
}
129+
130+
public void start() {
128131
activeLoadAgent.start();
129132
}
130133

134+
public void stop() {
135+
activeLoadAgent.stop();
136+
synchronized (uuid2CleanupTask) {
137+
uuid2CleanupTask.values().forEach(CleanupTask::cancel);
138+
uuid2CleanupTask.clear();
139+
cleanupTaskQueue.clear();
140+
}
141+
new HashSet<>(uuid2WriterManager.keySet()).forEach(this::forceCloseWriterManager);
142+
}
143+
131144
private long getCleanupTaskDelayInMs() {
132145
return CONFIG.getLoadCleanupTaskExecutionDelayTimeSeconds() * 1000L;
133146
}

iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/load/active/ActiveLoadAgent.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,12 @@ public synchronized void start() {
6262
activeLoadMetricsCollector.start();
6363
}
6464

65+
public synchronized void stop() {
66+
activeLoadDirScanner.stop();
67+
activeLoadMetricsCollector.stop();
68+
activeLoadTsFileLoader.stop();
69+
}
70+
6571
/**
6672
* Clean up all listening directories for active load on DataNode first startup. This method will
6773
* clean up all files and subdirectories in the listening directories, including: 1. Pending

iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/load/active/ActiveLoadDirScanner.java

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
import java.nio.file.attribute.BasicFileAttributes;
4141
import java.util.Arrays;
4242
import java.util.Map;
43+
import java.util.Objects;
4344
import java.util.Set;
4445
import java.util.concurrent.CopyOnWriteArraySet;
4546
import java.util.concurrent.atomic.AtomicBoolean;
@@ -54,6 +55,7 @@ public class ActiveLoadDirScanner extends ActiveLoadScheduledExecutorService {
5455
private static final String MODS = ".mods";
5556

5657
private final AtomicReference<String[]> listeningDirsConfig = new AtomicReference<>();
58+
private final AtomicReference<String> pipeListeningDirConfig = new AtomicReference<>();
5759
private final Set<String> listeningDirs = new CopyOnWriteArraySet<>();
5860

5961
private final Set<String> noPermissionDirs = new CopyOnWriteArraySet<>();
@@ -201,8 +203,20 @@ private void hotReloadActiveLoadDirs() {
201203
} else {
202204
listeningDirs.clear();
203205
}
204-
// Hot reload active load listening dir for pipe data sync
205-
// Active load is always enabled for pipe data sync
206+
if (!Objects.equals(
207+
IOTDB_CONFIG.getLoadActiveListeningPipeDir(), pipeListeningDirConfig.get())) {
208+
synchronized (this) {
209+
if (!Objects.equals(
210+
IOTDB_CONFIG.getLoadActiveListeningPipeDir(), pipeListeningDirConfig.get())) {
211+
if (pipeListeningDirConfig.get() != null) {
212+
listeningDirs.remove(pipeListeningDirConfig.get());
213+
}
214+
pipeListeningDirConfig.set(IOTDB_CONFIG.getLoadActiveListeningPipeDir());
215+
}
216+
}
217+
}
218+
219+
// Active load is always enabled for pipe data sync.
206220
listeningDirs.add(IOTDB_CONFIG.getLoadActiveListeningPipeDir());
207221

208222
// Create directories if not exists

iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/load/active/ActiveLoadScheduledExecutorService.java

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -45,14 +45,19 @@ public abstract class ActiveLoadScheduledExecutorService {
4545

4646
private static final long MIN_EXECUTION_INTERVAL_SECONDS =
4747
IOTDB_CONFIG.getLoadActiveListeningCheckIntervalSeconds();
48-
private final ScheduledExecutorService scheduledExecutorService;
48+
private final ThreadName threadName;
49+
private ScheduledExecutorService scheduledExecutorService;
4950
private Future<?> future;
5051

5152
private final List<Pair<WrappedRunnable, Long>> jobs = new CopyOnWriteArrayList<>();
5253

5354
protected ActiveLoadScheduledExecutorService(final ThreadName threadName) {
54-
scheduledExecutorService =
55-
IoTDBThreadPoolFactory.newSingleThreadScheduledExecutor(threadName.name());
55+
this.threadName = threadName;
56+
scheduledExecutorService = newScheduledExecutorService();
57+
}
58+
59+
private ScheduledExecutorService newScheduledExecutorService() {
60+
return IoTDBThreadPoolFactory.newSingleThreadScheduledExecutor(threadName.name());
5661
}
5762

5863
public void register(Runnable runnable) {
@@ -73,6 +78,9 @@ public void runMayThrow() {
7378

7479
public synchronized void start() {
7580
if (future == null) {
81+
if (scheduledExecutorService.isShutdown()) {
82+
scheduledExecutorService = newScheduledExecutorService();
83+
}
7684
future =
7785
ScheduledExecutorUtil.safelyScheduleWithFixedDelay(
7886
scheduledExecutorService,
@@ -96,5 +104,12 @@ public synchronized void stop() {
96104
future = null;
97105
LOGGER.info("Active load periodical jobs executor is stopped successfully.");
98106
}
107+
scheduledExecutorService.shutdownNow();
108+
try {
109+
scheduledExecutorService.awaitTermination(30, TimeUnit.SECONDS);
110+
} catch (InterruptedException e) {
111+
LOGGER.warn("{} still doesn't exit after 30s", threadName.getName());
112+
Thread.currentThread().interrupt();
113+
}
99114
}
100115
}

iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/load/active/ActiveLoadTsFileLoader.java

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,25 @@ private void adjustExecutorIfNecessary() {
154154
}
155155
}
156156

157+
public void stop() {
158+
final WrappedThreadPoolExecutor executor = activeLoadExecutor.getAndSet(null);
159+
if (executor == null) {
160+
return;
161+
}
162+
163+
executor.shutdownNow();
164+
try {
165+
if (!executor.awaitTermination(30, TimeUnit.SECONDS)) {
166+
LOGGER.warn(
167+
"{} still doesn't exit after 30s", ThreadName.ACTIVE_LOAD_TSFILE_LOADER.getName());
168+
}
169+
} catch (final InterruptedException e) {
170+
LOGGER.warn(
171+
"{} still doesn't exit after 30s", ThreadName.ACTIVE_LOAD_TSFILE_LOADER.getName());
172+
Thread.currentThread().interrupt();
173+
}
174+
}
175+
157176
private void tryLoadPendingTsFiles() {
158177
final IClientSession session =
159178
new InternalClientSession(
@@ -200,18 +219,22 @@ private Optional<ActiveLoadPendingQueue.ActiveLoadEntry> tryGetNextPendingFile()
200219
Math.max(1, IOTDB_CONFIG.getLoadActiveListeningCheckIntervalSeconds() << 1);
201220
long currentRetryTimes = 0;
202221

203-
while (true) {
222+
while (!Thread.currentThread().isInterrupted()) {
204223
final ActiveLoadPendingQueue.ActiveLoadEntry entry = pendingQueue.dequeueFromPending();
205224
if (Objects.nonNull(entry)) {
206225
return Optional.of(entry);
207226
}
208227

209228
LockSupport.parkNanos(TimeUnit.SECONDS.toNanos(1));
229+
if (Thread.currentThread().isInterrupted()) {
230+
return Optional.empty();
231+
}
210232

211233
if (currentRetryTimes++ >= maxRetryTimes) {
212234
return Optional.empty();
213235
}
214236
}
237+
return Optional.empty();
215238
}
216239

217240
private TSStatus loadTsFile(

iotdb-core/datanode/src/test/resources/iotdb-system.properties

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ udf_lib_dir=target/ext/udf
3232
trigger_lib_dir=target/ext/trigger
3333
pipe_lib_dir=target/ext/pipe
3434
load_active_listening_dirs=target/ext/load/pending
35+
load_active_listening_pipe_dir=target/ext/load/pipe
3536
load_active_listening_fail_dir=target/ext/load/failed
3637

3738
####################

iotdb-core/node-commons/src/assembly/resources/conf/iotdb-system.properties.template

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2062,6 +2062,18 @@ load_active_listening_enable=true
20622062
# If its prefix is "/", then the path is absolute. Otherwise, it is relative.
20632063
load_active_listening_dirs=ext/load/pending
20642064

2065+
# The directory to be actively listened for tsfile loading from Pipe.
2066+
# Only one directory can be configured.
2067+
# effectiveMode: hot_reload
2068+
# Datatype: String
2069+
# For windows platform
2070+
# If its prefix is a drive specifier followed by "\\", or if its prefix is "\\\\", then the path is absolute.
2071+
# Otherwise, it is relative.
2072+
# load_active_listening_pipe_dir=ext\\load\\pipe
2073+
# For Linux platform
2074+
# If its prefix is "/", then the path is absolute. Otherwise, it is relative.
2075+
load_active_listening_pipe_dir=ext/load/pipe
2076+
20652077
# The directory where tsfile are moved if the active listening mode fails to load them.
20662078
# Only one directory can be configured.
20672079
# effectiveMode: hot_reload

0 commit comments

Comments
 (0)