|
1 /*------------------------------------------------------------------------------ |
|
2 * Copyright (C) 2003-2006 Ben van Klinken and the CLucene Team |
|
3 * |
|
4 * Distributable under the terms of either the Apache License (Version 2.0) or |
|
5 * the GNU Lesser General Public License, as specified in the COPYING file. |
|
6 ------------------------------------------------------------------------------*/ |
|
7 #include "clucene/stdheader.h" |
|
8 #include "IndexReader.h" |
|
9 #include "IndexWriter.h" |
|
10 |
|
11 #include "clucene/store/directory.h" |
|
12 #include "CLucene/store/FSDirectory.h" |
|
13 #include "CLucene/store/Lock.h" |
|
14 #include "clucene/document/document.h" |
|
15 #include "clucene/search/similarity.h" |
|
16 #include "SegmentInfos.h" |
|
17 #include "MultiReader.h" |
|
18 #include "Terms.h" |
|
19 |
|
20 CL_NS_USE(util) |
|
21 CL_NS_USE(store) |
|
22 CL_NS_DEF(index) |
|
23 |
|
24 IndexReader::IndexReader(Directory* dir): |
|
25 directory(_CL_POINTER(dir)){ |
|
26 //Constructor. |
|
27 //Func - Creates an instance of IndexReader |
|
28 //Pre - true |
|
29 //Post - An instance has been created with writeLock = NULL |
|
30 |
|
31 writeLock = NULL; |
|
32 segmentInfos = NULL; |
|
33 directoryOwner = false; |
|
34 closeDirectory = false; |
|
35 stale = false; |
|
36 hasChanges = false; |
|
37 } |
|
38 |
|
39 IndexReader::IndexReader(Directory* directory, SegmentInfos* segmentInfos, bool closeDirectory) { |
|
40 this->directory = _CL_POINTER(directory); |
|
41 this->segmentInfos = segmentInfos; |
|
42 directoryOwner = true; |
|
43 this->closeDirectory = closeDirectory; |
|
44 stale = false; |
|
45 hasChanges = false; |
|
46 writeLock = NULL; |
|
47 } |
|
48 |
|
49 IndexReader::~IndexReader(){ |
|
50 //Func - Destructor |
|
51 // Destroys the instance and releases the writeLock if needed |
|
52 //Pre - true |
|
53 //Post - The instance has been destroyed if pre(writeLock) exists is has been released |
|
54 if (writeLock != NULL) { |
|
55 //release writeLock |
|
56 writeLock->release(); |
|
57 _CLDELETE(writeLock); |
|
58 } |
|
59 _CLDELETE(segmentInfos); |
|
60 _CLDECDELETE(directory); |
|
61 } |
|
62 |
|
63 IndexReader* IndexReader::open(const char* path){ |
|
64 //Func - Static method. |
|
65 // Returns an IndexReader reading the index in an FSDirectory in the named path. |
|
66 //Pre - path != NULL and contains the path of the index for which an IndexReader must be |
|
67 // instantiated |
|
68 // closeDir indicates if the directory needs to be closed |
|
69 //Post - An IndexReader has been returned that reads tnhe index located at path |
|
70 |
|
71 CND_PRECONDITION(path != NULL, "path is NULL"); |
|
72 |
|
73 Directory* dir = FSDirectory::getDirectory(path,false); |
|
74 IndexReader* reader = open(dir,true); |
|
75 //because fsdirectory will now have a refcount of 1 more than |
|
76 //if the reader had been opened with a directory object, |
|
77 //we need to do a refdec |
|
78 _CLDECDELETE(dir); |
|
79 return reader; |
|
80 } |
|
81 |
|
82 IndexReader* IndexReader::open( Directory* directory, bool closeDirectory){ |
|
83 //Func - Static method. |
|
84 // Returns an IndexReader reading the index in an FSDirectory in the named path. |
|
85 //Pre - directory represents a directory |
|
86 // closeDir indicates if the directory needs to be closed |
|
87 //Post - An IndexReader has been returned that reads the index located at directory |
|
88 |
|
89 // in- & inter-process sync |
|
90 // CPIXASYNC SCOPED_LOCK_MUTEX(directory->THIS_LOCK) |
|
91 SCOPED_LOCK_CRUCIAL_MUTEX(directory->Directory_THIS_LOCK) |
|
92 |
|
93 IndexReader* ret = NULL; |
|
94 |
|
95 LuceneLock* lock = directory->makeLock("commit.lock"); |
|
96 |
|
97 //Instantiate an IndexReader::LockWith which can produce an IndexReader |
|
98 IndexReader::LockWith with(lock,directory); |
|
99 |
|
100 try{ |
|
101 //Create an IndexReader reading the index |
|
102 ret = with.runAndReturn(); |
|
103 }_CLFINALLY( |
|
104 _CLDELETE( lock ); |
|
105 ); |
|
106 |
|
107 ret->closeDirectory = closeDirectory; |
|
108 |
|
109 CND_CONDITION(ret != NULL,"ret is NULL"); |
|
110 //return reference |
|
111 return ret; |
|
112 } |
|
113 |
|
114 CL_NS(document)::Document* IndexReader::document(const int32_t n){ |
|
115 CL_NS(document)::Document* ret = _CLNEW CL_NS(document)::Document; |
|
116 if (!document(n,ret) ) |
|
117 _CLDELETE(ret); |
|
118 return ret; |
|
119 } |
|
120 |
|
121 IndexReader* IndexReader::LockWith::doBody() { |
|
122 //Func - Reads the segmentinfo file and depending on the number of segments found |
|
123 // it returns a SegmentsReader or a SegmentReader |
|
124 //Pre - directory != NULL |
|
125 //Post - Depending on the number of Segments present in directory this method |
|
126 // returns an empty SegmentsReader when there are no segments, a SegmentReader when |
|
127 // directory contains 1 segment and a nonempty SegmentsReader when directory |
|
128 // contains multiple segements |
|
129 |
|
130 CND_PRECONDITION(directory != NULL, "directory is NULL"); |
|
131 |
|
132 //Instantiate SegmentInfos |
|
133 SegmentInfos* infos = _CLNEW SegmentInfos; |
|
134 try{ |
|
135 //Have SegmentInfos read the segments file in directory |
|
136 infos->read(directory); |
|
137 }catch(...){ |
|
138 //make sure infos is cleaned up |
|
139 _CLDELETE(infos); |
|
140 throw; |
|
141 } |
|
142 |
|
143 // If there is at least one segment (if infos.size() >= 1), the last |
|
144 // SegmentReader object will close the directory when the SegmentReader |
|
145 // object itself is closed (see SegmentReader::doClose). |
|
146 // If there are no segments, there will be no "last SegmentReader object" |
|
147 // to fulfill this responsibility, so we need to explicitly close the |
|
148 // directory in the segmentsreader.close |
|
149 |
|
150 //Count the number segments in the directory |
|
151 const uint32_t nSegs = infos->size(); |
|
152 |
|
153 if (nSegs == 1 ) { |
|
154 // index is optimized |
|
155 return _CLNEW SegmentReader(infos, infos->info(0)); |
|
156 }else{ |
|
157 //Instantiate an array of pointers to SegmentReaders of size nSegs (The number of segments in the index) |
|
158 IndexReader** readers = NULL; |
|
159 |
|
160 if (nSegs > 0){ |
|
161 uint32_t infosize=infos->size(); |
|
162 readers = _CL_NEWARRAY(IndexReader*,infosize+1); |
|
163 for (uint32_t i = 0; i < infosize; ++i) { |
|
164 //Instantiate a SegementReader responsible for reading the i-th segment and store it in |
|
165 //the readers array |
|
166 readers[i] = _CLNEW SegmentReader(infos->info(i)); |
|
167 } |
|
168 readers[infosize] = NULL; |
|
169 } |
|
170 |
|
171 //return an instance of SegmentsReader which is a reader that manages all Segments |
|
172 return _CLNEW MultiReader(directory, infos, readers); |
|
173 }// end if |
|
174 } |
|
175 |
|
176 uint64_t IndexReader::lastModified(const char* directory) { |
|
177 //Func - Static method |
|
178 // Returns the time the index in the named directory was last modified. |
|
179 //Pre - directory != NULL and contains the path name of the directory to check |
|
180 //Post - The last modified time of the index has been returned |
|
181 |
|
182 CND_PRECONDITION(directory != NULL, "directory is NULL"); |
|
183 |
|
184 return FSDirectory::fileModified(directory,"segments"); |
|
185 } |
|
186 |
|
187 int64_t IndexReader::getCurrentVersion(Directory* directory) { |
|
188 // CPIXASYNC SCOPED_LOCK_MUTEX(directory->THIS_LOCK) // in- & inter-process sync |
|
189 SCOPED_LOCK_CRUCIAL_MUTEX(directory->Directory_THIS_LOCK) // in- & inter-process sync |
|
190 LuceneLock* commitLock=directory->makeLock(IndexWriter::COMMIT_LOCK_NAME); |
|
191 bool locked=false; |
|
192 int64_t ret = 0; |
|
193 try { |
|
194 locked=commitLock->obtain(IndexWriter::COMMIT_LOCK_TIMEOUT); |
|
195 ret = SegmentInfos::readCurrentVersion(directory); |
|
196 }_CLFINALLY( |
|
197 if (locked) { |
|
198 commitLock->release(); |
|
199 } |
|
200 _CLDELETE(commitLock); |
|
201 ) |
|
202 return ret; |
|
203 } |
|
204 |
|
205 |
|
206 int64_t IndexReader::getCurrentVersion(const char* directory){ |
|
207 Directory* dir = FSDirectory::getDirectory(directory, false); |
|
208 int64_t version = getCurrentVersion(dir); |
|
209 dir->close(); |
|
210 _CLDECDELETE(dir); |
|
211 return version; |
|
212 } |
|
213 int64_t IndexReader::getVersion() { |
|
214 return segmentInfos->getVersion(); |
|
215 } |
|
216 |
|
217 bool IndexReader::isCurrent() { |
|
218 // CPIXASYNC SCOPED_LOCK_MUTEX(directory->THIS_LOCK) // in- & inter-process sync |
|
219 SCOPED_LOCK_CRUCIAL_MUTEX(directory->Directory_THIS_LOCK) // in- & inter-process sync |
|
220 LuceneLock* commitLock = directory->makeLock(IndexWriter::COMMIT_LOCK_NAME); |
|
221 bool locked=false; |
|
222 bool ret = false; |
|
223 try { |
|
224 locked=commitLock->obtain(IndexWriter::COMMIT_LOCK_TIMEOUT); |
|
225 ret = SegmentInfos::readCurrentVersion(directory) == segmentInfos->getVersion(); |
|
226 } _CLFINALLY( |
|
227 if (locked) { |
|
228 commitLock->release(); |
|
229 } |
|
230 ) |
|
231 return ret; |
|
232 } |
|
233 |
|
234 uint64_t IndexReader::lastModified(const Directory* directory) { |
|
235 //Func - Static method |
|
236 // Returns the time the index in this directory was last modified. |
|
237 //Pre - directory contains a valid reference |
|
238 //Post - The last modified time of the index has been returned |
|
239 |
|
240 return directory->fileModified("segments"); |
|
241 } |
|
242 |
|
243 |
|
244 bool IndexReader::indexExists(const char* directory){ |
|
245 //Func - Static method |
|
246 // Checks if an index exists in the named directory |
|
247 //Pre - directory != NULL |
|
248 //Post - Returns true if an index exists at the specified directory-> |
|
249 // If the directory does not exist or if there is no index in it. |
|
250 // false is returned. |
|
251 |
|
252 CND_PRECONDITION(directory != NULL, "directory is NULL"); |
|
253 |
|
254 //Create a buffer of length CL_MAXDIR |
|
255 char f[CL_MAX_PATH]; |
|
256 //Copy the directory string to the buffer. leave room for /segments |
|
257 strncpy(f,directory,CL_MAX_PATH-10); |
|
258 //Cat the name of the segments to buffer |
|
259 strcat(f, "/segments"); |
|
260 //Check if the segments file exists |
|
261 return Misc::dir_Exists(f); |
|
262 } |
|
263 |
|
264 |
|
265 void IndexReader::setNorm(int32_t doc, const TCHAR* field, uint8_t value){ |
|
266 // CPIXASYNC SCOPED_LOCK_MUTEX(THIS_LOCK) |
|
267 SCOPED_LOCK_CRUCIAL_MUTEX(IndexReader_THIS_LOCK) |
|
268 if(directoryOwner) |
|
269 aquireWriteLock(); |
|
270 doSetNorm(doc, field, value); |
|
271 hasChanges = true; |
|
272 } |
|
273 |
|
274 void IndexReader::aquireWriteLock() { |
|
275 if (stale) |
|
276 _CLTHROWA(CL_ERR_IO,"IndexReader out of date and no longer valid for delete, undelete, or setNorm operations"); |
|
277 |
|
278 if (writeLock == NULL) { |
|
279 LuceneLock* writeLock = directory->makeLock("write.lock"); |
|
280 if (!writeLock->obtain(IndexWriter::WRITE_LOCK_TIMEOUT)) // obtain write lock |
|
281 _CLTHROWA(CL_ERR_IO,"Index locked for write"); // + writeLock |
|
282 this->writeLock = writeLock; |
|
283 |
|
284 // we have to check whether index has changed since this reader was opened. |
|
285 // if so, this reader is no longer valid for deletion |
|
286 if (SegmentInfos::readCurrentVersion(directory) > segmentInfos->getVersion()) { |
|
287 stale = true; |
|
288 this->writeLock->release(); |
|
289 _CLDELETE(this->writeLock); |
|
290 _CLTHROWA(CL_ERR_IO,"IndexReader out of date and no longer valid for delete, undelete, or setNorm operations"); |
|
291 } |
|
292 } |
|
293 } |
|
294 |
|
295 |
|
296 void IndexReader::setNorm(int32_t doc, const TCHAR* field, float_t value){ |
|
297 setNorm(doc, field, CL_NS(search)::Similarity::encodeNorm(value)); |
|
298 } |
|
299 |
|
300 bool IndexReader::indexExists(const Directory* directory){ |
|
301 //Func - Static method |
|
302 // Checks if an index exists in the directory |
|
303 //Pre - directory is a valid reference |
|
304 //Post - Returns true if an index exists at the specified directory-> |
|
305 // If the directory does not exist or if there is no index in it. |
|
306 // false is returned. |
|
307 |
|
308 return directory->fileExists("segments"); |
|
309 } |
|
310 |
|
311 TermDocs* IndexReader::termDocs(Term* term) const { |
|
312 //Func - Returns an enumeration of all the documents which contain |
|
313 // term. For each document, the document number, the frequency of |
|
314 // the term in that document is also provided, for use in search scoring. |
|
315 // Thus, this method implements the mapping: |
|
316 // |
|
317 // Term => <docNum, freq>* |
|
318 // The enumeration is ordered by document number. Each document number |
|
319 // is greater than all that precede it in the enumeration. |
|
320 //Pre - term != NULL |
|
321 //Post - A reference to TermDocs containing an enumeration of all found documents |
|
322 // has been returned |
|
323 |
|
324 CND_PRECONDITION(term != NULL, "term is NULL"); |
|
325 |
|
326 //Reference an instantiated TermDocs instance |
|
327 TermDocs* _termDocs = termDocs(); |
|
328 //Seek all documents containing term |
|
329 _termDocs->seek(term); |
|
330 //return the enumaration |
|
331 return _termDocs; |
|
332 } |
|
333 |
|
334 TermPositions* IndexReader::termPositions(Term* term) const{ |
|
335 //Func - Returns an enumeration of all the documents which contain term. For each |
|
336 // document, in addition to the document number and frequency of the term in |
|
337 // that document, a list of all of the ordinal positions of the term in the document |
|
338 // is available. Thus, this method implements the mapping: |
|
339 // |
|
340 // Term => <docNum, freq,<pos 1, pos 2, ...pos freq-1>>* |
|
341 // |
|
342 // This positional information faciliates phrase and proximity searching. |
|
343 // The enumeration is ordered by document number. Each document number is greater than |
|
344 // all that precede it in the enumeration. |
|
345 //Pre - term != NULL |
|
346 //Post - A reference to TermPositions containing an enumeration of all found documents |
|
347 // has been returned |
|
348 |
|
349 CND_PRECONDITION(term != NULL, "term is NULL"); |
|
350 |
|
351 //Reference an instantiated termPositions instance |
|
352 TermPositions* _termPositions = termPositions(); |
|
353 //Seek all documents containing term |
|
354 _termPositions->seek(term); |
|
355 //return the enumeration |
|
356 return _termPositions; |
|
357 } |
|
358 |
|
359 void IndexReader::deleteDocument(const int32_t docNum) { |
|
360 //Func - Deletes the document numbered docNum. Once a document is deleted it will not appear |
|
361 // in TermDocs or TermPostitions enumerations. Attempts to read its field with the document |
|
362 // method will result in an error. The presence of this document may still be reflected in |
|
363 // the docFreq statistic, though this will be corrected eventually as the index is further modified. |
|
364 //Pre - docNum >= 0 |
|
365 //Post - If successful the document identified by docNum has been deleted. If no writelock |
|
366 // could be obtained an exception has been thrown stating that the index was locked or has no write access |
|
367 |
|
368 // CPIXASYNC SCOPED_LOCK_MUTEX(THIS_LOCK) |
|
369 SCOPED_LOCK_CRUCIAL_MUTEX(IndexReader_THIS_LOCK) |
|
370 |
|
371 CND_PRECONDITION(docNum >= 0, "docNum is negative"); |
|
372 |
|
373 if (directoryOwner) |
|
374 aquireWriteLock(); |
|
375 |
|
376 //Have the document identified by docNum deleted |
|
377 doDelete(docNum); |
|
378 hasChanges = true; |
|
379 } |
|
380 |
|
381 /** |
|
382 * Commit changes resulting from delete, undeleteAll, or setNorm operations |
|
383 * |
|
384 * @throws IOException |
|
385 */ |
|
386 void IndexReader::commit(){ |
|
387 // CPIXASYNC SCOPED_LOCK_MUTEX(THIS_LOCK) |
|
388 SCOPED_LOCK_CRUCIAL_MUTEX(IndexReader_THIS_LOCK) |
|
389 if(hasChanges){ |
|
390 if(directoryOwner){ |
|
391 { |
|
392 // CPIXASYNC SCOPED_LOCK_MUTEX(directory->THIS_LOCK) // in- & inter-process sync |
|
393 SCOPED_LOCK_CRUCIAL_MUTEX(directory->Directory_THIS_LOCK) // in- & inter-process sync |
|
394 |
|
395 LuceneLock* commitLock = directory->makeLock("commit.lock"); |
|
396 IndexReader::CommitLockWith cl(commitLock,this); |
|
397 cl.run(); |
|
398 _CLDELETE(commitLock); |
|
399 |
|
400 } |
|
401 if (writeLock != NULL) { |
|
402 writeLock->release(); // release write lock |
|
403 _CLDELETE(writeLock); |
|
404 } |
|
405 }else |
|
406 doCommit(); |
|
407 } |
|
408 hasChanges = false; |
|
409 } |
|
410 |
|
411 |
|
412 void IndexReader::undeleteAll(){ |
|
413 // CPIXASYNC SCOPED_LOCK_MUTEX(THIS_LOCK) |
|
414 SCOPED_LOCK_CRUCIAL_MUTEX(IndexReader_THIS_LOCK) |
|
415 if(directoryOwner) |
|
416 aquireWriteLock(); |
|
417 doUndeleteAll(); |
|
418 hasChanges = true; |
|
419 } |
|
420 |
|
421 int32_t IndexReader::deleteDocuments(Term* term) { |
|
422 //Func - Deletes all documents containing term. This is useful if one uses a |
|
423 // document field to hold a unique ID string for the document. Then to delete such |
|
424 // a document, one merely constructs a term with the appropriate field and the unique |
|
425 // ID string as its text and passes it to this method. |
|
426 //Pre - term != NULL |
|
427 //Post - All documents containing term have been deleted. The number of deleted documents |
|
428 // has been returned |
|
429 |
|
430 CND_PRECONDITION(term != NULL, "term is NULL"); |
|
431 |
|
432 //Search for the documents contain term |
|
433 TermDocs* docs = termDocs(term); |
|
434 |
|
435 //Check if documents have been found |
|
436 if ( docs == NULL ){ |
|
437 return 0; |
|
438 } |
|
439 |
|
440 //initialize |
|
441 int32_t Counter = 0; |
|
442 try { |
|
443 //iterate through the found documents |
|
444 while (docs->next()) { |
|
445 //Delete the document |
|
446 deleteDocument(docs->doc()); |
|
447 ++Counter; |
|
448 } |
|
449 }_CLFINALLY( |
|
450 //Close the enumeration |
|
451 docs->close(); |
|
452 ); |
|
453 |
|
454 //Delete the enumeration of found documents |
|
455 _CLDELETE( docs ); |
|
456 |
|
457 //Return the number of deleted documents |
|
458 return Counter; |
|
459 } |
|
460 |
|
461 TCHAR** IndexReader::getFieldNames(){ |
|
462 CL_NS(util)::StringArrayWithDeletor array; |
|
463 getFieldNames(IndexReader::ALL, array); |
|
464 |
|
465 array.setDoDelete(false); |
|
466 TCHAR** ret = _CL_NEWARRAY(TCHAR*,array.size()+1); |
|
467 int j=0; |
|
468 CL_NS(util)::StringArrayWithDeletor::iterator itr = array.begin(); |
|
469 while ( itr != array.end() ){ |
|
470 ret[j]=*itr; |
|
471 ++j;++itr; |
|
472 } |
|
473 ret[j]=NULL; |
|
474 return ret; |
|
475 } |
|
476 TCHAR** IndexReader::getFieldNames(bool indexed){ |
|
477 CL_NS(util)::StringArrayWithDeletor array; |
|
478 getFieldNames(indexed?IndexReader::INDEXED:IndexReader::UNINDEXED, array); |
|
479 |
|
480 array.setDoDelete(false); |
|
481 TCHAR** ret = _CL_NEWARRAY(TCHAR*,array.size()+1); |
|
482 int j=0; |
|
483 CL_NS(util)::StringArrayWithDeletor::iterator itr = array.begin(); |
|
484 while ( itr != array.end() ){ |
|
485 ret[j]=*itr; |
|
486 ++j;++itr; |
|
487 } |
|
488 ret[j]=NULL; |
|
489 return ret; |
|
490 } |
|
491 |
|
492 |
|
493 void IndexReader::close() { |
|
494 //Func - Closes files associated with this index and also saves any new deletions to disk. |
|
495 // No other methods should be called after this has been called. |
|
496 //Pre - true |
|
497 //Post - All files associated with this index have been deleted and new deletions have been |
|
498 // saved to disk |
|
499 // CPIXASYNC SCOPED_LOCK_MUTEX(THIS_LOCK) |
|
500 SCOPED_LOCK_CRUCIAL_MUTEX(IndexReader_THIS_LOCK) |
|
501 |
|
502 CloseCallbackMap::iterator iter = closeCallbacks.begin(); |
|
503 for ( ;iter!=closeCallbacks.end();iter++){ |
|
504 CloseCallback callback = *iter->first; |
|
505 callback(this,iter->second); |
|
506 } |
|
507 |
|
508 commit(); |
|
509 doClose(); |
|
510 |
|
511 if(closeDirectory){ |
|
512 directory->close(); |
|
513 _CLDECDELETE(directory); |
|
514 } |
|
515 } |
|
516 |
|
517 bool IndexReader::isLocked(Directory* directory) { |
|
518 //Func - Static method |
|
519 // Checks if the index in the directory is currently locked. |
|
520 //Pre - directory is a valid reference to a directory to check for a lock |
|
521 //Post - Returns true if the index in the named directory is locked otherwise false |
|
522 |
|
523 //Check the existence of the file write.lock and return true when it does and false |
|
524 //when it doesn't |
|
525 LuceneLock* l1 = directory->makeLock("write.lock"); |
|
526 LuceneLock* l2 = directory->makeLock("commit.lock"); |
|
527 |
|
528 bool ret = l1->isLocked() || l2->isLocked(); |
|
529 |
|
530 _CLDELETE(l1); |
|
531 _CLDELETE(l2); |
|
532 return ret; |
|
533 } |
|
534 |
|
535 bool IndexReader::isLocked(const char* directory) { |
|
536 //Func - Static method |
|
537 // Checks if the index in the named directory is currently locked. |
|
538 //Pre - directory != NULL and contains the directory to check for a lock |
|
539 //Post - Returns true if the index in the named directory is locked otherwise false |
|
540 |
|
541 CND_PRECONDITION(directory != NULL, "directory is NULL"); |
|
542 |
|
543 //Create a buffer of length CL_MAXDIR |
|
544 char f[CL_MAX_PATH]; //todo: potential buffer overflow |
|
545 //Copy the directory string to the buffer. leave room for /write.lock |
|
546 strncpy(f,directory,CL_MAX_PATH-12); |
|
547 //Cat the name of the write.lock file to buffer |
|
548 strcat ( f,"/write.lock" ); |
|
549 |
|
550 Directory* dir = FSDirectory::getDirectory(directory,false); |
|
551 bool ret = isLocked(dir); |
|
552 dir->close(); |
|
553 _CLDECDELETE(dir); |
|
554 |
|
555 return ret; |
|
556 } |
|
557 |
|
558 /** Returns true if there are norms stored for this field. */ |
|
559 bool IndexReader::hasNorms(const TCHAR* field) { |
|
560 // backward compatible implementation. |
|
561 // SegmentReader has an efficient implementation. |
|
562 return norms(field) != NULL; |
|
563 } |
|
564 |
|
565 void IndexReader::unlock(const char* path){ |
|
566 FSDirectory* dir = FSDirectory::getDirectory(path,false); |
|
567 unlock(dir); |
|
568 dir->close(); |
|
569 _CLDECDELETE(dir); |
|
570 } |
|
571 void IndexReader::unlock(Directory* directory){ |
|
572 //Func - Static method |
|
573 // Forcibly unlocks the index in the named directory-> |
|
574 // Caution: this should only be used by failure recovery code, |
|
575 // when it is known that no other process nor thread is in fact |
|
576 // currently accessing this index. |
|
577 //Pre - directory is a valid reference to a directory |
|
578 //Post - The directory has been forcibly unlocked |
|
579 LuceneLock* lock; |
|
580 |
|
581 lock = directory->makeLock("write.lock"); |
|
582 lock->release(); |
|
583 _CLDELETE(lock); |
|
584 |
|
585 lock = directory->makeLock("commit.lock"); |
|
586 lock->release(); |
|
587 _CLDELETE(lock); |
|
588 } |
|
589 |
|
590 bool IndexReader::isLuceneFile(const char* filename){ |
|
591 if ( !filename ) |
|
592 return false; |
|
593 size_t len = strlen(filename); |
|
594 if ( len < 6 ) //need at least x.frx |
|
595 return false; |
|
596 const char* ext=filename+len; |
|
597 while(*ext != '.' && ext!=filename) |
|
598 ext--; |
|
599 |
|
600 if ( strcmp(ext, ".cfs") == 0 ) |
|
601 return true; |
|
602 else if ( strcmp(ext, ".fnm") == 0 ) |
|
603 return true; |
|
604 else if ( strcmp(ext, ".fdx") == 0 ) |
|
605 return true; |
|
606 else if ( strcmp(ext, ".fdt") == 0 ) |
|
607 return true; |
|
608 else if ( strcmp(ext, ".tii") == 0 ) |
|
609 return true; |
|
610 else if ( strcmp(ext, ".tis") == 0 ) |
|
611 return true; |
|
612 else if ( strcmp(ext, ".frq") == 0 ) |
|
613 return true; |
|
614 else if ( strcmp(ext, ".prx") == 0 ) |
|
615 return true; |
|
616 else if ( strcmp(ext, ".del") == 0 ) |
|
617 return true; |
|
618 else if ( strcmp(ext, ".tvx") == 0 ) |
|
619 return true; |
|
620 else if ( strcmp(ext, ".tvd") == 0 ) |
|
621 return true; |
|
622 else if ( strcmp(ext, ".tvf") == 0 ) |
|
623 return true; |
|
624 else if ( strcmp(ext, ".tvp") == 0 ) |
|
625 return true; |
|
626 |
|
627 else if ( strcmp(filename, "segments") == 0 ) |
|
628 return true; |
|
629 else if ( strcmp(filename, "segments.new") == 0 ) |
|
630 return true; |
|
631 else if ( strcmp(filename, "deletable") == 0 ) |
|
632 return true; |
|
633 |
|
634 else if ( strncmp(ext,".f",2)==0 ){ |
|
635 const char* n = ext+2; |
|
636 if ( *n && _istdigit(*n) ) |
|
637 return true; |
|
638 } |
|
639 |
|
640 return false; |
|
641 } |
|
642 |
|
643 void IndexReader::addCloseCallback(CloseCallback callback, void* parameter){ |
|
644 closeCallbacks.put(callback, parameter); |
|
645 } |
|
646 |
|
647 |
|
648 //Constructor |
|
649 IndexReader::LockWith::LockWith(CL_NS(store)::LuceneLock* lock, CL_NS(store)::Directory* dir): |
|
650 CL_NS(store)::LuceneLockWith<IndexReader*>(lock,IndexWriter::COMMIT_LOCK_TIMEOUT) |
|
651 { |
|
652 this->directory = dir; |
|
653 } |
|
654 //Constructor |
|
655 IndexReader::CommitLockWith::CommitLockWith( CL_NS(store)::LuceneLock* lock, IndexReader* r ): |
|
656 CL_NS(store)::LuceneLockWith<void>(lock,IndexWriter::COMMIT_LOCK_TIMEOUT), |
|
657 reader(r) |
|
658 { |
|
659 } |
|
660 void IndexReader::CommitLockWith::doBody(){ |
|
661 reader->doCommit(); |
|
662 reader->segmentInfos->write(reader->getDirectory()); |
|
663 } |
|
664 |
|
665 CL_NS_END |