*******************************************************************************/
package org.simantics.db.indexing;
-import java.io.File;
-import java.io.FileFilter;
import java.io.IOException;
+import java.nio.file.FileAlreadyExistsException;
+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;
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.
*/
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)
+ "." + 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());
}
/**
*
* @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);
+ if (!Files.exists(changedFile)) {
+ Files.createFile(changedFile);
+ FileUtils.sync(changedFile);
+ } else if (!Files.isRegularFile(changedFile)) {
+ throw new FileAlreadyExistsException(changedFile.toString(), null, "index dirtyness indicator file already exists but it is not a regular file");
}
}
} catch (IOException e) {
- Logger.defaultLogError(e);
+ LOGGER.error("Could not mark index changed for indexPath={} and changedFile={}", indexPath.toAbsolutePath(), changedFile.toAbsolutePath());
}
}
}
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 {
}
- 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.emptyDirectory(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);
}
}