Mercurial Hosting > luan
comparison src/luan/modules/lucene/LuceneIndex.java @ 1267:9fa8b8389578
add LuanTable.luan;
support metatable __gc();
add luan.sql;
author | Franklin Schmidt <fschmidt@gmail.com> |
---|---|
date | Mon, 12 Nov 2018 02:10:41 -0700 |
parents | 475905984870 |
children | 48f302bdc187 |
comparison
equal
deleted
inserted
replaced
1266:05934fbf635a | 1267:9fa8b8389578 |
---|---|
92 private DirectoryReader reader; | 92 private DirectoryReader reader; |
93 private IndexSearcher searcher; | 93 private IndexSearcher searcher; |
94 private final ThreadLocal<IndexSearcher> threadLocalSearcher = new ThreadLocal<IndexSearcher>(); | 94 private final ThreadLocal<IndexSearcher> threadLocalSearcher = new ThreadLocal<IndexSearcher>(); |
95 private boolean isClosed = true; | 95 private boolean isClosed = true; |
96 private final MultiFieldParser mfp; | 96 private final MultiFieldParser mfp; |
97 public final LuanTable indexed_only_fields = new LuanTable(); | 97 public final LuanTable indexed_only_fields; |
98 private final Analyzer analyzer; | 98 private final Analyzer analyzer; |
99 private final Exception created = new Exception("created"); | 99 private final Exception created = new Exception("created"); |
100 | 100 |
101 private static ConcurrentMap<File,AtomicInteger> globalWriteCounters = new ConcurrentHashMap<File,AtomicInteger>(); | 101 private static ConcurrentMap<File,AtomicInteger> globalWriteCounters = new ConcurrentHashMap<File,AtomicInteger>(); |
102 private File fileDir; | 102 private File fileDir; |
103 private int writeCount; | 103 private int writeCount; |
104 | 104 |
105 public LuceneIndex(LuanState luan,String indexDirStr,FieldParser defaultFieldParser,String[] defaultFields) throws LuanException, IOException { | 105 public LuceneIndex(LuanState luan,String indexDirStr,FieldParser defaultFieldParser,String[] defaultFields) |
106 throws LuanException, IOException | |
107 { | |
108 indexed_only_fields = new LuanTable(luan); // not good, not thread safe | |
106 mfp = defaultFieldParser==null ? new MultiFieldParser() : new MultiFieldParser(defaultFieldParser,defaultFields); | 109 mfp = defaultFieldParser==null ? new MultiFieldParser() : new MultiFieldParser(defaultFieldParser,defaultFields); |
107 mfp.fields.put( "type", STRING_FIELD_PARSER ); | 110 mfp.fields.put( "type", STRING_FIELD_PARSER ); |
108 mfp.fields.put( "id", NumberFieldParser.LONG ); | 111 mfp.fields.put( "id", NumberFieldParser.LONG ); |
109 File indexDir = new File(indexDirStr); | 112 File indexDir = new File(indexDirStr); |
110 this.indexDir = indexDir; | 113 this.indexDir = indexDir; |
175 } | 178 } |
176 } | 179 } |
177 | 180 |
178 public void save(LuanState luan,LuanTable doc) throws LuanException, IOException { | 181 public void save(LuanState luan,LuanTable doc) throws LuanException, IOException { |
179 Set indexedOnlySet = new HashSet(); | 182 Set indexedOnlySet = new HashSet(); |
180 Object typeObj = doc.get(luan,"type"); | 183 Object typeObj = doc.get("type"); |
181 if( typeObj==null ) | 184 if( typeObj==null ) |
182 throw new LuanException("missing 'type' field"); | 185 throw new LuanException("missing 'type' field"); |
183 if( !(typeObj instanceof String) ) | 186 if( !(typeObj instanceof String) ) |
184 throw new LuanException("type must be string"); | 187 throw new LuanException("type must be string"); |
185 String type = (String)typeObj; | 188 String type = (String)typeObj; |
186 Object indexedOnlyObj = indexed_only_fields.get(luan,type); | 189 Object indexedOnlyObj = indexed_only_fields.get(type); |
187 if( indexedOnlyObj != null ) { | 190 if( indexedOnlyObj != null ) { |
188 if( !(indexedOnlyObj instanceof LuanTable) ) | 191 if( !(indexedOnlyObj instanceof LuanTable) ) |
189 throw new LuanException("indexed_only_fields elements must be tables"); | 192 throw new LuanException("indexed_only_fields elements must be tables"); |
190 LuanTable indexedOnly = (LuanTable)indexedOnlyObj; | 193 LuanTable indexedOnly = (LuanTable)indexedOnlyObj; |
191 for( Map.Entry<Object,Object> entry : indexedOnly.iterable(luan) ) { | 194 for( Map.Entry<Object,Object> entry : indexedOnly.iterable() ) { |
192 Object key = entry.getKey(); | 195 Object key = entry.getKey(); |
193 if( !(key instanceof String) ) | 196 if( !(key instanceof String) ) |
194 throw new LuanException("indexed_only_fields."+type+" entries must be strings"); | 197 throw new LuanException("indexed_only_fields."+type+" entries must be strings"); |
195 String name = (String)key; | 198 String name = (String)key; |
196 Object value = entry.getValue(); | 199 Object value = entry.getValue(); |
197 if( !(value instanceof LuanFunction) ) | 200 if( !(value instanceof LuanFunction) ) |
198 throw new LuanException("indexed_only_fields."+type+" values must be functions"); | 201 throw new LuanException("indexed_only_fields."+type+" values must be functions"); |
199 LuanFunction fn = (LuanFunction)value; | 202 LuanFunction fn = (LuanFunction)value; |
200 value = Luan.first(fn.call(luan,new Object[]{doc})); | 203 value = Luan.first(fn.call(luan,new Object[]{doc})); |
201 doc.put(luan, name, value ); | 204 doc.put( name, value ); |
202 indexedOnlySet.add(name); | 205 indexedOnlySet.add(name); |
203 } | 206 } |
204 } | 207 } |
205 Object obj = doc.get(luan,"id"); | 208 Object obj = doc.get("id"); |
206 Long id; | 209 Long id; |
207 try { | 210 try { |
208 id = (Long)obj; | 211 id = (Long)obj; |
209 } catch(ClassCastException e) { | 212 } catch(ClassCastException e) { |
210 throw new LuanException("id should be Long but is "+obj.getClass().getSimpleName()); | 213 throw new LuanException("id should be Long but is "+obj.getClass().getSimpleName()); |
213 boolean commit = !writeLock.isHeldByCurrentThread(); | 216 boolean commit = !writeLock.isHeldByCurrentThread(); |
214 writeLock.lock(); | 217 writeLock.lock(); |
215 try { | 218 try { |
216 if( id == null ) { | 219 if( id == null ) { |
217 id = nextId(luan); | 220 id = nextId(luan); |
218 doc.put(luan,"id",id); | 221 doc.put("id",id); |
219 writer.addDocument(toLucene(luan,doc,indexedOnlySet)); | 222 writer.addDocument(toLucene(doc,indexedOnlySet)); |
220 } else { | 223 } else { |
221 writer.updateDocument( term("id",id), toLucene(luan,doc,indexedOnlySet) ); | 224 writer.updateDocument( term("id",id), toLucene(doc,indexedOnlySet) ); |
222 } | 225 } |
223 if(commit) writer.commit(); | 226 if(commit) writer.commit(); |
224 } finally { | 227 } finally { |
225 wrote(); | 228 wrote(); |
226 writeLock.unlock(); | 229 writeLock.unlock(); |
275 } | 278 } |
276 | 279 |
277 public synchronized long nextId(LuanState luan) throws LuanException, IOException { | 280 public synchronized long nextId(LuanState luan) throws LuanException, IOException { |
278 if( ++id > idLim ) { | 281 if( ++id > idLim ) { |
279 idLim += idBatch; | 282 idLim += idBatch; |
280 LuanTable doc = new LuanTable(); | 283 LuanTable doc = new LuanTable(luan); |
281 doc.rawPut( "type", "next_id" ); | 284 doc.rawPut( "type", "next_id" ); |
282 doc.rawPut( FLD_NEXT_ID, idLim ); | 285 doc.rawPut( FLD_NEXT_ID, idLim ); |
283 writer.updateDocument(new Term("type","next_id"),toLucene(luan,doc,Collections.EMPTY_SET)); | 286 writer.updateDocument(new Term("type","next_id"),toLucene(doc,Collections.EMPTY_SET)); |
284 wrote(); | 287 wrote(); |
285 } | 288 } |
286 return id; | 289 return id; |
287 } | 290 } |
288 | 291 |
312 | 315 |
313 public Object snapshot(LuanState luan,LuanFunction fn) throws LuanException, IOException { | 316 public Object snapshot(LuanState luan,LuanFunction fn) throws LuanException, IOException { |
314 IndexCommit ic = snapshotDeletionPolicy.snapshot(); | 317 IndexCommit ic = snapshotDeletionPolicy.snapshot(); |
315 try { | 318 try { |
316 String dir = fileDir.toString(); | 319 String dir = fileDir.toString(); |
317 LuanTable fileNames = new LuanTable(new ArrayList(ic.getFileNames())); | 320 LuanTable fileNames = new LuanTable(luan,new ArrayList(ic.getFileNames())); |
318 return fn.call(luan,new Object[]{dir,fileNames}); | 321 return fn.call(luan,new Object[]{dir,fileNames}); |
319 } finally { | 322 } finally { |
320 snapshotDeletionPolicy.release(ic); | 323 snapshotDeletionPolicy.release(ic); |
321 } | 324 } |
322 } | 325 } |
353 this.searcher = searcher; | 356 this.searcher = searcher; |
354 } | 357 } |
355 | 358 |
356 @Override public Object call(LuanState luan,Object[] args) throws LuanException { | 359 @Override public Object call(LuanState luan,Object[] args) throws LuanException { |
357 try { | 360 try { |
358 return toTable(searcher.doc(docID)); | 361 return toTable(luan,searcher.doc(docID)); |
359 } catch(IOException e) { | 362 } catch(IOException e) { |
360 throw new LuanException(e); | 363 throw new LuanException(e); |
361 } | 364 } |
362 } | 365 } |
363 } | 366 } |
516 return new StoredField(name, b); | 519 return new StoredField(name, b); |
517 } else | 520 } else |
518 throw new LuanException("invalid value type "+value.getClass()+"' for '"+name+"'"); | 521 throw new LuanException("invalid value type "+value.getClass()+"' for '"+name+"'"); |
519 } | 522 } |
520 | 523 |
521 private Document toLucene(LuanState luan,LuanTable table,Set indexOnly) throws LuanException { | 524 private Document toLucene(LuanTable table,Set indexOnly) throws LuanException { |
522 Set<String> indexed = mfp.fields.keySet(); | 525 Set<String> indexed = mfp.fields.keySet(); |
523 Document doc = new Document(); | 526 Document doc = new Document(); |
524 for( Map.Entry<Object,Object> entry : table.iterable(luan) ) { | 527 for( Map.Entry<Object,Object> entry : table.iterable() ) { |
525 Object key = entry.getKey(); | 528 Object key = entry.getKey(); |
526 if( !(key instanceof String) ) | 529 if( !(key instanceof String) ) |
527 throw new LuanException("key must be string"); | 530 throw new LuanException("key must be string"); |
528 String name = (String)key; | 531 String name = (String)key; |
529 Object value = entry.getValue(); | 532 Object value = entry.getValue(); |
551 if( s != null ) | 554 if( s != null ) |
552 return s; | 555 return s; |
553 throw new LuanException("invalid field type for "+ifld); | 556 throw new LuanException("invalid field type for "+ifld); |
554 } | 557 } |
555 | 558 |
556 private static LuanTable toTable(Document doc) throws LuanException { | 559 private static LuanTable toTable(LuanState luan,Document doc) throws LuanException { |
557 if( doc==null ) | 560 if( doc==null ) |
558 return null; | 561 return null; |
559 LuanTable table = new LuanTable(); | 562 LuanTable table = new LuanTable(luan); |
560 for( IndexableField ifld : doc ) { | 563 for( IndexableField ifld : doc ) { |
561 String name = ifld.name(); | 564 String name = ifld.name(); |
562 Object value = getValue(ifld); | 565 Object value = getValue(ifld); |
563 Object old = table.rawGet(name); | 566 Object old = table.rawGet(name); |
564 if( old == null ) { | 567 if( old == null ) { |
566 } else { | 569 } else { |
567 LuanTable list; | 570 LuanTable list; |
568 if( old instanceof LuanTable ) { | 571 if( old instanceof LuanTable ) { |
569 list = (LuanTable)old; | 572 list = (LuanTable)old; |
570 } else { | 573 } else { |
571 list = new LuanTable(); | 574 list = new LuanTable(luan); |
572 list.rawPut(1,old); | 575 list.rawPut(1,old); |
573 table.rawPut(name,list); | 576 table.rawPut(name,list); |
574 } | 577 } |
575 list.rawPut(list.rawLength()+1,value); | 578 list.rawPut(list.rawLength()+1,value); |
576 } | 579 } |