Skip to content

Commit

Permalink
Cleanup spark tmp dir on startup
Browse files Browse the repository at this point in the history
  • Loading branch information
lucko committed Jul 29, 2024
1 parent 7076811 commit 6e7cc88
Show file tree
Hide file tree
Showing 3 changed files with 122 additions and 20 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
import me.lucko.spark.common.monitor.ping.PlayerPingProvider;
import me.lucko.spark.common.monitor.tick.SparkTickStatistics;
import me.lucko.spark.common.monitor.tick.TickStatistics;
import me.lucko.spark.common.platform.PlatformInfo;
import me.lucko.spark.common.platform.PlatformStatisticsProvider;
import me.lucko.spark.common.sampler.BackgroundSamplerManager;
import me.lucko.spark.common.sampler.SamplerContainer;
Expand Down Expand Up @@ -123,7 +124,10 @@ public SparkPlatform(SparkPlugin plugin) {
this.plugin = plugin;
SparkStaticLogger.setLogger(plugin::log);

this.temporaryFiles = new TemporaryFiles(this.plugin.getPluginDirectory().resolve("tmp"));
this.temporaryFiles = new TemporaryFiles(this.plugin.getPlatformInfo().getType() == PlatformInfo.Type.CLIENT
? this.plugin.getPluginDirectory().resolve("tmp")
: this.plugin.getPluginDirectory().resolve("tmp-client")
);
this.configuration = Configuration.combining(
RuntimeConfiguration.SYSTEM_PROPERTIES,
RuntimeConfiguration.ENVIRONMENT_VARIABLES,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,11 @@
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.FileSystems;
import java.nio.file.FileVisitResult;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.SimpleFileVisitor;
import java.nio.file.attribute.BasicFileAttributes;
import java.nio.file.attribute.FileAttribute;
import java.nio.file.attribute.PosixFilePermission;
import java.nio.file.attribute.PosixFilePermissions;
Expand Down Expand Up @@ -58,16 +61,21 @@ public final class TemporaryFiles {
private final Set<Path> files = Collections.synchronizedSet(new HashSet<>());

public TemporaryFiles(Path tmpDirectory) {
this.tmpDirectory = tmpDirectory;
boolean useOsTmpDir = Boolean.parseBoolean(System.getProperty("spark.useOsTmpDir", "false"));
if (useOsTmpDir) {
this.tmpDirectory = null;
} else {
this.tmpDirectory = init(tmpDirectory);
}
}

public Path create(String prefix, String suffix) throws IOException {
Path file;
if (ensureDirectoryIsReady()) {
if (this.tmpDirectory == null) {
file = Files.createTempFile(prefix, suffix);
} else {
String name = prefix + Long.toHexString(System.nanoTime()) + suffix;
file = Files.createFile(this.tmpDirectory.resolve(name), OWNER_ONLY_FILE_PERMISSIONS);
} else {
file = Files.createTempFile(prefix, suffix);
}
return register(file);
}
Expand All @@ -92,19 +100,33 @@ public void deleteTemporaryFiles() {
}
}

private boolean ensureDirectoryIsReady() {
if (Boolean.parseBoolean(System.getProperty("spark.useOsTmpDir", "false"))) {
return false;
}

if (Files.isDirectory(this.tmpDirectory)) {
return true;
}

private static Path init(Path tmpDirectory) {
try {
Files.createDirectories(this.tmpDirectory);

Files.write(this.tmpDirectory.resolve("about.txt"), ImmutableList.of(
Files.createDirectories(tmpDirectory);
Path readmePath = tmpDirectory.resolve("about.txt");

Files.walkFileTree(
tmpDirectory,
new SimpleFileVisitor<Path>() {
@Override
public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException {
if (!dir.equals(tmpDirectory)) {
Files.delete(dir);
}
return FileVisitResult.CONTINUE;
}

@Override
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
if (!file.equals(readmePath)) {
Files.delete(file);
}
return FileVisitResult.CONTINUE;
}
}
);

Files.write(readmePath, ImmutableList.of(
"# What is this directory?",
"",
"* In order to perform certain functions, spark sometimes needs to write temporary data to the disk. ",
Expand All @@ -116,11 +138,10 @@ private boolean ensureDirectoryIsReady() {
"",
"tl;dr: spark uses this folder to store some temporary data."
), StandardCharsets.UTF_8);

return true;
} catch (IOException e) {
return false;
// ignore
}
return tmpDirectory;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
/*
* This file is part of spark.
*
* Copyright (c) lucko (Luck) <[email protected]>
* Copyright (c) contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

package me.lucko.spark.common.util;

import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.io.TempDir;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;

public class TemporaryFilesTest {

@Test
public void testDelete(@TempDir Path tempDir) throws IOException {
Path dir = tempDir.resolve("test");
TemporaryFiles temporaryFiles = new TemporaryFiles(dir);

assertTrue(Files.exists(dir) && Files.isDirectory(dir));
assertTrue(Files.exists(dir.resolve("about.txt")));
assertEquals("# What is this directory?", Files.readAllLines(dir.resolve("about.txt")).get(0));

Path temporaryFile = temporaryFiles.create("test", ".txt");
Files.write(temporaryFile, "Hello, world!".getBytes());

assertTrue(Files.exists(temporaryFile));
temporaryFiles.deleteTemporaryFiles();
assertFalse(Files.exists(temporaryFile));
}

@Test
public void testCleanupOnInit(@TempDir Path tempDir) throws IOException {
Path dir = tempDir.resolve("test");

Path nestedDirectory = dir.resolve("hello").resolve("world");
Files.createDirectories(nestedDirectory);

Path testFile = nestedDirectory.resolve("file.txt");
Files.write(testFile, "Hello, world!".getBytes());
assertTrue(Files.exists(testFile));

TemporaryFiles temporaryFiles = new TemporaryFiles(dir);

assertFalse(Files.exists(testFile));
}

@Test
public void testSecondInit(@TempDir Path tempDir) throws IOException {
Path dir = tempDir.resolve("test");

TemporaryFiles temporaryFiles = new TemporaryFiles(dir);
TemporaryFiles temporaryFiles2 = new TemporaryFiles(dir);
}

}

0 comments on commit 6e7cc88

Please sign in to comment.