Index: common-build.xml =================================================================== --- common-build.xml (revision 777664) +++ common-build.xml (working copy) @@ -395,6 +395,7 @@ + Index: CHANGES.txt =================================================================== --- CHANGES.txt (revision 777664) +++ CHANGES.txt (working copy) @@ -107,10 +107,10 @@ that's visited. All core collectors now use this API. (Mark Miller, Mike McCandless) -8. LUCENE-1546: Add IndexReader.flush(String commitUserData), allowing - you to record an opaque commitUserData into the commit written by - IndexReader. This matches IndexWriter's commit methods. (Jason - Rutherglen via Mike McCandless) +8. LUCENE-1546: Add IndexReader.flush(Map commitUserData), allowing + you to record an opaque commitUserData (maps String -> String) into + the commit written by IndexReader. This matches IndexWriter's + commit methods. (Jason Rutherglen via Mike McCandless) 9. LUCENE-652: Added org.apache.lucene.document.CompressionTools, to enable compressing & decompressing binary content, external to @@ -189,10 +189,11 @@ when building transactional support on top of Lucene. (Mike McCandless) - 2. LUCENE-1382: Add an optional arbitrary String "commitUserData" to - IndexWriter.commit(), which is stored in the segments file and is - then retrievable via IndexReader.getCommitUserData instance and - static methods. (Shalin Shekhar Mangar via Mike McCandless) + 2. LUCENE-1382: Add an optional arbitrary Map (String -> String) + "commitUserData" to IndexWriter.commit(), which is stored in the + segments file and is then retrievable via + IndexReader.getCommitUserData instance and static methods. + (Shalin Shekhar Mangar via Mike McCandless) 3. LUCENE-1406: Added Arabic analyzer. (Robert Muir via Grant Ingersoll) Index: src/test/org/apache/lucene/index/TestIndexReader.java =================================================================== --- src/test/org/apache/lucene/index/TestIndexReader.java (revision 777664) +++ src/test/org/apache/lucene/index/TestIndexReader.java (working copy) @@ -26,6 +26,7 @@ import java.util.HashSet; import java.util.Iterator; import java.util.Map; +import java.util.HashMap; import java.util.Set; import junit.framework.TestSuite; @@ -70,9 +71,10 @@ public void testCommitUserData() throws Exception { RAMDirectory d = new MockRAMDirectory(); + + Map commitUserData = new HashMap(); + commitUserData.put("foo", "fighters"); - String cmpCommitUserData = "foo fighters"; - // set up writer IndexWriter writer = new IndexWriter(d, new StandardAnalyzer(), true, IndexWriter.MaxFieldLength.LIMITED); writer.setMaxBufferedDocs(2); @@ -82,14 +84,14 @@ IndexReader r = IndexReader.open(d); r.deleteDocument(5); - r.flush(cmpCommitUserData); + r.flush(commitUserData); r.close(); SegmentInfos sis = new SegmentInfos(); sis.read(d); IndexReader r2 = IndexReader.open(d); IndexCommit c = r.getIndexCommit(); - assertEquals(c.getUserData(), cmpCommitUserData); + assertEquals(c.getUserData(), commitUserData); assertEquals(sis.getCurrentSegmentFileName(), c.getSegmentsFileName()); Index: src/test/org/apache/lucene/index/TestIndexWriter.java =================================================================== --- src/test/org/apache/lucene/index/TestIndexWriter.java (revision 777664) +++ src/test/org/apache/lucene/index/TestIndexWriter.java (working copy) @@ -26,6 +26,8 @@ import java.util.Arrays; import java.util.List; import java.util.Random; +import java.util.Map; +import java.util.HashMap; import org.apache.lucene.analysis.Analyzer; import org.apache.lucene.analysis.SinkTokenizer; @@ -4096,31 +4098,33 @@ addDoc(w); w.close(); - assertEquals(null, IndexReader.getCommitUserData(dir)); + assertEquals(0, IndexReader.getCommitUserData(dir).size()); IndexReader r = IndexReader.open(dir); - // commit(String) never called for this index - assertEquals(null, r.getCommitUserData()); + // commit(Map) never called for this index + assertEquals(0, r.getCommitUserData().size()); r.close(); w = new IndexWriter(dir, new WhitespaceAnalyzer(), IndexWriter.MaxFieldLength.LIMITED); w.setMaxBufferedDocs(2); for(int j=0;j<17;j++) addDoc(w); - w.commit("test1"); + Map data = new HashMap(); + data.put("label", "test1"); + w.commit(data); w.close(); - assertEquals("test1", IndexReader.getCommitUserData(dir)); + assertEquals("test1", IndexReader.getCommitUserData(dir).get("label")); r = IndexReader.open(dir); - assertEquals("test1", r.getCommitUserData()); + assertEquals("test1", r.getCommitUserData().get("label")); r.close(); w = new IndexWriter(dir, new WhitespaceAnalyzer(), IndexWriter.MaxFieldLength.LIMITED); w.optimize(); w.close(); - assertEquals("test1", IndexReader.getCommitUserData(dir)); + assertEquals("test1", IndexReader.getCommitUserData(dir).get("label")); dir.close(); } Index: src/test/org/apache/lucene/index/TestCheckIndex.java =================================================================== --- src/test/org/apache/lucene/index/TestCheckIndex.java (revision 777664) +++ src/test/org/apache/lucene/index/TestCheckIndex.java (working copy) @@ -28,6 +28,7 @@ import org.apache.lucene.analysis.WhitespaceAnalyzer; import org.apache.lucene.document.Document; import org.apache.lucene.document.Field; +import org.apache.lucene.util.Constants; public class TestCheckIndex extends LuceneTestCase { @@ -55,11 +56,22 @@ System.out.println(bos.toString()); fail(); } - assertTrue(((CheckIndex.Status.SegmentInfoStatus) indexStatus.segmentInfos.get(0)).openReaderPassed); + + final CheckIndex.Status.SegmentInfoStatus seg = (CheckIndex.Status.SegmentInfoStatus) indexStatus.segmentInfos.get(0); + assertTrue(seg.openReaderPassed); + assertNotNull(seg.diagnostics); + assertTrue(seg.diagnostics.size() > 0); final List onlySegments = new ArrayList(); onlySegments.add("_0"); assertTrue(checker.checkIndex(onlySegments).clean == true); } + + public void testLuceneConstantVersion() throws IOException { + // common-build.xml sets lucene.version + final String version = System.getProperty("lucene.version"); + assertEquals(version, Constants.LUCENE_MAIN_VERSION); + assertTrue(Constants.LUCENE_VERSION.startsWith(version)); + } } Index: src/test/org/apache/lucene/index/TestTransactionRollback.java =================================================================== --- src/test/org/apache/lucene/index/TestTransactionRollback.java (revision 777664) +++ src/test/org/apache/lucene/index/TestTransactionRollback.java (working copy) @@ -23,6 +23,8 @@ import java.util.Collection; import java.util.Iterator; import java.util.List; +import java.util.Map; +import java.util.HashMap; import junit.framework.TestCase; @@ -55,9 +57,9 @@ Collection commits = IndexReader.listCommits(dir); for (Iterator iterator = commits.iterator(); iterator.hasNext();) { IndexCommit commit = (IndexCommit) iterator.next(); - String ud=commit.getUserData(); - if (ud != null) - if (ud.endsWith(ids)) + Map ud=commit.getUserData(); + if (ud.size() > 0) + if (((String) ud.get("index")).endsWith(ids)) last=commit; } @@ -66,7 +68,9 @@ IndexWriter w = new IndexWriter(dir, new WhitespaceAnalyzer(), new RollbackDeletionPolicy(id), MaxFieldLength.UNLIMITED, last); - w.commit("Rolled back to 1-"+id); + Map data = new HashMap(); + data.put("index", "Rolled back to 1-"+id); + w.commit(data); w.close(); } @@ -101,6 +105,7 @@ assertEquals("Should have 0 docs remaining ", 0 ,expecteds.cardinality()); } + /* private void showAvailableCommitPoints() throws Exception { Collection commits = IndexReader.listCommits(dir); for (Iterator iterator = commits.iterator(); iterator.hasNext();) { @@ -114,6 +119,7 @@ System.out.println(); } } + */ protected void setUp() throws Exception { dir = new MockRAMDirectory(); @@ -126,15 +132,15 @@ //Build index, of records 1 to 100, committing after each batch of 10 IndexDeletionPolicy sdp=new KeepAllDeletionPolicy(); IndexWriter w=new IndexWriter(dir,new WhitespaceAnalyzer(),sdp,MaxFieldLength.UNLIMITED); - int firstRecordIdInThisTransaction=1; for(int currentRecordId=1;currentRecordId<=100;currentRecordId++) { Document doc=new Document(); doc.add(new Field(FIELD_RECORD_ID,""+currentRecordId,Field.Store.YES,Field.Index.ANALYZED)); w.addDocument(doc); if (currentRecordId%10 == 0) { - String userData="records 1-"+currentRecordId; - w.commit(userData); + Map data = new HashMap(); + data.put("index", "records 1-"+currentRecordId); + w.commit(data); } } @@ -155,12 +161,13 @@ public void onInit(List commits) throws IOException { for (Iterator iterator = commits.iterator(); iterator.hasNext();) { IndexCommit commit = (IndexCommit) iterator.next(); - String userData=commit.getUserData(); - if (userData != null) { + Map userData=commit.getUserData(); + if (userData.size() > 0) { // Label for a commit point is "Records 1-30" // This code reads the last id ("30" in this example) and deletes it // if it is after the desired rollback point - String lastVal = userData.substring(userData.lastIndexOf("-")+1); + String x = (String) userData.get("index"); + String lastVal = x.substring(x.lastIndexOf("-")+1); int last = Integer.parseInt(lastVal); if (last>rollbackPoint) { /* Index: src/test/org/apache/lucene/index/TestIndexReaderReopen.java =================================================================== --- src/test/org/apache/lucene/index/TestIndexReaderReopen.java (revision 777664) +++ src/test/org/apache/lucene/index/TestIndexReaderReopen.java (working copy) @@ -25,6 +25,8 @@ import java.util.Iterator; import java.util.List; import java.util.Random; +import java.util.Map; +import java.util.HashMap; import java.util.Set; import org.apache.lucene.analysis.KeywordAnalyzer; @@ -1233,11 +1235,15 @@ Document doc = new Document(); doc.add(new Field("id", ""+i, Field.Store.NO, Field.Index.NOT_ANALYZED)); writer.addDocument(doc); - writer.commit(""+i); + Map data = new HashMap(); + data.put("index", i+""); + writer.commit(data); } for(int i=0;i<4;i++) { writer.deleteDocuments(new Term("id", ""+i)); - writer.commit(""+(4+i)); + Map data = new HashMap(); + data.put("index", (4+i)+""); + writer.commit(data); } writer.close(); @@ -1259,13 +1265,13 @@ // expected } - final String s = commit.getUserData(); + final Map s = commit.getUserData(); final int v; - if (s == null) { + if (s.size() == 0) { // First commit created by IW v = -1; } else { - v = Integer.parseInt(s); + v = Integer.parseInt((String) s.get("index")); } if (v < 4) { assertEquals(1+v, r2.numDocs()); Index: src/java/org/apache/lucene/index/DirectoryIndexReader.java =================================================================== --- src/java/org/apache/lucene/index/DirectoryIndexReader.java (revision 777664) +++ src/java/org/apache/lucene/index/DirectoryIndexReader.java (working copy) @@ -25,6 +25,7 @@ import java.util.ArrayList; import java.util.Iterator; import java.util.Collections; +import java.util.Map; import org.apache.lucene.store.Directory; import org.apache.lucene.store.Lock; @@ -344,7 +345,7 @@ return segmentInfos.getVersion(); } - public String getCommitUserData() { + public Map getCommitUserData() { ensureOpen(); return segmentInfos.getUserData(); } @@ -396,7 +397,7 @@ * (transactional semantics). * @throws IOException if there is a low-level IO error */ - protected void doCommit(String commitUserData) throws IOException { + protected void doCommit(Map commitUserData) throws IOException { if (hasChanges) { if (segmentInfos != null) { segmentInfos.setUserData(commitUserData); @@ -557,7 +558,7 @@ long generation; long version; final boolean isOptimized; - final String userData; + final Map userData; ReaderCommit(SegmentInfos infos, Directory dir) throws IOException { segmentsFileName = infos.getCurrentSegmentFileName(); @@ -590,7 +591,7 @@ public boolean isDeleted() { return false; } - public String getUserData() { + public Map getUserData() { return userData; } } Index: src/java/org/apache/lucene/index/SegmentInfo.java =================================================================== --- src/java/org/apache/lucene/index/SegmentInfo.java (revision 777664) +++ src/java/org/apache/lucene/index/SegmentInfo.java (working copy) @@ -23,6 +23,8 @@ import org.apache.lucene.util.BitVector; import java.io.IOException; import java.util.List; +import java.util.Map; +import java.util.HashMap; import java.util.ArrayList; final class SegmentInfo { @@ -79,6 +81,8 @@ private boolean hasProx; // True if this segment has any fields with omitTermFreqAndPositions==false + private Map diagnostics; + public String toString() { return "si: "+dir.toString()+" "+name+" docCount: "+docCount+" delCount: "+delCount+" delFileName: "+getDelFileName(); } @@ -139,6 +143,16 @@ delCount = src.delCount; } + // must be Map + void setDiagnostics(Map diagnostics) { + this.diagnostics = diagnostics; + } + + // returns Map + Map getDiagnostics() { + return diagnostics; + } + /** * Construct a new SegmentInfo instance by reading a * previously saved SegmentInfo from input. @@ -192,6 +206,12 @@ hasProx = input.readByte() == 1; else hasProx = true; + + if (format <= SegmentInfos.FORMAT_DIAGNOSTICS) { + diagnostics = input.readStringStringMap(); + } else { + diagnostics = new HashMap(); + } } else { delGen = CHECK_DIR; normGen = null; @@ -203,6 +223,7 @@ docStoreSegment = null; delCount = -1; hasProx = true; + diagnostics = new HashMap(); } } @@ -290,8 +311,10 @@ si.isCompoundFile = isCompoundFile; si.delGen = delGen; si.delCount = delCount; + si.hasProx = hasProx; si.preLockless = preLockless; si.hasSingleNormFile = hasSingleNormFile; + si.diagnostics = new HashMap(diagnostics); if (normGen != null) { si.normGen = (long[]) normGen.clone(); } @@ -527,6 +550,7 @@ output.writeByte(isCompoundFile); output.writeInt(delCount); output.writeByte((byte) (hasProx ? 1:0)); + output.writeStringStringMap(diagnostics); } void setHasProx(boolean hasProx) { Index: src/java/org/apache/lucene/index/ParallelReader.java =================================================================== --- src/java/org/apache/lucene/index/ParallelReader.java (revision 777664) +++ src/java/org/apache/lucene/index/ParallelReader.java (working copy) @@ -441,7 +441,7 @@ doCommit(null); } - protected void doCommit(String commitUserData) throws IOException { + protected void doCommit(Map commitUserData) throws IOException { for (int i = 0; i < readers.size(); i++) ((IndexReader)readers.get(i)).commit(commitUserData); } Index: src/java/org/apache/lucene/index/SnapshotDeletionPolicy.java =================================================================== --- src/java/org/apache/lucene/index/SnapshotDeletionPolicy.java (revision 777664) +++ src/java/org/apache/lucene/index/SnapshotDeletionPolicy.java (working copy) @@ -20,6 +20,7 @@ import java.util.Collection; import java.util.List; import java.util.ArrayList; +import java.util.Map; import java.io.IOException; import org.apache.lucene.store.Directory; @@ -118,7 +119,7 @@ public long getGeneration() { return cp.getGeneration(); } - public String getUserData() throws IOException { + public Map getUserData() throws IOException { return cp.getUserData(); } } Index: src/java/org/apache/lucene/index/SegmentInfos.java =================================================================== --- src/java/org/apache/lucene/index/SegmentInfos.java (revision 777664) +++ src/java/org/apache/lucene/index/SegmentInfos.java (working copy) @@ -32,6 +32,8 @@ import java.util.Vector; import java.util.Collection; import java.util.HashSet; +import java.util.HashMap; +import java.util.Map; final class SegmentInfos extends Vector { @@ -76,8 +78,12 @@ /** This format adds optional commit userData (String) storage. */ public static final int FORMAT_USER_DATA = -8; + /** This format adds optional per-segment String + * dianostics storage, and switches userData to Map */ + public static final int FORMAT_DIAGNOSTICS = -9; + /* This must always point to the most recent file format. */ - static final int CURRENT_FORMAT = FORMAT_USER_DATA; + static final int CURRENT_FORMAT = FORMAT_DIAGNOSTICS; public int counter = 0; // used to name new segments /** @@ -91,7 +97,7 @@ // or wrote; this is normally the same as generation except if // there was an IOException that had interrupted a commit - private String userData; // Opaque String that user can specify during IndexWriter.commit + private Map userData = new HashMap(); // Opaque Map that user can specify during IndexWriter.commit /** * If non-null, information about loading segments_N files @@ -252,10 +258,16 @@ } if (format <= FORMAT_USER_DATA) { - if (0 == input.readByte()) - userData = null; - else - userData = input.readString(); + if (format <= FORMAT_DIAGNOSTICS) { + userData = input.readStringStringMap(); + } else { + userData = new HashMap(); + if (0 != input.readByte()) { + userData.put("userData", input.readString()); + } + } + } else { + userData = new HashMap(); } if (format <= FORMAT_CHECKSUM) { @@ -323,12 +335,7 @@ for (int i = 0; i < size(); i++) { info(i).write(segnOutput); } - if (userData == null) - segnOutput.writeByte((byte) 0); - else { - segnOutput.writeByte((byte) 1); - segnOutput.writeString(userData); - } + segnOutput.writeStringStringMap(userData); segnOutput.prepareCommit(); success = true; pendingSegnOutput = segnOutput; @@ -362,6 +369,7 @@ for(int i=0;i that includes certain + * debugging details that IndexWriter records into + * each segment it creates */ + public Map diagnostics; } } @@ -310,6 +319,8 @@ sFormat = "FORMAT_HAS_PROX [Lucene 2.4]"; else if (format == SegmentInfos.FORMAT_USER_DATA) sFormat = "FORMAT_USER_DATA [Lucene 2.9]"; + else if (format == SegmentInfos.FORMAT_DIAGNOSTICS) + sFormat = "FORMAT_DIAGNOSTICS [Lucene 2.9]"; else if (format < SegmentInfos.CURRENT_FORMAT) { sFormat = "int=" + format + " [newer version of Lucene than this tool]"; skip = true; @@ -318,11 +329,19 @@ } } - msg("Segments file=" + segmentsFileName + " numSegments=" + numSegments + " version=" + sFormat); result.segmentsFileName = segmentsFileName; result.numSegments = numSegments; result.segmentFormat = sFormat; + result.userData = sis.getUserData(); + String userDataString; + if (sis.getUserData().size() > 0) { + userDataString = " userData=" + sis.getUserData(); + } else { + userDataString = ""; + } + msg("Segments file=" + segmentsFileName + " numSegments=" + numSegments + " version=" + sFormat + userDataString); + if (onlySegments != null) { result.partial = true; if (infoStream != null) @@ -369,8 +388,12 @@ segInfoStat.numFiles = info.files().size(); msg(" size (MB)=" + nf.format(info.sizeInBytes()/(1024.*1024.))); segInfoStat.sizeMB = info.sizeInBytes()/(1024.*1024.); + Map diagnostics = info.getDiagnostics(); + segInfoStat.diagnostics = diagnostics; + if (diagnostics.size() > 0) { + msg(" diagnostics = " + diagnostics); + } - final int docStoreOffset = info.getDocStoreOffset(); if (docStoreOffset != -1) { msg(" docStoreOffset=" + docStoreOffset); Index: src/java/org/apache/lucene/index/MultiReader.java =================================================================== --- src/java/org/apache/lucene/index/MultiReader.java (revision 777664) +++ src/java/org/apache/lucene/index/MultiReader.java (working copy) @@ -360,7 +360,7 @@ doCommit(null); } - protected void doCommit(String commitUserData) throws IOException { + protected void doCommit(Map commitUserData) throws IOException { for (int i = 0; i < subReaders.length; i++) subReaders[i].commit(commitUserData); } Index: src/java/org/apache/lucene/index/IndexCommit.java =================================================================== --- src/java/org/apache/lucene/index/IndexCommit.java (revision 777664) +++ src/java/org/apache/lucene/index/IndexCommit.java (working copy) @@ -18,6 +18,7 @@ */ import java.util.Collection; +import java.util.Map; import java.io.IOException; import org.apache.lucene.store.Directory; @@ -122,8 +123,9 @@ } /** Returns userData, previously passed to {@link - * IndexWriter#commit(String)} for this commit. */ - public String getUserData() throws IOException { + * IndexWriter#commit(Map)} for this commit. Map is + * String -> String. */ + public Map getUserData() throws IOException { throw new UnsupportedOperationException("This IndexCommit does not support this method."); } } Index: src/java/org/apache/lucene/index/FilterIndexReader.java =================================================================== --- src/java/org/apache/lucene/index/FilterIndexReader.java (revision 777664) +++ src/java/org/apache/lucene/index/FilterIndexReader.java (working copy) @@ -23,6 +23,7 @@ import java.io.IOException; import java.util.Collection; +import java.util.Map; /** A FilterIndexReader contains another IndexReader, which it * uses as its basic source of data, possibly transforming the data along the @@ -213,7 +214,7 @@ /** @deprecated */ protected void doCommit() throws IOException { doCommit(null); } - protected void doCommit(String commitUserData) throws IOException { in.commit(commitUserData); } + protected void doCommit(Map commitUserData) throws IOException { in.commit(commitUserData); } protected void doClose() throws IOException { in.close(); } Index: src/java/org/apache/lucene/index/IndexReader.java =================================================================== --- src/java/org/apache/lucene/index/IndexReader.java (revision 777664) +++ src/java/org/apache/lucene/index/IndexReader.java (working copy) @@ -27,6 +27,7 @@ import java.io.IOException; import java.util.Arrays; import java.util.Collection; +import java.util.Map; /** IndexReader is an abstract class, providing an interface for accessing an index. Search of an index is done entirely through this abstract interface, @@ -525,9 +526,9 @@ /** * Reads commitUserData, previously passed to {@link - * IndexWriter#commit(String)}, from current index + * IndexWriter#commit(Map)}, from current index * segments file. This will return null if {@link - * IndexWriter#commit(String)} has never been called for + * IndexWriter#commit(Map)} has never been called for * this index. * * @param directory where the index resides. @@ -537,7 +538,7 @@ * * @see #getCommitUserData() */ - public static String getCommitUserData(Directory directory) throws CorruptIndexException, IOException { + public static Map getCommitUserData(Directory directory) throws CorruptIndexException, IOException { return SegmentInfos.readCurrentUserData(directory); } @@ -552,12 +553,12 @@ /** * Retrieve the String userData optionally passed to * IndexWriter#commit. This will return null if {@link - * IndexWriter#commit(String)} has never been called for + * IndexWriter#commit(Map)} has never been called for * this index. * * @see #getCommitUserData(Directory) */ - public String getCommitUserData() { + public Map getCommitUserData() { throw new UnsupportedOperationException("This reader does not support this method."); } @@ -1017,12 +1018,13 @@ } /** - * @param commitUserData Opaque String that's recorded - * into the segments file in the index, and retrievable - * by {@link IndexReader#getCommitUserData}. + * @param commitUserData Opaque Map (String -> String) + * that's recorded into the segments file in the index, + * and retrievable by {@link + * IndexReader#getCommitUserData}. * @throws IOException */ - public final synchronized void flush(String commitUserData) throws IOException { + public final synchronized void flush(Map commitUserData) throws IOException { ensureOpen(); commit(commitUserData); } @@ -1049,7 +1051,7 @@ * (transactional semantics). * @throws IOException if there is a low-level IO error */ - protected final synchronized void commit(String commitUserData) throws IOException { + protected final synchronized void commit(Map commitUserData) throws IOException { if (hasChanges) { doCommit(commitUserData); } @@ -1057,13 +1059,13 @@ } /** Implements commit. - * @deprecated Please implement {@link #doCommit(String) + * @deprecated Please implement {@link #doCommit(Map) * instead}. */ protected abstract void doCommit() throws IOException; /** Implements commit. NOTE: subclasses should override * this. In 3.0 this will become an abstract method. */ - void doCommit(String commitUserData) throws IOException { + void doCommit(Map commitUserData) throws IOException { // Default impl discards commitUserData; all Lucene // subclasses override this (do not discard it). doCommit(); Index: src/java/org/apache/lucene/index/IndexWriter.java =================================================================== --- src/java/org/apache/lucene/index/IndexWriter.java (revision 777664) +++ src/java/org/apache/lucene/index/IndexWriter.java (working copy) @@ -3718,6 +3718,7 @@ segmentInfos.clear(); // pop old infos & add new info = new SegmentInfo(mergedName, docCount, directory, false, true, -1, null, false, merger.hasProx()); + setDiagnostics(info, "addIndexes(IndexReader[])"); segmentInfos.add(info); } @@ -3831,16 +3832,16 @@ * you should immediately close the writer. See above for details.

* - * @see #prepareCommit(String) */ + * @see #prepareCommit(Map) */ public final void prepareCommit() throws CorruptIndexException, IOException { ensureOpen(); prepareCommit(null); } /**

Expert: prepare for commit, specifying - * commitUserData String. This does the first phase of - * 2-phase commit. You can only call this when - * autoCommit is false. This method does all steps + * commitUserData Map (String -> String). This does the + * first phase of 2-phase commit. You can only call this + * when autoCommit is false. This method does all steps * necessary to commit changes since this writer was * opened: flushes pending added and deleted docs, syncs * the index files, writes most of next segments_N file. @@ -3849,7 +3850,7 @@ * #rollback()} to revert the commit and undo all changes * done since the writer was opened.

* - * You can also just call {@link #commit(String)} directly + * You can also just call {@link #commit(Map)} directly * without prepareCommit first in which case that method * will internally call prepareCommit. * @@ -3857,11 +3858,12 @@ * you should immediately close the writer. See above for details.

* - * @param commitUserData Opaque String that's recorded - * into the segments file in the index, and retrievable - * by {@link IndexReader#getCommitUserData}. Note that - * when IndexWriter commits itself, for example if open - * with autoCommit=true, or, during {@link #close}, the + * @param commitUserData Opaque Map (String->String) + * that's recorded into the segments file in the index, + * and retrievable by {@link + * IndexReader#getCommitUserData}. Note that when + * IndexWriter commits itself, for example if open with + * autoCommit=true, or, during {@link #close}, the * commitUserData is unchanged (just carried over from * the prior commit). If this is null then the previous * commitUserData is kept. Also, the commitUserData will @@ -3869,11 +3871,11 @@ * index to commit. Therefore it's best to use this * feature only when autoCommit is false. */ - public final void prepareCommit(String commitUserData) throws CorruptIndexException, IOException { + public final void prepareCommit(Map commitUserData) throws CorruptIndexException, IOException { prepareCommit(commitUserData, false); } - private final void prepareCommit(String commitUserData, boolean internal) throws CorruptIndexException, IOException { + private final void prepareCommit(Map commitUserData, boolean internal) throws CorruptIndexException, IOException { if (hitOOM) { throw new IllegalStateException("this writer hit an OutOfMemoryError; cannot commit"); @@ -3926,22 +3928,22 @@ * href="#OOME">above for details.

* * @see #prepareCommit - * @see #commit(String) + * @see #commit(Map) */ public final void commit() throws CorruptIndexException, IOException { commit(null); } /** Commits all changes to the index, specifying a - * commitUserData String. This just calls {@link - * #prepareCommit(String)} (if you didn't already call - * it) and then {@link #finishCommit}. + * commitUserData Map (String -> String). This just + * calls {@link #prepareCommit(Map)} (if you didn't + * already call it) and then {@link #finishCommit}. * *

NOTE: if this method hits an OutOfMemoryError * you should immediately close the writer. See above for details.

*/ - public final void commit(String commitUserData) throws CorruptIndexException, IOException { + public final void commit(Map commitUserData) throws CorruptIndexException, IOException { ensureOpen(); @@ -4136,6 +4138,7 @@ docStoreOffset, docStoreSegment, docStoreIsCompoundFile, docWriter.hasProx()); + setDiagnostics(newSegment, "flush"); } docWriter.pushDeletes(); @@ -4646,6 +4649,13 @@ docStoreIsCompoundFile, false); + + Map details = new HashMap(); + details.put("optimize", merge.optimize+""); + details.put("mergeFactor", end+""); + details.put("mergeDocStores", mergeDocStores+""); + setDiagnostics(merge.info, "merge", details); + // Also enroll the merged segment into mergingSegments; // this prevents it from getting selected for a merge // after our merge is done but while we are building the @@ -4653,6 +4663,25 @@ mergingSegments.add(merge.info); } + private void setDiagnostics(SegmentInfo info, String source) { + setDiagnostics(info, source, null); + } + + private void setDiagnostics(SegmentInfo info, String source, Map details) { + Map diagnostics = new HashMap(); + diagnostics.put("source", source); + diagnostics.put("lucene.version", Constants.LUCENE_VERSION); + diagnostics.put("os", Constants.OS_NAME+""); + diagnostics.put("os.arch", Constants.OS_ARCH+""); + diagnostics.put("os.version", Constants.OS_VERSION+""); + diagnostics.put("java.version", Constants.JAVA_VERSION+""); + diagnostics.put("java.vendor", Constants.JAVA_VENDOR+""); + if (details != null) { + diagnostics.putAll(details); + } + info.setDiagnostics(diagnostics); + } + /** This is called after merging a segment and before * building its CFS. Return true if the files should be * sync'd. If you return false, then the source segment @@ -5142,7 +5171,7 @@ * if it wasn't already. If that succeeds, then we * prepare a new segments_N file but do not fully commit * it. */ - private void startCommit(long sizeInBytes, String commitUserData) throws IOException { + private void startCommit(long sizeInBytes, Map commitUserData) throws IOException { assert testPoint("startStartCommit"); Index: src/java/org/apache/lucene/index/IndexFileDeleter.java =================================================================== --- src/java/org/apache/lucene/index/IndexFileDeleter.java (revision 777664) +++ src/java/org/apache/lucene/index/IndexFileDeleter.java (working copy) @@ -585,7 +585,7 @@ long version; long generation; final boolean isOptimized; - final String userData; + final Map userData; public CommitPoint(Collection commitsToDelete, Directory directory, SegmentInfos segmentInfos) throws IOException { this.directory = directory; @@ -625,7 +625,7 @@ return generation; } - public String getUserData() { + public Map getUserData() { return userData; } Index: src/java/org/apache/lucene/store/IndexInput.java =================================================================== --- src/java/org/apache/lucene/store/IndexInput.java (revision 777664) +++ src/java/org/apache/lucene/store/IndexInput.java (working copy) @@ -18,6 +18,8 @@ */ import java.io.IOException; +import java.util.Map; +import java.util.HashMap; /** Abstract base class for input from a file in a {@link Directory}. A * random-access input stream. Used for all Lucene index input operations. @@ -226,4 +228,16 @@ return clone; } + // returns Map + public Map readStringStringMap() throws IOException { + final Map map = new HashMap(); + final int count = readInt(); + for(int i=0;i + public void writeStringStringMap(Map map) throws IOException { + if (map == null) { + writeInt(0); + } else { + writeInt(map.size()); + final Iterator it = map.entrySet().iterator(); + while(it.hasNext()) { + Map.Entry entry = (Map.Entry) it.next(); + writeString((String) entry.getKey()); + writeString((String) entry.getValue()); + } + } + } } Index: src/java/org/apache/lucene/util/Constants.java =================================================================== --- src/java/org/apache/lucene/util/Constants.java (revision 777664) +++ src/java/org/apache/lucene/util/Constants.java (working copy) @@ -17,6 +17,11 @@ * limitations under the License. */ +import java.util.jar.Manifest; +import java.util.jar.Attributes; +import java.io.InputStream; +import java.net.URL; + /** * Some useful constants. * @@ -44,4 +49,36 @@ public static final boolean WINDOWS = OS_NAME.startsWith("Windows"); /** True iff running on SunOS. */ public static final boolean SUN_OS = OS_NAME.startsWith("SunOS"); + + public static final String OS_ARCH = System.getProperty("os.arch"); + public static final String OS_VERSION = System.getProperty("os.version"); + public static final String JAVA_VENDOR = System.getProperty("java.vendor"); + + public static final String LUCENE_VERSION; + + public static final String LUCENE_MAIN_VERSION = "2.9-dev"; + + static { + String v = LUCENE_MAIN_VERSION; + try { + // TODO: this should have worked, but doesn't seem to? + // Package.getPackage("org.apache.lucene.util").getImplementationVersion(); + String classContainer = Constants.class.getProtectionDomain().getCodeSource().getLocation().toString(); + URL manifestUrl = new URL("jar:" + classContainer + "!/META-INF/MANIFEST.MF"); + InputStream s = manifestUrl.openStream(); + try { + Manifest manifest = new Manifest(s); + Attributes attr = manifest.getMainAttributes(); + v = attr.getValue(Attributes.Name.IMPLEMENTATION_VERSION); + } finally { + if (s != null) { + s.close(); + } + } + } catch (Throwable t) { + // ignore + } + + LUCENE_VERSION = v; + } } Index: src/site/src/documentation/content/xdocs/fileformats.xml =================================================================== --- src/site/src/documentation/content/xdocs/fileformats.xml (revision 777664) +++ src/site/src/documentation/content/xdocs/fileformats.xml (working copy) @@ -834,12 +834,12 @@ 2.9 and above: Segments --> Format, Version, NameCounter, SegCount, <SegName, SegSize, DelGen, DocStoreOffset, [DocStoreSegment, DocStoreIsCompoundFile], HasSingleNormFile, NumField, NormGenNumField, - IsCompoundFile, DeletionCount, HasProx>SegCount, HasUserData, CommitUserData?, Checksum + IsCompoundFile, DeletionCount, HasProx>SegCount, HasUserData, CommitUserData?, DiagnosticsCount, <DiagnosticKey, DiagnosticValue>DiagnosticsCountChecksum

Format, NameCounter, SegCount, SegSize, NumField, - DocStoreOffset, DeletionCount --> Int32 + DocStoreOffset, DeletionCount, DiagnosticsCount --> Int32

@@ -847,7 +847,7 @@

- SegName, DocStoreSegment, CommitUserData --> String + SegName, DocStoreSegment, CommitUserData, DiagnosticKey, DiagnosticValue --> String

@@ -856,7 +856,7 @@

- Format is -1 as of Lucene 1.4, -3 (SegmentInfos.FORMAT_SINGLE_NORM_FILE) as of Lucene 2.1 and 2.2, -4 (SegmentInfos.FORMAT_SHARED_DOC_STORE) as of Lucene 2.3, -7 (SegmentInfos.FORMAT_HAS_PROX) as of Lucene 2.4, and -8 (SegmentInfos.FORMAT_USER_DATA) as of Lucene 2.9. + Format is -1 as of Lucene 1.4, -3 (SegmentInfos.FORMAT_SINGLE_NORM_FILE) as of Lucene 2.1 and 2.2, -4 (SegmentInfos.FORMAT_SHARED_DOC_STORE) as of Lucene 2.3, -7 (SegmentInfos.FORMAT_HAS_PROX) as of Lucene 2.4, and -9 (SegmentInfos.FORMAT_DIAGNOSTICS) as of Lucene 2.9.

@@ -963,6 +963,16 @@ a string previously passed to IndexWriter's commit or prepareCommit method.

+

+ If DiagnosticsCount is non-zero, then that number + of String -> String (key/value map) diagnostics is + stored. Currently these diagnostics are privately + written by IndexWriter, as a debugging aid, for + each segment it creates. It includes things like + the current Lucene version, OS, Java version, why + the segment was created (merge, flush, + addIndexes), etc. +

Index: docs/fileformats.pdf =================================================================== --- docs/fileformats.pdf (revision 777664) +++ docs/fileformats.pdf (working copy) @@ -8,7 +8,7 @@ << /Length 1117 /Filter [ /ASCII85Decode /FlateDecode ] >> stream -Gb!$G9lo#B&;KZO$6@53W]k9ICdOP`P=a5[dnAEt!C8gORi4Z:^TSn%I4u(M/f6Qu5V)`b?+hcW?/#04U4=qR5W\?WoeGhWYioMGj;W_>r>%*jBf#hS$N07??;IG:iWe2$GTd%P5A[5AGK.,clStMnIs*foQHm-?;6D7rjp(_fkuW9P8UVE3V0PI;7%6iam]H;hfIlOSITofT^+bJa!4,V)0b+f8okNaP[D!`crot;@qgDZ/Q,oMcirC.FFE03DgO%D/GNrrb][MfLhU*Qmad9XH*(>sh([0>P%hOHi!(FagE2O5c4Nk&\/+QG3O1@heA$Z`U8iek<0JVAPD"J$fgc$)54&K$fAj``m5pu3!*MF\&CN:;4(+,C4&R4h40sA])K64jDS(%7PP_nM'RnQXB(a.Jf#AaCNo`5O!^bp?PMcD>_SL2%%VC(D/5Z;4dMa/&4Fq'2FFK;?W]H=V`=&E;V$hEk.bF?b:[F__"Q'.[+r79T3j?H.7ZaVCIAlmVZp\E0+m>O$/No*es2]Sb?a:h.oZ>h"X8me"Ggq4?1Qh&P;RgklK_F/[Kh3%/q+F +Gb!$G9lo#B&;KZO$6@53W]k9ICdOP`P=a5[dnAEt!C8gORi4Z:^TSn%I4u(M/f6Qu5V)`b?+hcW?/#04U4=qR5W\?WoeGhWYioMGj;W_>r>%*jBf#hS$N07??;IG:iWe2$GTd%P5A[5AGK.,clStMnIs*foQHm-?;6D7rjp(_fkuW9P8UVE3V0PI;7%6iam]H;hfIlOSITofT^+bJa!4,V)0b+f8okNaP[D!`crot;@qgDZ/Q,oMcirC.FFE03DgO%D/GNrrb][MfLhU*Qmad9XH*(>sh([0>P%hOHi!(FagE2O5c4Nk&\/+QG3O1@heA$Z`U8iek<0JVAPD"J$fgc$)54&K$fAj``m5pu3!*MF\&CN:;4(+,C4&R4h40sA])K64jDS(%7PP_nM'RnQXB(a.Jf#AaCNo`5O!^bp?PMcD>_SL2%%VC(D/5Z;4dMa/&4Fq'2FFK;?W]H=V`=&E;V$hEk.bF?b:[F__"Q'.[+r79T3j?H.7ZaVCIAlmVZp\E0+m>O$/No*es2]Sb?a:h.oZ>h"X8me"Ggq4?1Qh&P<+%S@b-k>7pZEDYr5kt:60mG9ku;$S^=Xs5PVdAU+$6KUC_%_F@6fT*fdln<)AYO5!J(+tn/@Lecc&;#Rf;Lj&]Hga`&ZAEQ4Jchb@ZYa8`c=%?*+?)?B&%TF2QeCB#ZCU&`KO[(f#Xrp$\pa&-5591RYMLY'fAW%MBVLrbcnS`Wm6G$*j,CrHPWLUP(B$I&.^#-~> endstream endobj 6 0 obj @@ -267,10 +267,10 @@ >> endobj 52 0 obj -<< /Length 626 /Filter [ /ASCII85Decode /FlateDecode ] +<< /Length 627 /Filter [ /ASCII85Decode /FlateDecode ] >> stream -Gaua<9i'Ou&;KZL'm%S?E,EX&3L2uW.TB8&i^,Xn=mltP+-=aUV8'aLZc"ajj;+97N:P]oN5ma;H1WQG5VU':mii2;L]AJ\1A]Ma'V$:s)<;7^`=gQ-gdD'`'%'9-$YY-:.*-PgCuC7mZ[[@"Psa*07K:"$lThL&'*M'-@MZm-^qd---LN-Fb],#RgqFosp!ZdIAYfp/X$S/G;Hd'mL(XhXTuQ4)Hp2`)r2")inGB<0@1EJ$Z2OrUTQDPpQ2L@q#.d=WhK4_LMa4un2I9p.)^K?2F:?]6';?_RSFip+,f\US((#d;CO$4f>gduU$F86Y1g#W'6pg_%L&87!9X,p0UI(WA4L +Gaua<9lJN8&;KZL'g?4?*W0d;81BZd'e1Ee!Z[r9G8htQD)Mcd?Vg#>Z!F0fQ9(o]jgF7hO(YVRj@q6<_15C&82*(O"QASiP>=tL.0rJg;:2+VW<0Xu5>^li(=?9l#Ufce$OS\s4*3oFh*8TPX0M*)Ed6:]kCCgC%0C1Xlp<.0+U3CM0lo,TgiKfEmSJuUk4*9!W]$d";$1?_(LjXE9E\0fbh%\=_-MPjmH)&'mtI/bm\'@Y/Q\W7V>tsVYmMKX54q9I2YE]jP5@;dbA-C!bq_!o9Jfmi>-1.B%GF1mFm)X5^Zhq6;qCujWEdO;3k<1;2cK&'U#UYFAXUgBM&hhZ`Vc806Rmc"s6_SdJ.6mRdWb'kf;bOF0g+mE?m&_\Q1\9J_oQd-;8:?$VCTUB1'DZU%O/76%i3J4p endstream endobj 53 0 obj @@ -454,10 +454,10 @@ >> endobj 81 0 obj -<< /Length 1848 /Filter [ /ASCII85Decode /FlateDecode ] +<< /Length 1905 /Filter [ /ASCII85Decode /FlateDecode ] >> stream -Gat=->ArL\'Ro4H7.W19<'3anKkR;c0r;7Y]!P\/eO[jjRG^>R+mI!T./ii)h!d&'+]MIBfWfk=o:9[PDj/c.V"J*IkHeVemVJ\$X7Hqs3MJdr?3Vf45RCRmFP22qM6fbYPnjD:o>#0AmOKF\a4'Rj#J)2m;a0=ra*]-Ynm"EHKC\V/6-LD=ZEnTT4dY!9cG"hnG,mZJ&0H`*Rki,jF>'K39OE';j<SmXXP6:L+:k6SA'.j*h%&^NX8X@NA`nsqRJlCdQ-puZ3Z'nM*D7m8!Ii"Da[hZ#^trm`5b_pXL"LC60L(iF[1)Ie8iJlokS:I'Rkpt,qr1brfd?2G7UK6.89_Ue$]!dJLD1"KpbN-GEPS1g[m#WS+#AKKp3)3U:TmB;%&4rBB^kZbHZ(YY%nHATGI%l#bm))+]BQ_,AmH.p""ng,`C(8e["*'g#gtaAntGeuf:V`.DJ/"Oe&t=Ea2CM6GBN>e-L*iEmPu[+^%(Ibjlsf3&@gH@2?G+?WM`jYbPb_,kPP&BA_-jl49*4mVmt#Y?7@kS2+qssgaR^s1]86E&`Yt+XC4]+eC4SJi[hN:DA,a,O]I#TAb!t_OYVgqZ,6A^WKiPreQB;kpFV&G%hN]<#G`RMhcln'R[$Iiu(KD-":+N_A`rXFYfcDuT`ca.n%L1HF3%G+OV)XDVhk;O8C9DX[]EKcbd4-ug?FkDF*Ahf?="K(s*iq\i0S:RrIgAP1:h#^&&L8\g!eu=UQ@Y/pdfDJ&`2Gp9.OqoVdf_\p-Wi44KmHlXV%AR^Gfp>]/VO\+olN\YZDT,P9qDo2JrRiUaHfCc`IcFI[>!*[q,(C<5FO/G&hoJ'M>&lTf1DK/WXVZg0k@PWoq:JBaalA'>bK&iQ2P3S/jXKdL@+6)%\ldkiL)g'm8fpq;HDHk&CR4a8;614!X,=(7_fObN4b^CJ'&V2!NrrJ)7A4g7WqTSQp<2D8!QS8gJ*dOeG"&.Et1Vr]^O7SKoo_AZQ-mO/pO9Db)Ie#Qn[4RmjB%$0$!qbboc@%RInT4#K<_lJPX]EhnP:$[H#I2SDU(KoEC\KKQ_3lj"g6?;O[Od)p+]#\q5'Af)rVV8n#=P[[2Ah'G7'DWAMQ1"5?rTpDqcs1dWCR:Cb3\p*hC-SZ"p'iH_cU(pHK`$dqU+d*+Ch0TQrsPL&kup"?msnj$aE)1"CGG49ii(W,Fe=?1 +Gat=-D/\\t'`QC]M!gVa8gQD&Gp1nkM$p.kl_&%GeWn.-9Q2*n,[DBBV8%K)$hu]dBrEM]fWfjroCt>d-cstSlYbGQYGEa"qR^[VR]7gFD:AN^Q!LjNdniab_9/MF8*fK[_nQU375sG$C!bTs/etEXT7XrWX/Yg-1U<'LKDM6a-Gkj57('h-q0eqRb`__n]!6/Eeman9[_98eYR_,pO:!b0e1(AN?]o2r#=AVn83=4rYk\6P200KOCkKGEM4O%&4%RO[)MhR3!$\omqJ+)^:gj;K@oqH35Le$+?7&J(G&Wh]6/T2s4B[*p+=qh..%kg`>jkOll/\*29hni.]VeADX3-VR:Y+e=uLr!-taF4!eTX,/`uiiFX32K+dIA'XpGD2026,-$'?-3-890/S.!]=1Zp)t_'G&7$=Em"*=.uEhA$JTh%#WCTl.;X8:V;C>pI]<#OM;,kMlh%WN.A]hX7W6fi>S8UF:qT3h/>4hODg(dJ3_2DEar"q/GtN2nPC1'Y)QpU9-a:o;CcnpIcV_\)H1_N3lk6;TiTs(ZQBlHM?HV2]_S)O$RedU#f%)$+\8LCmL\>3+-/8n"I9+KW4-L?&HVep[&)>h%)2^7rp#>#mT/`MlI&Vqlqg%C6nR\1?S)puX?e,Z5%0OThRq[/)+S0USYEC%C*\QXrVj#uCV5s]J-81hf%,*`gmA;2m9A2%=&*/(L.K$\,Y!,t\tO=(:OGe/VIf$=sn_<39B$lmDY/)C^C'Kfs7d:>1ZgBA9.FRLJU#WPFR(dYl'=b,%uF9[*tS5i"'d/\MBo6NH2,d/$&LI`Jf>`d;AVUCo1'/pd0$AO1UEB(39)3mZLs-sNfj&jaMM3Uj!<#UKPA85@>1^n5!Bl1^dN.<3Qn3OQW=CJgX;n=J!j!q-Bbj?8r%mW+aJAH?dViA'S5T\+T2'il7(,fpD&]C4O7516\neOO<"8;N?;UhAG]D]ar\6s1TX`alo(61@+e[/$=[q/L6[p[NAbWu2K:3tFMC/Z@O@BTY56*V4E^K[PUK\4$30`^!9Wj\(C03='N*76b]7%(UFMX3e.tIt[nT+,':eu.eLMs6IfZiGI/~> endstream endobj 82 0 obj @@ -469,10 +469,10 @@ >> endobj 83 0 obj -<< /Length 2288 /Filter [ /ASCII85Decode /FlateDecode ] +<< /Length 2322 /Filter [ /ASCII85Decode /FlateDecode ] >> stream -Gatm=D3(/U&H7-n!o94"(;\m.8!\!liIB?(Y=I;.:=0bKMcg]WGPeY'udEID)B+;Z1rh("pO6VUMO@ht*?#M=3nZn0=uEf&GuhX4PZME849<%+AS?q\F>(X''UW\#X?d>sI#Jm7BJ;6`fZ>/dF5m%aN$8=P1%hgA5*e>.Tch%N3QH+W":jYhGd\!,RrGa.!XUNRV$Z!_'XF\):)7)C"%*LA8ijp.1Sqg=JUq(#hRA<&E%KSeg-O4OO*7!09)n87ob)h.r/(X4fq$i!1*Zdn94^f>m[f?]9kFW-bfVC8T,qkS*#k\IZ_R*EX57IlsH\c&jZNBSmChE/n%K!o@:5&kT(2V*NM^-kGSh\Y:'i<9+W&`!Y)Ap+pLj'X_Tb0PJ)B#E8/5A\>dBfcL7a@,LK8i>A?_&n_MGBn&4su^t7'"&^%mfW$`KDlS%H;=N$5k@J$rjk9FQY\mp;qWZ!_Pq?]n?`[aa=[!TD)I`@8q0\F!5fmg.A%q"bfr01Z7C(;%>eA'm(uU@)=C=[YG2][OeuE)pN*F7fXsUL(u*FTQRn\f4mK48t/W6N^Co=Q^7Hj:N*A<1%Zl-%&la5haO)E?o=3odhuVBCnF,Fl0qP5#XJ6W8A5M-Y4*@J79ul3"XNYjj7.:`4@LZFJ1g5E#lM8o&D.FXoUhKYE10auEk&da\dTEI0rkA,qU>:kY'GR4>7FeB(=frnkkjEI!O\@-q?:N=I(FPkII2H_mqG<.?4p5\P:>2`;>/O^L`=r+c`W.=]Q$e6FpPTOfN^D.;#3M=X8R[.ZTpoi`FH!9j!!A-&W;Ao**aJec#0M+W:Xq3l$H\"a#j0cmtDd-\&=X/5U/&O;(.+>L<07VEfq0pd][>*R5o6_Eke>WEsk%rrQ543]/s?(6+eiOb/UF/_@U@/].SqXZXs$^RI_fL(48;5[@_o`c$BL#pT7[>C5"N1=5I$jMr;2u>&)P*.IN.]NmMKPk!-M)*ETL-6i!,7uJ]XbcN\/5oa`BXDdpqg,A>8MkAR8_'&1@+P5e.DJ%LM@L-;HU<<'H4lW<8Q6Ho43bLV=lk^?P+3LDMNiObYeY)g816JL](Xc=I[0DgX)$I>a-)p/T;67(+;#KY]t>O7 +Gatm=D/\/e&H88.+lphpTj]6MY8]0g9p[J$d<:M)%TnI:Q7/5Y/@m$:a8>P),g/5HUuMo"d70p"o'UekNL)TqMkB/Kh_%$(.K@)n86t:;;&%.PK/Qg\9c?(HbjIfW@0_<042f6\h/srm`BKD.askKI`'_Uel;Gs/]eO`#C"/Zj*q#JT(;FIg&nsF_.q>WRp',P0(uD_[EtY3E^/p;c<)MjP9(d.OU_]!$=Q[.jd(UEWhc1FVQjc&d;5c\/YGk_H5-;3BW*Dr3]DUn?g=h-+WQQZ,$kc)jKmX`DpO66m=7a4>o3R&28LOP!F8Z=/3dEkp!KYp/k$Eaj5lZ\uqJ^]s9HN*'NaCuSu7Kl&Ho/MsDp6t<1S/$+h]ar*:1qXJqPLUqe>]!+aj;,.-u1J\A5,!2<5<&^D.0re%QP[:VLkd:B:&GkoLtj_:R:lc\,H[BLdgXh-*M3ZHVA<]6X0X&',gTT;+_OWuC"1YLB/gUL/^b^:tF#D-Vm34K@ChBgfmYh6!8=T_]c7eRUiMFXgt?40;&nCiU_4[/]-`N:9FLYAkRd30o/E9@/d]K:M(q)aTGUkLoX\q4t@:?RTi>)RYl@k58Ro^-ud97a9&/:@Mr1?Uhb]-8B5rX.s)*"IF[sI.AlQKW3)j2*`T62UcIV\&$N==Dtg*^Y[<\-0cjoo6S;=7Bt0.Y$Gc+)n_3jsO%R[mgs(*odto3R(8qBu0PLThW8o0e[J8n.&Q%BDQZ6&=Oi^8ol$@Esp'pn1CV,@+L*2CiXH_BVM]Z$a2Na/[Z(4detllZTt'#8u=Up&R5Y:3tCsI0k8dUHX_OZ$mD"NVOh4q[k>jf?B$e?H0c.AVQ#D6.3+\_=\MRjPg+P?,)@VP8j>:kh$mCNIhIQXt5!BO6l[gDYDD10e#K1=bMd1e>TT>0TO@,%23cO]Au$>N#=D=MPT0M;&R$1%Yd`-H9N>T1*6PprETCBdLq3R+o$\?CUl4#p7";>L0eL:&l'1=%H^kH;WBO@\l^hTcN1%&1qJj5I7*Q748@sl0Q(H]+Kq;FNB@rTNZP*`=$@"-^1ln`?=+RPU_oK1IM(VEke1]RRjbMe$`.!c>P;c>*sS/3%6^!'M6_^16VD3)+;WY5"PQ`?^!2`Te)bDEqB#A1I`KeR5C^.4l+2@^JjlgGjH?bO&DS[L]a"rFd5nrqFWV([)m_lSmS9-d:&%uuD]5BHc%L$Z5!9eRcHWGsY_$^%,gU?"#gK#*lbPDjH+*;.:0UA]OhNAjHaF=3E[l"$~> endstream endobj 84 0 obj @@ -484,10 +484,10 @@ >> endobj 85 0 obj -<< /Length 1538 /Filter [ /ASCII85Decode /FlateDecode ] +<< /Length 1575 /Filter [ /ASCII85Decode /FlateDecode ] >> stream -Gatm@Y9VrFC-iNm>[r^3iXA6ckAk1sa>_kmGMC*/$QL/Yn&Ijoa_OeP6jNh(^JeonCsFTr2''Mh?8AW$FcQ7_iFq*Bmj;[X'IJYq5-'DL_CW2=TN8[9=i:ePG^7n^`P7O[q9,8L/+L\d70Cf8#2nlI6/UoH#gEJ/CL-=o[q9@#KFrCCN:t?h>9.^>,(nh]*![p,F_G/h/W@m$lYS'i,FkjFW$=-!$;:9T`.^Nijjt^^S+lJqYD]fmYBAla$b!*]Z%NqbQ9,175T*>eni1fllIm7lPlS\W;]3YEZ0ZRLGB_//AUpd2QrT(Y.4Xs@0:*WGblU$d,l:34iu^:0i$Y%ibJJr&S`2fO-NSbIH_?EM%%)Zj#X#DC=L=2.*T6"-)=jICEkMG\'_d!9DdVX?!O)]!'ghu3><2dI5%%[lPf'l+g@E]$N5"3FuOi65^(Kfq_;L_C=FVDCL4?nBU$*H->]6j't$@pV%sDg[Y%Ap1B_jhA/!f;p+oif/%A4"I)'<)c?\1n"d8B&QDV/ImCRrpLeiW%1-dQI@+m@[Adk:3aC73kdb(>?8GT,pb^9;;\PX'j0O'BI>ib-Qldhc6=n(')boFIncJDB7kaW^a:BQ9W%9!,6g"Ik08#7(CXpj>$Dj/FK`H?$BD^^HJ07A`nW93H_@hS3enT7^+1p,aW7#u(W,$YZnL$VWiiDQIbn2YO#7nS[f1,KHV%i#J-1EeYH"gh][p>B'Q1`4mbsG3r/RHhQ3A@79ZX0)ZPX<+o,TWR,-UNBT2WpNQd*^oMlsO1T1%6$8",&LZ+uE'12\J)A:nB"bjtN1\6.Z?es3t#'@pe@TlN[J_Y`VHnVFDK?2[COJ]tBK(\r=TaXK9$X%:.1f%iUK&,1(!GLNNj?4X>~> +Gatm.*e"`s3\S@NE#FJ1sfI!PVEJu7YmN`IOmagOKa'*A>oP%CrNZ/i\C';'J:PohW.qLo+HI4K^j:s=M$_E]t@_5*]J1NYP?mPMqW7u1\Ch*apkTm2j0(s:k>n:uj*F)YM!=_b5)a6O1L-jB?%U?%r:D>kh"FM26+mU39]g(OQ"lDp&/07fij>3:nc]QDO36MjsG]en`CmJZSnW'^i?=(F*q7rPPLd2h!ioP1HZ%ahM#+CgRh7I7uVNAOSPQHlq($60i6-O#h6WgF5'&!hX4k>rE(^-=GU;dW1#&CZG0)pSI>PO71LP?YbL0rjUiJ>d)%Wr>A8Gu8gBJMCJR/+V!Ogg2k=KQ.h,mMQ0U'=i`_S-ieJ?=jIm$cX29VPG7"RKCp&i8mSWr??](ss<8'>,-LWZA]"8!q5M$t9@gV0_/0q2-lCaY@(p`lD;HKiQ/dk[@@mmJ!KYH<37k4@-78N#k!nI*T@;QcmXn5X!g%&Tcp3i$jqa1omd%:-=]Z.'e6IhHIfgTCnDWgRl6$U&2XEPaE+22_Jn>E\Ybr<@s"#o=TC[),[S"ph6V:eYD&l-l\!Kb,lfa/%.l#Smb1%kYZEo/=fKNX*t_Sq?[gU1/8qsa^M4-e76`JH\U)_-QmA[B7TKf\D+DA/pto3!P&De^)&(350-)I261-,HngA57H;B=?_T78/l(J%Y1)V*I;S/P0Tpjte/l[V:J=SU]'P6Ocj=b=d?\U<)(l-R>;+$G@1^ endstream endobj 86 0 obj @@ -499,10 +499,10 @@ >> endobj 87 0 obj -<< /Length 1455 /Filter [ /ASCII85Decode /FlateDecode ] +<< /Length 1386 /Filter [ /ASCII85Decode /FlateDecode ] >> stream -Gatm;>Ar7S'Roe[i7jcq<^]R0A`s3>c!4d-[VkX3Y[mnRM7/,[U.`mT;XDGbOsT]rVNM?*MT.]i*.Ih2Q1O+uqrQo1"J`C(s*g.-Sr]TodXOXKr8I(\N6Gm87X3\Uq8CE=YF(.VS_QW5@g([lGZ=<:+-d0>Y^.s35l6ueJNeY^\5)"&R8Xfj]:'*E>(a3KO4^6btW7ONd=J#4l?s=f![n[CT%`Z*u?1bf2m8[pX#YW#CJ/NcjW,_?prmiXDu4K)0RFVC(j=AO_=McUrf=GgV:p`[fsqDne0e\urR1)WJ]f[39,b_Yd9AXVAQ]g/9r*iE"'p>.\pqe56!?"]O9NiZ)PsjrD=o4j;0tp$K@"M]Kls2p/g-5V?+l`g-=W=5%H9Je/,%/=U"V'E_Vn(*_+M<2,h@T&WQp6&mbNKh5IHC"J1#mQ7f6nn:LaB>m9?i$ao6P+RnbnlH[4`%0r"%"(NA1[-n"r,&nLD"+5n]WJ)?Y\uM&`F:]-9(Q:$%&)XpN:P5>P5'F)[;25QFHLX#o\^bP./VnH7;=L);kae5$a2j;O"Rrph*N+([ELrcX>XXP[R>,OTRa,9/\s3357e`T.:bp'C#!\HLc.?"Aqi[S^X%>OOmPFn,q#*X';#)0m(Q&;%iq'K\?CAKf+q!gct\hF**9_4]Q"*_[TU[o^[ImF^NPTYq3][*[EbS59o8g+Z*Zke>g9T!&;7a'KZS"G'`q)OagWl%+1"=`b/g1EbbEWS6nI:$du_5PAR?EN1MpD(&]_PiMJ=L!q)'HUJ8*gOZ90+a\Jh%7MP)'4slhKhML'`/Cp:K29&3,R=o#o&`8Y.e=#nV!;9Ulm"56>lNRQ*'JTI!lk$*QN~> +Gatm;>Ar7S'Roe[d+a_WAjfhPA`sKFm6"o-ee[uUY[n?P7,,Rhd?EcT.JDdld?8aQ:iV@$JHHsNkJD:(IcQp#-9n[\s%KZ+PbR0j[5TDcda]Q)793cBIsJ)%#AQ&RJhaZ-X4GCoi^TmAU#Ip_-.H$]R'Aa[BWC"`%rDG.$f#[=NX!g+'XuIte1[_\Q=E/1lN9PdkZ9i0#i1;^RIU/U7M_7,UJ5oM#Dr_R3]j+Y%/InG%MFt_;R3s:JVO\V_-+?*;C9iP?6p)_AnH9!\]Q?tQ6;0tX@N#P1!-([\5F#p3;*(hlmoq$me3K>Enb-JB]&%gh-HMH+XX>oeIUSr7%M\:DDo'J44b2'5NP0e5dRi1bk]?3qe\1Nl^i7T^q*$8sP>%n#FKO5k!$B[)*W`(NoGr`1c;'$Zg!03PHCt.m,&2UDNH$V#Dj\?-mbq\J0LQ))"VbCY)_X'"c@8Q\\RhiZlb2"KDUm6:R]6a`q@LYM?%#1h63YES#=kMbIF>epV:e0Ro2P.a9*(l;WdG=NW*H[n[kfTdHTX8k=5[)s9$m<#'>NoH@?nSSEM\L[4;PEg3+bU(.?CP;I,mLe_=bso3UD2g3e;p(s8Ec+eiJe"q`!lo+93qf,Jn"n;4$omo_72->Us/?Y^9@n2^jL[:6!uQON17L/Qlu^D'X$tDba,=3a?EssN`^9&E%m)Jh1F2W)f"tVK7WK\2Q!pT"pb%)^e;*g@,gXXo$%=W0Xt0`eSt8YC%cKK.*XgOXOrD&7135GI^_WcJ%WOe2n+o"^D-'0:_JK#",FL\RT`VHZ1Ki1p;L_m7($[54"\&:DOP8;E5I'W,22bH4sIAu\i3pHNJCq@Pu\X*QNS^sg8I6AXmHW4Y]&m#hd8R)8JG"J]OOQ2&lL@m endstream endobj 88 0 obj @@ -514,10 +514,10 @@ >> endobj 89 0 obj -<< /Length 1481 /Filter [ /ASCII85Decode /FlateDecode ] +<< /Length 1492 /Filter [ /ASCII85Decode /FlateDecode ] >> stream -Gb!k4gMYb(o\EjtjCJWoX!2ZkL&c!N%j'.B6eoE"H]TPr-74W\7:3@(+!jSBTgP\P([P]eD"o"?goo^mg$%VPk])9GV>U6.l/YLH';fLD+;TqL/"pe]6QCOFscb1+Pk$8*.i'EfQAmjJ!o=Ao$RjCZO>3IlaoC,tW>*)3,ppl-Dk+It"gM2pN7a@]osoCB`+sABd1>1Cd1.7KFg;a<:1MPTRKQ8X/:"PrpGb\0@MO]9:kFAj!e-aP$29i=0?U&DrY#AD:8fgpA]T@9Q=;G?G+=%tDt95asUJfYrJTT-mFN<6*$K5%0tm$$9'XjU6I1^s"0"<*V<,I"tIGX9&X?q&QP5AF]csf2jR_DNi7h.U?O,Ylan`p/12CC@i+T$].DD0SQYjO%GD7[k;[a]5+PXki@"PO=>L=m-_:%`\CJFSA3U,b`$R2emC"^"/Qg")n?;Ru+.s&\g!:3P"r79<0+K`Je[Pf+8mfm+NY?1nM8bOd[g_3AN=*dpQ6uH-5.*qUMJ2(0kqQ8\-K$X*A):j/No'MmqU4MH@V3nSmA6-soEI=6toft/im45@G_hL%S(YK`lIA&:IAN!l(mX,Os5()I+OTOfS(RQ:\`"VH)JCs)_r`tTDMJUPdf@6f"IR/@PKErVGcYNg/>dW=gKqJX4gE-\FrH>C]T^+>kj^g!cf\I4f]*/+u0h>?U:5KrWoT)R_#hsc89g'(V#po],Mf="7bYO]Z5ADjP+H7TSQc'PPX?k[]K8(93HPE4/BSR%l]*`=,[6"+SmZqkFhh0%;aKW>]/(H5=8`qpLPIO]i5$R +Gatm$spViYI3)D7Dji$VTI.`7Xm&)E_#uKtYhI>mNFaD$l9^KN+eWuePe"@@u3h9UB7JH5ArC>0kmG6lmf[UF:5rmI&6"PWg\TC@Qb-#Wdt\,\Ua;luJ/MDc)UPT3[Pkr25s>]&*:&#Vr)HT3g3\%)6+7ABp0DW^dYhprFeDX)iA'M,3JasoZks-IR&fk+BK+u39o8%*1nDWqh:RZYbDil3Uf:Jc:XDQqbj8mdfC@:5?6V(od:i8o1D`0">#*9k*SOa2XT;5b-5U\P6o6/[Rk.qGV[&1na[q\mma-MJTV.Gudp1bCcM[b@6KA]6c7t:qk(?QE+KGS2i7d_jT+HSL#(f(b9[&)llI'iO3G#B>"4m]?P%!"K6sI_f$N`?.]RO?>[9rV_70l.SI.!FTVMrD8Ydt&Z0ldIY@NO@:D*X%*l"#5%+!c?eaE0_,N+1.fZ(Wh_lg+!9b/dJaMbT/F5l*cu_Y*a9F)W@.IiGGW)<4%5Z`2(;%L#Bk=#/j.m@2Qf"N7!LgXH/phGEIdt@(O"FZ)>fV=#FgQ2>6kj\11IDM]A'J)q1=q":[AgO#rk9]o@neB6!K+Im;+c5h@64K]]'AO-e5gKF&-gd?C>(>0VPe6:nR':J4":SlV@[K;=M,A8r!"Fn9hiKQ`LD&B9ZlNCRI17Q\Y+ehkL6+<>YK$XXd7C&-oOoe\>t,r#d+Rcn("UfM.F&WNk_`kQYV.(hl=gqA\H%Y&:S:IdFQ,[/M98UO]`'fQ+LA@]Rb[#c1+2nm/[\Q/N:!N8*ae%i$K%P)-oG/(C)[`PbCojaNi/pO':`Cq8iZOeggc%LCW9eO!cZlJ)5F!CGD?ms-@Sq_<)`bZ1BqXM%XZ^fFH]dHPPa>$\DP;`@m7aScVaW]?C~> endstream endobj 90 0 obj @@ -529,10 +529,10 @@ >> endobj 91 0 obj -<< /Length 1756 /Filter [ /ASCII85Decode /FlateDecode ] +<< /Length 1687 /Filter [ /ASCII85Decode /FlateDecode ] >> stream -GauHL>Ar7S'Roe[&Gi[885tGsc+m/KQ[-Z6!?:=sA_mM@;%>;OF8>U%O,*Y;R/F=Y4AOmDXoY.JP_,2AaLl:"$]E%U%8$^L=RP=NeOQ6&8gL^9u3(8F9Y@Aq<'Rt_/*haUaTso:rBM4VP?]`*,db-1Xk2E=$Za6nHL+*G%r5PMR8Idcc:.hA*2]gk)eb,Bq!BUJ>[MId_,oZ_-fMZF3=C0nA^&uTnqa.eh=l#%,Bd4_Q[Zf_nL=un$ThO=Qj%I1rq^[-H1[^O61iODfa'I(jDkAX,#S?\H\=%7]p4iugMVNA!^e?iC1WH`=Bl$rQ(&*OEV1D@IaDS`+_j'FU,F]5L@%EU4*&o`\m@JCfI,&\QNcVO#`e_\,Qht+N*Hod\)_KP=fo$>j>hY+-Ls#%s-n;*K3rco1X_:uR:9I^g6bI8^k*:Wtm4^@\X];6/eTMjQ6kCpY4\Fdh?.AU-H0_qN4"Z(jQ%G]lA6``3'6NqrmTXT$ngLBCJH^Y!n4bOa=-l-Wu]9224E.T5J03=tj$%FqJC%QBj1pLRW^:Pg(Tm5[ntkYkI5@[ASOTDb;V_fNiK:!LabHi<:OZib(O"F6@MSTUM!qE@G'>&7!()n?Q8oZe#fXh+6V"/S`q`]1..Y$$R)tqAPXDlf<\R0CZZUoIgZUU$Dr3b&J`"JLcS^POg5nPm_ic5]!%$E.`aI3F+]W1Ml28n(mJjGuQ7gi73I4T'"H$"\"fo3s4TLlFYZ$gs$9=J"@?DY+rXH&JIrPP\NjW;DpDaqs:JuE>SYk?s97nEc#fM'o+5,e1.us;gRVS"gQ7.a;#XqU&7Yc'KIK7a\a.HKdGF4"AF4K>PL/`qBHS+%aHJ\d_M,;HL\Qr4nr<(.F]S6~> +Gb"/(>Ar7S'Roe[&Gi[8LfoScc+m.`DNVVQ3R6=^fJ!F76qZXbO5Ds.hTn\Vc:@W(^g$'\T12a$q-G&]qJR3.cf8]%UE4.Q]moS8DeG1K@/X\DN;Q`!f0=g&ph:rk@2/U42d^pH?d&Yds%#dO0"iuW[9_im;6a^JQ"EeI;)?jDaVIPX.U;l8p\klZ$DJ9Pp15WD;KOS(i&ohIcR0(]%@HOX>W1[,pk*At`.33I&CD)gE\-@+?LpBre7\n1R^:<`b@tYBgGfE5jNh?oAf4R1Y\DY5_^/2X3ap\!i1/fkMQ#1"Z&_,+DiY&d(p*8XB!T+7`pt?"gh92FMnr7mA.E\E"JC=HpDXrpcL=Z>s-jNS961kDVA_oeA4#:keplM\IR_rBdRU-FThj0NRKS=^Fc(eebGW'l__8p^jf#1l&BVOK/.oL@QF8)Pl_U,O>Va&ks2)fYnc[rtlY?K=!0VnC9pN'?WsU(*E"<\V5#m%S'nT`S.Va-e$9eR_$qtIgi3RUiNXsN\U8,4-*:2WoUjt)?%hq&7_PI2=@'"#.\HQF"^_>;+*hH;3eG!p'7OU39Wgri;N"7?AUA`/l1KBGA[c%'c@SFI=9C[AKdKZ.X7^OGr%u0@](?BL%8T*XG#mu7/.O_j)CCZPA($Aa1):W6VJ`Y7Y(2VFfMI/=3#>-+A7\t2W[?f%-.$sc1F:&erV65Q@WWeb.Xq>ij\g*08tXA7'h`6L(MPHH$jL+*_(jrek[_K6^"O=)S$N:j.=3O,_);AsO'qTq1($bF8"d;A'&H*ZR-0+a)6j&7VIb%>*fPHho\'PoCTI#tmR<1-jnW3squ=MPP[8A0VME?&qG1CjZsLAD1J#;VEGrG)e/*^I_`fsidOcp[5&+\\Usu8m)6tfme`IB-@CR+e9"OG-M&Jp.$uRsa=&J"sS1g=KUqQNePhcnUJpjrM:C[&hTX$3#5\0g?]Bs#UV#HYINiZa=_0NXL/Sd<."R@,\]H&FH]`-0ec%9hL!N2b<;BPr`Mo)8\&:Es$~> endstream endobj 92 0 obj @@ -544,10 +544,10 @@ >> endobj 93 0 obj -<< /Length 1742 /Filter [ /ASCII85Decode /FlateDecode ] +<< /Length 1758 /Filter [ /ASCII85Decode /FlateDecode ] >> stream -Gau`TgMZ%0&:O:SkcG>0/#)H8"<2HHAs#MYUg9aD=Dn4CU26R0kYP0Io]o.BQ8t0X451.#+LXh'1NS:`0'7r.jN#7#BnD:$s8P'8/CQA%hrgW7-_BLmK1t0D%#0bljQFX?_Zn9mUX4#ina.MG^-*tR%>1dBnX%"<1_(ut=/nO`=j_26(Dt6PY85g0C+Q^d+#;QPY%'rB2ATNWb;:mno>6mLNM,MV_bW-B&q\:7j/]H[U]]e)B&j.dGSZ(4W:gX1\#NH9[V^=3C=Opp=DB]Lp*<-GahbTB(0+%c;U/6\CJN"Z]VCmB:2*UEE<0G82^I&bABP9!_q,W8gR0&$3A&fI(9'2TUDeoeR'"GO3m?9n\Z^=+'jO)7*'kOE9jA,nb*h@U!24L-WWa4Qi/K;59>%nkFbY6OBVNdk_2:>9<0kds/MH2/I/[F^Xqof?Z)\$,qtp]Ph8WG'eqmrsZkhe>9]/2N*Vn+i4Jre8h9n^8BP"fI)>%L$Lur/aEF-Uk!#Dj;qQ!Z&m7N[gON3#-m78M:(gG*?=o.J`JPYA;K<@F0-dI;M#p8u@BB%\a-q&Am5R\"0H?D^VY+@a/aD^11VILR03R&7jrI:f/X^hf*t=SSC#&EJ]YWm<[.^dCOOZM.Iq5Yl?+BVG=3%%(>E.[&;,bQ*IE+.'DWZt_G>14E%g!p3Ong1+BH]&b$lgbJ_#BO,A8\KEZR.p6nQajH`J;:ofGRm61qN3Mk`KnnIa-nWK$DrR^brCo#?3tj2`a-ZT(>"@%`G)e5%>dV:b0L`I7kJ?.r.chf_N]i,bU#8cMcV>`uaRi0l(E4(2;c-f))Jf-Jk$E3OK-IUkEb"3M>NZa[l#ePBfru83"O7jBp&%=G9PR0*(%h,A'H(K:\0A<,4/f5/cc+U3C@coGQqm'W7,aK"f+gD;##1f7i-+%-[;tqh$d^/uR6k2HMTAA%Q@c66Bnp,!4inIT]l"(J,<`.=kIp(UIu3Cu9Gf6p+c#^HtMIY>23NTDLObfn*SJI_#RUY=Y@m]\OBX^#FqX.//dliG.?c4-J^?U^I't0\=$OK^34R_L],LG0L1KV$i7;Dk%G*EC_]TF)6SS)`f$M0Vb4#h^,#[H#r6QL(s6H9qmL,KA?a_Z3R]=+CSCY_ld`iC(+4=.3::$Hjo4,NQ8d8EV5hnQfI.+Pq]ZgEUH\(-$'!V9mSdI#p'Y=I$"U;,_tY?8KcPIUC+*@X$3%>9'N^gl)-A*7*3LV?e+U`!ACb$[,-B+PCPK[AjMuMI.RP7BN5TaVUM>O,i-O +GatU4gMZ%0&:O:Skg;\57\m1n"<6\Socch.UlEbcXLE^2;`7KE9QZ,TIXOf015@VrB=A/0L_Mjjk!#QdMp]k/dIRWJ)tEf:1p`<]q7\N]\t4;@HGi=Vk?%nq,X;Se8m([W`@b_:fb6%CUHns+@DoK$i&0p"3C$6A1/mu!Bl`H!;+`op!$\*W\6AJV*ke,mhFoTb$WX1EnO.)Dr4NiBN.LnA<;g622LbdirT8)HH8dPQGOsO]'H@=]Cf;jk+_YSrj>_JLF`sJh+XBiY&:`@dG5LPM"rfBRd.@2A&incupu9ho/^spZu$r=iJB!Ieh##X,Tnnjri*k-[(WS`Ui1RYTt,)TcM5J>3I)f8W,;g%aa@NT[,L?@j^T;E,&Ol$Ts*uT]>?!*qBOKK?i&g..D3!G&]REe10U+'sW-7=/;pNNX60/k&Hs>*5:9H)3"DTm8HRW`_4JG%A:\?D%Dln&$=&nLqHLFA?XcI1L^F@oZc]SYg%%Js9W&u_ibBXpb?H:>T<&(&;&+Y'o%4DTo6r6u&8WHIK>2L2cZ')7[lfs<-JEA$U04,^!,4a]QDR[S(!%S[?[jk0p)W8VS]F0kY7>^FT&uMWgXB3p#+Y^qc;YsXi\RL9p>#!#UCjFtP\V?.%j?Y6HMY<[2V7D1BXS5VXQA\.W)+[2Vj"!V_N`D5>$:]M9:6rqpb:"6%lc0=>D*Z@mYc#.Bo9p2?_=qL"#uhUd];AKh/D#1oIT1a@8H:T3Y6XJ:8egIqmW,)d2GjMH'GV@@CXM)A+Zb$V'!oqGBU0p\:jEKCtS4jIEuPjl/:K#8GW]OU(J"A1BnaQp$%h+W!uXD'tN'o^p)#(EX@6;c-d72)Y1/]6i4*"H(9@/AS8s-3c.Ndd'^Z,HqtG$Ci7m2Z(6N;b9[kTq%`5Jn\1n7g$:VP7eM.F>DGPp")aa'ftCaL-he4F$T\Mjm((l4HA_oF59rf!`(8OPhnHgFp^4&<\1"XX^f_?Sn:LA??GD+8Dcl5`F[*U'RC?3ctpSJPjc!==LL,CobB0Dd8YQK$&H:Wcs?(H0]`aTnASpa?+"u4j_pf'6ergE_`\I\OU^]+GP&5B'o+a:LYSd+9V_6"[932pN9/NI;>jbmc9-\pi&,@C&kfg79,f]Dbr+:aO'"B"\Ep.d^k'NC2bqRgdl\7X;'l:3nlkb=L@O*!q.q78I>4''SZjWP endstream endobj 94 0 obj @@ -559,10 +559,10 @@ >> endobj 95 0 obj -<< /Length 1915 /Filter [ /ASCII85Decode /FlateDecode ] +<< /Length 2076 /Filter [ /ASCII85Decode /FlateDecode ] >> stream -Gb!#]>Ar7S'Roe[csqqZN(Af:$qlL9M2N'^OfcW0jpb^7g(l#nY!hIDmmg!9GUQL6g'g=\Zk4VTSF`:5:Ynl:f9=V6&b_OUhhP(o,N"ER8GsW.rHq(+N!Km*P'cquha['q*XI.P#hXSiVB.)Lb@E?ulVkOo_-V2G&et/82d(KWT%rpk./=hNN7=(ej9dHPr0(u8$H^HrQHPP=58UZnRMXDbaU7W%iT9o2<11ru;'GO[>k5(eU3XY6\QR^QilV1)nsLoh4k]i*-6ISZJeWnjT$<;#3@,I'R6U33fo6NJ!=&r<%mZL#c8a#C!BBrI.E#/%pe5914F`*3Z&#ae.OS1.+jr\gcu(/URALC#L]OPWP*OIt+)O&uWu;&i$?u=J5+@^"A7AcrqS$EZ]67t3aM'W!ILEaH?am\8ETGhF;iHl_k?*taN_aK)Z&FeGfN2OZ;-sHJ!&o"a$QP^@1><)-;(N*s8$SruAp[_$[:1/dil"7O9GEY$791rEoStBu0RtReclimQG-P?1o\Y<26W&:!0*q6nO=_3#N%a=8<,8IghH$;ShIFef&MlpO=MZ5PTIB#mVqt_ra5k3L)Em>9%q2dJT?AA);AKTV]?`5+P;2EG4Ro'(V7J4^42h,W-%M.^TMNgEq5:L$A=j!pVXUp6[h6Vg$ElDiru*R]GtN%=c0cDdJ&NYUDU0,Q/u5\.fDALc"f3>[Sbt6=_8)h>VT>\f@sPB)d'>*neW2snr;mZ,W$gJI%)GH2uZq6_.6on&JV3TU^Z%Z!;hp`qGSLbLB].RhDttof=pR?fo-sp6qapB\0s/=BX#PI"?NBp),MRIZ"Efbk_A(&+'+3?jR*3gK^EkC#?jOVZrs$a6(j2+>*]NmC8J=>Xo^:7(L$j8^Oo:tU&;2GAj,RoTB4UG8R*Ck''N".PGdJol5`9'1C3IER=OsfN_Si[/[QAN'i!6hl0q3#g@YCQ4J)%PVNM@?C(CK]7KYkeI%>[567ZRt(ltW!PA)\d_KNU2)TE~> +Gb!#]gN)%,&:N/3n?)E6VFg:6WKV$Kb,"'.e4+@V3s1D6KIKJH,im/+(Ec.d5m!4?Ui",8=J,pNcGAr%`VS,*p3&In4EIWaq"JZl34<=N@4;-L"8VaJ5`$KcSlHHiG4s\We]A,((tf2-IPhWe(Q!'rg!"/C3TA)e\sWT)6cZ[%L%WL>)n,b<2m(B-9@PS:OCqV>iabM8*Y.,eN0YShNX2,3b8*\-'.#knn3N;Id%W*1A6-J6YP17I`-D)7Sh"oK'r]5Yn-+;\uH_1br.f>Yi$t3SSacn^Y2CIbY7"?sf+SK.>!#E^*ajUXZA[#MN^K!uHJ^6kAbq`1\EXeUO2(M/"CVZ^l7Ql!)jGpMd0Hpe[&O!+NrJ#^V8aH*>kS['Wo%tba$>H3GT'c0s^D4Wk`;_c];nPDZfPurgQg'/MYW8pM9?mAe]$9#lEW`'K:2dXulkJGSko+VHD@H=3d:+X_]ndUkiC+,:%L;A>99$5&'Un4,bCVU9;cYg7fVIT,]IL!9CA+ZAjS:]O]&]L728"UtO:"]mWHc<[KpKrQlPmgPEfp3>kaHG[)OuegUPI58K/L+TB%:@WF'?D5IDX:XE/5]<*Oq!;_Z=%'-:8+IbY[d&T:,H>n8#AcuO:&!C%!rBp4]5P0uXYZCJ1GFdBAYWm@PDm/UbDeTpn!&r:&cC.t"m\^3%/;DZ;SM0.d.l[=[]"nU@2lpb:G7j%gF-4&pa=VkJ0([(.V5\3'giVmo1JSRapAR5d[Tsn>'o96n_d<^?S[]_ZCp2'rhhXdRlcO87?0;"'SJaj#S&8Rt0TNjNYBcZ43<(Z3%nBr-C/Ju%$3XjMHU(!0q&lP&7M`=J=eSO>@lIYQ>BH2aCtb6p4Su1I_9k_1i8'-Im:kAlm'dm3,d4?h1*"X_q(hj*";P8bXTgFehZh?W)*2;k[T2bJE=t@)-%Gfp.t7e!&mJDMZ-6SSrm'etlU]f5ikDtkqR3.Uj0.U-,o_lM]<8B!UIkbBi?,5G8H+L&PpeO7&UeIS=k:g,aRi&%J#M`aQ'/;"-\)Xq^uu,MVTW:q+o^PoJ6^fMFm0'"0*%f\&uM>Dd_I,^cb:*c_!(pC7m-pp\[UJu)8?[apZkK<6._K#]R(9kRY,j?^s$MX@5&8A,l\B4949HCBcJ;n.=254Tio9:N\X'A66tahA9G9O+t@=6IJbb=dqFITH@AlK=n;1\= endstream endobj 96 0 obj @@ -574,10 +574,10 @@ >> endobj 97 0 obj -<< /Length 1851 /Filter [ /ASCII85Decode /FlateDecode ] +<< /Length 1686 /Filter [ /ASCII85Decode /FlateDecode ] >> stream -GatmCshu:kM>#SI&=7&cM/!lV:3FFroS7HYLodi>Z@KSVo?Ig')H:YjQFLs&:9'`IHauKPW/,PtXY0CZHQ<3:mqJIna4S$aJ:OpKa]d![$*NM1@M^1],`n*kD7E+T/0UD7)M&DB-P/sP*;75d$9SC'G8=&u2+DFNh\6HZ&<)M_f5`Il(?hI/[(gi-lZE35)'L%/^_FOkDektr(K&m8t&D5ot=:I6Ki$EMB_cl?5_/1P?oc9_M+eZ:7kUJ^FjfR,rD2$L&]L_6JX@#kXNpY/%9d*pAYMEgednm\DBpHGI#JR_)+=uM@D,bT';9PPV9bI@X)A6;A@30Va-TYJ,.=La>)VI[`Yc0"hO\`@\Er8Zj"6frL7Qe![j5.U,dok:rU2gCqd8Q+Cfu.&R3-nRB^P[I0C_n%oN))Q>Ns22kE4kNW,&UOLqVG2OlPjQN_f`Dn2'*/>gO:gesUTLMOUQ;kt7`673RQd8@EgS$4X,/C.[V406$dGk%*Tuk8d)F)c<`Q3XJ1M^pn3-#".f%(hOTs!9?^#db<-m,Rr\EeT3nAKL)f(ieNQZSp9N/hP:"<4\NNh@e(sZAW:C1S!t!Z9LnkUD]k$.EaTd4A,_":`jej-iMNQQBE04&+rrEj$=8OO!Q;oVP!D^`h#X>F)1?*?.4GtrmaiS9an8qn:f@sKA5B@m\JT*!;:Xsp?8Hc4oXjW(t2P;"o+[(k%K)Q-]B>,DA>H9-0q'ljW[-oh:R`b=>4kI#1WHNDg>(7l;)7brC\9A/!ZjGs^-!#sSf@J+pcdI>!gJ@h-&OV$m;MK<[X7.Y^$,NWi_GD#d3V;cD23/=kb78G!4m&qcgpq;kJ2OYcC-N+LGl&;[a,ff6$IJU`e%%bJRkF`r=9Wpde!~> +Gatmi7XQMSSPE9AdUHI'Un,G.Yn_5M57%q@3jKcW]_VT$!t^"*b'O`P's"#9YYH*$5WG,I7s-q4d3E*4Xo5nkp3Fu>?;cY/ODF:H08rKGZRXcDT>IT$rJ..iSc_M=C8Kgm@.HgmrhVZNW;P]%kD[!ge]Ioi6C4-SsI%l37,tSc]*KCb/m?GI=%F/KXPckE4=rO,Q\Mm2g:F?]*r_NM-3_[3=4dD%ns-M"6Gc!:EaJ7>u@GpI0E,#H6lqpEI7p5B'W!Rtgkpb&9jn^k@Q^8GRndF,TUb![SU:CUbq2mP;V7S+eJiD,KT&9_qY,5f(m;3sfRf0p-<15+D0)\A;QrB3])7m.@IU[?^@E/ud9iJ:#^5RckCB6.QC>r&6$]VC8[0Xk9EY'4EPjX4;7bt*H=1k9lok-&?I`]3-`B0VN2ibn(p-:#iq!;]rL>g6/Pg$eBKQNA8=[09U#2WI5dqa>MaXCon&CuaS2%a#iQIOM`_Vlq,KoLjI?OP!ioVKWZiW=]b$D^$srPkSZ%\MC2.=UX7&0E=9?s&:Ojfb>+X0i&QWZqS9[YmL4j,6OE*5Z2j)ajcJ%5]hHiSp1ph5PBIf8)C][iW:!%SnqZF+p>'&n5CP?+PjkCkXFQY,#u8\l`)>tFNFd1h.FhpW:\*5L:m']tYF)s&6D.mOjB<6a(V'VTC6^,NQn[DPfTCDenu>Ef[O!rJ,hoPA_gA5t%I$u%N3g[Y)"4XRLgYTt[l>R`i;P[a^8F1%6)4[q?.cen$3D=Ium*`Fe;._=H9GZh`9Uq>8dsr#6A^.uYCIo)*m.e)k_J\I:tr">i=JD9mB.8HNol"d&&.&A^5q9h[j"V&hh1_d^O6f4]5+H.N*>4$4s!4SD$T*7eO.js!-IW'L1f%(J"Q(>QFnhJE]DP@bI[9.#4:7n(t4Y*H^]O]rZ@j@:CR~> endstream endobj 98 0 obj @@ -589,10 +589,10 @@ >> endobj 99 0 obj -<< /Length 1746 /Filter [ /ASCII85Decode /FlateDecode ] +<< /Length 1923 /Filter [ /ASCII85Decode /FlateDecode ] >> stream -Gb!#\CN%rc'`IH,Tl4^sQk_&JO0ohO/p3:b9n-XS4Q>H4=APJfu*(P\X[Tt?d>@UQ2uc13Y_.e(Nr?JW+8XgkoDHOrP'5G9ono6Th/a#pKf";Z`@GqCL-#_(V=l`%b1@i>%5rTeD,2I6;51%O&QF>b;,-.MiNF:1aT4BCCBm(,/5*de!:tle-S5Yo:=sC?]h4>n'PVm0#^V.HU?SLWB""K)0FS=AJ(fdCQN2#/Ara[W.i@8F^>si`jRF:pF8%+mRQDP+h.Og\gc+KK!GI[_FWkbNGGOB5N2TZLYbm.@9gU'SH^6GAGJGkD66[S5OY3\Cd5H]7q?t$87OKNf_5s>HFn>AV(7Ce(bQQ*Po.[Y`1/+S:)_[^(*dAL>'W6/^hZ6VOB4&s")`*VH_V*&1K1'h_!kW=b2[Cf="6.>T`VO[9kr*6Qf';F*"[b?Hu_RO19q'Oo*#Oktp"rjCB0HI\Ksr6%i0=e%H2hMHRO&n;;q.EXs90f>El]$oA&bsuadqgmAsVAM8,R@hEh="QT0bNmL2^9s^Z7Id(ZUWBoJ_7-bl_nj,#5oE*'-@;Pg[ZNj9kKrJ&r4Wr3KSZb]Ot%o;BVZ4CIai-cO,J't(Bc-oGRn1q9Am87Ft5%=031"4@P"s1+j+m9F*^ZD3dijPW;BRE$ON>E?Gda3eP"Mf(\A@7ec(d_Q&>]+]%*Z[[H7])6@Cm.pH/7O3A32f"E4G2UAEijL>&iqrH:In;51Oh_%h3@%k8sm2M]^qom]jCQb.Q/OloaIU3,&n9R;h72gU&uVpk*"/`-JMb:BQtqRp4n9$!_uo@$i05`^H?`GVI5b$dj+:1Lo?.O$'\XXQpUgWK,`'#ONFS12IJs`#^F7GPKh.8'b)oLp]%E;+^dXCtPQD92_8OhKWS,(H&-0[ukcXF_F5Zhh0@;^pQda4l=P,F=N)5/Xd?eB5`i:TK?Y#B>'_u8h'anW**IHTg>HYNs^3WntH'/E4X)6G9*W5pU&KUmbI\P4%nUp(Ye,Q=K^@_MW-OB#fC7BHp9H_:?)!Mi4X;],P(]9]3FZpbaMa0.glWMXk.13mOc8B93scKmhX&kIfl8+;c!~> +Gau0DgMZ%0&:O:SkcGdHAjfPHA[a(ll,HpDD3?5`>+dJTfqrQdZKN%b>l+,iAB>h6U?r,q#a1Q30/I6QcHPd(1:W_\^'q6P<55%1Oc*JbpO2_dA(B`cUCm&7FUIQ\#/:VM:MqTd%!4TgtOu22aR/+0=G[>!#H>88`L%Dc0q7-S-`Q2fq\;?oPQ%jV'o=7tBE+KGqcU;$8q,5OT7%-JCibZf#*abfk36<0R+M,Y;36a#ldGZV[kHaN<.N%p,@Ftqg%M]<&?Aa5E\\Our390h`#R_NUT,"9HA]jdBM#,mm&S$g?$rrS+U3jo/O"JBK?oNj*u=tJ1\57B'-CZg?>=^5!c\YKq+io&")a-'pFG=Ja3k:_ZCYTJd]LmK4#OLA[48Zt^r1IdWU?4>ob*A]8M3^c\qM>)Vs5^%lFnbqpmFEc"8X9FP^A8<]8kq>gkLbtig+U8gAEp(IDPm%2qRLj?r+0gB)tg>JG>+Ejl_0FrZ89s!>PbYZg"*6D^];X,Et'"bf9XY9RBDQO7r,=TCfj4?_'O1BYj*$.!2FerV&"Kr\HJ?*N*"#p+ILO41idnL)#>"SIbFUCNN0MUVO^Q-UlB)5S5>)8QBSZdX8nTkYHS4MF'XdNR!IY&W45/hg9V_q3Km\'S-"81#*J`4]_^;[[W7)5eIra"L,/`PcA#H1[*<$I+7Y\/k>;9`A3\YS8ej`,Ze@,Orj!Mm`G>`H.cYom?\+^I>uX#&R\Ft8]"(Qn8[uHO"AdrFe$s'DLX^(gIo7/NgM0!9,Xqg/Gh?&;/Io-m`$I,.Zr1`Aj4t""NhLgn-Ips:,[=>`[n%@E2:mtPU7bfDg8&58qP%%>jDakrLrH8VT6?7qhmWjG$^k%5IQ=DBBLcIVm<5V_b'oIP:SX\&J%4V60a)\-4aL:eCr6\mon*Phh*(]4EUqH)c,8T:mZpt3p6Y0:kJ3)\Go!'0LUDn]os`$?]+WilTVR>qAT=Zk?-GjDa[KGG$IB4=7&\$JPa+grX/t)3aVgXe[6?X88NPAK!N\KsE/8WZ9FN[i?L>4Rs6!pbR-H3W+;@6gaW,l?oV/@@XsRB9,1"R$@o=>H+`''iKR%s?5^GEQ1!-cT)G!N=.PYU2G)iqhVn(Q`$A%,.Dj8sJTAddZ9Q*HPu;iI,Z!VPC__*bfSIh2PB2O1TLQN:/i-qPg;h`K6jt2q/N+MhAPu[&'$sY=?G:OU'ph;\;Gbjoh^Z_B`lbe;\M2)SrHK$@DocE'H3:7f.;4T,BNbX.H8LAlNHo.sK5@=;@V4CPjna&QY0/8R%YBY1QG,X@.4U%u!:oomOJ0n&$ endstream endobj 100 0 obj @@ -604,10 +604,10 @@ >> endobj 101 0 obj -<< /Length 1528 /Filter [ /ASCII85Decode /FlateDecode ] +<< /Length 1395 /Filter [ /ASCII85Decode /FlateDecode ] >> stream -Gau0D95iiK&AJ$C#eB:+L_Z%u(Q0h&mCL@_:!uH!V'uc)U20k9kS5C*rqE612MVq0-ANetCe,"J^3L67)bn%:PFiM!XSBQf-_Y*TL?Ej[\)TAr:L+4ss%6`O-@\d.5>6MhEt-W87Hqa*:KdT#)9MU.5t_D,Kkt1i$dVYLaFai@_X69).69D`-9JaBTX&Ld(;h_\VV8HX,W5V)C;pO;q[UO0E$3O:6Bijd`/c^"ss\'+LWD:8)ugP:@BW;3KpkDja1qUR+o?2o4SSUQ:#.RM^m!ZFp//E5S>a%"5iEM&#@/,K4#Mu=3?_P`W1LWC7Nf[J-te,=fF:eG!nBg-2C]-@[RfTKco;A[nZ5-H%#a_gHL6IED+cF5hI1b286A4OjaEi^U>25^!maRBKhoLP&]&[GU84OFuYeVlc1hnU]OmAar+9QWCiQkU_=l5AjWR'='L--%Q7QKZKGL>GU@Ds8os_$r5Z;1TDA6EQb19C%(2@0n\/=m!r*e*:.)'KlWGF@NgBKSYAii)jNt].)IBn.8mS85'SsOd=^Td$)M3dXWB@%s0Dc)74*^+mm+>Wo"Y`%15ssnul>SnO,gG368[5;H5it_1o'IARIor<$q2]j>FrfPi:83K^93#Smp1`8>.#Yc15E(9IF$,BhXY1VO2aWa\*tFEP61;R0gob1Hs2!IuL&E*,7G'8.3]LT^@dJ+Y#V#(q&AMnr?)lrc3H*ig&qg+aUcrn7/P+,s>]Co9*MAS,^8rf%7SjNb\naOq_MgK8f%;72crX,nCtgY1\dFsO0@#4R\8&mn!aJ@`bUp'q@S&eFkN^AgTUZpbOPC5#CYD,2!dg[a@UCA(C,JjSn=O;Y)BEjJ/>'8J:*f#ZS_(h3$!`)dIG=:J_^'E92?P(oL6CiYJ#N],fPdFRO]NYBQ7)"$<)3@HFfT]A_q&%!)O;LUG"/3*C%g*(UHR'IN'2'r\irfnJ)mt=eZ7\-F=F!Aink9tb0iK,n3Pkeq_S?bYNqGWJ6+Vf:&H5oQ3ORt3\9NR?q^(?)K-pMJ)l=tLQJ2acK?E8E`p9r6A\0:d%0cE+e9M2eqY*p\7O.au&6[.9@@S%dWAamaOrRg5ARp`P3RQp\n&r#YE-]TRuB&87"@o&_sQ%']31n575Kc-UNk^u=RRNn:IVHRQ5N\ojb)`#Ogo(Prm8/5NAD;!8\1FRApYVU`DA_JX!UlQS>q_+r&A>V'(3%'0a[j\AJRgiEDr\'p97~> +Gb!#[h,!&j&:a.U&b30.6pp=Zq,jb$/[sIJ-Or+lqJr*$C$RU-%!d,8_hli>#7e#gM;'6Z/S!fBO,.q"5:A543Ql#<>iTt>I6F?aKb7XV%k.ARA>3O(r"B,:V[4.?DE.+OmS*MZm&769DlR8'hJq;b..f+qiD%8,OR#/lgoLl&]^&.n8DI7f#ts!`[oD#S8GuIJX"57i*-\MX"+PP30XA\PFWt$%?coB7Hl3pGa8?\/D1,30%*j"q_"T(5p]'X-7JrbP0oGQ0^(VCb41RC/N.!\+\H76E2VMP9u7s-/(r#VHO&>aLeMP0PV^hs=P[Ro,N42(o/tg,s3t`?#g&0O)@[m^GaTMj-h\e3(42C>N5Q*8/:Y5p1h*V`.\/[Aa:S"6HV`@LMX`(2*FJ[CNcA6NddeQk@Qe3pKG&sFI71)B[-=`8Ee%C'E7'M.rGlHZ]g!9s@<1.C+Y+M*;Pq0C.W/:6"REW<5PiBYI'CnWHkIsn\Pb8r2U.Md!]QMs90/>ng4mL=?R(Hg+F?t((K>AYFG0-eZ2qjLBMOl1nOL9cF,U>.;-L9-6)Ur*Te2mj)C\!RdOjo12Wh^-/o#3*Ch+m=-@'iU`GQLA;8ra(Y$RSG4D8(A$#m;L,1bI/Lc"DNG:F)D6s=aD1n\0-XV(,'5SBeJK4nXL@b1Z1f^In&_^=JAC`E+nt7Sb+WoIjGk8(Uockig"4BEQ`@I-/&+OadLa+K`Z%Rlu&,@AOX3+6A/4L(qo8L.G*-_TMjpA:;T3.d7bX\5*hq7A!bh#u:Tce/Q),--fYiGMAl:\]5JEpD8M5C-HD[G7AN7Gm^=:l(q2B,5p\gp%pMO&VB\V0/F".6h68H~> endstream endobj 102 0 obj @@ -619,10 +619,10 @@ >> endobj 103 0 obj -<< /Length 1832 /Filter [ /ASCII85Decode /FlateDecode ] +<< /Length 1786 /Filter [ /ASCII85Decode /FlateDecode ] >> stream -GatU4>Ar7S'Roe[d+]2WAk;2n$j5X0$!J$I[s6Xpdg*miD/PO#lJaeBIf)`.2@jBAb7GA)79Vh:I-5n?6Hp=1T,*VD'B3lYhn)I;&b_qI;Z?rpI\$]T5uHim-2/H.^J)(QLicR`n+/OX:Mqn2O'r)UOHSa@_])%P%]]L`K+dYpKMn6Ln5'r4^0!'MXdNC`IobCZRP0bG\Zc';(;A=k]ZXU3$7OMC0bcKA>"2B]84Nh"^AAPRNfjY,h>o),"=n.-CC2j#`b6r:94B?j)&Y"cV/8?L=E-A)6Ui]\:GDhFh'BC6trK,Q6fke+Zn;`jA?3d^IhEko9TQ=\$[KZqm+)5*h=TW:MR\0%Z"!)H;:oeYI#nr9=&^/4XcR9uU#(4gY0O#')r#W#cc><3f=j3LRr`5Fc:ZnH94]G24@=lq&DP_P&bj83pq5\?.F=YP)eXr`Lj+-4mdcV^Fn;cleALkLT`C^g`-`S:WnI_#h'^Ue*7QM%,^a)SI@Vb>DprZC@NhH8T&]U_DWRs-t[Gb7$^=0)e0m!^2&o&7>E/cGLs#Bs[(12>9#9(Bq26JCFL*'UOLn[,jNL]`A'+(?%!csoA82?-`4*?&;lP6A-1I,]K.'mFkn:4Z_Em(QB)chk[Y]A'qL0p1?@lm^;lRfKqA\S=&%LmFQ@@8u'^2hd857%`;!,jJ,>JjcD2#/@$Kh\_poAd0":)#Toi4!nT&ZMCH8p^cs`5C+ghrqGY8KP%L-#QNk28hT&^/naKZI"U@.tNdn;jOG<6dmPl?hB'T83fiQfEL3Gl,eN]G(TDg>7Y@>d-Og3r*Xf*+'Q)mGQ+s1Z/mH.bu-%4eP>h7e^`uQ9="^Z"XuMA#:,+Gl#\Hr%VSn80)pYhRLR:Bb6;sC;jJrac65Sk1alpQfVSO;$f[:1*F3LBfMH;'m.C0@FCX@=YA@mh?_QdJ-+r*@iY0^9]t0f!9re8smYHXh6:kRB25#HQP4rr7FCT15k22rHKI5#1'o-=*=q5$'k8Isc42%:ctE";<9;f@U3)C1TZ_.0=So>kdF)/#\A2=[+c7[%gR(?:FPPsc>5EdkMKjN\JcOf@f.'NuO"q$fP?;,`7B\It3fr7QQ2'IuW)FsEJg=huuX*7&BVk)Q`L=p7&=?3P!n9$J$\qg%EN=cVBG-?t[9nm883'k\t0+C_jpJucS)dApeUF4h"GF>-3)NB@\Hs%_'Lsd^DoR2eo[JR)]4dTWaD&jWED,mDU0e8-$A6++;mhW]cmJ:.ll_hJcF??u.UK1"t"HI&]=gYajYZC@!\MrnW3U^>>+XWH~> +GauHL>Ar7S'Roe[&GhW!2FHc4@Ml>VF-*(tZc1Z?l96USAIF\i9c(i&p>\[.@\'8jDMATf&DO#%F8aBY\#\0mX4a+$B'eUYh(54P)QrDK:YSa](QN&=fTuMW;L.G:Yg"2QakO'8p3]u,FX.:X8\@'s+kO_HA+ek)$MBZ4[RKOhPdP3dnd]0sV$Bl;<@fmj-S-CX8e`79'7tj@SlF[QjOm"=iS!,VZ`5:gHF8OfVEBN:T)hlQ-)Zk2'DC(u;8`jaR?'4DSR><(p6pnQK#jfA,`-9ga?-.*4&I0LM;(U(C9QnB_)t%3*:Yb@8m_H\D?,?b\:ES>ZP*=-0W`-cC*fHI*T7s2@'&r,[><_0@?LlA[Om7Ue4k$_iWhZT%/"HnVS4&hpkDZ4N9Q,4g_jrk42*_n1U@BVnUIn;$tcmZh2C&po,%e$fh1TC%p8Ed:O!&frEa=*<5PVf@\]aY\/#BeY8>*b(i^qo$C4#MG9#1+J\4N!#,"a*Y'6V]'fNr43"=sf*-hAuQOo;*HO`@dKYH<>."J,ZX"_gQ89pD3`[Rqpg_#$%-n3gGjVBqU[bZ/S2'$:%_n4=Vp^QRj1;A.TR'Wpf=ZJq+s_Kd/bsHdpT3@iVY'cIGoksE<*W4,U^e0#CIq/'9(X#TXjN;K-pZ>$cpk]Z/)['oV)/eb?#hD/c_h[$(4L9'cnNV+L;GF^u<=.;Tfu\bo`7qrF[qegftC+e]k0jT/]AXYjH]sTmLd6'aAinT5"I'\`B?t19nQ>j?")W2u`[M)l?WXPb.u4S,ZA6'SY0uW/'Zl4OdR*lCp-mMR^J6!B:+m/:&N#85;uF@-QY/"r+[df0:DDn7.*:IckoSM34bKRuNLZQau#MdG=.N`NG>Ce(Oo]REE/>oOGA@[MlePn:drkPT]SDrW*tIi84BLZh?Lf#`k*d^,[@Y_2:XS.(NG,5F9s7,oP5Wb&>DZe-dn*(AE*#=]4C3boiB[H^]GfsE/*Kt*EL5.MTgP(5i&Qur*#oX!-I1G-#dR4XS#'io`.er-9hf*nNoA*2S!cQ$qW5!s2@=dP#s?frY!1>ST&HdT>2?6p6T`J/'HB$"((C`6l@iMZ3iZB;DAK.gFOVQWooh?SMlij<.C'Q<`:l'd<*AcZ\6)6H:7#lPR>f/^QNHS]FSq]\>@Gi;&@89ns0.P>ZU,FlD+.JG#B(UPPr5%X@Bd;GFQmlDY*"Q6aABiE_&C9\@ endstream endobj 104 0 obj @@ -634,10 +634,10 @@ >> endobj 105 0 obj -<< /Length 751 /Filter [ /ASCII85Decode /FlateDecode ] +<< /Length 1018 /Filter [ /ASCII85Decode /FlateDecode ] >> stream -Gat%!_2b!=&A@ZM5%^XNf64BLA%1/k=nU-VfjP$%nd6`Z)4l6;"')(%tgW%AWWSsU_WYcPLW]j9%5G2V68btp^Ya8ZhG7ML?&.aZBC(a[D0HYF4-8u5'E?mKu71@)Mbh,54]d:(`o!b.Dh4,=J>tVVhD?n:G2:fKdJK6GA4I[1nkQ$6%:E:=a.sB=mE.n$e'@"nN-E79.rk>kMhh\KiHo@ThWM\X'u\CaVa60;"Y970Ss2#OK&8[DAVAg3nTb>Kp/\&\SQ_"f;*,g&cWscFI':u?4ui*bq!!V`tEGO?+BQ2\)mVqI778&5W%U_lMpTobW95\$!oI,\FHr4`f;RWT,cC+LGbprPfL-HIN`SDc\/e)-N0Hg7>FM6@g2L-dY,J^bjs<@57;Dcs+3Nlp"=?8$,=?bn`+Ij^K^E+]t`7(%)u^8-2=dWh68Gbm+gb@Pc%2(1JaI&mlVb/I9'D<6q9KN_[F^5]RZ@p8#gc;SfR8aZ4.O'ifC:,Bg+h`Yl[^ejjN.W$UNB%;R*"='@igVA7_-Y+u%:^I!,RUM0lnP=j@2-YR9ckJ'HEXf),<'1@nGPjep5Mo8&4)+4PR^Ua^ltqA0=kiS\FD+Ch:9(%S&%fJ#C>gX_mY'=:?9bNpD]O6Sne~> +GatU2968Q9&AJ$CkXIXtW0T!XnrY\%V]?74!uuiDOsmTOQ;^"Go'_\_M-$sO;OG\Hg9l**qsCl`?I,13\b#$p=G4Qa;#OpXe5+s2"[`"h4ob*%/TO/o]86@.r%l)o:Pk-ha&&qc_YND#c^h+>J4R@^^33bgEJt.o,H*J2T%VE:4@S-["MR9&g:4\<+/a*-b;dti-2N2Tp[(ODj5@A(lS0qM5=VLQF"=JU#]0[u6-Vk7Zn]UAF%?=X^WY\S/4&2gW:;*1"6/"AKXH\\uE#\t5Uu(i4@;;#T\8e?oK@ak%g9:[WF@'(`@D\LQ<`m"A72(l]_jf`84+QuRb5D5apJ\SQ%'QqduJKpU@f2796l"8RtG=kDcKU*6!`[FA\^';)c8%fC3PEA@.PEFjP8=30Tn6Smd+h2sqCN?*rjO>1ae.16M%0H\MB`:n8mI3b1OThA_VVSDk`!QJZ(=$:4:P`e9-$ibr_jB!C58X&)"OAOu^n5Z:_=sT'=I^U_fKP"cuIIj?'cd4`Z#Pr"4A/~> endstream endobj 106 0 obj @@ -1053,73 +1053,73 @@ 43 0 obj << /S /GoTo -/D [84 0 R /XYZ 85.0 421.0 null] +/D [84 0 R /XYZ 85.0 360.2 null] >> endobj 45 0 obj << /S /GoTo -/D [84 0 R /XYZ 85.0 282.547 null] +/D [84 0 R /XYZ 85.0 221.747 null] >> endobj 47 0 obj << /S /GoTo -/D [84 0 R /XYZ 85.0 204.894 null] +/D [86 0 R /XYZ 85.0 659.0 null] >> endobj 49 0 obj << /S /GoTo -/D [86 0 R /XYZ 85.0 492.2 null] +/D [86 0 R /XYZ 85.0 406.547 null] >> endobj 51 0 obj << /S /GoTo -/D [86 0 R /XYZ 85.0 439.866 null] +/D [86 0 R /XYZ 85.0 354.213 null] >> endobj 56 0 obj << /S /GoTo -/D [88 0 R /XYZ 85.0 175.0 null] +/D [90 0 R /XYZ 85.0 616.6 null] >> endobj 58 0 obj << /S /GoTo -/D [94 0 R /XYZ 85.0 659.0 null] +/D [94 0 R /XYZ 85.0 598.2 null] >> endobj 60 0 obj << /S /GoTo -/D [96 0 R /XYZ 85.0 357.8 null] +/D [96 0 R /XYZ 85.0 291.8 null] >> endobj 62 0 obj << /S /GoTo -/D [98 0 R /XYZ 85.0 399.8 null] +/D [98 0 R /XYZ 85.0 336.2 null] >> endobj 64 0 obj << /S /GoTo -/D [100 0 R /XYZ 85.0 469.8 null] +/D [100 0 R /XYZ 85.0 393.0 null] >> endobj 66 0 obj << /S /GoTo -/D [104 0 R /XYZ 85.0 659.0 null] +/D [104 0 R /XYZ 85.0 587.0 null] >> endobj 68 0 obj << /S /GoTo -/D [104 0 R /XYZ 85.0 197.347 null] +/D [106 0 R /XYZ 85.0 659.0 null] >> endobj 107 0 obj @@ -1130,149 +1130,149 @@ xref 0 144 0000000000 65535 f -0000050670 00000 n -0000050873 00000 n -0000050966 00000 n +0000050950 00000 n +0000051153 00000 n +0000051246 00000 n 0000000015 00000 n 0000000071 00000 n 0000001280 00000 n 0000001400 00000 n 0000001572 00000 n -0000051118 00000 n +0000051398 00000 n 0000001707 00000 n -0000051181 00000 n +0000051461 00000 n 0000001842 00000 n -0000051247 00000 n +0000051527 00000 n 0000001979 00000 n -0000051311 00000 n +0000051591 00000 n 0000002116 00000 n -0000051377 00000 n +0000051657 00000 n 0000002253 00000 n -0000051443 00000 n +0000051723 00000 n 0000002390 00000 n -0000051509 00000 n +0000051789 00000 n 0000002527 00000 n -0000051573 00000 n +0000051853 00000 n 0000002664 00000 n -0000051637 00000 n +0000051917 00000 n 0000002801 00000 n -0000051703 00000 n +0000051983 00000 n 0000002938 00000 n -0000051769 00000 n +0000052049 00000 n 0000003075 00000 n -0000051835 00000 n +0000052115 00000 n 0000003212 00000 n -0000051901 00000 n +0000052181 00000 n 0000003349 00000 n -0000051967 00000 n +0000052247 00000 n 0000003486 00000 n -0000052031 00000 n +0000052311 00000 n 0000003622 00000 n -0000052097 00000 n +0000052377 00000 n 0000003759 00000 n -0000052161 00000 n +0000052441 00000 n 0000003895 00000 n -0000052227 00000 n +0000052507 00000 n 0000004032 00000 n -0000052291 00000 n +0000052571 00000 n 0000004169 00000 n -0000052357 00000 n +0000052637 00000 n 0000004305 00000 n -0000052423 00000 n +0000052701 00000 n 0000004442 00000 n -0000052487 00000 n +0000052767 00000 n 0000004578 00000 n -0000005296 00000 n -0000005419 00000 n -0000005488 00000 n -0000052553 00000 n -0000005621 00000 n -0000052617 00000 n -0000005754 00000 n -0000052681 00000 n -0000005887 00000 n -0000052745 00000 n -0000006020 00000 n -0000052809 00000 n -0000006153 00000 n -0000052874 00000 n -0000006285 00000 n -0000052939 00000 n -0000006418 00000 n -0000008566 00000 n -0000008674 00000 n -0000010825 00000 n -0000010933 00000 n -0000013256 00000 n -0000013364 00000 n -0000015437 00000 n -0000015545 00000 n -0000017944 00000 n -0000018052 00000 n -0000020032 00000 n -0000020140 00000 n -0000022081 00000 n -0000022189 00000 n -0000024570 00000 n -0000024678 00000 n -0000026309 00000 n -0000026417 00000 n -0000027965 00000 n -0000028073 00000 n -0000029647 00000 n -0000029755 00000 n -0000031604 00000 n -0000031712 00000 n -0000033547 00000 n -0000033655 00000 n -0000035663 00000 n -0000035771 00000 n -0000037715 00000 n -0000037823 00000 n -0000039662 00000 n -0000039771 00000 n -0000041393 00000 n -0000041503 00000 n -0000043429 00000 n -0000043539 00000 n -0000044383 00000 n -0000053006 00000 n -0000044493 00000 n -0000044693 00000 n -0000044911 00000 n -0000045117 00000 n -0000045325 00000 n -0000045493 00000 n -0000045693 00000 n -0000045851 00000 n -0000046026 00000 n -0000046267 00000 n -0000046396 00000 n -0000046550 00000 n -0000046704 00000 n -0000046848 00000 n -0000046998 00000 n -0000047139 00000 n -0000047379 00000 n -0000047561 00000 n -0000047734 00000 n -0000047937 00000 n -0000048125 00000 n -0000048377 00000 n -0000048518 00000 n -0000048727 00000 n -0000048913 00000 n -0000049087 00000 n -0000049332 00000 n -0000049523 00000 n -0000049729 00000 n -0000049890 00000 n -0000050004 00000 n -0000050115 00000 n -0000050227 00000 n -0000050336 00000 n -0000050443 00000 n -0000050560 00000 n +0000005297 00000 n +0000005420 00000 n +0000005489 00000 n +0000052833 00000 n +0000005622 00000 n +0000052897 00000 n +0000005755 00000 n +0000052961 00000 n +0000005888 00000 n +0000053025 00000 n +0000006021 00000 n +0000053089 00000 n +0000006154 00000 n +0000053154 00000 n +0000006286 00000 n +0000053219 00000 n +0000006419 00000 n +0000008567 00000 n +0000008675 00000 n +0000010826 00000 n +0000010934 00000 n +0000013257 00000 n +0000013365 00000 n +0000015438 00000 n +0000015546 00000 n +0000017945 00000 n +0000018053 00000 n +0000020033 00000 n +0000020141 00000 n +0000022139 00000 n +0000022247 00000 n +0000024662 00000 n +0000024770 00000 n +0000026438 00000 n +0000026546 00000 n +0000028025 00000 n +0000028133 00000 n +0000029718 00000 n +0000029826 00000 n +0000031606 00000 n +0000031714 00000 n +0000033565 00000 n +0000033673 00000 n +0000035842 00000 n +0000035950 00000 n +0000037729 00000 n +0000037837 00000 n +0000039853 00000 n +0000039962 00000 n +0000041451 00000 n +0000041561 00000 n +0000043441 00000 n +0000043551 00000 n +0000044663 00000 n +0000053284 00000 n +0000044773 00000 n +0000044973 00000 n +0000045191 00000 n +0000045397 00000 n +0000045605 00000 n +0000045773 00000 n +0000045973 00000 n +0000046131 00000 n +0000046306 00000 n +0000046547 00000 n +0000046676 00000 n +0000046830 00000 n +0000046984 00000 n +0000047128 00000 n +0000047278 00000 n +0000047419 00000 n +0000047659 00000 n +0000047841 00000 n +0000048014 00000 n +0000048217 00000 n +0000048405 00000 n +0000048657 00000 n +0000048798 00000 n +0000049007 00000 n +0000049193 00000 n +0000049367 00000 n +0000049612 00000 n +0000049803 00000 n +0000050009 00000 n +0000050170 00000 n +0000050284 00000 n +0000050395 00000 n +0000050507 00000 n +0000050616 00000 n +0000050723 00000 n +0000050840 00000 n trailer << /Size 144 @@ -1280,5 +1280,5 @@ /Info 4 0 R >> startxref -53060 +53338 %%EOF Index: docs/fileformats.html =================================================================== --- docs/fileformats.html (revision 777664) +++ docs/fileformats.html (working copy) @@ -1343,24 +1343,24 @@ 2.9 and above: Segments --> Format, Version, NameCounter, SegCount, <SegName, SegSize, DelGen, DocStoreOffset, [DocStoreSegment, DocStoreIsCompoundFile], HasSingleNormFile, NumField, NormGenNumField, - IsCompoundFile, DeletionCount, HasProx>SegCount, HasUserData, CommitUserData?, Checksum + IsCompoundFile, DeletionCount, HasProx>SegCount, HasUserData, CommitUserData?, DiagnosticsCount, <DiagnosticKey, DiagnosticValue>DiagnosticsCountChecksum

Format, NameCounter, SegCount, SegSize, NumField, - DocStoreOffset, DeletionCount --> Int32 + DocStoreOffset, DeletionCount, DiagnosticsCount --> Int32

Version, DelGen, NormGen, Checksum --> Int64

- SegName, DocStoreSegment, CommitUserData --> String + SegName, DocStoreSegment, CommitUserData, DiagnosticKey, DiagnosticValue --> String

IsCompoundFile, HasSingleNormFile, DocStoreIsCompoundFile, HasProx, HasUserData --> Int8

- Format is -1 as of Lucene 1.4, -3 (SegmentInfos.FORMAT_SINGLE_NORM_FILE) as of Lucene 2.1 and 2.2, -4 (SegmentInfos.FORMAT_SHARED_DOC_STORE) as of Lucene 2.3, -7 (SegmentInfos.FORMAT_HAS_PROX) as of Lucene 2.4, and -8 (SegmentInfos.FORMAT_USER_DATA) as of Lucene 2.9. + Format is -1 as of Lucene 1.4, -3 (SegmentInfos.FORMAT_SINGLE_NORM_FILE) as of Lucene 2.1 and 2.2, -4 (SegmentInfos.FORMAT_SHARED_DOC_STORE) as of Lucene 2.3, -7 (SegmentInfos.FORMAT_HAS_PROX) as of Lucene 2.4, and -9 (SegmentInfos.FORMAT_DIAGNOSTICS) as of Lucene 2.9.

Version counts how often the index has been @@ -1453,7 +1453,17 @@ a string previously passed to IndexWriter's commit or prepareCommit method.

-
+

+ If DiagnosticsCount is non-zero, then that number + of String -> String (key/value map) diagnostics is + stored. Currently these diagnostics are privately + written by IndexWriter, as a debugging aid, for + each segment it creates. It includes things like + the current Lucene version, OS, Java version, why + the segment was created (merge, flush, + addIndexes), etc. +

+

Lock File

The write lock, which is stored in the index @@ -1471,7 +1481,7 @@ Note that prior to version 2.1, Lucene also used a commit lock. This was removed in 2.1.

- +

Deletable File

Prior to Lucene 2.1 there was a file "deletable" @@ -1480,7 +1490,7 @@ the files that are deletable, instead, so no file is written.

- +

Compound Files

Starting with Lucene 1.4 the compound file format became default. This is simply a container for all files described in the next section @@ -1507,14 +1517,14 @@ - +

Per-Segment Files

The remaining files are all per-segment, and are thus defined by suffix.

- +

Fields

@@ -1736,7 +1746,7 @@ - +

Term Dictionary

The term dictionary is represented as two files: @@ -1926,7 +1936,7 @@ - +

Frequencies

The .frq file contains the lists of documents @@ -2054,7 +2064,7 @@ entry in level-1. In the example has entry 15 on level 1 a pointer to entry 15 on level 0 and entry 31 on level 1 a pointer to entry 31 on level 0.

- +

Positions

The .prx file contains the lists of positions that @@ -2124,7 +2134,7 @@ Payload. If PayloadLength is not stored, then this Payload has the same length as the Payload at the previous position.

- +

Normalization Factors

@@ -2228,7 +2238,7 @@ 2.1 and above: Separate norm files are created (when adequate) for both compound and non compound segments.

- +

Term Vectors

Term Vector support is an optional on a field by @@ -2361,7 +2371,7 @@ - +

Deleted Documents

The .del file is optional, and only exists when a segment contains deletions. @@ -2433,7 +2443,7 @@

- +

Limitations