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%2Finternal%2FAcornDatabase.java;h=8109df6cd25fd8a4ca2f4a9cdacd405ff6b60b7c;hp=be505c6039712e322ce80ffa653c1b4c6babac13;hb=e5c006a3e29dcb1f29ae5bcc21ac28573bd37648;hpb=0cbe7783b5f5297ab926fa742e023cfcbdcba43d diff --git a/bundles/org.simantics.acorn/src/org/simantics/acorn/internal/AcornDatabase.java b/bundles/org.simantics.acorn/src/org/simantics/acorn/internal/AcornDatabase.java index be505c603..8109df6cd 100644 --- a/bundles/org.simantics.acorn/src/org/simantics/acorn/internal/AcornDatabase.java +++ b/bundles/org.simantics.acorn/src/org/simantics/acorn/internal/AcornDatabase.java @@ -13,20 +13,32 @@ import java.nio.file.SimpleFileVisitor; import java.nio.file.attribute.BasicFileAttributes; import java.util.EnumSet; import java.util.Properties; +import java.util.stream.Stream; import org.simantics.acorn.GraphClientImpl2; import org.simantics.db.Database; import org.simantics.db.DatabaseUserAgent; import org.simantics.db.ServiceLocator; -import org.simantics.db.common.utils.Logger; +import org.simantics.db.server.DatabaseStartException; import org.simantics.db.server.ProCoreException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import fi.vtt.simantics.procore.internal.StaticSessionProperties; /** * @author Tuukka Lehtonen */ public class AcornDatabase implements Database { + private static final Logger LOGGER = LoggerFactory.getLogger(AcornDatabase.class); + + private static final String LOCK_FILE_NAME = "lock"; + private final Path folder; + private final Path lockFile; + + private GraphClientImpl2 currentClient; private DatabaseUserAgent userAgent; @@ -38,6 +50,7 @@ public class AcornDatabase implements Database { public AcornDatabase(Path folder) { this.folder = folder; + this.lockFile = folder.resolve(LOCK_FILE_NAME); } @Override @@ -85,7 +98,7 @@ public class AcornDatabase implements Database { try (DirectoryStream folderStream = Files.newDirectoryStream(path)) { return !folderStream.iterator().hasNext(); } catch (IOException e) { - Logger.defaultLogError("Failed to open folder stream. folder=" + path, e); + LOGGER.error("Failed to open folder stream. folder=" + path, e); return false; } } @@ -102,25 +115,31 @@ public class AcornDatabase implements Database { @Override public void deleteFiles() throws ProCoreException { deleteTree(folder); + File vgPath = StaticSessionProperties.virtualGraphStoragePath; + if (vgPath != null) { + try (Stream vgs = Files.list(vgPath.toPath())) { + for (Path p : vgs.toArray(Path[]::new)) + deleteTree(p); + } catch (IOException e) { + throw new ProCoreException(e); + } + } } @Override - public void start() throws ProCoreException { - Path lockFile = folder.resolve("lock"); + public synchronized void start() throws ProCoreException { try { - if (!Files.exists(lockFile)) - Files.createFile(lockFile); - raLockFile = new RandomAccessFile(lockFile.toFile(), "rw"); lock = raLockFile.getChannel().tryLock(); if (lock == null) { + safeLoggingClose(raLockFile, lockFile); throw new ProCoreException("The database in folder " + folder.toAbsolutePath() + " is already in use!"); } - isRunning = true; - } catch (IOException e) { - e.printStackTrace(); + LOGGER.error("Failed to start database at " + folder.toAbsolutePath(), e); + safeLoggingClose(raLockFile, lockFile); + throw new ProCoreException("Failed to start database at " + folder.toAbsolutePath(), e); } } @@ -130,19 +149,21 @@ public class AcornDatabase implements Database { } @Override - public boolean tryToStop() throws ProCoreException { + public synchronized boolean tryToStop() throws ProCoreException { + if (!isRunning) + return false; try { - lock.release(); - raLockFile.close(); - - Files.deleteIfExists(folder.resolve("lock")); - + safeLoggingClose(lock, lockFile); + lock = null; + safeLoggingClose(raLockFile, lockFile); + raLockFile = null; + Files.deleteIfExists(lockFile); isRunning = false; - + safeLoggingClose(currentClient, currentClient.getDbFolder()); + currentClient = null; } catch (IOException e) { - e.printStackTrace(); + LOGGER.error("Failed to start database at " + folder.toAbsolutePath(), e); } - return true; } @@ -190,22 +211,22 @@ public class AcornDatabase implements Database { @Override public void purgeDatabase() throws ProCoreException { - // TODO: implement - throw new UnsupportedOperationException(); + if(currentClient == null) throw new IllegalStateException("No current session."); + currentClient.purgeDatabase(); } @Override public long serverGetTailChangeSetId() throws ProCoreException { - // "We have it all" - // But after purging we don't so beware. - // TODO: beware for purge - return 1; + if(currentClient == null) throw new IllegalStateException("No current session."); + return currentClient.getTailChangeSetId(); } @Override public Session newSession(ServiceLocator locator) throws ProCoreException { try { - return new GraphClientImpl2(this, folder, locator); + if(currentClient != null) throw new DatabaseStartException(folder.toFile(), "A session is already running. Only one session is supported."); + currentClient = new GraphClientImpl2(this, folder, locator); + return currentClient; } catch (IOException e) { throw new ProCoreException(e); } @@ -217,39 +238,37 @@ public class AcornDatabase implements Database { throw new UnsupportedOperationException(); } - private static void deleteTree(Path path) throws ProCoreException { - if (!Files.exists(path)) - return; - - class Visitor extends SimpleFileVisitor { - @Override - public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException { + static class Visitor extends SimpleFileVisitor { + @Override + public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException { + try { + Files.delete(file); + } catch (IOException ioe) { + LOGGER.error("Failed to delete file {}", file, ioe); + throw ioe; + } + return FileVisitResult.CONTINUE; + } + @Override + public FileVisitResult postVisitDirectory(Path dir, IOException e) throws IOException { + if (e == null) { try { - Files.delete(file); + Files.delete(dir); } catch (IOException ioe) { - ioe.printStackTrace(); + LOGGER.error("Failed to delete directory {}", dir, ioe); throw ioe; } return FileVisitResult.CONTINUE; } - @Override - public FileVisitResult postVisitDirectory(Path dir, IOException e) throws IOException { - if (e == null) { - try { - Files.delete(dir); - } catch (IOException ioe) { - ioe.printStackTrace(); - throw ioe; - } - return FileVisitResult.CONTINUE; - } - throw e; - } + throw e; } + } + + private static void deleteTree(Path path) throws ProCoreException { + if (!Files.exists(path)) + return; try { - Visitor v = new Visitor(); - EnumSet opts = EnumSet.noneOf(FileVisitOption.class); - Files.walkFileTree(path, opts, Integer.MAX_VALUE, v); + Files.walkFileTree(path, EnumSet.noneOf(FileVisitOption.class), Integer.MAX_VALUE, new Visitor()); } catch (IOException e) { throw new ProCoreException("Could not delete " + path, e); } @@ -260,4 +279,23 @@ public class AcornDatabase implements Database { return "LZ4"; } + private static void safeLoggingClose(AutoCloseable closeable, Path file) { + if (closeable == null) + return; + try (AutoCloseable c = closeable) { + } catch (Exception e) { + LOGGER.error("Failed to close " + closeable.getClass() + " of " + file.toAbsolutePath(), e); + } + } + + private static void safeLoggingClose(Database.Session session, Path file) { + if (session == null) + return; + try { + session.close(); + } catch (Exception e) { + LOGGER.error("Failed to close " + session.getClass() + " of " + file.toAbsolutePath(), e); + } + } + }