]> gerrit.simantics Code Review - simantics/platform.git/blobdiff - bundles/org.simantics.db.indexing/src/org/simantics/db/indexing/DatabaseIndexing.java
Improve startup time for fresh or rollback'd session in index writing
[simantics/platform.git] / bundles / org.simantics.db.indexing / src / org / simantics / db / indexing / DatabaseIndexing.java
index abd6e1ba54ef1203f7508ee285b8e26a4ed442fd..f8a19504c8dc0165f38ddb34f27b7b31fe8a38ed 100644 (file)
  *******************************************************************************/
 package org.simantics.db.indexing;
 
-import java.io.File;
-import java.io.FileFilter;
 import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
 import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.function.Consumer;
+import java.util.stream.Stream;
 
 import org.simantics.db.Resource;
 import org.simantics.db.Session;
 import org.simantics.db.WriteGraph;
 import org.simantics.db.common.request.IndexRoot;
 import org.simantics.db.common.request.WriteRequest;
-import org.simantics.db.common.utils.Logger;
 import org.simantics.db.exception.DatabaseException;
 import org.simantics.db.indexing.internal.IndexChangedWriter;
 import org.simantics.db.layer0.adapter.GenericRelationIndex;
@@ -29,6 +31,7 @@ import org.simantics.db.layer0.genericrelation.IndexedRelations;
 import org.simantics.db.layer0.internal.SimanticsInternal;
 import org.simantics.db.service.ServerInformation;
 import org.simantics.utils.FileUtils;
+import org.slf4j.LoggerFactory;
 
 /**
  * A facade for Simantics graph database index management facilities.
@@ -37,18 +40,13 @@ import org.simantics.utils.FileUtils;
  */
 public final class DatabaseIndexing {
 
-    private static final boolean DEBUG = IndexPolicy.TRACE_INDEX_MANAGEMENT;
+    private static final org.slf4j.Logger LOGGER = LoggerFactory.getLogger(DatabaseIndexing.class);
 
-    public static File getIndexBaseLocation() {
-       return Activator.getDefault().getIndexBaseFile();
-//     Activator activator = Activator.getDefault();
-//        Bundle b = Platform.getBundle(Activator.BUNDLE_ID);
-//        IPath state = Platform.getStateLocation(b);
-//        File path = state.append("index").toFile();
-//        return path;
+    public static Path getIndexBaseLocation() {
+        return Activator.getDefault().getIndexBaseFile();
     }
 
-    public static File getIndexLocation(Session session, Resource relation, Resource input) {
+    public static Path getIndexLocation(Session session, Resource relation, Resource input) {
         if (session == null)
             throw new NullPointerException("null session");
         if (relation == null)
@@ -60,45 +58,48 @@ public final class DatabaseIndexing {
         + "." + relation.getResourceId()
         + "." + input.getResourceId();
 
-        return new File(getIndexBaseLocation(), dir);
+        return getIndexBaseLocation().resolve(dir);
     }
 
-    private static File getAllDirtyFile() {
-        return new File(getIndexBaseLocation(), ".dirty");
+    private static Path getAllDirtyFile() {
+        return getIndexBaseLocation().resolve(".dirty");
     }
 
-    private static File getChangedFile(File indexPath) {
-        return new File(indexPath, ".changed");
+    private static Path getChangedFile(Path indexPath) {
+        return indexPath.resolve(".changed");
     }
 
     public static void markAllDirty() throws IOException {
-        File indexBase = getIndexBaseLocation();
-        if (!indexBase.exists() || !indexBase.isDirectory())
+        Path indexBase = getIndexBaseLocation();
+        if (!Files.exists(indexBase) || !Files.isDirectory(indexBase))
             return;
-        if (DEBUG)
-            System.out.println("Marking all indexes dirty");
-        File allDirtyFile = getAllDirtyFile();
-        if (allDirtyFile.createNewFile()) {
-            FileUtils.syncFile(allDirtyFile);
+        if (LOGGER.isDebugEnabled())
+            LOGGER.debug("Marking all indexes dirty");
+        Path allDirtyFile = getAllDirtyFile();
+        if (!Files.exists(allDirtyFile)) {
+            Files.createFile(allDirtyFile);
+            FileUtils.sync(allDirtyFile);
         }
     }
 
     public static void clearAllDirty() throws IOException {
-        if (DEBUG)
-            System.out.println("Clearing dirty state of all indexes");
+        if (LOGGER.isDebugEnabled())
+            LOGGER.debug("Clearing dirty state of all indexes");
 
-        File indexBase = getIndexBaseLocation();
-        if (!indexBase.exists() || !indexBase.isDirectory())
+        Path indexBase = getIndexBaseLocation();
+        if (!Files.exists(indexBase) || !Files.isDirectory(indexBase))
             return;
 
-        forEachIndexPath(new Procedure<File, IOException>() {
-            @Override
-            public void execute(File indexPath) throws IOException {
-                getChangedFile(indexPath).delete();
+        forEachIndexPath(indexPath -> {
+            Path p = getChangedFile(indexPath);
+            try {
+                FileUtils.delete(p);
+            } catch (IOException e) {
+                LOGGER.error("Could not delete {}", p.toAbsolutePath(), e);
             }
         });
 
-        getAllDirtyFile().delete();
+        FileUtils.delete(getAllDirtyFile());
     }
     
     /**
@@ -107,21 +108,20 @@ public final class DatabaseIndexing {
      * 
      * @param indexPath
      */
-    static void markIndexChanged(Session session, File indexPath) {
-        if (DEBUG)
-            System.out.println("Marking index dirty: " + indexPath);
+    static void markIndexChanged(Session session, Path indexPath) {
+        if (LOGGER.isDebugEnabled())
+            LOGGER.debug("Marking index dirty: " + indexPath);
+        Path changedFile = getChangedFile(indexPath);
         try {
-            File changedFile = getChangedFile(indexPath);
+            
             // Mark change only once per DB session.
             if (getIndexChangedWriter(session).markDirty(changedFile)) {
-                if (indexPath.mkdirs()) {
-                    if (changedFile.createNewFile()) {
-                        FileUtils.syncFile(changedFile);
-                    }
-                }
+                Files.createDirectories(indexPath);
+                Files.createFile(changedFile);
+                FileUtils.sync(changedFile);
             }
         } catch (IOException e) {
-            Logger.defaultLogError(e);
+            LOGGER.error("Could not mark index changed for indexPath={} and changedFile={}", indexPath.toAbsolutePath(), changedFile.toAbsolutePath());
         }
     }
 
@@ -137,14 +137,14 @@ public final class DatabaseIndexing {
     }
 
     public static void deleteAllIndexes() throws IOException {
-        File indexBase = DatabaseIndexing.getIndexBaseLocation();
+        Path indexBase = DatabaseIndexing.getIndexBaseLocation();
 
-        ArrayList<String> filter = new ArrayList<>(2);
-        filter.add(getAllDirtyFile().getAbsolutePath());
-        filter.add(indexBase.getAbsolutePath());
+        ArrayList<Path> filter = new ArrayList<>(2);
+        filter.add(getAllDirtyFile());
+        filter.add(indexBase);
 
-        FileUtils.deleteAllWithFilter(indexBase, filter);
-        FileUtils.deleteAll(indexBase);
+        FileUtils.deleteWithFilter(indexBase, path -> !filter.contains(path));
+        FileUtils.delete(indexBase);
     }
 
     public static void deleteIndex(final Resource relation, final Resource modelPart) throws DatabaseException {
@@ -172,64 +172,60 @@ public final class DatabaseIndexing {
        
     }
     
-    public static void deleteIndex(File indexPath) throws IOException {
-        if (DEBUG)
-            System.out.println("Deleting index " + indexPath);
+    public static void deleteIndex(Path indexPath) throws IOException {
+        if (LOGGER.isDebugEnabled())
+            LOGGER.debug("Deleting index " + indexPath.toAbsolutePath());
 
-        ArrayList<String> filter = new ArrayList<>(2);
-        filter.add(getChangedFile(indexPath).getAbsolutePath());
-        filter.add(indexPath.getAbsolutePath());
+        ArrayList<Path> filter = new ArrayList<>(2);
+        filter.add(getChangedFile(indexPath));
+        filter.add(indexPath);
 
-        FileUtils.deleteAllWithFilter(indexPath, filter);
-        FileUtils.deleteAll(indexPath);
+        FileUtils.deleteWithFilter(indexPath, path -> !filter.contains(path));
+        FileUtils.delete(indexPath);
     }
 
     public static void validateIndexes() throws IOException {
-        File indexBase = getIndexBaseLocation();
-        if (DEBUG)
-            System.out.println("Validating indexes at " + indexBase);
-        if (!indexBase.exists())
+        Path indexBase = getIndexBaseLocation();
+        if (LOGGER.isDebugEnabled())
+            LOGGER.debug("Validating indexes at " + indexBase);
+        if (!Files.exists(indexBase))
             return;
-        if (!indexBase.isDirectory()) {
+        if (!Files.isDirectory(indexBase)) {
             // Make sure that index-base is a valid directory
-            if (DEBUG)
-                System.out.println(indexBase + " is not a directory! Removing it.");
-            FileUtils.deleteAll(indexBase);
-            indexBase.mkdirs();
+            if (LOGGER.isDebugEnabled())
+                LOGGER.debug(indexBase + " is not a directory! Removing it.");
+            FileUtils.delete(indexBase);
+            Files.createDirectories(indexBase);
             return;
         }
-        File allDirtyFile = getAllDirtyFile();
-        if (allDirtyFile.isFile()) {
-            if (DEBUG)
-                System.out.println("All indexes marked dirty, removing them.");
+        Path allDirtyFile = getAllDirtyFile();
+        if (Files.isRegularFile(allDirtyFile)) {
+            if (LOGGER.isDebugEnabled())
+                LOGGER.debug("All indexes marked dirty, removing them.");
             deleteAllIndexes();
         } else {
-            forEachIndexPath(new Procedure<File, IOException>() {
-                @Override
-                public void execute(File indexPath) throws IOException {
-                    File changed = getChangedFile(indexPath);
-                    if (changed.isFile()) {
-                        if (DEBUG)
-                            System.out.println("Index is dirty, removing: " + indexPath);
+            forEachIndexPath(indexPath -> {
+                Path changed = getChangedFile(indexPath);
+                if (Files.isRegularFile(changed)) {
+                    if (LOGGER.isDebugEnabled())
+                        LOGGER.debug("Index is dirty, removing: " + indexPath);
+                    try {
                         deleteIndex(indexPath);
+                    } catch (IOException e) {
+                        LOGGER.error("Could not delete index {}", indexPath.toAbsolutePath(), e);
                     }
                 }
             });
         }
     }
 
-    interface Procedure<T, E extends Throwable> {
-        void execute(T t) throws E;
-    }
-
-    private static <E extends Throwable> void forEachIndexPath(Procedure<File, E> callback) throws E {
-        for (File indexPath : getIndexBaseLocation().listFiles(new FileFilter() {
-            @Override
-            public boolean accept(File pathname) {
-                return pathname.isDirectory();
+    private static void forEachIndexPath(Consumer<Path> callback) throws IOException {
+        try (Stream<Path> paths = Files.walk(getIndexBaseLocation(), 1).filter(Files::isDirectory)) {
+            Iterator<Path> iter = paths.iterator();
+            while (iter.hasNext()) {
+                Path p = iter.next();
+                callback.accept(p);
             }
-        })) {
-            callback.execute(indexPath);
         }
     }