/// <summary> /// Flush pages from startPage (inclusive) to endPage (exclusive) /// to specified log device and obj device /// </summary> /// <param name="startPage"></param> /// <param name="endPage"></param> /// <param name="device"></param> /// <param name="completed"></param> public void AsyncFlushPagesToDevice(long startPage, long endPage, IDevice device, out CountdownEvent completed) { ISegmentedDevice objlogDevice = null; if (Key.HasObjectsToSerialize() || Value.HasObjectsToSerialize()) { objlogDevice = CreateObjectLogDevice(device); } int totalNumPages = (int)(endPage - startPage); completed = new CountdownEvent(totalNumPages); for (long flushPage = startPage; flushPage < endPage; flushPage++) { var asyncResult = new PageAsyncFlushResult <Empty> { handle = completed, count = 1 }; long pageStartAddress = flushPage << LogPageSizeBits; long pageEndAddress = (flushPage + 1) << LogPageSizeBits; WriteAsync(pointers[flushPage % BufferSize], (ulong)(AlignedPageSizeBytes * (flushPage - startPage)), PageSize, AsyncFlushPageToDeviceCallback, asyncResult, device, objlogDevice); } }
public void AsyncReadPagesFromDevice(int numPages, long destinationStartPage, IDevice device, out CountdownEvent completed) { var asyncResult = new PageAsyncFlushResult(); ISegmentedDevice objlogDevice = null; if (Key.HasObjectsToSerialize() || Value.HasObjectsToSerialize()) { objlogDevice = CreateObjectLogDevice(device); throw new Exception("Reading pages with object log not yet supported"); } completed = new CountdownEvent(numPages); asyncResult.handle = completed; asyncResult.objlogDevice = objlogDevice; for (long flushPage = destinationStartPage; flushPage < destinationStartPage + numPages; flushPage++) { long pageStartAddress = flushPage << LogPageSizeBits; long pageEndAddress = (flushPage + 1) << LogPageSizeBits; device.ReadAsync( (ulong)(AlignedPageSizeBytes * (flushPage - destinationStartPage)), pointers[flushPage % BufferSize], PageSize, AsyncReadPageFromDeviceCallback, asyncResult); } }
/// <summary> /// Flush pages from startPage (inclusive) to endPage (exclusive) /// to specified log device and obj device /// </summary> /// <param name="startPage"></param> /// <param name="endPage"></param> /// <param name="device"></param> public void AsyncFlushPagesToDevice(long startPage, long endPage, IDevice device, out CountdownEvent completed) { var asyncResult = new PageAsyncFlushResult(); int numPages = (int)(endPage - startPage); ISegmentedDevice objlogDevice = null; if (Key.HasObjectsToSerialize() || Value.HasObjectsToSerialize()) { numPages = numPages * 2; objlogDevice = CreateObjectLogDevice(device); } completed = new CountdownEvent(numPages); asyncResult.handle = completed; for (long flushPage = startPage; flushPage < endPage; flushPage++) { long pageStartAddress = flushPage << LogPageSizeBits; long pageEndAddress = (flushPage + 1) << LogPageSizeBits; WriteAsync(pointers[flushPage % BufferSize], (ulong)(AlignedPageSizeBytes * (flushPage - startPage)), (uint)(PageSize * PrivateRecordSize), AsyncFlushPageToDeviceCallback, asyncResult, device, objlogDevice); } }
public WrappedDevice(ISegmentedDevice device) { _device = device; _segmentSize = device.GetSegmentSize(); if (!Utility.IsPowerOfTwo(_segmentSize)) { throw new Exception("Invalid segment size"); } _segmentSizeBits = Utility.GetLogBase2((ulong)_segmentSize); _segmentSizeMask = _segmentSize - 1; }
public void AsyncReadPagesFromDevice <TContext>( long readPageStart, int numPages, IOCompletionCallback callback, TContext context, out CountdownEvent completed, long devicePageOffset = 0, IDevice device = null) { var usedDevice = (device != null) ? device : this.device; ISegmentedDevice usedObjlogDevice = null; if (Key.HasObjectsToSerialize() || Value.HasObjectsToSerialize()) { usedObjlogDevice = (device != null) ? CreateObjectLogDevice(device) : objlogDevice; } completed = new CountdownEvent(numPages); for (long readPage = readPageStart; readPage < (readPageStart + numPages); readPage++) { int pageIndex = (int)(readPage % BufferSize); if (values[pageIndex] == null) { // Allocate a new page AllocatePage(pageIndex); } else { ClearPage(pageIndex, readPage == 0); } var asyncResult = new PageAsyncReadResult <TContext>() { page = readPage, context = context, handle = completed, count = 1 }; ulong offsetInFile = (ulong)(AlignedPageSizeBytes * readPage); if (device != null) { offsetInFile = (ulong)(AlignedPageSizeBytes * (readPage - devicePageOffset)); } ReadAsync(offsetInFile, pointers[pageIndex], PageSize, callback, asyncResult, usedDevice, usedObjlogDevice); } }
public PersistentMemoryMalloc(IDevice device, long startAddress) { // Console.WriteLine("Total memory (GB) = " + totalSize/1000000000); // Console.WriteLine("BufferSize = " + BufferSize); // Console.WriteLine("ReadOnlyLag = " + (ReadOnlyLagAddress >> PageSizeBits)); if (BufferSize < 16) { throw new Exception("HLOG buffer must be at least 16 pages"); } this.device = device; objlogDevice = CreateObjectLogDevice(device); sectorSize = (int)device.GetSectorSize(); epoch = LightEpoch.Instance; ioBufferPool = new NativeSectorAlignedBufferPool(1, sectorSize); if (ForceUnpinnedAllocation) { IsPinned = false; } else { IsPinned = true; try { var tmp = new T[1]; var h = GCHandle.Alloc(tmp, GCHandleType.Pinned); var p = h.AddrOfPinnedObject(); //PrivateRecordSize = Marshal.SizeOf(tmp[0]); AlignedPageSizeBytes = (((PrivateRecordSize * PageSize) + (sectorSize - 1)) & ~(sectorSize - 1)); } catch (Exception) { IsPinned = false; } } ptrHandle = GCHandle.Alloc(pointers, GCHandleType.Pinned); nativePointers = (long *)ptrHandle.AddrOfPinnedObject(); Initialize(startAddress); }
public PersistentMemoryMalloc(IDevice device, long startAddress) { if (BufferSize < 16) { throw new Exception("HLOG buffer must be at least 16 pages"); } this.device = device; objlogDevice = CreateObjectLogDevice(device); sectorSize = (int)device.GetSectorSize(); epoch = LightEpoch.Instance; ioBufferPool = new NativeSectorAlignedBufferPool(1, sectorSize); AlignedPageSizeBytes = ((PageSize + (sectorSize - 1)) & ~(sectorSize - 1)); ptrHandle = GCHandle.Alloc(pointers, GCHandleType.Pinned); nativePointers = (long *)ptrHandle.AddrOfPinnedObject(); Initialize(startAddress); }
private void ReadAsync <TContext>( ulong alignedSourceAddress, IntPtr alignedDestinationAddress, uint aligned_read_length, IOCompletionCallback callback, PageAsyncReadResult <TContext> asyncResult, IDevice device, ISegmentedDevice objlogDevice) { if (!Key.HasObjectsToSerialize() && !Value.HasObjectsToSerialize()) { device.ReadAsync(alignedSourceAddress, alignedDestinationAddress, aligned_read_length, callback, asyncResult); return; } asyncResult.callback = callback; asyncResult.count++; asyncResult.objlogDevice = objlogDevice; device.ReadAsync(alignedSourceAddress, alignedDestinationAddress, aligned_read_length, AsyncReadPageCallback <TContext>, asyncResult); }
private void WriteAsync <TContext>(IntPtr alignedSourceAddress, ulong alignedDestinationAddress, uint numBytesToWrite, IOCompletionCallback callback, PageAsyncFlushResult <TContext> asyncResult, IDevice device, ISegmentedDevice objlogDevice) { if (!Key.HasObjectsToSerialize() && !Value.HasObjectsToSerialize()) { device.WriteAsync(alignedSourceAddress, alignedDestinationAddress, numBytesToWrite, callback, asyncResult); return; } // need to write both page and object cache asyncResult.count++; MemoryStream ms = new MemoryStream(); var buffer = ioBufferPool.Get(PageSize); Buffer.MemoryCopy((void *)alignedSourceAddress, buffer.aligned_pointer, numBytesToWrite, numBytesToWrite); long ptr = (long)buffer.aligned_pointer; List <long> addr = new List <long>(); asyncResult.freeBuffer1 = buffer; // Correct for page 0 of HLOG if (alignedDestinationAddress >> LogPageSizeBits == 0) { ptr += Constants.kFirstValidAddress; } while (ptr < (long)buffer.aligned_pointer + numBytesToWrite) { if (!Layout.GetInfo(ptr)->Invalid) { long pos = ms.Position; Key *key = Layout.GetKey(ptr); Key.Serialize(key, ms); ((AddressInfo *)key)->IsDiskAddress = true; ((AddressInfo *)key)->Address = pos; ((AddressInfo *)key)->Size = (int)(ms.Position - pos); addr.Add((long)key); pos = ms.Position; Value *value = Layout.GetValue(ptr); Value.Serialize(value, ms); ((AddressInfo *)value)->IsDiskAddress = true; ((AddressInfo *)value)->Address = pos; ((AddressInfo *)value)->Size = (int)(ms.Position - pos); addr.Add((long)value); } ptr += Layout.GetPhysicalSize(ptr); } var s = ms.ToArray(); var objBuffer = ioBufferPool.Get(s.Length); asyncResult.freeBuffer2 = objBuffer; var alignedLength = (s.Length + (sectorSize - 1)) & ~(sectorSize - 1); var objAddr = Interlocked.Add(ref segmentOffsets[(alignedDestinationAddress >> LogSegmentSizeBits) % SegmentBufferSize], alignedLength) - alignedLength; fixed(void *src = s) Buffer.MemoryCopy(src, objBuffer.aligned_pointer, s.Length, s.Length); foreach (var address in addr) { *((long *)address) += objAddr; } objlogDevice.WriteAsync( (IntPtr)objBuffer.aligned_pointer, (int)(alignedDestinationAddress >> LogSegmentSizeBits), (ulong)objAddr, (uint)alignedLength, callback, asyncResult); device.WriteAsync((IntPtr)buffer.aligned_pointer, alignedDestinationAddress, numBytesToWrite, callback, asyncResult); }