public DataFile(string filePath, long initialSize, int growthIncrement) { try { bool isNew = !File.Exists(filePath); memoryMapper = new MemoryMapper(filePath, initialSize); mapping = MemoryMapping.Create(memoryMapper.fs, Constants.AllocationGranularity); dataFileHeaderPointer = (DataFileHeader *)mapping.GetBaseAddress(); this.growthIncrement = (growthIncrement + Constants.AllocationGranularityMask) / Constants.AllocationGranularity * Constants.AllocationGranularity; if (isNew) { InitializeHeader(); } else { ValidateHeader(); } } catch { Dispose(); throw; } }
public MemoryMapper(string filePath, long initialFileSize) { try { if (initialFileSize <= 0 || initialFileSize % Constants.AllocationGranularity != 0) { throw new ArgumentException("The initial file size must be a multiple of 64Kb and grater than zero"); } bool existingFile = File.Exists(filePath); fs = new FileStream(filePath, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.None); if (existingFile) { if (fs.Length <= 0 || fs.Length % Constants.AllocationGranularity != 0) { throw new ArgumentException("Invalid file. Its lenght must be a multiple of 64Kb and greater than zero"); } } else { fs.SetLength(initialFileSize); } mapping = MemoryMapping.Create(fs); } catch { Dispose(); throw; } }
internal void AddMapping(MemoryMapping mapping) { try { } // prevent ThreadAbortException from corrupting mappings collection finally { mappings.Add(mapping); mapping.AddRef(); baseAddress = mapping.GetBaseAddress(); BaseAddressChanged?.Invoke(this, new BaseAddressChangedEventArgs(baseAddress)); } }
internal static MemoryMapping Grow(long bytesToGrow, MemoryMapping mapping) { if (bytesToGrow <= 0 || bytesToGrow % Constants.AllocationGranularity != 0) { throw new ArgumentException("The growth must be a multiple of 64Kb and greater than zero"); } long offset = mapping.fileStream.Length; mapping.fileStream.SetLength(mapping.fileStream.Length + bytesToGrow); var mmf = MemoryMappedFile.CreateFromFile(mapping.fileStream, null, mapping.fileStream.Length, MemoryMappedFileAccess.ReadWrite, HandleInheritability.None, true); uint *offsetPointer = (uint *)&offset; var lastArea = mapping.areas[mapping.areas.Count - 1]; byte *desiredAddress = lastArea.Address + lastArea.Size; ulong bytesToMap = (ulong)bytesToGrow; var address = Win32FileMapping.MapViewOfFileEx(mmf.SafeMemoryMappedFileHandle.DangerousGetHandle(), Win32FileMapping.FileMapAccess.Read | Win32FileMapping.FileMapAccess.Write, offsetPointer[1], offsetPointer[0], new UIntPtr(bytesToMap), desiredAddress); if (address == null) { bytesToMap = (ulong)mapping.fileStream.Length; address = Win32FileMapping.MapViewOfFileEx(mmf.SafeMemoryMappedFileHandle.DangerousGetHandle(), Win32FileMapping.FileMapAccess.Read | Win32FileMapping.FileMapAccess.Write, 0, 0, new UIntPtr(bytesToMap), null); if (address == null) { throw new Win32Exception(); } mapping = new MemoryMapping() { baseAddress = address, fileStream = mapping.fileStream, refCount = 1 }; } var area = new MemoryMappedArea { Address = address, Mmf = mmf, Size = (long)bytesToMap }; mapping.areas.Add(area); return(mapping); }
public void Dispose() { if (IsDisposed) { return; } lock (SyncObject) { if (IsDisposed) { return; } IsDisposed = true; List <Exception> exceptions = new List <Exception>(); if (mapping != null) { try { mapping.Release(); mapping = null; } catch (Exception ex) { exceptions.Add(ex); } } if (fs != null) { try { fs.Dispose(); fs = null; } catch (Exception ex) { exceptions.Add(ex); } } if (exceptions.Count > 0) { throw new AggregateException(exceptions); } } }
public byte *Grow(long bytesToGrow) { CheckDisposed(); lock (SyncObject) { CheckDisposed(); var newMapping = MemoryMapping.Grow(bytesToGrow, mapping); if (mapping != newMapping) { var oldMapping = mapping; mapping = newMapping; oldMapping.Release(); foreach (var session in sessions) { session.AddMapping(newMapping); } } return(mapping.GetBaseAddress()); } }
public void Dispose() { if (IsDisposed) { return; } IsDisposed = true; List <Exception> exceptions = new List <Exception>(); if (mapping != null) { try { mapping.Release(); mapping = null; } catch (Exception ex) { exceptions.Add(ex); } } if (memoryMapper != null) { try { memoryMapper.Dispose(); memoryMapper = null; } catch (Exception ex) { exceptions.Add(ex); } } if (exceptions.Count > 0) { throw new AggregateException(exceptions); } }
internal static MemoryMapping Create(FileStream fs, long bytesToMap = 0) { var mmf = MemoryMappedFile.CreateFromFile(fs, null, fs.Length, MemoryMappedFileAccess.ReadWrite, HandleInheritability.None, true); var address = Win32FileMapping.MapViewOfFileEx(mmf.SafeMemoryMappedFileHandle.DangerousGetHandle(), Win32FileMapping.FileMapAccess.Read | Win32FileMapping.FileMapAccess.Write, 0, 0, new UIntPtr((ulong)bytesToMap), null); if (address == null) { throw new Win32Exception(); } var mapping = new MemoryMapping() { refCount = 1, fileStream = fs, baseAddress = address }; mapping.areas.Add(new MemoryMappedArea(mmf, address, fs.Length)); return(mapping); }