private unsafe bool BufferAndLoad(long currentAddress, long currentPage, long currentFrame, long headAddress) { for (int i = 0; i < frameSize; i++) { var nextPage = currentPage + i; // Cannot load page if its not fully written to storage if (headAddress < (nextPage + 1) << allocator.LogPageSizeBits) { continue; } var nextFrame = (currentFrame + i) % frameSize; long val; while ((val = nextLoadedPage[nextFrame]) < nextPage || loadedPage[nextFrame] < nextPage) { if (val < nextPage && Interlocked.CompareExchange(ref nextLoadedPage[nextFrame], nextPage, val) == val) { var tmp_i = i; epoch.BumpCurrentEpoch(() => { allocator.AsyncReadPagesFromDeviceToFrame(tmp_i + (currentAddress >> allocator.LogPageSizeBits), 1, endAddress, AsyncReadPagesCallback, Empty.Default, frame, out loaded[nextFrame], 0, null, null, loadedCancel[nextFrame]); loadedPage[nextFrame] = nextPage; }); } else { epoch.ProtectAndDrain(); } } } return(WaitForFrameLoad(currentAddress, currentFrame)); }
/// <summary> /// Buffer and load /// </summary> /// <param name="currentAddress"></param> /// <param name="currentPage"></param> /// <param name="currentFrame"></param> /// <param name="headAddress"></param> /// <param name="endAddress"></param> /// <returns></returns> protected unsafe bool BufferAndLoad(long currentAddress, long currentPage, long currentFrame, long headAddress, long endAddress) { for (int i = 0; i < frameSize; i++) { var nextPage = currentPage + i; var pageStartAddress = nextPage << logPageSizeBits; // Cannot load page if it is entirely in memory or beyond the end address if (pageStartAddress >= headAddress || pageStartAddress >= endAddress) { continue; } var pageEndAddress = (nextPage + 1) << logPageSizeBits; if (endAddress < pageEndAddress) { pageEndAddress = endAddress; } if (headAddress < pageEndAddress) { pageEndAddress = headAddress; } var nextFrame = (currentFrame + i) % frameSize; long val; while ((val = nextLoadedPage[nextFrame]) < pageEndAddress || loadedPage[nextFrame] < pageEndAddress) { if (val < pageEndAddress && Interlocked.CompareExchange(ref nextLoadedPage[nextFrame], pageEndAddress, val) == val) { var tmp_i = i; if (epoch != null) { epoch.BumpCurrentEpoch(() => { AsyncReadPagesFromDeviceToFrame(tmp_i + (currentAddress >> logPageSizeBits), 1, endAddress, Empty.Default, out loaded[nextFrame], 0, null, null, loadedCancel[nextFrame]); loadedPage[nextFrame] = pageEndAddress; }); } else { AsyncReadPagesFromDeviceToFrame(tmp_i + (currentAddress >> logPageSizeBits), 1, endAddress, Empty.Default, out loaded[nextFrame], 0, null, null, loadedCancel[nextFrame]); loadedPage[nextFrame] = pageEndAddress; } } else { epoch?.ProtectAndDrain(); } } } return(WaitForFrameLoad(currentAddress, currentFrame)); }
private unsafe bool BufferAndLoad(long currentAddress, long currentPage, long currentFrame, long headAddress) { for (int i = 0; i < frameSize; i++) { var nextPage = currentPage + i; var pageEndAddress = (nextPage + 1) << allocator.LogPageSizeBits; if (fasterLog.readOnlyMode) { // Support partial page reads of committed data var _flush = fasterLog.CommittedUntilAddress; if (_flush < pageEndAddress) { pageEndAddress = _flush; } } // Cannot load page if its not fully written to storage if (headAddress < pageEndAddress) { continue; } var nextFrame = (currentFrame + i) % frameSize; long val; while ((val = nextLoadedPage[nextFrame]) < pageEndAddress || loadedPage[nextFrame] < pageEndAddress) { if (val < pageEndAddress && Interlocked.CompareExchange(ref nextLoadedPage[nextFrame], pageEndAddress, val) == val) { var tmp_i = i; epoch.BumpCurrentEpoch(() => { allocator.AsyncReadPagesFromDeviceToFrame(tmp_i + (currentAddress >> allocator.LogPageSizeBits), 1, endAddress, AsyncReadPagesCallback, Empty.Default, frame, out loaded[nextFrame], 0, null, null, loadedCancel[nextFrame]); loadedPage[nextFrame] = pageEndAddress; }); } else { epoch.ProtectAndDrain(); } } } return(WaitForFrameLoad(currentAddress, currentFrame)); }