1 package org.apache.lucene.index; 2 3 18 19 import org.apache.lucene.document.Document; 20 import org.apache.lucene.document.Field; 21 import org.apache.lucene.search.Similarity; 22 import org.apache.lucene.store.Directory; 23 import org.apache.lucene.store.FSDirectory; 24 import org.apache.lucene.store.IndexInput; 25 import org.apache.lucene.store.Lock; 26 27 import java.io.File ; 28 import java.io.FileOutputStream ; 29 import java.io.IOException ; 30 import java.util.Arrays ; 31 import java.util.Collection ; 32 import java.util.HashSet ; 33 import java.util.Set ; 34 35 54 public abstract class IndexReader { 55 56 public static final class FieldOption { 57 private String option; 58 private FieldOption() { } 59 private FieldOption(String option) { 60 this.option = option; 61 } 62 public String toString() { 63 return this.option; 64 } 65 public static final FieldOption ALL = new FieldOption ("ALL"); 67 public static final FieldOption INDEXED = new FieldOption ("INDEXED"); 69 public static final FieldOption UNINDEXED = new FieldOption ("UNINDEXED"); 71 public static final FieldOption INDEXED_WITH_TERMVECTOR = new FieldOption ("INDEXED_WITH_TERMVECTOR"); 73 public static final FieldOption INDEXED_NO_TERMVECTOR = new FieldOption ("INDEXED_NO_TERMVECTOR"); 75 public static final FieldOption TERMVECTOR = new FieldOption ("TERMVECTOR"); 77 public static final FieldOption TERMVECTOR_WITH_POSITION = new FieldOption ("TERMVECTOR_WITH_POSITION"); 79 public static final FieldOption TERMVECTOR_WITH_OFFSET = new FieldOption ("TERMVECTOR_WITH_OFFSET"); 81 public static final FieldOption TERMVECTOR_WITH_POSITION_OFFSET = new FieldOption ("TERMVECTOR_WITH_POSITION_OFFSET"); 83 } 84 85 91 protected IndexReader(Directory directory) { 92 this.directory = directory; 93 } 94 95 103 IndexReader(Directory directory, SegmentInfos segmentInfos, boolean closeDirectory) { 104 init(directory, segmentInfos, closeDirectory, true); 105 } 106 107 void init(Directory directory, SegmentInfos segmentInfos, boolean closeDirectory, boolean directoryOwner) { 108 this.directory = directory; 109 this.segmentInfos = segmentInfos; 110 this.directoryOwner = directoryOwner; 111 this.closeDirectory = closeDirectory; 112 } 113 114 private Directory directory; 115 private boolean directoryOwner; 116 private boolean closeDirectory; 117 118 private SegmentInfos segmentInfos; 119 private Lock writeLock; 120 private boolean stale; 121 private boolean hasChanges; 122 123 124 126 public static IndexReader open(String path) throws IOException { 127 return open(FSDirectory.getDirectory(path, false), true); 128 } 129 130 132 public static IndexReader open(File path) throws IOException { 133 return open(FSDirectory.getDirectory(path, false), true); 134 } 135 136 137 public static IndexReader open(final Directory directory) throws IOException { 138 return open(directory, false); 139 } 140 141 private static IndexReader open(final Directory directory, final boolean closeDirectory) throws IOException { 142 synchronized (directory) { return (IndexReader)new Lock.With( 144 directory.makeLock(IndexWriter.COMMIT_LOCK_NAME), 145 IndexWriter.COMMIT_LOCK_TIMEOUT) { 146 public Object doBody() throws IOException { 147 SegmentInfos infos = new SegmentInfos(); 148 infos.read(directory); 149 if (infos.size() == 1) { return SegmentReader.get(infos, infos.info(0), closeDirectory); 151 } 152 IndexReader[] readers = new IndexReader[infos.size()]; 153 for (int i = 0; i < infos.size(); i++) 154 readers[i] = SegmentReader.get(infos.info(i)); 155 return new MultiReader(directory, infos, closeDirectory, readers); 156 157 } 158 }.run(); 159 } 160 } 161 162 163 public Directory directory() { return directory; } 164 165 170 public static long lastModified(String directory) throws IOException { 171 return lastModified(new File (directory)); 172 } 173 174 179 public static long lastModified(File directory) throws IOException { 180 return FSDirectory.fileModified(directory, IndexFileNames.SEGMENTS); 181 } 182 183 188 public static long lastModified(Directory directory) throws IOException { 189 return directory.fileModified(IndexFileNames.SEGMENTS); 190 } 191 192 201 public static long getCurrentVersion(String directory) throws IOException { 202 return getCurrentVersion(new File (directory)); 203 } 204 205 214 public static long getCurrentVersion(File directory) throws IOException { 215 Directory dir = FSDirectory.getDirectory(directory, false); 216 long version = getCurrentVersion(dir); 217 dir.close(); 218 return version; 219 } 220 221 230 public static long getCurrentVersion(Directory directory) throws IOException { 231 synchronized (directory) { Lock commitLock=directory.makeLock(IndexWriter.COMMIT_LOCK_NAME); 233 234 boolean locked=false; 235 236 try { 237 locked=commitLock.obtain(IndexWriter.COMMIT_LOCK_TIMEOUT); 238 239 return SegmentInfos.readCurrentVersion(directory); 240 } finally { 241 if (locked) { 242 commitLock.release(); 243 } 244 } 245 } 246 } 247 248 251 public long getVersion() { 252 return segmentInfos.getVersion(); 253 } 254 255 262 public boolean isCurrent() throws IOException { 263 synchronized (directory) { Lock commitLock=directory.makeLock(IndexWriter.COMMIT_LOCK_NAME); 265 266 boolean locked=false; 267 268 try { 269 locked=commitLock.obtain(IndexWriter.COMMIT_LOCK_TIMEOUT); 270 271 return SegmentInfos.readCurrentVersion(directory) == segmentInfos.getVersion(); 272 } finally { 273 if (locked) { 274 commitLock.release(); 275 } 276 } 277 } 278 } 279 280 294 abstract public TermFreqVector[] getTermFreqVectors(int docNumber) 295 throws IOException ; 296 297 298 312 abstract public TermFreqVector getTermFreqVector(int docNumber, String field) 313 throws IOException ; 314 315 322 public static boolean indexExists(String directory) { 323 return (new File (directory, IndexFileNames.SEGMENTS)).exists(); 324 } 325 326 332 public static boolean indexExists(File directory) { 333 return (new File (directory, IndexFileNames.SEGMENTS)).exists(); 334 } 335 336 343 public static boolean indexExists(Directory directory) throws IOException { 344 return directory.fileExists(IndexFileNames.SEGMENTS); 345 } 346 347 348 public abstract int numDocs(); 349 350 354 public abstract int maxDoc(); 355 356 358 public abstract Document document(int n) throws IOException ; 359 360 361 public abstract boolean isDeleted(int n); 362 363 364 public abstract boolean hasDeletions(); 365 366 367 public boolean hasNorms(String field) throws IOException { 368 return norms(field) != null; 371 } 372 373 378 public abstract byte[] norms(String field) throws IOException ; 379 380 385 public abstract void norms(String field, byte[] bytes, int offset) 386 throws IOException ; 387 388 397 public final synchronized void setNorm(int doc, String field, byte value) 398 throws IOException { 399 if(directoryOwner) 400 aquireWriteLock(); 401 doSetNorm(doc, field, value); 402 hasChanges = true; 403 } 404 405 406 protected abstract void doSetNorm(int doc, String field, byte value) 407 throws IOException ; 408 409 415 public void setNorm(int doc, String field, float value) 416 throws IOException { 417 setNorm(doc, field, Similarity.encodeNorm(value)); 418 } 419 420 424 public abstract TermEnum terms() throws IOException ; 425 426 430 public abstract TermEnum terms(Term t) throws IOException ; 431 432 433 public abstract int docFreq(Term t) throws IOException ; 434 435 445 public TermDocs termDocs(Term term) throws IOException { 446 TermDocs termDocs = termDocs(); 447 termDocs.seek(term); 448 return termDocs; 449 } 450 451 452 public abstract TermDocs termDocs() throws IOException ; 453 454 470 public TermPositions termPositions(Term term) throws IOException { 471 TermPositions termPositions = termPositions(); 472 termPositions.seek(term); 473 return termPositions; 474 } 475 476 477 public abstract TermPositions termPositions() throws IOException ; 478 479 485 private void aquireWriteLock() throws IOException { 486 if (stale) 487 throw new IOException ("IndexReader out of date and no longer valid for delete, undelete, or setNorm operations"); 488 489 if (writeLock == null) { 490 Lock writeLock = directory.makeLock(IndexWriter.WRITE_LOCK_NAME); 491 if (!writeLock.obtain(IndexWriter.WRITE_LOCK_TIMEOUT)) throw new IOException ("Index locked for write: " + writeLock); 493 this.writeLock = writeLock; 494 495 if (SegmentInfos.readCurrentVersion(directory) > segmentInfos.getVersion()) { 498 stale = true; 499 this.writeLock.release(); 500 this.writeLock = null; 501 throw new IOException ("IndexReader out of date and no longer valid for delete, undelete, or setNorm operations"); 502 } 503 } 504 } 505 506 515 public final synchronized void delete(int docNum) throws IOException { 516 deleteDocument(docNum); 517 } 518 519 526 public final synchronized void deleteDocument(int docNum) throws IOException { 527 if(directoryOwner) 528 aquireWriteLock(); 529 doDelete(docNum); 530 hasChanges = true; 531 } 532 533 534 537 protected abstract void doDelete(int docNum) throws IOException ; 538 539 550 public final int delete(Term term) throws IOException { 551 return deleteDocuments(term); 552 } 553 554 563 public final int deleteDocuments(Term term) throws IOException { 564 TermDocs docs = termDocs(term); 565 if (docs == null) return 0; 566 int n = 0; 567 try { 568 while (docs.next()) { 569 deleteDocument(docs.doc()); 570 n++; 571 } 572 } finally { 573 docs.close(); 574 } 575 return n; 576 } 577 578 579 public final synchronized void undeleteAll() throws IOException { 580 if(directoryOwner) 581 aquireWriteLock(); 582 doUndeleteAll(); 583 hasChanges = true; 584 } 585 586 587 protected abstract void doUndeleteAll() throws IOException ; 588 589 594 protected final synchronized void commit() throws IOException { 595 if(hasChanges){ 596 if(directoryOwner){ 597 synchronized (directory) { new Lock.With(directory.makeLock(IndexWriter.COMMIT_LOCK_NAME), 599 IndexWriter.COMMIT_LOCK_TIMEOUT) { 600 public Object doBody() throws IOException { 601 doCommit(); 602 segmentInfos.write(directory); 603 return null; 604 } 605 }.run(); 606 } 607 if (writeLock != null) { 608 writeLock.release(); writeLock = null; 610 } 611 } 612 else 613 doCommit(); 614 } 615 hasChanges = false; 616 } 617 618 619 protected abstract void doCommit() throws IOException ; 620 621 626 public final synchronized void close() throws IOException { 627 commit(); 628 doClose(); 629 if(closeDirectory) 630 directory.close(); 631 } 632 633 634 protected abstract void doClose() throws IOException ; 635 636 637 protected void finalize() { 638 if (writeLock != null) { 639 writeLock.release(); writeLock = null; 641 } 642 } 643 644 652 public abstract Collection getFieldNames() throws IOException ; 653 654 665 public abstract Collection getFieldNames(boolean indexed) throws IOException ; 666 667 675 public Collection getIndexedFieldNames(boolean storedTermVector){ 676 if(storedTermVector){ 677 Set fieldSet = new HashSet (); 678 fieldSet.addAll(getIndexedFieldNames(Field.TermVector.YES)); 679 fieldSet.addAll(getIndexedFieldNames(Field.TermVector.WITH_POSITIONS)); 680 fieldSet.addAll(getIndexedFieldNames(Field.TermVector.WITH_OFFSETS)); 681 fieldSet.addAll(getIndexedFieldNames(Field.TermVector.WITH_POSITIONS_OFFSETS)); 682 return fieldSet; 683 } 684 else 685 return getIndexedFieldNames(Field.TermVector.NO); 686 } 687 688 697 public abstract Collection getIndexedFieldNames(Field.TermVector tvSpec); 698 699 706 public abstract Collection getFieldNames(FieldOption fldOption); 707 708 714 public static boolean isLocked(Directory directory) throws IOException { 715 return 716 directory.makeLock(IndexWriter.WRITE_LOCK_NAME).isLocked() || 717 directory.makeLock(IndexWriter.COMMIT_LOCK_NAME).isLocked(); 718 } 719 720 726 public static boolean isLocked(String directory) throws IOException { 727 Directory dir = FSDirectory.getDirectory(directory, false); 728 boolean result = isLocked(dir); 729 dir.close(); 730 return result; 731 } 732 733 740 public static void unlock(Directory directory) throws IOException { 741 directory.makeLock(IndexWriter.WRITE_LOCK_NAME).release(); 742 directory.makeLock(IndexWriter.COMMIT_LOCK_NAME).release(); 743 } 744 745 752 public static void main(String [] args) { 753 String filename = null; 754 boolean extract = false; 755 756 for (int i = 0; i < args.length; ++i) { 757 if (args[i].equals("-extract")) { 758 extract = true; 759 } else if (filename == null) { 760 filename = args[i]; 761 } 762 } 763 764 if (filename == null) { 765 System.out.println("Usage: org.apache.lucene.index.IndexReader [-extract] <cfsfile>"); 766 return; 767 } 768 769 Directory dir = null; 770 CompoundFileReader cfr = null; 771 772 try { 773 File file = new File (filename); 774 String dirname = file.getAbsoluteFile().getParent(); 775 filename = file.getName(); 776 dir = FSDirectory.getDirectory(dirname, false); 777 cfr = new CompoundFileReader(dir, filename); 778 779 String [] files = cfr.list(); 780 Arrays.sort(files); 782 for (int i = 0; i < files.length; ++i) { 783 long len = cfr.fileLength(files[i]); 784 785 if (extract) { 786 System.out.println("extract " + files[i] + " with " + len + " bytes to local directory..."); 787 IndexInput ii = cfr.openInput(files[i]); 788 789 FileOutputStream f = new FileOutputStream (files[i]); 790 791 byte[] buffer = new byte[1024]; 793 int chunk = buffer.length; 794 while(len > 0) { 795 final int bufLen = (int) Math.min(chunk, len); 796 ii.readBytes(buffer, 0, bufLen); 797 f.write(buffer, 0, bufLen); 798 len -= bufLen; 799 } 800 801 f.close(); 802 ii.close(); 803 } 804 else 805 System.out.println(files[i] + ": " + len + " bytes"); 806 } 807 } catch (IOException ioe) { 808 ioe.printStackTrace(); 809 } 810 finally { 811 try { 812 if (dir != null) 813 dir.close(); 814 if (cfr != null) 815 cfr.close(); 816 } 817 catch (IOException ioe) { 818 ioe.printStackTrace(); 819 } 820 } 821 } 822 } 823 | Popular Tags |