private unsafe long CalculateSize(IEventPayloads payloads) { // event count + crc // foreach event: meta + payload long size = sizeof(byte) + sizeof(uint); foreach (var e in payloads) { size += sizeof(EventMeta); size += e.Count; } return(size); }
public unsafe Task <IEnumerable <EventMeta> > Write(IEventPayloads payload) { lock (_view) { // early out if we are complete if (_isComplete) { return(null); } // early out if we don't have enough space left in the log var space = _view.Capacity - _position; if (space < CalculateSize(payload)) { return(null); } var events = new List <EventMeta>(); try { byte *ptr = null; _view.SafeMemoryMappedViewHandle.AcquirePointer(ref ptr); var start = _position; // write event count in the batch *(ptr + _position) = (byte)payload.Count; _position += sizeof(byte); foreach (var e in payload) { // write event meta block var meta = new EventMeta { Created = DateTime.UtcNow, Id = _start + _count }; *(EventMeta *)(ptr + _position) = meta; _position += sizeof(EventMeta); // write event payload *(ushort *)(ptr + _position) = (ushort)e.Count; _position += sizeof(ushort); Marshal.Copy(e.Array, e.Offset, (IntPtr)(ptr + _position), e.Count); _position += e.Count; // increment event count _count++; events.Add(meta); } // post-fix batch with crc var length = (int)(_position - start); var crcBuffer = GetBuffer(length); Marshal.Copy((IntPtr)(ptr + start), crcBuffer, 0, length); var crc = Crc32Algorithm.Compute(crcBuffer, 0, length); *(uint *)(ptr + _position) = crc; _position += sizeof(uint); } finally { _view.SafeMemoryMappedViewHandle.ReleasePointer(); } // store a handle to the task - to be completed when the buffer is flushed var tcs = new TaskCompletionSource <IEnumerable <EventMeta> >(); _awaiting.Add(() => tcs.SetResult(events)); return(tcs.Task); } }
public Task <IEnumerable <EventMeta> > Store(IEventPayloads payload) => throw new NotImplementedException();