pylucene 3.5.0-3
[pylucene.git] / lucene-java-3.5.0 / lucene / src / java / org / apache / lucene / index / FieldsWriter.java
1 package org.apache.lucene.index;
2
3 /**
4  * Copyright 2004 The Apache Software Foundation
5  * 
6  * Licensed under the Apache License, Version 2.0 (the "License"); you may not
7  * use this file except in compliance with the License. You may obtain a copy of
8  * the License at
9  * 
10  * http://www.apache.org/licenses/LICENSE-2.0
11  * 
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
14  * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
15  * License for the specific language governing permissions and limitations under
16  * the License.
17  */
18
19 import java.io.IOException;
20 import java.util.List;
21
22 import org.apache.lucene.document.Document;
23 import org.apache.lucene.document.Fieldable;
24 import org.apache.lucene.document.NumericField;
25 import org.apache.lucene.store.Directory;
26 import org.apache.lucene.store.IndexInput;
27 import org.apache.lucene.store.IndexOutput;
28 import org.apache.lucene.store.RAMOutputStream;
29 import org.apache.lucene.util.IOUtils;
30
31 final class FieldsWriter {
32   static final int FIELD_IS_TOKENIZED = 1 << 0;
33   static final int FIELD_IS_BINARY = 1 << 1;
34
35   /** @deprecated Kept for backwards-compatibility with <3.0 indexes; will be removed in 4.0 */
36   @Deprecated
37   static final int FIELD_IS_COMPRESSED = 1 << 2;
38
39   private static final int _NUMERIC_BIT_SHIFT = 3;
40   static final int FIELD_IS_NUMERIC_MASK = 0x07 << _NUMERIC_BIT_SHIFT;
41
42   static final int FIELD_IS_NUMERIC_INT = 1 << _NUMERIC_BIT_SHIFT;
43   static final int FIELD_IS_NUMERIC_LONG = 2 << _NUMERIC_BIT_SHIFT;
44   static final int FIELD_IS_NUMERIC_FLOAT = 3 << _NUMERIC_BIT_SHIFT;
45   static final int FIELD_IS_NUMERIC_DOUBLE = 4 << _NUMERIC_BIT_SHIFT;
46   // currently unused: static final int FIELD_IS_NUMERIC_SHORT = 5 << _NUMERIC_BIT_SHIFT;
47   // currently unused: static final int FIELD_IS_NUMERIC_BYTE = 6 << _NUMERIC_BIT_SHIFT;
48
49   // the next possible bits are: 1 << 6; 1 << 7
50   
51   // Original format
52   static final int FORMAT = 0;
53
54   // Changed strings to UTF8
55   static final int FORMAT_VERSION_UTF8_LENGTH_IN_BYTES = 1;
56   
57   // Lucene 3.0: Removal of compressed fields
58   static final int FORMAT_LUCENE_3_0_NO_COMPRESSED_FIELDS = 2;
59
60   // Lucene 3.2: NumericFields are stored in binary format
61   static final int FORMAT_LUCENE_3_2_NUMERIC_FIELDS = 3;
62
63   // NOTE: if you introduce a new format, make it 1 higher
64   // than the current one, and always change this if you
65   // switch to a new format!
66   static final int FORMAT_CURRENT = FORMAT_LUCENE_3_2_NUMERIC_FIELDS;
67   
68   private FieldInfos fieldInfos;
69
70   // If null - we were supplied with streams, if notnull - we manage them ourselves
71   private Directory directory;
72   private String segment;
73   private IndexOutput fieldsStream;
74   private IndexOutput indexStream;
75
76   FieldsWriter(Directory directory, String segment, FieldInfos fn) throws IOException {
77     this.directory = directory;
78     this.segment = segment;
79     fieldInfos = fn;
80
81     boolean success = false;
82     try {
83       fieldsStream = directory.createOutput(IndexFileNames.segmentFileName(segment, IndexFileNames.FIELDS_EXTENSION));
84       indexStream = directory.createOutput(IndexFileNames.segmentFileName(segment, IndexFileNames.FIELDS_INDEX_EXTENSION));
85
86       fieldsStream.writeInt(FORMAT_CURRENT);
87       indexStream.writeInt(FORMAT_CURRENT);
88
89       success = true;
90     } finally {
91       if (!success) {
92         abort();
93       }
94     }
95   }
96
97   FieldsWriter(IndexOutput fdx, IndexOutput fdt, FieldInfos fn) {
98     directory = null;
99     segment = null;
100     fieldInfos = fn;
101     fieldsStream = fdt;
102     indexStream = fdx;
103   }
104
105   void setFieldsStream(IndexOutput stream) {
106     this.fieldsStream = stream;
107   }
108
109   // Writes the contents of buffer into the fields stream
110   // and adds a new entry for this document into the index
111   // stream.  This assumes the buffer was already written
112   // in the correct fields format.
113   void flushDocument(int numStoredFields, RAMOutputStream buffer) throws IOException {
114     indexStream.writeLong(fieldsStream.getFilePointer());
115     fieldsStream.writeVInt(numStoredFields);
116     buffer.writeTo(fieldsStream);
117   }
118
119   void skipDocument() throws IOException {
120     indexStream.writeLong(fieldsStream.getFilePointer());
121     fieldsStream.writeVInt(0);
122   }
123
124   void close() throws IOException {
125     if (directory != null) {
126       try {
127         IOUtils.close(fieldsStream, indexStream);
128       } finally {
129         fieldsStream = indexStream = null;
130       }
131     }
132   }
133
134   void abort() {
135     if (directory != null) {
136       try {
137         close();
138       } catch (IOException ignored) {
139       }
140       try {
141         directory.deleteFile(IndexFileNames.segmentFileName(segment, IndexFileNames.FIELDS_EXTENSION));
142       } catch (IOException ignored) {
143       }
144       try {
145         directory.deleteFile(IndexFileNames.segmentFileName(segment, IndexFileNames.FIELDS_INDEX_EXTENSION));
146       } catch (IOException ignored) {
147       }
148     }
149   }
150
151   final void writeField(FieldInfo fi, Fieldable field) throws IOException {
152     fieldsStream.writeVInt(fi.number);
153     int bits = 0;
154     if (field.isTokenized())
155       bits |= FIELD_IS_TOKENIZED;
156     if (field.isBinary())
157       bits |= FIELD_IS_BINARY;
158     if (field instanceof NumericField) {
159       switch (((NumericField) field).getDataType()) {
160         case INT:
161           bits |= FIELD_IS_NUMERIC_INT; break;
162         case LONG:
163           bits |= FIELD_IS_NUMERIC_LONG; break;
164         case FLOAT:
165           bits |= FIELD_IS_NUMERIC_FLOAT; break;
166         case DOUBLE:
167           bits |= FIELD_IS_NUMERIC_DOUBLE; break;
168         default:
169           assert false : "Should never get here";
170       }
171     }
172     fieldsStream.writeByte((byte) bits);
173
174     if (field.isBinary()) {
175       final byte[] data;
176       final int len;
177       final int offset;
178       data = field.getBinaryValue();
179       len = field.getBinaryLength();
180       offset =  field.getBinaryOffset();
181
182       fieldsStream.writeVInt(len);
183       fieldsStream.writeBytes(data, offset, len);
184     } else if (field instanceof NumericField) {
185       final NumericField nf = (NumericField) field;
186       final Number n = nf.getNumericValue();
187       switch (nf.getDataType()) {
188         case INT:
189           fieldsStream.writeInt(n.intValue()); break;
190         case LONG:
191           fieldsStream.writeLong(n.longValue()); break;
192         case FLOAT:
193           fieldsStream.writeInt(Float.floatToIntBits(n.floatValue())); break;
194         case DOUBLE:
195           fieldsStream.writeLong(Double.doubleToLongBits(n.doubleValue())); break;
196         default:
197           assert false : "Should never get here";
198       }
199     } else {
200       fieldsStream.writeString(field.stringValue());
201     }
202   }
203
204   /** Bulk write a contiguous series of documents.  The
205    *  lengths array is the length (in bytes) of each raw
206    *  document.  The stream IndexInput is the
207    *  fieldsStream from which we should bulk-copy all
208    *  bytes. */
209   final void addRawDocuments(IndexInput stream, int[] lengths, int numDocs) throws IOException {
210     long position = fieldsStream.getFilePointer();
211     long start = position;
212     for(int i=0;i<numDocs;i++) {
213       indexStream.writeLong(position);
214       position += lengths[i];
215     }
216     fieldsStream.copyBytes(stream, position-start);
217     assert fieldsStream.getFilePointer() == position;
218   }
219
220   final void addDocument(Document doc) throws IOException {
221     indexStream.writeLong(fieldsStream.getFilePointer());
222
223     int storedCount = 0;
224     List<Fieldable> fields = doc.getFields();
225     for (Fieldable field : fields) {
226       if (field.isStored())
227           storedCount++;
228     }
229     fieldsStream.writeVInt(storedCount);
230
231
232
233     for (Fieldable field : fields) {
234       if (field.isStored())
235         writeField(fieldInfos.fieldInfo(field.name()), field);
236     }
237   }
238 }