import java.io.File;
import java.io.FileFilter;
import java.io.IOException;
+import java.util.ArrayList;
import org.simantics.db.Resource;
import org.simantics.db.Session;
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.genericrelation.IndexedRelations;
import org.simantics.db.layer0.internal.SimanticsInternal;
return;
if (DEBUG)
System.out.println("Marking all indexes dirty");
- getAllDirtyFile().createNewFile();
+ File allDirtyFile = getAllDirtyFile();
+ if (allDirtyFile.createNewFile()) {
+ FileUtils.syncFile(allDirtyFile);
+ }
}
public static void clearAllDirty() throws IOException {
File indexBase = getIndexBaseLocation();
if (!indexBase.exists() || !indexBase.isDirectory())
return;
- delete(getAllDirtyFile());
forEachIndexPath(new Procedure<File, IOException>() {
@Override
public void execute(File indexPath) throws IOException {
- delete(getChangedFile(indexPath));
+ getChangedFile(indexPath).delete();
}
});
- }
+ getAllDirtyFile().delete();
+ }
+
/**
* Internal to indexing, invoked by {@link IndexedRelationsImpl} which
* doesn't want to throw these exceptions forward. Just log it.
*
* @param indexPath
*/
- static void markIndexChanged(File indexPath) {
- if (!indexPath.exists())
- throw new IllegalArgumentException("index path " + indexPath + " does not exist");
- if (!indexPath.isDirectory())
- throw new IllegalArgumentException("index path " + indexPath + " is not a directory");
+ static void markIndexChanged(Session session, File indexPath) {
+ if (DEBUG)
+ System.out.println("Marking index dirty: " + indexPath);
try {
- if (DEBUG)
- System.out.println("Marking index dirty: " + indexPath);
- getChangedFile(indexPath).createNewFile();
+ 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);
+ }
+ }
+ }
} catch (IOException e) {
Logger.defaultLogError(e);
}
}
+ private static IndexChangedWriter getIndexChangedWriter(Session session) {
+ IndexChangedWriter writer = session.peekService(IndexChangedWriter.class);
+ if (writer == null) {
+ synchronized (IndexChangedWriter.class) {
+ if (writer == null)
+ session.registerService(IndexChangedWriter.class, writer = new IndexChangedWriter());
+ }
+ }
+ return writer;
+ }
+
public static void deleteAllIndexes() throws IOException {
File indexBase = DatabaseIndexing.getIndexBaseLocation();
- delete(indexBase);
+
+ ArrayList<String> filter = new ArrayList<>(2);
+ filter.add(getAllDirtyFile().getAbsolutePath());
+ filter.add(indexBase.getAbsolutePath());
+
+ FileUtils.deleteAllWithFilter(indexBase, filter);
+ FileUtils.deleteAll(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);
- delete(indexPath);
+
+ ArrayList<String> filter = new ArrayList<>(2);
+ filter.add(getChangedFile(indexPath).getAbsolutePath());
+ filter.add(indexPath.getAbsolutePath());
+
+ FileUtils.deleteAllWithFilter(indexPath, filter);
+ FileUtils.deleteAll(indexPath);
}
public static void validateIndexes() throws IOException {
// Make sure that index-base is a valid directory
if (DEBUG)
System.out.println(indexBase + " is not a directory! Removing it.");
- delete(indexBase);
+ FileUtils.deleteAll(indexBase);
indexBase.mkdirs();
return;
}
if (allDirtyFile.isFile()) {
if (DEBUG)
System.out.println("All indexes marked dirty, removing them.");
- delete(allDirtyFile);
deleteAllIndexes();
} else {
forEachIndexPath(new Procedure<File, IOException>() {
}
}
-
- private static void delete(File fileOrDir) throws IOException {
- if (fileOrDir.exists())
- FileUtils.deleteAll(fileOrDir);
- }
-
interface Procedure<T, E extends Throwable> {
void execute(T t) throws E;
}
try {
+ DatabaseIndexing.markIndexChanged(processor.getSession(), searcher.getIndexPath());
if(!searcher.startAccess(null, processor.getSession(), true)) {
// Could not write index for some reason. Ignore and let the next index query reinitialize the index.
return;
}
searcher.insertIndex(progress.newChild(40), relation, 1, documents);
- DatabaseIndexing.markIndexChanged(searcher.getIndexPath());
} catch (InvalidResourceReferenceException e) {
throw new IndexException(e);
LockHandle handle = lock(processor, Pair.make(relationResource, input), true);
try {
+ DatabaseIndexing.markIndexChanged(processor.getSession(), searcher.getIndexPath());
if(!searcher.startAccess(null, processor.getSession(), true)) {
// Could not write index for some reason. Ignore and let the next index query reinitialize the index.
return;
}
searcher.removeIndex(progress.newChild(40), relation, processor, key, keyValues);
- DatabaseIndexing.markIndexChanged(searcher.getIndexPath());
} catch (DatabaseException e) {
throw new IndexException(e);
try {
+ DatabaseIndexing.markIndexChanged(processor.getSession(), searcher.getIndexPath());
if(!searcher.startAccess(null, processor.getSession(), true)) {
// Could not write index for some reason. Ignore and let the next index query reinitialize the index.
return true;
}
- didChange = searcher.replaceIndex(progress.newChild(40), key, keyValues, relation, 1, documents);
- if(didChange)
- DatabaseIndexing.markIndexChanged(searcher.getIndexPath());
+ searcher.replaceIndex(progress.newChild(40), key, keyValues, relation, 1, documents);
} catch (InvalidResourceReferenceException e) {
throw new IndexException(e);
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2017 Association for Decentralized Information Management
+ * in Industry THTH ry.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Semantum Oy - initial API and implementation
+ *******************************************************************************/
+package org.simantics.db.indexing.internal;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * An internal in-memory container for telling whether a certain index has been
+ * changed since the platform was last started up.
+ *
+ * @author Jussi Koskela
+ * @since 1.28.0
+ */
+public class IndexChangedWriter {
+ private Set<String> dirtyFiles = new HashSet<>();
+
+ public synchronized boolean markDirty(File dirtyFile) throws IOException {
+ return dirtyFiles.add(dirtyFile.getAbsolutePath());
+ }
+}