/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
using System;
namespace Lucene.Net.Store
{
/// An {@link FSDirectory} implementation that uses
/// java.nio's FileChannel's positional read, which allows
/// multiple threads to read from the same file without
/// synchronizing.
///
/// This class only uses FileChannel when reading; writing
/// is achieved with {@link SimpleFSDirectory.SimpleFSIndexOutput}.
///
/// NOTE: NIOFSDirectory is not recommended on Windows because of a bug
/// in how FileChannel.read is implemented in Sun's JRE.
/// Inside of the implementation the position is apparently
/// synchronized. See here
/// for details.
///
public class NIOFSDirectory:FSDirectory
{
/// Create a new NIOFSDirectory for the named location.
///
///
/// the path of the directory
///
/// the lock factory to use, or null for the default.
///
/// IOException
[System.Obsolete("Use the constructor that takes a DirectoryInfo, this will be removed in the 3.0 release")]
public NIOFSDirectory(System.IO.FileInfo path, LockFactory lockFactory):base(new System.IO.DirectoryInfo(path.FullName), lockFactory)
{
}
/// Create a new NIOFSDirectory for the named location.
///
///
/// the path of the directory
///
/// the lock factory to use, or null for the default.
///
/// IOException
public NIOFSDirectory(System.IO.DirectoryInfo path, LockFactory lockFactory) : base(path, lockFactory)
{
}
/// Create a new NIOFSDirectory for the named location and the default lock factory.
///
///
/// the path of the directory
///
/// IOException
[System.Obsolete("Use the constructor that takes a DirectoryInfo, this will be removed in the 3.0 release")]
public NIOFSDirectory(System.IO.FileInfo path):base(new System.IO.DirectoryInfo(path.FullName), null)
{
}
/// Create a new NIOFSDirectory for the named location and the default lock factory.
///
///
/// the path of the directory
///
/// IOException
public NIOFSDirectory(System.IO.DirectoryInfo path) : base(path, null)
{
}
// back compatibility so FSDirectory can instantiate via reflection
///
///
[Obsolete]
internal NIOFSDirectory()
{
}
/// Creates an IndexInput for the file with the given name.
public override IndexInput OpenInput(System.String name, int bufferSize)
{
EnsureOpen();
return new NIOFSIndexInput(new System.IO.FileInfo(System.IO.Path.Combine(GetFile().FullName, name)), bufferSize, GetReadChunkSize());
}
/// Creates an IndexOutput for the file with the given name.
public override IndexOutput CreateOutput(System.String name)
{
InitOutput(name);
return new SimpleFSDirectory.SimpleFSIndexOutput(new System.IO.FileInfo(System.IO.Path.Combine(directory.FullName, name)));
}
public /*protected internal*/ class NIOFSIndexInput:SimpleFSDirectory.SimpleFSIndexInput
{
private System.IO.MemoryStream byteBuf; // wraps the buffer for NIO
private byte[] otherBuffer;
private System.IO.MemoryStream otherByteBuf;
internal System.IO.BinaryReader channel;
/// Please use ctor taking chunkSize
///
[Obsolete("Please use ctor taking chunkSize")]
public NIOFSIndexInput(System.IO.FileInfo path, int bufferSize):this(path, bufferSize, FSDirectory.DEFAULT_READ_CHUNK_SIZE)
{
}
public NIOFSIndexInput(System.IO.FileInfo path, int bufferSize, int chunkSize):base(path, bufferSize, chunkSize)
{
channel = (System.IO.BinaryReader) file;
}
protected internal override void NewBuffer(byte[] newBuffer)
{
base.NewBuffer(newBuffer);
// {{Aroush-2.9}} byteBuf = ByteBuffer.wrap(newBuffer);
System.Diagnostics.Debug.Fail("Port issue:", "byteBuf = ByteBuffer.wrap(newBuffer)"); // {{Aroush-2.9}}
}
public override void Close()
{
if (!isClone && file.isOpen)
{
// Close the channel & file
try
{
channel.Close();
}
finally
{
file.Close();
}
}
}
public override void ReadInternal(byte[] b, int offset, int len)
{
System.IO.MemoryStream bb;
// Determine the ByteBuffer we should use
if (b == buffer && 0 == offset)
{
// Use our own pre-wrapped byteBuf:
System.Diagnostics.Debug.Assert(byteBuf != null);
byteBuf.Position = 0;
byteBuf.Capacity = len;
bb = byteBuf;
}
else
{
if (offset == 0)
{
if (otherBuffer != b)
{
// Now wrap this other buffer; with compound
// file, we are repeatedly called with its
// buffer, so we wrap it once and then re-use it
// on subsequent calls
otherBuffer = b;
// otherByteBuf = ByteBuffer.wrap(b); {{Aroush-2.9}}
System.Diagnostics.Debug.Fail("Port issue:", "otherByteBuf = ByteBuffer.wrap(b)"); // {{Aroush-2.9}}
}
else
otherByteBuf.Position = 0;
otherByteBuf.Capacity = len;
bb = otherByteBuf;
}
else
{
// Always wrap when offset != 0
bb = null; // bb = ByteBuffer.wrap(b, offset, len); {{Aroush-2.9}}
System.Diagnostics.Debug.Fail("Port issue:", "bb = ByteBuffer.wrap(b, offset, len)"); // {{Aroush-2.9}}
}
}
int readOffset = (int) bb.Position;
int readLength = bb.Capacity - readOffset;
System.Diagnostics.Debug.Assert(readLength == len);
long pos = GetFilePointer();
try
{
while (readLength > 0)
{
int limit;
if (readLength > chunkSize)
{
// LUCENE-1566 - work around JVM Bug by breaking
// very large reads into chunks
limit = readOffset + chunkSize;
}
else
{
limit = readOffset + readLength;
}
bb.Capacity = limit;
int i = -1; // int i = channel.Read(bb, pos, limit); // {{Aroush-2.9}} must read from 'channel' into 'bb'
System.Diagnostics.Debug.Fail("Port issue:", "channel.Read(bb, pos, limit)"); // {{Aroush-2.9}}
if (i == - 1)
{
throw new System.IO.IOException("read past EOF");
}
pos += i;
readOffset += i;
readLength -= i;
}
}
catch (System.OutOfMemoryException e)
{
// propagate OOM up and add a hint for 32bit VM Users hitting the bug
// with a large chunk size in the fast path.
System.OutOfMemoryException outOfMemoryError = new System.OutOfMemoryException("OutOfMemoryError likely caused by the Sun VM Bug described in " + "https://issues.apache.org/jira/browse/LUCENE-1566; try calling FSDirectory.setReadChunkSize " + "with a a value smaller than the current chunk size (" + chunkSize + ")", e);
throw outOfMemoryError;
}
}
}
}
}