]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.db.indexing/src/org/simantics/db/indexing/DatabaseIndexing.java
Fixed all line endings of the repository
[simantics/platform.git] / bundles / org.simantics.db.indexing / src / org / simantics / db / indexing / DatabaseIndexing.java
1 /*******************************************************************************
2  * Copyright (c) 2007, 2010 Association for Decentralized Information Management
3  * in Industry THTH ry.
4  * All rights reserved. This program and the accompanying materials
5  * are made available under the terms of the Eclipse Public License v1.0
6  * which accompanies this distribution, and is available at
7  * http://www.eclipse.org/legal/epl-v10.html
8  *
9  * Contributors:
10  *     VTT Technical Research Centre of Finland - initial API and implementation
11  *******************************************************************************/
12 package org.simantics.db.indexing;
13
14 import java.io.File;
15 import java.io.FileFilter;
16 import java.io.IOException;
17
18 import org.simantics.db.Resource;
19 import org.simantics.db.Session;
20 import org.simantics.db.WriteGraph;
21 import org.simantics.db.common.request.IndexRoot;
22 import org.simantics.db.common.request.WriteRequest;
23 import org.simantics.db.common.utils.Logger;
24 import org.simantics.db.exception.DatabaseException;
25 import org.simantics.db.layer0.adapter.GenericRelationIndex;
26 import org.simantics.db.layer0.genericrelation.IndexedRelations;
27 import org.simantics.db.layer0.internal.SimanticsInternal;
28 import org.simantics.db.service.ServerInformation;
29 import org.simantics.utils.FileUtils;
30
31 /**
32  * A facade for Simantics graph database index management facilities.
33  * 
34  * @author Tuukka Lehtonen
35  */
36 public final class DatabaseIndexing {
37
38     private static final boolean DEBUG = IndexPolicy.TRACE_INDEX_MANAGEMENT;
39
40     public static File getIndexBaseLocation() {
41         return Activator.getDefault().getIndexBaseFile();
42 //      Activator activator = Activator.getDefault();
43 //        Bundle b = Platform.getBundle(Activator.BUNDLE_ID);
44 //        IPath state = Platform.getStateLocation(b);
45 //        File path = state.append("index").toFile();
46 //        return path;
47     }
48
49     public static File getIndexLocation(Session session, Resource relation, Resource input) {
50         if (session == null)
51             throw new NullPointerException("null session");
52         if (relation == null)
53             throw new NullPointerException("null relation");
54         if (input == null)
55             throw new NullPointerException("null input");
56
57         String dir = session.getService(ServerInformation.class).getDatabaseId()
58         + "." + relation.getResourceId()
59         + "." + input.getResourceId();
60
61         return new File(getIndexBaseLocation(), dir);
62     }
63
64     private static File getAllDirtyFile() {
65         return new File(getIndexBaseLocation(), ".dirty");
66     }
67
68     private static File getChangedFile(File indexPath) {
69         return new File(indexPath, ".changed");
70     }
71
72     public static void markAllDirty() throws IOException {
73         File indexBase = getIndexBaseLocation();
74         if (!indexBase.exists() || !indexBase.isDirectory())
75             return;
76         if (DEBUG)
77             System.out.println("Marking all indexes dirty");
78         getAllDirtyFile().createNewFile();
79     }
80
81     public static void clearAllDirty() throws IOException {
82         if (DEBUG)
83             System.out.println("Clearing dirty state of all indexes");
84
85         File indexBase = getIndexBaseLocation();
86         if (!indexBase.exists() || !indexBase.isDirectory())
87             return;
88         delete(getAllDirtyFile());
89
90         forEachIndexPath(new Procedure<File, IOException>() {
91             @Override
92             public void execute(File indexPath) throws IOException {
93                 delete(getChangedFile(indexPath));
94             }
95         });
96     }
97
98     /**
99      * Internal to indexing, invoked by {@link IndexedRelationsImpl} which
100      * doesn't want to throw these exceptions forward. Just log it.
101      * 
102      * @param indexPath
103      */
104     static void markIndexChanged(File indexPath) {
105         if (!indexPath.exists())
106             throw new IllegalArgumentException("index path " + indexPath + " does not exist");
107         if (!indexPath.isDirectory())
108             throw new IllegalArgumentException("index path " + indexPath + " is not a directory");
109         try {
110             if (DEBUG)
111                 System.out.println("Marking index dirty: " + indexPath);
112             getChangedFile(indexPath).createNewFile();
113         } catch (IOException e) {
114             Logger.defaultLogError(e);
115         }
116     }
117
118     public static void deleteAllIndexes() throws IOException {
119         File indexBase = DatabaseIndexing.getIndexBaseLocation();
120         delete(indexBase);
121     }
122
123     public static void deleteIndex(final Resource relation, final Resource modelPart) throws DatabaseException {
124
125         SimanticsInternal.getSession().syncRequest(new WriteRequest() {
126
127                         @Override
128                         public void perform(WriteGraph graph) throws DatabaseException {
129                                 deleteIndex(graph, relation, modelPart);
130                         }
131                 
132         });
133
134     }
135
136     public static void deleteIndex(WriteGraph graph, final Resource relation, final Resource modelPart) throws DatabaseException {
137         
138         Resource model = graph.syncRequest(new IndexRoot(modelPart));
139         GenericRelationIndex index = graph.adapt(relation, GenericRelationIndex.class);
140         IndexedRelations ir = graph.getService(IndexedRelations.class);
141         // Deletes index files
142         ir.reset(null, graph, relation, model);
143         // Notifies DB listeners
144         index.reset(graph, model);
145         
146     }
147     
148     public static void deleteIndex(File indexPath) throws IOException {
149         if (DEBUG)
150             System.out.println("Deleting index " + indexPath);
151         delete(indexPath);
152     }
153
154     public static void validateIndexes() throws IOException {
155         File indexBase = getIndexBaseLocation();
156         if (DEBUG)
157             System.out.println("Validating indexes at " + indexBase);
158         if (!indexBase.exists())
159             return;
160         if (!indexBase.isDirectory()) {
161             // Make sure that index-base is a valid directory
162             if (DEBUG)
163                 System.out.println(indexBase + " is not a directory! Removing it.");
164             delete(indexBase);
165             indexBase.mkdirs();
166             return;
167         }
168         File allDirtyFile = getAllDirtyFile();
169         if (allDirtyFile.isFile()) {
170             if (DEBUG)
171                 System.out.println("All indexes marked dirty, removing them.");
172             delete(allDirtyFile);
173             deleteAllIndexes();
174         } else {
175             forEachIndexPath(new Procedure<File, IOException>() {
176                 @Override
177                 public void execute(File indexPath) throws IOException {
178                     File changed = getChangedFile(indexPath);
179                     if (changed.isFile()) {
180                         if (DEBUG)
181                             System.out.println("Index is dirty, removing: " + indexPath);
182                         deleteIndex(indexPath);
183                     }
184                 }
185             });
186         }
187     }
188
189
190     private static void delete(File fileOrDir) throws IOException {
191         if (fileOrDir.exists())
192             FileUtils.deleteAll(fileOrDir);
193     }
194
195     interface Procedure<T, E extends Throwable> {
196         void execute(T t) throws E;
197     }
198
199     private static <E extends Throwable> void forEachIndexPath(Procedure<File, E> callback) throws E {
200         for (File indexPath : getIndexBaseLocation().listFiles(new FileFilter() {
201             @Override
202             public boolean accept(File pathname) {
203                 return pathname.isDirectory();
204             }
205         })) {
206             callback.execute(indexPath);
207         }
208     }
209
210 }