]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.db.indexing/src/org/simantics/db/indexing/IndexedRelationsSearcher.java
Migrated source code from Simantics SVN
[simantics/platform.git] / bundles / org.simantics.db.indexing / src / org / simantics / db / indexing / IndexedRelationsSearcher.java
1 /*******************************************************************************\r
2  * Copyright (c) 2007, 2010 Association for Decentralized Information Management\r
3  * in Industry THTH ry.\r
4  * All rights reserved. This program and the accompanying materials\r
5  * are made available under the terms of the Eclipse Public License v1.0\r
6  * which accompanies this distribution, and is available at\r
7  * http://www.eclipse.org/legal/epl-v10.html\r
8  *\r
9  * Contributors:\r
10  *     VTT Technical Research Centre of Finland - initial API and implementation\r
11  *******************************************************************************/\r
12 package org.simantics.db.indexing;\r
13 \r
14 import java.io.IOException;\r
15 import java.util.ArrayList;\r
16 import java.util.Collection;\r
17 import java.util.HashMap;\r
18 import java.util.List;\r
19 import java.util.Map;\r
20 \r
21 import org.apache.lucene.index.CorruptIndexException;\r
22 import org.apache.lucene.queryparser.classic.ParseException;\r
23 import org.eclipse.core.runtime.IProgressMonitor;\r
24 import org.simantics.db.RequestProcessor;\r
25 import org.simantics.db.Resource;\r
26 import org.simantics.db.Session;\r
27 import org.simantics.db.exception.DatabaseException;\r
28 import org.simantics.db.layer0.adapter.GenericRelation;\r
29 import org.simantics.utils.datastructures.Pair;\r
30 \r
31 /**\r
32  * @author Tuukka Lehtonen\r
33  * @author Antti Villberg\r
34  */\r
35 public class IndexedRelationsSearcher extends IndexedRelationsSearcherBase {\r
36     \r
37     IndexedRelationsMemorySearcher cache;\r
38 \r
39     IndexedRelationsSearcher(RequestProcessor session, Resource relation, Resource input, GenericRelation r) throws DatabaseException {\r
40         super(session, relation, input);\r
41         this.cache = new IndexedRelationsMemorySearcher(session, this, relation, input, r);\r
42     }\r
43 \r
44     @Override\r
45     String getDescriptor() {\r
46         return "DISK: ";\r
47     }\r
48 \r
49     @Override\r
50     public void setProblem(Throwable t) {\r
51         super.setProblem(t);\r
52         cache.setProblem(t);\r
53     }\r
54     \r
55     @Override\r
56     boolean startAccess(IProgressMonitor monitor, Session session, boolean forWriting) {\r
57         boolean success = super.startAccess(monitor, session, false);\r
58         if(!success) return false;\r
59         success = cache.startAccess(monitor, session, forWriting);\r
60         if(!success) {\r
61                 setProblem(cache.getException());\r
62                 return false;\r
63         } else return true;\r
64     }\r
65     \r
66     @Override\r
67     void insertIndex(IProgressMonitor monitor, GenericRelation r, int boundLength, Collection<Object[]> documentsData)\r
68             throws CorruptIndexException, IOException, DatabaseException {\r
69 \r
70         Collection<Object> keyValues = new ArrayList<Object>();\r
71         for(Object[] data : documentsData) {\r
72             keyValues.add(data[1]);\r
73         }\r
74         \r
75         cache.replaceIndex(monitor, "Resource", keyValues, r, boundLength, documentsData);\r
76         //cache.commit();\r
77         \r
78     }\r
79     \r
80     @Override\r
81     void removeIndex(IProgressMonitor monitor, GenericRelation r, RequestProcessor processor, String key, Collection<Object> keyValues) throws DatabaseException,CorruptIndexException, IOException {\r
82         \r
83         Collection<Object[]> documentsData = new ArrayList<Object[]>();\r
84 \r
85         Pair<String,String>[] fields = r.getFields(); \r
86 \r
87         for(Object keyValue : keyValues) {\r
88             Object[] data = new Object[fields.length-1];\r
89             int index = 0;\r
90             for(int i=1;i<fields.length;i++) {\r
91                 String fieldName = fields[i].first;\r
92                 if(key.equals(fieldName)) {\r
93                     data[index++] = keyValue;\r
94                 } else {\r
95                     String fieldClass = fields[i].second;\r
96                     if ("Long".equals(fieldClass)) {\r
97                         data[index++] = 0L;\r
98                     } else if ("String".equals(fieldClass) || "Text".equals(fieldClass)) {\r
99                         data[index++] = "";\r
100                     } else {\r
101                         throw new DatabaseException("Can only index Long and String fields, encountered class " + fieldClass);\r
102                     }\r
103                 }\r
104             }\r
105             documentsData.add(data);\r
106         }\r
107 \r
108         cache.replaceIndex(monitor, key, keyValues, r, 1, documentsData);\r
109 //        cache.commit();\r
110         \r
111     }\r
112     \r
113     @Override\r
114     boolean replaceIndex(IProgressMonitor monitor, String key, Collection<Object> keyValues, GenericRelation r,\r
115             int boundLength, Collection<Object[]> documentsData) throws CorruptIndexException, IOException,\r
116             DatabaseException {\r
117 \r
118         boolean result = cache.replaceIndex(monitor, key, keyValues, r, boundLength, documentsData);\r
119 //        cache.commit();\r
120         return result; \r
121         \r
122     }\r
123     \r
124     List<Map<String, Object>> persistentCachedSearch(IProgressMonitor monitor, RequestProcessor processor, String search,\r
125             int maxResultCount) throws ParseException, IOException, DatabaseException {\r
126         \r
127         MemoryIndexing mem = MemoryIndexing.getInstance(session.getSession());\r
128         \r
129         String key = indexPath.getAbsolutePath();\r
130         \r
131         Map<String,List<Map<String, Object>>> cache = mem.persistentCache.get(key);\r
132         if(cache != null) {\r
133             List<Map<String,Object>> result = cache.get(search);\r
134             if(result != null) return result;\r
135         }\r
136 \r
137         startAccess(monitor, processor.getSession(), false);\r
138 \r
139         List<Map<String, Object>> results = super.doSearch(monitor, processor, search, maxResultCount);\r
140         if(cache == null) {\r
141             cache = new HashMap<String,List<Map<String,Object>>>();\r
142             mem.persistentCache.put(key, cache);\r
143         }\r
144 \r
145         if(results.size() < 500)\r
146             cache.put(search, results);\r
147         \r
148         return results;\r
149         \r
150     }\r
151 \r
152     List<Resource> persistentCachedSearchResources(IProgressMonitor monitor, RequestProcessor processor, String search,\r
153             int maxResultCount) throws ParseException, IOException, DatabaseException {\r
154         \r
155         MemoryIndexing mem = MemoryIndexing.getInstance(session.getSession());\r
156         \r
157         String key = indexPath.getAbsolutePath();\r
158         \r
159         Map<String,List<Resource>> cache = mem.persistentCacheResources.get(key);\r
160         if(cache != null) {\r
161             List<Resource> result = cache.get(search);\r
162             if(result != null) return result;\r
163         }\r
164 \r
165         startAccess(monitor, processor.getSession(), false);\r
166 \r
167         List<Resource> results = super.doSearchResources(monitor, processor, search, maxResultCount);\r
168         if(cache == null) {\r
169             cache = new HashMap<String,List<Resource>>();\r
170             mem.persistentCacheResources.put(key, cache);\r
171         }\r
172 \r
173         if(results.size() < 500)\r
174             cache.put(search, results);\r
175         \r
176         return results;\r
177         \r
178     }\r
179     \r
180     List<Object> persistentCachedList(IProgressMonitor monitor, RequestProcessor processor) throws ParseException, IOException, DatabaseException {\r
181         \r
182         startAccess(monitor, processor.getSession(), false);\r
183 \r
184         List<Object> results = super.doList(monitor, processor);\r
185         \r
186         return results;\r
187         \r
188     }\r
189     \r
190     @Override\r
191     List<Map<String, Object>> doSearch(IProgressMonitor monitor, RequestProcessor processor, String search,\r
192             int maxResultCount) throws ParseException, IOException, DatabaseException {\r
193         \r
194         List<Map<String,Object>> persistent = persistentCachedSearch(monitor, processor, search, maxResultCount);\r
195         List<Map<String,Object>> cached = cache.doSearch(monitor, processor, search, maxResultCount);\r
196 \r
197         ArrayList<Map<String,Object>> result = new ArrayList<Map<String,Object>>();\r
198 \r
199         for(Map<String,Object> m : persistent) {\r
200             Resource r = (Resource)m.get("Resource");\r
201             if(!cache.changed.contains(r.getResourceId())) {\r
202                 result.add(m);\r
203             }\r
204         }\r
205         result.addAll(cached);\r
206         return result;\r
207         \r
208     }\r
209     \r
210     @Override\r
211     List<Resource> doSearchResources(IProgressMonitor monitor, RequestProcessor processor, String search,\r
212                 int maxResultCount) throws ParseException, IOException, DatabaseException {\r
213 \r
214         List<Resource> persistent = persistentCachedSearchResources(monitor, processor, search, maxResultCount);\r
215         List<Resource> cached = cache.doSearchResources(monitor, processor, search, maxResultCount);\r
216 \r
217         ArrayList<Resource> result = new ArrayList<Resource>();\r
218         for(Resource r : persistent) {\r
219             if(!cache.changed.contains(r.getResourceId())) {\r
220                 result.add(r);\r
221             }\r
222         }\r
223         result.addAll(cached);\r
224         return result;\r
225         \r
226     }\r
227     \r
228     List<Object> doList(IProgressMonitor monitor, RequestProcessor processor) throws ParseException, IOException, DatabaseException {\r
229 \r
230         List<Object> persistent = persistentCachedList(monitor, processor);\r
231         \r
232         // TODO: check that caches have been properly flushed\r
233         //List<Object> cached = cache.doList(monitor, processor);\r
234         //if(!cached.isEmpty()) throw new DatabaseException("doList does not support caching");\r
235 \r
236         return persistent;\r
237         \r
238     }\r
239 \r
240     void applyChanges(IProgressMonitor monitor, Session session, GenericRelation r, Collection<Object[]> os) throws Exception {\r
241         \r
242         if(!os.isEmpty()) {\r
243         \r
244                 ArrayList<Object> replaceKeys = new ArrayList<Object>();\r
245                 ArrayList<Object[]> replaceValues = new ArrayList<Object[]>();\r
246                 ArrayList<Object> removeKeys = new ArrayList<Object>();\r
247                 for(Object[] o : os) {\r
248                     Long parent = (Long)o[0];\r
249                     Long key = (Long)o[1];\r
250                     if(parent != 0) {\r
251                         replaceKeys.add(key);\r
252                         replaceValues.add(o);\r
253                     } else {\r
254                         removeKeys.add(key);\r
255                     }\r
256                 }\r
257                 \r
258                 changeState(monitor, session, State.READY);\r
259                 \r
260                 super.startAccess(null, session, true);\r
261                 \r
262                 super.replaceIndex(null, "Resource", replaceKeys, r, 1, replaceValues);\r
263                 super.removeIndex(null, r, null, "Resource", removeKeys);\r
264                 \r
265         }\r
266         \r
267         changeState(monitor, session, State.READY);\r
268         \r
269     }\r
270     \r
271     @Override\r
272     Throwable bestEffortClear(IProgressMonitor monitor, Session session) {\r
273 \r
274         // Free the index\r
275         changeState(monitor, session, State.NONE);\r
276         \r
277         Throwable t = clearDirectory(monitor, session);\r
278         if(t != null) return t;\r
279 \r
280         t = cache.bestEffortClear(monitor, session);\r
281         if(t != null) return t;\r
282         \r
283         String key = indexPath.getAbsolutePath();\r
284         MemoryIndexing mem = MemoryIndexing.getInstance(session);\r
285         mem.persistentCache.remove(key);\r
286         mem.persistentCacheResources.remove(key);\r
287         \r
288         return null;\r
289         \r
290     }\r
291     \r
292 }\r