private PTable(string filename,
Guid id,
int initialReaders = ESConsts.PTableInitialReaderCount,
int maxReaders = ESConsts.PTableMaxReaderCount,
int depth = 16)
{
Ensure.NotNullOrEmpty(filename, "filename");
Ensure.NotEmptyGuid(id, "id");
Ensure.Positive(maxReaders, "maxReaders");
Ensure.Nonnegative(depth, "depth");
if (!File.Exists(filename))
throw new CorruptIndexException(new PTableNotFoundException(filename));
_id = id;
_filename = filename;
Log.Trace("Loading and Verification of PTable '{0}' started...", Path.GetFileName(Filename));
var sw = Stopwatch.StartNew();
_size = new FileInfo(_filename).Length;
File.SetAttributes(_filename, FileAttributes.ReadOnly | FileAttributes.NotContentIndexed);
_workItems = new ObjectPool<WorkItem>(string.Format("PTable {0} work items", _id),
initialReaders,
maxReaders,
() => new WorkItem(filename, DefaultBufferSize),
workItem => workItem.Dispose(),
pool => OnAllWorkItemsDisposed());
var readerWorkItem = GetWorkItem();
try
{
readerWorkItem.Stream.Seek(0, SeekOrigin.Begin);
var header = PTableHeader.FromStream(readerWorkItem.Stream);
if ((header.Version != PTableVersions.Index32Bit) &&
(header.Version != PTableVersions.Index64Bit))
throw new CorruptIndexException(new WrongFileVersionException(_filename, header.Version, Version));
_version = header.Version;
if (_version == PTableVersions.Index32Bit)
{
_indexEntrySize = IndexEntry32Size;
_indexKeySize = IndexKey32Size;
}
if (_version == PTableVersions.Index64Bit)
{
_indexEntrySize = IndexEntry64Size;
_indexKeySize = IndexKey64Size;
}
_count = ((_size - PTableHeader.Size - MD5Size) / _indexEntrySize);
if (Count == 0)
{
_minEntry = new IndexEntryKey(ulong.MaxValue, int.MaxValue);
_maxEntry = new IndexEntryKey(ulong.MinValue, int.MinValue);
}
else
{
var minEntry = ReadEntry(_indexEntrySize, Count - 1, readerWorkItem, _version);
_minEntry = new IndexEntryKey(minEntry.Stream, minEntry.Version);
var maxEntry = ReadEntry(_indexEntrySize, 0, readerWorkItem, _version);
_maxEntry = new IndexEntryKey(maxEntry.Stream, maxEntry.Version);
}
}
catch (Exception)
{
Dispose();
throw;
}
finally
{
ReturnWorkItem(readerWorkItem);
}
int calcdepth = 0;
try
{
calcdepth = GetDepth(_size, depth);
_midpoints = CacheMidpointsAndVerifyHash(calcdepth);
}
catch (PossibleToHandleOutOfMemoryException)
{
Log.Error("Unable to create midpoints for PTable '{0}' ({1} entries, depth {2} requested). "
+ "Performance hit will occur. OOM Exception.", Path.GetFileName(Filename), Count, depth);
}
Log.Trace("Loading PTable (Version: {0}) '{1}' ({2} entries, cache depth {3}) done in {4}.",
_version, Path.GetFileName(Filename), Count, calcdepth, sw.Elapsed);
}