From: Tuukka Lehtonen Date: Sun, 7 May 2017 08:09:27 +0000 (+0300) Subject: Merge changes I09c034e1,Ideac8aae,Ib7751212,Id09d9a3c,I39696ee5, ... X-Git-Tag: v1.29.0~70 X-Git-Url: https://gerrit.simantics.org/r/gitweb?p=simantics%2Fplatform.git;a=commitdiff_plain;h=04a7cb7f4ec34ddd4747723fd51ea22edd5ede0b;hp=cf9bdb9c3223ccee2b0a264d72dcc84091718043 Merge changes I09c034e1,Ideac8aae,Ib7751212,Id09d9a3c,I39696ee5, ... * changes: Use ListIndexRoots in migration ListIndexRoots request SingletonRead base class GenericReadBase2 without the unused template parameter Initial selection for diagram viewer should be the diagram itself Support VP.Test in action browse context contribution InstanceOf tester (VP.Test) --- diff --git a/bundles/org.simantics.acorn/src/org/simantics/acorn/AcornManagement.java b/bundles/org.simantics.acorn/src/org/simantics/acorn/AcornManagement.java index c21491210..231578ac6 100644 --- a/bundles/org.simantics.acorn/src/org/simantics/acorn/AcornManagement.java +++ b/bundles/org.simantics.acorn/src/org/simantics/acorn/AcornManagement.java @@ -1,6 +1,5 @@ package org.simantics.acorn; -import java.nio.file.Path; import java.util.Properties; import org.simantics.db.Database; diff --git a/bundles/org.simantics.acorn/src/org/simantics/acorn/ClusterManager.java b/bundles/org.simantics.acorn/src/org/simantics/acorn/ClusterManager.java index e0bcbebf7..4c8df9337 100644 --- a/bundles/org.simantics.acorn/src/org/simantics/acorn/ClusterManager.java +++ b/bundles/org.simantics.acorn/src/org/simantics/acorn/ClusterManager.java @@ -263,11 +263,11 @@ public class ClusterManager { // Nothing has been written => no need to do anything long amountOfFiles = countFiles(workingDirectory); if(!fullSave && amountOfFiles == 0) { - // System.err.println("amountOfFiles < 3"); + //LOGGER.info("makeSnapshot: " + amountOfFiles + " files, skipping snapshot"); return false; } - LOGGER.info("makeSnapshot"); + LOGGER.info("makeSnapshot: start with " + amountOfFiles + " files"); // Schedule writing of all data to disk refreshHeadState(); @@ -287,13 +287,11 @@ public class ClusterManager { persistHeadState(); - if (fullSave) - mainState.save(dbFolder); - - amountOfFiles = countFiles(workingDirectory); - - LOGGER.info(" -finished: amount of files is {}", amountOfFiles); - + if (LOGGER.isInfoEnabled()) { + amountOfFiles = countFiles(workingDirectory); + LOGGER.info(" -finished: amount of files is {}", amountOfFiles); + } + workingDirectory = dbFolder.resolve(Integer.toString(mainState.headDir)); if (!Files.exists(workingDirectory)) { Files.createDirectories(workingDirectory); diff --git a/bundles/org.simantics.acorn/src/org/simantics/acorn/GraphClientImpl2.java b/bundles/org.simantics.acorn/src/org/simantics/acorn/GraphClientImpl2.java index dce477ebe..07fe18e61 100644 --- a/bundles/org.simantics.acorn/src/org/simantics/acorn/GraphClientImpl2.java +++ b/bundles/org.simantics.acorn/src/org/simantics/acorn/GraphClientImpl2.java @@ -192,7 +192,7 @@ public class GraphClientImpl2 implements Database.Session { try { if (!unexpectedClose) makeSnapshot(true); - + mainProgram.close(); clusters.shutdown(); executor.shutdown(); @@ -201,7 +201,13 @@ public class GraphClientImpl2 implements Database.Session { boolean saverTerminated = saver.awaitTermination(500, TimeUnit.MILLISECONDS); System.err.println("executorTerminated=" + executorTerminated + ", saverTerminated=" + saverTerminated); - + + try { + clusters.mainState.save(dbFolder); + } catch (IOException e) { + LOGGER.error("Failed to save " + MainState.MAIN_STATE + " file in database folder " + dbFolder); + } + mainProgram = null; executor = null; saver = null; 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 1025cc6a5..12f0552e4 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 @@ -2,14 +2,16 @@ package org.simantics.acorn.internal; import java.io.File; import java.io.IOException; -import java.io.RandomAccessFile; +import java.nio.channels.FileChannel; import java.nio.channels.FileLock; import java.nio.file.DirectoryStream; +import java.nio.file.FileAlreadyExistsException; import java.nio.file.FileVisitOption; import java.nio.file.FileVisitResult; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.SimpleFileVisitor; +import java.nio.file.StandardOpenOption; import java.nio.file.attribute.BasicFileAttributes; import java.util.EnumSet; import java.util.Properties; @@ -18,24 +20,28 @@ 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.exception.SDBException; import org.simantics.db.server.DatabaseStartException; import org.simantics.db.server.ProCoreException; -import org.simantics.db.server.internal.InternalException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** * @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; - private RandomAccessFile raLockFile; + private FileChannel lockFileChannel; private FileLock lock; @@ -43,6 +49,7 @@ public class AcornDatabase implements Database { public AcornDatabase(Path folder) { this.folder = folder; + this.lockFile = folder.resolve(LOCK_FILE_NAME); } @Override @@ -90,7 +97,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; } } @@ -110,22 +117,25 @@ public class AcornDatabase implements Database { } @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(); + try { + lockFileChannel = lockFile.getFileSystem().provider().newFileChannel(lockFile, + EnumSet.of(StandardOpenOption.CREATE_NEW, StandardOpenOption.WRITE)); + } catch (FileAlreadyExistsException e) { + throw new ProCoreException("The database in folder " + folder.toAbsolutePath() + " is already in use!", e); + } + + lock = lockFileChannel.tryLock(); if (lock == null) { + safeLoggingClose(lockFileChannel, 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(lockFileChannel, lockFile); } } @@ -135,19 +145,19 @@ 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(lockFileChannel, lockFile); + lockFileChannel = null; + Files.deleteIfExists(lockFile); isRunning = false; - } catch (IOException e) { - e.printStackTrace(); + LOGGER.error("Failed to start database at " + folder.toAbsolutePath(), e); } - return true; } @@ -265,4 +275,13 @@ 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()); + } + } + }