X-Git-Url: https://gerrit.simantics.org/r/gitweb?p=simantics%2Fplatform.git;a=blobdiff_plain;f=bundles%2Forg.simantics.acorn%2Fsrc%2Forg%2Fsimantics%2Facorn%2Fbackup%2FAcornBackupProvider.java;h=cb4b3cdeea1d18f5477387d0fc0e5b4a6a93b2a4;hp=5ea0799d82fd116d2c9467a24a81a47cfeb1e6ac;hb=f347cbef328d1ae417ae095c0e2d81a358bdd598;hpb=87b6edd49f4370516d7f37bcb34c91324b95052c diff --git a/bundles/org.simantics.acorn/src/org/simantics/acorn/backup/AcornBackupProvider.java b/bundles/org.simantics.acorn/src/org/simantics/acorn/backup/AcornBackupProvider.java index 5ea0799d8..cb4b3cdee 100644 --- a/bundles/org.simantics.acorn/src/org/simantics/acorn/backup/AcornBackupProvider.java +++ b/bundles/org.simantics.acorn/src/org/simantics/acorn/backup/AcornBackupProvider.java @@ -1,6 +1,5 @@ package org.simantics.acorn.backup; -import java.io.BufferedReader; import java.io.IOException; import java.nio.file.FileVisitResult; import java.nio.file.Files; @@ -16,11 +15,15 @@ import java.util.concurrent.Semaphore; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; +import org.simantics.acorn.AcornSessionManagerImpl; import org.simantics.acorn.GraphClientImpl2; +import org.simantics.acorn.exception.IllegalAcornStateException; import org.simantics.backup.BackupException; import org.simantics.backup.IBackupProvider; import org.simantics.db.server.ProCoreException; import org.simantics.utils.FileUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** * @author Jani @@ -29,23 +32,29 @@ import org.simantics.utils.FileUtils; */ public class AcornBackupProvider implements IBackupProvider { + private static final Logger LOGGER = LoggerFactory.getLogger(AcornBackupProvider.class); + private static final String IDENTIFIER = "AcornBackupProvider"; private long trId = -1; private final Semaphore lock = new Semaphore(1); + private final GraphClientImpl2 client; + + public AcornBackupProvider() { + this.client = AcornSessionManagerImpl.getInstance().getClient(); + } - private static Path getAcornMetadataFile(Path dbFolder) { + public static Path getAcornMetadataFile(Path dbFolder) { return dbFolder.getParent().resolve(IDENTIFIER); } - + @Override public void lock() throws BackupException { try { if (trId != -1) throw new IllegalStateException(this + " backup provider is already locked"); - trId = GraphClientImpl2.getInstance().askWriteTransaction(-1) - .getTransactionId(); + trId = client.askWriteTransaction(-1).getTransactionId(); } catch (ProCoreException e) { - e.printStackTrace(); + LOGGER.error("Failed to lock backup provider", e); } } @@ -54,32 +63,15 @@ public class AcornBackupProvider implements IBackupProvider { boolean releaseLock = true; try { lock.acquire(); - - GraphClientImpl2 client = GraphClientImpl2.getInstance(); - client.makeSnapshot(true); - - Path dbDir = client.getDbFolder(); - int newestFolder = client.clusters.mainState.headDir - 1; - int latestFolder = -2; - Path AcornMetadataFile = getAcornMetadataFile(dbDir); - if (Files.exists(AcornMetadataFile)) { - try (BufferedReader br = Files.newBufferedReader(AcornMetadataFile)) { - latestFolder = Integer.parseInt( br.readLine() ); - } - } - - AcornBackupRunnable r = new AcornBackupRunnable( - lock, targetPath, revision, dbDir, latestFolder, newestFolder); - new Thread(r, "Acorn backup thread").start(); - - releaseLock = false; - return r; + Future r = client.getBackupRunnable(lock, targetPath, revision); + releaseLock = false; + return r; } catch (InterruptedException e) { releaseLock = false; throw new BackupException("Failed to lock Acorn for backup.", e); } catch (NumberFormatException e) { throw new BackupException("Failed to read Acorn head state file.", e); - } catch (IOException e) { + } catch (IllegalAcornStateException | IOException e) { throw new BackupException("I/O problem during Acorn backup.", e); } finally { if (releaseLock) @@ -92,7 +84,7 @@ public class AcornBackupProvider implements IBackupProvider { try { if (trId == -1) throw new BackupException(this + " backup provider is not locked"); - GraphClientImpl2.getInstance().endTransaction(trId); + client.endTransaction(trId); trId = -1; } catch (ProCoreException e) { throw new BackupException(e); @@ -105,7 +97,7 @@ public class AcornBackupProvider implements IBackupProvider { // 1. Resolve initial backup restore target. // This can be DB directory directly or a temporary directory that // will replace the DB directory. - Path dbRoot = GraphClientImpl2.getInstance().getDbFolder(); + Path dbRoot = client.getDbFolder(); Path restorePath = dbRoot; if (!Files.exists(dbRoot, LinkOption.NOFOLLOW_LINKS)) { Files.createDirectories(dbRoot); @@ -122,9 +114,9 @@ public class AcornBackupProvider implements IBackupProvider { if (dbRoot != restorePath) { FileUtils.deleteAll(dbRoot.toFile()); Files.move(restorePath, dbRoot); - } + } } catch (IOException e) { - e.printStackTrace(); + LOGGER.error("Failed to restore database revision {} from backup {}", revision, fromPath.toString(), e); } } @@ -147,9 +139,7 @@ public class AcornBackupProvider implements IBackupProvider { return FileVisitResult.CONTINUE; } else if (dir.getParent().getFileName().toString().equals(IDENTIFIER)) { Path targetPath = toPath.resolve(dirName); - if (!Files.exists(targetPath)) { - Files.createDirectory(targetPath); - } + Files.createDirectories(targetPath); return FileVisitResult.CONTINUE; } else if (dirName.toString().length() == 1 && Character.isDigit(dirName.toString().charAt(0))) { int dirNameInt = Integer.parseInt(dirName.toString()); @@ -167,13 +157,14 @@ public class AcornBackupProvider implements IBackupProvider { public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException { if (file.getFileName().toString().endsWith(".tar.gz")) return FileVisitResult.CONTINUE; - System.out.println("Restore " + file + " to " + toPath.resolve(currentSubFolder.relativize(file))); + if (LOGGER.isTraceEnabled()) + LOGGER.trace("Restore " + file + " to " + toPath.resolve(currentSubFolder.relativize(file))); Files.copy(file, toPath.resolve(currentSubFolder.relativize(file)), StandardCopyOption.REPLACE_EXISTING); return FileVisitResult.CONTINUE; } } - private static class AcornBackupRunnable implements Runnable, Future { + public static class AcornBackupRunnable implements Runnable, Future { private final Semaphore lock; private final Path targetPath; @@ -213,8 +204,7 @@ public class AcornBackupProvider implements IBackupProvider { private void doBackup() throws IOException { Path target = targetPath.resolve(String.valueOf(revision)).resolve(IDENTIFIER); - if (!Files.exists(target)) - Files.createDirectories(target); + Files.createDirectories(target); Files.walkFileTree(baseDir, new BackupCopyVisitor(baseDir, target)); } @@ -248,22 +238,19 @@ public class AcornBackupProvider implements IBackupProvider { @Override public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException { - Path dirName = dir.getFileName(); - if (dirName.equals(fromPath)) { + if (dir.equals(fromPath)) { Path targetPath = toPath.resolve(fromPath.relativize(dir)); - if (!Files.exists(targetPath)) { - Files.createDirectory(targetPath); - } + Files.createDirectories(targetPath); return FileVisitResult.CONTINUE; } else { - int dirNameInt = Integer.parseInt(dirName.toString()); - if (latestFolder < dirNameInt && dirNameInt <= newestFolder) { - Path targetPath = toPath.resolve(fromPath - .relativize(dir)); - if (!Files.exists(targetPath)) { - Files.createDirectory(targetPath); + try { + int dirNameInt = Integer.parseInt(dir.getFileName().toString()); + if (latestFolder < dirNameInt && dirNameInt <= newestFolder) { + Path targetPath = toPath.resolve(fromPath.relativize(dir)); + Files.createDirectories(targetPath); + return FileVisitResult.CONTINUE; } - return FileVisitResult.CONTINUE; + } catch (NumberFormatException e) { } return FileVisitResult.SKIP_SUBTREE; } @@ -272,8 +259,8 @@ public class AcornBackupProvider implements IBackupProvider { @Override public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException { - System.out.println("Backup " + file + " to " - + toPath.resolve(fromPath.relativize(file))); + if (LOGGER.isTraceEnabled()) + LOGGER.trace("Backup " + file + " to " + toPath.resolve(fromPath.relativize(file))); Files.copy(file, toPath.resolve(fromPath.relativize(file)), StandardCopyOption.REPLACE_EXISTING); return FileVisitResult.CONTINUE;