Skip to content

Commit 07b2151

Browse files
committed
[improve][misc] Make nar extraction "atomic" so that possible previously failed extraction won't prevent broker restarts
1 parent 46f99b9 commit 07b2151

File tree

1 file changed

+29
-6
lines changed

1 file changed

+29
-6
lines changed

pulsar-common/src/main/java/org/apache/pulsar/common/nar/NarUnpacker.java

+29-6
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,9 @@
3232
import java.io.RandomAccessFile;
3333
import java.nio.channels.FileChannel;
3434
import java.nio.channels.FileLock;
35+
import java.nio.file.Files;
3536
import java.nio.file.Path;
37+
import java.nio.file.StandardCopyOption;
3638
import java.security.MessageDigest;
3739
import java.security.NoSuchAlgorithmException;
3840
import java.util.Base64;
@@ -86,19 +88,40 @@ static File doUnpackNar(final File nar, final File baseWorkingDirectory, Runnabl
8688
try (FileChannel channel = new RandomAccessFile(lockFile, "rw").getChannel();
8789
FileLock lock = channel.lock()) {
8890
File narWorkingDirectory = new File(parentDirectory, md5Sum);
89-
if (narWorkingDirectory.mkdir()) {
91+
if (!narWorkingDirectory.exists()) {
92+
File narExtractionTempDirectory = new File(parentDirectory, md5Sum + ".tmp");
93+
if (narExtractionTempDirectory.exists()) {
94+
FileUtils.deleteFile(narExtractionTempDirectory, true);
95+
}
96+
if (!narExtractionTempDirectory.mkdir()) {
97+
throw new IOException("Cannot create " + narExtractionTempDirectory);
98+
}
99+
if (!narWorkingDirectory.mkdir()) {
100+
throw new IOException("Cannot create " + narWorkingDirectory);
101+
}
90102
try {
91-
log.info("Extracting {} to {}", nar, narWorkingDirectory);
103+
log.info("Extracting {} to {}", nar, narExtractionTempDirectory);
92104
if (extractCallback != null) {
93105
extractCallback.run();
94106
}
95-
unpack(nar, narWorkingDirectory);
107+
unpack(nar, narExtractionTempDirectory);
96108
} catch (IOException e) {
97-
log.error("There was a problem extracting the nar file. Deleting {} to clean up state.",
98-
narWorkingDirectory, e);
99-
FileUtils.deleteFile(narWorkingDirectory, true);
109+
log.error("There was a problem extracting the nar file. Deleting {} and {} to clean up state.",
110+
narExtractionTempDirectory, narWorkingDirectory, e);
111+
try {
112+
FileUtils.deleteFile(narExtractionTempDirectory, true);
113+
} catch (IOException e2) {
114+
log.error("Failed to delete temporary directory {}", narExtractionTempDirectory, e2);
115+
}
116+
try {
117+
FileUtils.deleteFile(narWorkingDirectory, true);
118+
} catch (IOException e2) {
119+
log.error("Failed to delete working directory {}", narWorkingDirectory, e2);
120+
}
100121
throw e;
101122
}
123+
Files.move(narExtractionTempDirectory.toPath(), narWorkingDirectory.toPath(),
124+
StandardCopyOption.ATOMIC_MOVE);
102125
}
103126
return narWorkingDirectory;
104127
}

0 commit comments

Comments
 (0)