Skip to content

Commit 58d5da8

Browse files
committed
Do not run the cleanup if there is nothing to clean up
1 parent d0eed45 commit 58d5da8

File tree

2 files changed

+75
-15
lines changed

2 files changed

+75
-15
lines changed

dd-java-agent/agent-profiling/profiling-controller/src/main/java/com/datadog/profiling/controller/TempLocationManager.java

Lines changed: 31 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
import java.util.Set;
2121
import java.util.concurrent.CountDownLatch;
2222
import java.util.concurrent.TimeUnit;
23+
import java.util.stream.Stream;
2324
import org.slf4j.Logger;
2425
import org.slf4j.LoggerFactory;
2526

@@ -31,6 +32,8 @@
3132
*/
3233
public final class TempLocationManager {
3334
private static final Logger log = LoggerFactory.getLogger(TempLocationManager.class);
35+
// accessible to tests
36+
static final String TEMPDIR_PREFIX = "pid_";
3437

3538
private static final class SingletonHolder {
3639
private static final TempLocationManager INSTANCE = new TempLocationManager();
@@ -106,7 +109,7 @@ public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs)
106109
}
107110
String fileName = dir.getFileName().toString();
108111
// the JFR repository directories are under <basedir>/pid_<pid>
109-
String pid = fileName.startsWith("pid_") ? fileName.substring(4) : null;
112+
String pid = fileName.startsWith(TEMPDIR_PREFIX) ? fileName.substring(4) : null;
110113
boolean isSelfPid = pid != null && pid.equals(PidHelper.getPid());
111114
shouldClean |= cleanSelf ? isSelfPid : !isSelfPid && !pidSet.contains(pid);
112115
if (shouldClean) {
@@ -168,7 +171,7 @@ public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOEx
168171
}
169172
String fileName = dir.getFileName().toString();
170173
// reset the flag only if we are done cleaning the top-level directory
171-
shouldClean = !fileName.startsWith("pid_");
174+
shouldClean = !fileName.startsWith(TEMPDIR_PREFIX);
172175
}
173176
return FileVisitResult.CONTINUE;
174177
}
@@ -236,10 +239,11 @@ private TempLocationManager() {
236239
}
237240

238241
TempLocationManager(ConfigProvider configProvider) {
239-
this(configProvider, CleanupHook.EMPTY);
242+
this(configProvider, true, CleanupHook.EMPTY);
240243
}
241244

242-
TempLocationManager(ConfigProvider configProvider, CleanupHook testHook) {
245+
TempLocationManager(
246+
ConfigProvider configProvider, boolean runStartupCleanup, CleanupHook testHook) {
243247
cleanupTestHook = testHook;
244248

245249
// In order to avoid racy attempts to clean up files which are currently being processed in a
@@ -278,8 +282,11 @@ private TempLocationManager() {
278282
baseTempDir = configuredTempDir.resolve("ddprof");
279283
baseTempDir.toFile().deleteOnExit();
280284

281-
tempDir = baseTempDir.resolve("pid_" + pid);
282-
AgentTaskScheduler.INSTANCE.execute(() -> cleanup(false));
285+
tempDir = baseTempDir.resolve(TEMPDIR_PREFIX + pid);
286+
if (runStartupCleanup) {
287+
// do not execute the background cleanup task when running in tests
288+
AgentTaskScheduler.INSTANCE.execute(() -> cleanup(false));
289+
}
283290

284291
Thread selfCleanup =
285292
new Thread(
@@ -364,6 +371,19 @@ boolean cleanup(boolean cleanSelf) {
364371
*/
365372
boolean cleanup(boolean cleanSelf, long timeout, TimeUnit unit) {
366373
try {
374+
if (!Files.exists(baseTempDir)) {
375+
// not event the main temp location exists; nothing to clean up
376+
return true;
377+
}
378+
try (Stream<Path> paths = Files.walk(baseTempDir)) {
379+
if (paths.noneMatch(
380+
path ->
381+
Files.isDirectory(path)
382+
&& path.getFileName().toString().startsWith(TEMPDIR_PREFIX))) {
383+
// nothing to clean up; bail out early
384+
return true;
385+
}
386+
}
367387
cleanupTestHook.onCleanupStart(cleanSelf, timeout, unit);
368388
CleanupVisitor visitor = new CleanupVisitor(cleanSelf, timeout, unit);
369389
Files.walkFileTree(baseTempDir, visitor);
@@ -394,4 +414,9 @@ boolean waitForCleanup(long timeout, TimeUnit unit) {
394414
}
395415
return false;
396416
}
417+
418+
// accessible for tests
419+
void createDirStructure() throws IOException {
420+
Files.createDirectories(baseTempDir);
421+
}
397422
}

dd-java-agent/agent-profiling/profiling-controller/src/test/java/com/datadog/profiling/controller/TempLocationManagerTest.java

Lines changed: 44 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
import java.util.UUID;
1919
import java.util.concurrent.Phaser;
2020
import java.util.concurrent.TimeUnit;
21+
import java.util.concurrent.atomic.AtomicBoolean;
2122
import java.util.concurrent.locks.LockSupport;
2223
import java.util.stream.Stream;
2324
import org.junit.jupiter.api.Test;
@@ -173,7 +174,7 @@ public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOEx
173174
}
174175
};
175176

176-
TempLocationManager mgr = instance(baseDir, blocker);
177+
TempLocationManager mgr = instance(baseDir, true, blocker);
177178

178179
// wait for the cleanup start
179180
phaser.arriveAndAwaitAdvance();
@@ -187,8 +188,9 @@ public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOEx
187188

188189
@ParameterizedTest
189190
@MethodSource("timeoutTestArguments")
190-
void testCleanupWithTimeout(boolean selfCleanup, String section) throws Exception {
191-
long timeoutMs = 500;
191+
void testCleanupWithTimeout(boolean selfCleanup, boolean shouldSucceed, String section)
192+
throws Exception {
193+
long timeoutMs = 10;
192194
TempLocationManager.CleanupHook delayer =
193195
new TempLocationManager.CleanupHook() {
194196
@Override
@@ -229,30 +231,63 @@ public FileVisitResult visitFile(Path file, BasicFileAttributes attrs)
229231
Files.createTempDirectory(
230232
"ddprof-test-",
231233
PosixFilePermissions.asFileAttribute(PosixFilePermissions.fromString("rwx------")));
232-
TempLocationManager instance = instance(baseDir, delayer);
233-
boolean rslt = instance.cleanup(selfCleanup, timeoutMs, TimeUnit.MILLISECONDS);
234-
assertTrue(rslt);
234+
TempLocationManager instance = instance(baseDir, false, delayer);
235+
Path mytempdir = instance.getTempDir();
236+
Path otherTempdir = mytempdir.getParent().resolve("pid_0000");
237+
Files.createDirectories(otherTempdir);
238+
Files.createFile(mytempdir.resolve("dummy"));
239+
Files.createFile(otherTempdir.resolve("dummy"));
240+
boolean rslt =
241+
instance.cleanup(
242+
selfCleanup, (long) (timeoutMs * (shouldSucceed ? 10 : 0.5d)), TimeUnit.MILLISECONDS);
243+
assertEquals(shouldSucceed, rslt);
244+
}
245+
246+
@Test
247+
void testShortCircuit() throws Exception {
248+
Path baseDir =
249+
Files.createTempDirectory(
250+
"ddprof-test-",
251+
PosixFilePermissions.asFileAttribute(PosixFilePermissions.fromString("rwx------")));
252+
AtomicBoolean executed = new AtomicBoolean();
253+
TempLocationManager.CleanupHook hook =
254+
new TempLocationManager.CleanupHook() {
255+
@Override
256+
public void onCleanupStart(boolean selfCleanup, long timeout, TimeUnit unit) {
257+
executed.set(true);
258+
}
259+
};
260+
TempLocationManager instance = instance(baseDir, false, hook);
261+
262+
instance.createDirStructure();
263+
264+
boolean ret = instance.cleanup(false);
265+
assertTrue(ret);
266+
assertFalse(executed.get());
235267
}
236268

237269
private static Stream<Arguments> timeoutTestArguments() {
238270
List<Arguments> argumentsList = new ArrayList<>();
239271
for (boolean selfCleanup : new boolean[] {true, false}) {
240272
for (String intercepted :
241273
new String[] {"preVisitDirectory", "visitFile", "postVisitDirectory"}) {
242-
argumentsList.add(Arguments.of(selfCleanup, intercepted));
274+
argumentsList.add(Arguments.of(selfCleanup, true, intercepted));
275+
argumentsList.add(Arguments.of(selfCleanup, false, intercepted));
243276
}
244277
}
245278
return argumentsList.stream();
246279
}
247280

248-
private TempLocationManager instance(Path baseDir, TempLocationManager.CleanupHook cleanupHook)
281+
private TempLocationManager instance(
282+
Path baseDir, boolean withStartupCleanup, TempLocationManager.CleanupHook cleanupHook)
249283
throws IOException {
250284
Properties props = new Properties();
251285
props.put(ProfilingConfig.PROFILING_TEMP_DIR, baseDir.toString());
252286
props.put(
253287
ProfilingConfig.PROFILING_UPLOAD_PERIOD,
254288
"0"); // to force immediate cleanup; must be a string value!
255289

256-
return new TempLocationManager(ConfigProvider.withPropertiesOverride(props), cleanupHook);
290+
return new TempLocationManager(
291+
ConfigProvider.withPropertiesOverride(props), withStartupCleanup, cleanupHook);
257292
}
258293
}

0 commit comments

Comments
 (0)