1 package org.apache.lucene.index; 2 3 18 19 import org.apache.lucene.store.Directory; 20 import org.apache.lucene.store.IndexOutput; 21 import org.apache.lucene.store.IndexInput; 22 import java.util.LinkedList ; 23 import java.util.HashSet ; 24 import java.util.Iterator ; 25 import java.io.IOException ; 26 27 28 51 final class CompoundFileWriter { 52 53 private static final class FileEntry { 54 55 String file; 56 57 58 long directoryOffset; 59 60 61 long dataOffset; 62 } 63 64 65 private Directory directory; 66 private String fileName; 67 private HashSet ids; 68 private LinkedList entries; 69 private boolean merged = false; 70 71 72 76 public CompoundFileWriter(Directory dir, String name) { 77 if (dir == null) 78 throw new NullPointerException ("directory cannot be null"); 79 if (name == null) 80 throw new NullPointerException ("name cannot be null"); 81 82 directory = dir; 83 fileName = name; 84 ids = new HashSet (); 85 entries = new LinkedList (); 86 } 87 88 89 public Directory getDirectory() { 90 return directory; 91 } 92 93 94 public String getName() { 95 return fileName; 96 } 97 98 106 public void addFile(String file) { 107 if (merged) 108 throw new IllegalStateException ( 109 "Can't add extensions after merge has been called"); 110 111 if (file == null) 112 throw new NullPointerException ( 113 "file cannot be null"); 114 115 if (! ids.add(file)) 116 throw new IllegalArgumentException ( 117 "File " + file + " already added"); 118 119 FileEntry entry = new FileEntry(); 120 entry.file = file; 121 entries.add(entry); 122 } 123 124 131 public void close() throws IOException { 132 if (merged) 133 throw new IllegalStateException ( 134 "Merge already performed"); 135 136 if (entries.isEmpty()) 137 throw new IllegalStateException ( 138 "No entries to merge have been defined"); 139 140 merged = true; 141 142 IndexOutput os = null; 144 try { 145 os = directory.createOutput(fileName); 146 147 os.writeVInt(entries.size()); 149 150 Iterator it = entries.iterator(); 154 while(it.hasNext()) { 155 FileEntry fe = (FileEntry) it.next(); 156 fe.directoryOffset = os.getFilePointer(); 157 os.writeLong(0); os.writeString(fe.file); 159 } 160 161 byte buffer[] = new byte[1024]; 164 it = entries.iterator(); 165 while(it.hasNext()) { 166 FileEntry fe = (FileEntry) it.next(); 167 fe.dataOffset = os.getFilePointer(); 168 copyFile(fe, os, buffer); 169 } 170 171 it = entries.iterator(); 173 while(it.hasNext()) { 174 FileEntry fe = (FileEntry) it.next(); 175 os.seek(fe.directoryOffset); 176 os.writeLong(fe.dataOffset); 177 } 178 179 IndexOutput tmp = os; 184 os = null; 185 tmp.close(); 186 187 } finally { 188 if (os != null) try { os.close(); } catch (IOException e) { } 189 } 190 } 191 192 196 private void copyFile(FileEntry source, IndexOutput os, byte buffer[]) 197 throws IOException 198 { 199 IndexInput is = null; 200 try { 201 long startPtr = os.getFilePointer(); 202 203 is = directory.openInput(source.file); 204 long length = is.length(); 205 long remainder = length; 206 int chunk = buffer.length; 207 208 while(remainder > 0) { 209 int len = (int) Math.min(chunk, remainder); 210 is.readBytes(buffer, 0, len); 211 os.writeBytes(buffer, len); 212 remainder -= len; 213 } 214 215 if (remainder != 0) 217 throw new IOException ( 218 "Non-zero remainder length after copying: " + remainder 219 + " (id: " + source.file + ", length: " + length 220 + ", buffer size: " + chunk + ")"); 221 222 long endPtr = os.getFilePointer(); 224 long diff = endPtr - startPtr; 225 if (diff != length) 226 throw new IOException ( 227 "Difference in the output file offsets " + diff 228 + " does not match the original file length " + length); 229 230 } finally { 231 if (is != null) is.close(); 232 } 233 } 234 } 235 | Popular Tags |