aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHarald Musum <musum@yahooinc.com>2024-06-05 15:42:21 +0200
committerGitHub <noreply@github.com>2024-06-05 15:42:21 +0200
commit211e238d3d5f26c64da0dce054633b096e96b414 (patch)
tree2ebd13f71921b95c272a8e6cda1d856076c5c27c
parent96cd2f346108ddec7f98f1eecd984e303772ce83 (diff)
parent678846da9c98d212f80349027d579d9daecf93d4 (diff)
Merge pull request #31448 from vespa-engine/hmusum/preprocess-and-move-atomically-take-4
Preprocess application package in temp dir, then move atomically to d…
-rw-r--r--config-application-package/src/main/java/com/yahoo/config/model/application/provider/FilesApplicationPackage.java35
1 files changed, 25 insertions, 10 deletions
diff --git a/config-application-package/src/main/java/com/yahoo/config/model/application/provider/FilesApplicationPackage.java b/config-application-package/src/main/java/com/yahoo/config/model/application/provider/FilesApplicationPackage.java
index 28bf8e10a93..df62f762c40 100644
--- a/config-application-package/src/main/java/com/yahoo/config/model/application/provider/FilesApplicationPackage.java
+++ b/config-application-package/src/main/java/com/yahoo/config/model/application/provider/FilesApplicationPackage.java
@@ -52,6 +52,7 @@ import java.io.IOException;
import java.io.InputStream;
import java.io.Reader;
import java.io.StringReader;
+import java.nio.file.AccessDeniedException;
import java.nio.file.Files;
import java.security.MessageDigest;
import java.util.ArrayList;
@@ -613,24 +614,38 @@ public class FilesApplicationPackage extends AbstractApplicationPackage {
@Override
public ApplicationPackage preprocess(Zone zone, DeployLogger logger) throws IOException {
- IOUtils.recursiveDeleteDir(preprocessedDir);
- IOUtils.copyDirectory(appDir, preprocessedDir, -1,
+ try {
+ java.nio.file.Path tempDir = Files.createTempDirectory(appDir.getParentFile().toPath(), "preprocess-tempdir");
+ preprocess(appDir, tempDir.toFile(), zone);
+ IOUtils.recursiveDeleteDir(preprocessedDir);
+ // Use 'move' to make sure we do this atomically, important to avoid writing only partial content e.g.
+ // when shutting down.
+ // Temp directory needs to be on the same file system as appDir for 'move' to work,
+ // if it fails (with DirectoryNotEmptyException (!)) we need to use 'copy' instead
+ // (this will always be the case for the application package for a standalone container).
+ Files.move(tempDir, preprocessedDir.toPath());
+ } catch (AccessDeniedException e) {
+ preprocess(appDir, preprocessedDir, zone);
+ }
+ FilesApplicationPackage preprocessedApp = fromFile(preprocessedDir, includeSourceFiles);
+ preprocessedApp.copyUserDefsIntoApplication();
+ return preprocessedApp;
+ }
+
+ private void preprocess(File appDir, File dir, Zone zone) throws IOException {
+ validateServicesFile();
+ IOUtils.copyDirectory(appDir, dir, - 1,
(__, name) -> ! List.of(preprocessed, SERVICES, HOSTS, CONFIG_DEFINITIONS_DIR).contains(name));
- File servicesFile = validateServicesFile();
- preprocessXML(applicationFile(preprocessedDir, SERVICES), servicesFile, zone);
- preprocessXML(applicationFile(preprocessedDir, HOSTS), getHostsFile(), zone);
- FilesApplicationPackage preprocessed = fromFile(preprocessedDir, includeSourceFiles);
- preprocessed.copyUserDefsIntoApplication();
- return preprocessed;
+ preprocessXML(applicationFile(dir, SERVICES), getServicesFile(), zone);
+ preprocessXML(applicationFile(dir, HOSTS), getHostsFile(), zone);
}
- private File validateServicesFile() throws IOException {
+ private void validateServicesFile() throws IOException {
File servicesFile = getServicesFile();
if ( ! servicesFile.exists())
throw new IllegalArgumentException(SERVICES + " does not exist in application package");
if (IOUtils.readFile(servicesFile).isEmpty())
throw new IllegalArgumentException(SERVICES + " in application package is empty");
- return servicesFile;
}
private void copyUserDefsIntoApplication() {