2 * Copyright 2005 The Apache Software Foundation
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 //using ByteBuffer = java.nio.ByteBuffer; // {{Aroush-1.9}}
18 //using FileChannel = java.nio.channels.FileChannel; // {{Aroush-1.9}}
19 //using MapMode = java.nio.channels.FileChannel.MapMode; // {{Aroush-1.9}}
20 namespace Lucene
.Net
.Store
23 /// <summary>File-based {@link Directory} implementation that uses mmap for input.
25 /// <p>To use this, invoke Java with the System property
26 /// Lucene.Net.FSDirectory.class set to
27 /// Lucene.Net.store.MMapDirectory. This will cause {@link
28 /// FSDirectory#GetDirectory(File,boolean)} to return instances of this class.
30 public class MMapDirectory
: FSDirectory
33 private class MMapIndexInput
: IndexInput
, System
.ICloneable
36 System
.IO
.FileStream buffer
; //{{}} private ByteBuffer buffer; // {{Aroush-1.9}}
39 internal MMapIndexInput(System
.IO
.FileStream raf
)
41 this.length
= raf
.Length
;
42 // this.buffer = raf.GetChannel().map(MapMode.READ_ONLY, 0, length); // {{Aroush-1.9}}
45 public override byte ReadByte()
47 return 0; // return buffer.get_Renamed(); // {{Aroush-1.9}}
50 public override void ReadBytes(byte[] b
, int offset
, int len
)
52 // buffer.get_Renamed(b, offset, len); // {{Aroush-1.9}}
55 public override long GetFilePointer()
57 return buffer
.Position
;
60 public override void Seek(long pos
)
62 buffer
.Seek(pos
, System
.IO
.SeekOrigin
.Begin
);
65 public override long Length()
70 public override System
.Object
Clone()
72 MMapIndexInput clone
= (MMapIndexInput
) base.Clone();
73 // clone.buffer = buffer.duplicate(); // {{Aroush-1.9}}
77 public override void Close()
82 /* Added class MultiMMapIndexInput, Paul Elschot.
83 * Slightly adapted constructor of MMapIndexInput.
84 * Licensed under the Apache License, Version 2.0.
86 private class MultiMMapIndexInput
:IndexInput
, System
.ICloneable
89 private System
.IO
.FileStream
[] buffers
; // private ByteBuffer[] buffers; // {{Aroush-1.9}}
90 private int[] bufSizes
; // keep here, ByteBuffer.size() method is optional
94 private int curBufIndex
;
95 private int maxBufSize
;
97 private System
.IO
.FileStream curBuf
; // private ByteBuffer curBuf; // {{Aroush-1.9}} // redundant for speed: buffers[curBufIndex]
98 private int curAvail
; // redundant for speed: (bufSizes[curBufIndex] - curBuf.position())
101 public MultiMMapIndexInput(System
.IO
.FileStream raf
, int maxBufSize
)
103 this.length
= raf
.Length
;
104 this.maxBufSize
= maxBufSize
;
107 throw new System
.ArgumentException("Non positive maxBufSize: " + maxBufSize
);
109 if ((length
/ maxBufSize
) > System
.Int32
.MaxValue
)
111 throw new System
.ArgumentException("RandomAccessFile too big for maximum buffer size: " + raf
.ToString());
114 int nrBuffers
= (int) (length
/ maxBufSize
);
115 if ((nrBuffers
* maxBufSize
) < length
)
118 this.buffers
= new System
.IO
.FileStream
[nrBuffers
]; // this.buffers = new ByteBuffer[nrBuffers]; // {{Aroush-1.9}}
119 this.bufSizes
= new int[nrBuffers
];
121 long bufferStart
= 0;
122 System
.IO
.FileStream rafc
= null; // FileChannel rafc = raf.getChannel(); // {{Aroush-1.9}}
123 for (int bufNr
= 0; bufNr
< nrBuffers
; bufNr
++)
125 int bufSize
= (length
> (bufferStart
+ maxBufSize
))?maxBufSize
:(int) (length
- bufferStart
);
126 // this.buffers[bufNr] = rafc.map(MapMode.READ_ONLY, bufferStart, bufSize); // {{Aroush-1.9}}
127 this.bufSizes
[bufNr
] = bufSize
;
128 bufferStart
+= bufSize
;
133 public override byte ReadByte()
135 // Performance might be improved by reading ahead into an array of
136 // eg. 128 bytes and readByte() from there.
140 curBuf
= buffers
[curBufIndex
]; // index out of bounds when too many bytes requested
141 curBuf
.Seek(0, System
.IO
.SeekOrigin
.Begin
);
142 curAvail
= bufSizes
[curBufIndex
];
145 return 0; // return curBuf.get_Renamed(); // {{Aroush-1.9}}
148 public override void ReadBytes(byte[] b
, int offset
, int len
)
150 while (len
> curAvail
)
152 // curBuf.get_Renamed(b, offset, curAvail); // {{Aroush-1.9}}
156 curBuf
= buffers
[curBufIndex
]; // index out of bounds when too many bytes requested
157 curBuf
.Seek(0, System
.IO
.SeekOrigin
.Begin
);
158 curAvail
= bufSizes
[curBufIndex
];
160 // curBuf.get_Renamed(b, offset, len); // {{Aroush-1.9}}
164 public override long GetFilePointer()
166 return (curBufIndex
* (long) maxBufSize
) + curBuf
.Position
;
169 public override void Seek(long pos
)
171 curBufIndex
= (int) (pos
/ maxBufSize
);
172 curBuf
= buffers
[curBufIndex
];
173 int bufOffset
= (int) (pos
- (curBufIndex
* maxBufSize
));
174 curBuf
.Seek(bufOffset
, System
.IO
.SeekOrigin
.Begin
);
175 curAvail
= bufSizes
[curBufIndex
] - bufOffset
;
178 public override long Length()
183 public override System
.Object
Clone()
185 MultiMMapIndexInput clone
= (MultiMMapIndexInput
) base.Clone();
186 // clone.buffers = new ByteBuffer[buffers.Length]; // {{Aroush-1.9}}
187 // No need to clone bufSizes.
188 // Since most clones will use only one buffer, duplicate() could also be
189 // done lazy in clones, eg. when adapting curBuf.
190 for (int bufNr
= 0; bufNr
< buffers
.Length
; bufNr
++)
192 // clone.buffers[bufNr] = buffers[bufNr].duplicate(); // {{Aroush-1.9}}
196 clone
.Seek(GetFilePointer());
198 catch (System
.IO
.IOException ioe
)
200 throw new System
.Exception(ioe
.ToString()); // {{Aroush-1.9}} should be re-thrown as RuntimeException
205 public override void Close()
210 private int MAX_BBUF
= System
.Int32
.MaxValue
;
212 public override IndexInput
OpenInput(System
.String name
)
214 System
.IO
.FileInfo f
= new System
.IO
.FileInfo(System
.IO
.Path
.Combine(GetFile().FullName
, name
));
215 System
.IO
.FileStream raf
= new System
.IO
.FileStream(f
.FullName
, System
.IO
.FileMode
.Open
, System
.IO
.FileAccess
.Read
);
218 return (raf
.Length
<= MAX_BBUF
) ? (IndexInput
) new MMapIndexInput(raf
) : (IndexInput
) new MultiMMapIndexInput(raf
, MAX_BBUF
);