/// <summary> /// Processes the GetBlock from the committed area. /// </summary> /// <param name="pageLock"></param> /// <param name="position"></param> /// <param name="pointer">an output parameter that contains the pointer for the provided position</param> /// <remarks>The valid length is at least the size of the buffer pools page size.</remarks> private void GetBlockFromCommittedSpace(PageReplacementAlgorithm.PageLock pageLock, long position, out IntPtr pointer) { //If the page is in the buffer, we can return and don't have to read it. if (pageLock.TryGetSubPage(position, out pointer)) { return; } //If the address doesn't exist in the current list. Read it from the disk. int poolPageIndex; IntPtr poolAddress; m_pool.AllocatePage(out poolPageIndex, out poolAddress); m_queue.Read(position, poolAddress); //Since a race condition exists, I need to check the buffer to make sure that //the most recently read page already exists in the PageReplacementAlgorithm. bool wasPageAdded; pointer = pageLock.GetOrAddPage(position, poolAddress, poolPageIndex, out wasPageAdded); //If I lost on the race condition, I need to re-release this page. if (!wasPageAdded) { m_pool.ReleasePage(poolPageIndex); } }
/// <summary> /// Populates the pointer data inside <see cref="args"/> for the desired block as specified in <see cref="args"/>. /// This function will block if needing to retrieve data from the disk. /// </summary> /// <param name="pageLock">The reusable lock information about what this block is currently using.</param> /// <param name="args">Contains what block needs to be read and when this function returns, /// it will contain the proper pointer information for this block.</param> private void GetBlock(PageReplacementAlgorithm.PageLock pageLock, BlockArguments args) { pageLock.Clear(); //Determines where the block is located. if (args.Position >= m_lengthOfCommittedData) { //If the block is in the uncommitted space, it is stored in the //MemoryPoolStreamCore. args.SupportsWriting = true; m_writeBuffer.GetBlock(args); } else if (args.Position < m_lengthOfHeader) { //If the block is in the header, error because this area of the file is not designed to be accessed. throw new ArgumentOutOfRangeException("args", "Cannot use this function to modify the file header."); } else { //If it is between the file header and uncommitted space, //it is in the committed space, which this space by design is never to be modified. if (args.IsWriting) { throw new ArgumentException("Cannot write to committed data space", "args"); } args.SupportsWriting = false; args.Length = m_diskBlockSize; //rounds to the beginning of the block to be looked up. args.FirstPosition = args.Position & ~(long)m_pool.PageMask; GetBlockFromCommittedSpace(pageLock, args.FirstPosition, out args.FirstPointer); //Make sure the block does not go beyond the end of the uncommitted space. if (args.FirstPosition + args.Length > m_lengthOfCommittedData) { args.Length = (int)(m_lengthOfCommittedData - args.FirstPosition); } } }