private void Cleanup() { bool waittingForCacheThreadFinish = false; lock (_CacheLock) { if (_CacheThread != null) { waittingForCacheThreadFinish = true; _Closing = true; } } if (waittingForCacheThreadFinish) { try { if (!_CacheThread.Join(5000)) { _CacheThread.Abort(); } } catch { } } if (_CacheBufferIndex != null) { long realseMemSize = 0; for (int index = 0; index < _CacheBufferIndex.Length; index++) { CachedFileBufferManager.Buffer buffer = _CacheBufferIndex[index]; if (buffer != null) { realseMemSize += buffer.Close(); } } if (realseMemSize >= 64 * 1024 * 1024) { //Large than 64M //Force collect GC GC.Collect(GC.MaxGeneration); } } }
public override int Read(byte[] array, int offset, int count) { if (_CacheBufferIndex != null) { int index = (int)(this.Position / CachedFileBufferManager.BufferUnitSize); int offsetInBuffer = (int)(this.Position % CachedFileBufferManager.BufferUnitSize); if (_CacheBufferIndex[index] != null) { CachedFileBufferManager.Buffer buffer = _CacheBufferIndex[index]; byte[] data = _CacheBufferIndex[index].Data; if (data != null) { if (data.Length - offsetInBuffer - buffer.HeadPosition >= count) { //Data inside one block. Array.Copy(data, offsetInBuffer + buffer.HeadPosition, array, offset, count); Position += count; return(count); } else { if (buffer.HeadPosition > 0 || index == _CacheBufferIndex.Length - 1 || count < 10 * 1024) { //Data outside one block. but the index is not the beginning of the block //Or it is the last block //Or small count less than 10K //Return part of the data int len = data.Length - offsetInBuffer - buffer.HeadPosition; Array.Copy(data, offsetInBuffer + buffer.HeadPosition, array, offset, len); Position += len; return(len); } } } } if ((_Type == CachedType.Dynamic || _Type == CachedType.Full) && CacheAllFinished) { OffsetLength ol = _LastOLWithBuffer[index]; if (offsetInBuffer >= ol.Offset && offsetInBuffer <= ol.Offset + ol.Length) { ol.Length += count - (ol.Offset + ol.Length - offsetInBuffer); } else { ol.Offset = offsetInBuffer; ol.Length = count; } _LastOLWithBuffer[index] = ol; if (ol.Length >= MinCacheLength) { //Cached if (LoadToBuffer(count, Position)) { return(Read(array, offset, count)); } } } //return data from file base.Seek(Position, SeekOrigin.Begin); int retLen = base.Read(array, offset, count); Position += retLen; return(retLen); } return(base.Read(array, offset, count)); }
/// <summary> /// Read and output to array /// </summary> /// <param name="array">array</param> /// <param name="offsetInArray">offset in array</param> /// <param name="offset">offset in file</param> /// <param name="count">count want to read</param> /// <returns>actual read count</returns> public int Read(out byte[] array, out int offsetInArray, int count) { if (_CacheBufferIndex != null) { int index = (int)(this.Position / CachedFileBufferManager.BufferUnitSize); int offsetInBuffer = (int)(this.Position % CachedFileBufferManager.BufferUnitSize); if (_CacheBufferIndex[index] != null) { CachedFileBufferManager.Buffer buffer = _CacheBufferIndex[index]; byte[] data = _CacheBufferIndex[index].Data; if (data != null) { if (data.Length - offsetInBuffer - buffer.HeadPosition >= count) { array = data; offsetInArray = offsetInBuffer + buffer.HeadPosition; Position += count; return(count); } else { if (buffer.HeadPosition > 0 || index == _CacheBufferIndex.Length - 1 || count < 10 * 1024) { //Data outside one block. but the index is not the beginning of the block //Or it is the last block //Or small count less than 10K //Return part of the data array = new byte[count]; Stream.ReadToBuf(this, array, 0, ref count); offsetInArray = 0; return(count); } } } } if ((_Type == CachedType.Dynamic || _Type == CachedType.Full) && CacheAllFinished) { OffsetLength ol = _LastOLWithBuffer[index]; if (offsetInBuffer >= ol.Offset && offsetInBuffer <= ol.Offset + ol.Length) { ol.Length += count - (ol.Offset + ol.Length - offsetInBuffer); } else { ol.Offset = offsetInBuffer; ol.Length = count; } _LastOLWithBuffer[index] = ol; if (ol.Length >= MinCacheLength) { //Cached if (LoadToBuffer(count, Position)) { return(Read(out array, out offsetInArray, count)); } } } //return data from file array = new byte[count]; Stream.ReadToBuf(this, array, 0, ref count); offsetInArray = 0; return(count); } array = new byte[count]; offsetInArray = 0; Stream.ReadToBuf(this, array, 0, ref count); return(count); }
private bool LoadToBuffer(int count, long position) { int index = (int)(position / CachedFileBufferManager.BufferUnitSize); int offsetInBuffer = (int)(position % CachedFileBufferManager.BufferUnitSize); if (count > CachedFileBufferManager.BufferUnitSize - offsetInBuffer) { int dataremain = (count - (CachedFileBufferManager.BufferUnitSize - offsetInBuffer)); int loadIndexes = 1 + dataremain / CachedFileBufferManager.BufferUnitSize; if ((dataremain % CachedFileBufferManager.BufferUnitSize) > 0) { loadIndexes++; } int loadLength = loadIndexes * CachedFileBufferManager.BufferUnitSize; if (index + loadIndexes >= _CacheBufferIndex.Length) { //To last buffer loadLength = (int)(_FileLength - index * CachedFileBufferManager.BufferUnitSize); } CachedFileBufferManager.Buffer buffer = _CachedFileMgr.Alloc(loadLength); if (buffer == null) { return(false); } byte[] data = buffer.Data; if (data != null) { base.Seek(index * CachedFileBufferManager.BufferUnitSize, SeekOrigin.Begin); int offset = 0; int read = 0; while ((read = base.Read(data, offset, data.Length - offset)) > 0) { offset += read; if (offset >= data.Length) { break; } } if (offset != data.Length) { throw new System.IO.IOException(); } } else { return(false); } lock (this) { CachedFileBufferManager.Buffer preBuffer = null; for (int i = index; i < index + loadIndexes; i++) { if (_CacheBufferIndex[i] != null) { _CacheBufferIndex[i].Close(); } if (i == index) { _CacheBufferIndex[i] = buffer; preBuffer = _CacheBufferIndex[i]; } else { _CacheBufferIndex[i] = buffer.Clone((i - index) * CachedFileBufferManager.BufferUnitSize); preBuffer.Next = _CacheBufferIndex[i]; preBuffer = _CacheBufferIndex[i]; } } } return(true); } else { return(InnerCacheUnit(index)); } }