using System; using System.IO; using ZeroLevel.Collections; using ZeroLevel.Services.Cache; using ZeroLevel.Services.FileSystem; using ZeroLevel.Services.Memory; namespace ZeroLevel.Services.PartitionStorage { internal sealed class PhisicalFileAccessorCachee : IDisposable { private readonly TimerCachee _indexReadersCachee; private readonly TimerCachee _dataReadersCachee; private readonly ConcurrentHashSet _lockedFiles = new ConcurrentHashSet(); public PhisicalFileAccessorCachee(TimeSpan dataExpirationPeriod, TimeSpan indexExpirationPeriod) { _dataReadersCachee = new TimerCachee(dataExpirationPeriod, s => new ParallelFileReader(s), i => i.Dispose(), 8192); _indexReadersCachee = new TimerCachee(indexExpirationPeriod, s => new ParallelFileReader(s), i => i.Dispose(), 8192); } #region DATA public void DropDataReader(string filePath) { _dataReadersCachee.Drop(filePath); } private ParallelFileReader GetDataReader(string filePath) { if (File.Exists(filePath) == false) throw new FileNotFoundException(filePath); return _dataReadersCachee.Get(filePath); } public IViewAccessor GetDataAccessor(string filePath, long offset) { if (false == _lockedFiles.Contains(filePath)) { var reader = GetDataReader(filePath); try { return reader.GetAccessor(offset); } catch (ObjectDisposedException) { _dataReadersCachee.Drop(filePath); reader = _dataReadersCachee.Get(filePath); } return reader.GetAccessor(offset); } return null; } public IViewAccessor GetDataAccessor(string filePath, long offset, int length) { if (false == _lockedFiles.Contains(filePath)) { var reader = GetDataReader(filePath); try { return reader.GetAccessor(offset, length); } catch (ObjectDisposedException) { _dataReadersCachee.Drop(filePath); reader = _dataReadersCachee.Get(filePath); } return reader.GetAccessor(offset, length); } return null; } public void DropAllDataReaders() { _dataReadersCachee.DropAll(); } #endregion #region Indexes public void DropIndexReader(string filePath) { _indexReadersCachee.Drop(filePath); } private ParallelFileReader GetIndexReader(string filePath) { if (File.Exists(filePath) == false) throw new FileNotFoundException(filePath); return _indexReadersCachee.Get(filePath); } public IViewAccessor GetIndexAccessor(string filePath, long offset) { if (false == _lockedFiles.Contains(filePath)) { var reader = GetIndexReader(filePath); try { return reader.GetAccessor(offset); } catch (ObjectDisposedException) { _indexReadersCachee.Drop(filePath); reader = _indexReadersCachee.Get(filePath); } return reader.GetAccessor(offset); } return null; } public IViewAccessor GetIndexAccessor(string filePath, long offset, int length) { if (false == _lockedFiles.Contains(filePath)) { var reader = GetIndexReader(filePath); try { return reader.GetAccessor(offset, length); } catch (ObjectDisposedException) { _indexReadersCachee.Drop(filePath); reader = _indexReadersCachee.Get(filePath); } return reader.GetAccessor(offset, length); } return null; } public void DropAllIndexReaders() { _indexReadersCachee.DropAll(); } #endregion public void LockFile(string filePath) { _lockedFiles.Add(filePath); DropDataReader(filePath); DropIndexReader(filePath); } public void UnlockFile(string filePath) { _lockedFiles.TryRemove(filePath); } public void Dispose() { _lockedFiles.Clear(); _dataReadersCachee.Dispose(); _indexReadersCachee.Dispose(); } } }