1 package org.apache.lucene.store; 2 3 18 19 import java.io.IOException ; 20 import java.io.File ; 21 import java.io.RandomAccessFile ; 22 import java.nio.ByteBuffer ; 23 import java.nio.channels.FileChannel ; 24 import java.nio.channels.FileChannel.MapMode; 25 26 33 public class MMapDirectory extends FSDirectory { 34 35 private static class MMapIndexInput extends IndexInput { 36 37 private ByteBuffer buffer; 38 private final long length; 39 40 private MMapIndexInput(RandomAccessFile raf) throws IOException { 41 this.length = raf.length(); 42 this.buffer = raf.getChannel().map(MapMode.READ_ONLY, 0, length); 43 } 44 45 public byte readByte() throws IOException { 46 return buffer.get(); 47 } 48 49 public void readBytes(byte[] b, int offset, int len) 50 throws IOException { 51 buffer.get(b, offset, len); 52 } 53 54 public long getFilePointer() { 55 return buffer.position(); 56 } 57 58 public void seek(long pos) throws IOException { 59 buffer.position((int)pos); 60 } 61 62 public long length() { 63 return length; 64 } 65 66 public Object clone() { 67 MMapIndexInput clone = (MMapIndexInput)super.clone(); 68 clone.buffer = buffer.duplicate(); 69 return clone; 70 } 71 72 public void close() throws IOException {} 73 } 74 75 79 private static class MultiMMapIndexInput extends IndexInput { 80 81 private ByteBuffer [] buffers; 82 private int[] bufSizes; 84 private final long length; 85 86 private int curBufIndex; 87 private final int maxBufSize; 88 89 private ByteBuffer curBuf; private int curAvail; 92 93 public MultiMMapIndexInput(RandomAccessFile raf, int maxBufSize) 94 throws IOException { 95 this.length = raf.length(); 96 this.maxBufSize = maxBufSize; 97 98 if (maxBufSize <= 0) 99 throw new IllegalArgumentException ("Non positive maxBufSize: " 100 + maxBufSize); 101 102 if ((length / maxBufSize) > Integer.MAX_VALUE) 103 throw new IllegalArgumentException 104 ("RandomAccessFile too big for maximum buffer size: " 105 + raf.toString()); 106 107 int nrBuffers = (int) (length / maxBufSize); 108 if ((nrBuffers * maxBufSize) < length) nrBuffers++; 109 110 this.buffers = new ByteBuffer [nrBuffers]; 111 this.bufSizes = new int[nrBuffers]; 112 113 long bufferStart = 0; 114 FileChannel rafc = raf.getChannel(); 115 for (int bufNr = 0; bufNr < nrBuffers; bufNr++) { 116 int bufSize = (length > (bufferStart + maxBufSize)) 117 ? maxBufSize 118 : (int) (length - bufferStart); 119 this.buffers[bufNr] = rafc.map(MapMode.READ_ONLY,bufferStart,bufSize); 120 this.bufSizes[bufNr] = bufSize; 121 bufferStart += bufSize; 122 } 123 seek(0L); 124 } 125 126 public byte readByte() throws IOException { 127 if (curAvail == 0) { 130 curBufIndex++; 131 curBuf = buffers[curBufIndex]; curBuf.position(0); 133 curAvail = bufSizes[curBufIndex]; 134 } 135 curAvail--; 136 return curBuf.get(); 137 } 138 139 public void readBytes(byte[] b, int offset, int len) throws IOException { 140 while (len > curAvail) { 141 curBuf.get(b, offset, curAvail); 142 len -= curAvail; 143 offset += curAvail; 144 curBufIndex++; 145 curBuf = buffers[curBufIndex]; curBuf.position(0); 147 curAvail = bufSizes[curBufIndex]; 148 } 149 curBuf.get(b, offset, len); 150 curAvail -= len; 151 } 152 153 public long getFilePointer() { 154 return (curBufIndex * (long) maxBufSize) + curBuf.position(); 155 } 156 157 public void seek(long pos) throws IOException { 158 curBufIndex = (int) (pos / maxBufSize); 159 curBuf = buffers[curBufIndex]; 160 int bufOffset = (int) (pos - (curBufIndex * maxBufSize)); 161 curBuf.position(bufOffset); 162 curAvail = bufSizes[curBufIndex] - bufOffset; 163 } 164 165 public long length() { 166 return length; 167 } 168 169 public Object clone() { 170 MultiMMapIndexInput clone = (MultiMMapIndexInput)super.clone(); 171 clone.buffers = new ByteBuffer [buffers.length]; 172 for (int bufNr = 0; bufNr < buffers.length; bufNr++) { 176 clone.buffers[bufNr] = buffers[bufNr].duplicate(); 177 } 178 try { 179 clone.seek(getFilePointer()); 180 } catch(IOException ioe) { 181 throw new RuntimeException (ioe); 182 }; 183 return clone; 184 } 185 186 public void close() throws IOException {} 187 } 188 189 private final int MAX_BBUF = Integer.MAX_VALUE; 190 191 public IndexInput openInput(String name) throws IOException { 192 File f = new File (getFile(), name); 193 RandomAccessFile raf = new RandomAccessFile (f, "r"); 194 try { 195 return (raf.length() <= MAX_BBUF) 196 ? (IndexInput) new MMapIndexInput(raf) 197 : (IndexInput) new MultiMMapIndexInput(raf, MAX_BBUF); 198 } finally { 199 raf.close(); 200 } 201 } 202 } 203 | Popular Tags |