internal long CalculateSize(TMeta metadata, int count) { long metaSize = MetaFormatter.Serialize <TMeta>(metadata).Length; long headerSize = Unsafe.SizeOf <Header>(); long dataSize = Unsafe.SizeOf <TStruct>() * count; return(metaSize + headerSize + dataSize); }
public void Write(TSet items, WriteType writeType = WriteType.Update) { if (!_initialized) { throw new NotSupportedException("Writing to an uninitialized Session is not supported"); } _syncLock.EnterWriteLock(); try { _data = Read(); if (_data.Count == 0 || writeType == WriteType.Overwrite) { _data = items; } else { if (writeType == WriteType.Update) { _data.Update(items); _data.MetaData = items.MetaData; } else if (writeType == WriteType.Append) { _data.Append(items); _data.MetaData = items.MetaData; } } long fileSize = CalculateSize(_data.MetaData, _data.Count); byte[] metaBytes = MetaFormatter.Serialize <TMeta>(_data.MetaData); long headerSize = Unsafe.SizeOf <Header>(); long dataStart = Unsafe.SizeOf <Header>() + metaBytes.Length; long dataEnd = dataStart + (Unsafe.SizeOf <TStruct>() * items.Count); Header info = new Header { MetaLen = metaBytes.Length, ItemCount = items.Count }; using (MemoryMappedFile memFile = MemoryMappedFile.CreateFromFile(_fileName, FileMode.Create, _mapName, fileSize, MemoryMappedFileAccess.ReadWrite)) using (MemoryMappedViewStream view = memFile.CreateViewStream(0, 0, MemoryMappedFileAccess.Write)) { TMap map = new TMap(); RuntimeHelpers.PrepareConstrainedRegions(); byte *ptr = (byte *)0; try { view.SafeMemoryMappedViewHandle.AcquirePointer(ref ptr); byte *start = ptr; byte *end = ptr + fileSize; Unsafe.Write <Header>(start, info); start += headerSize; Marshal.Copy(metaBytes, 0, IntPtr.Add(new IntPtr(ptr), (int)headerSize), metaBytes.Length); start += metaBytes.Length; int len = Unsafe.SizeOf <TStruct>(); foreach (TData item in items) { TStruct strct = map.ToStruct(item); Unsafe.Write <TStruct>(start, strct); start += len; } } finally { if (ptr != null) { view.SafeMemoryMappedViewHandle.ReleasePointer(); } } } } catch (Exception e) { throw e; } finally { _syncLock.ExitWriteLock(); } }