Пример #1
0
nsresult FileBlockCache::Run()
{
    MonitorAutoLock mon(mDataMonitor);
    NS_ASSERTION(!NS_IsMainThread(), "Don't call on main thread");
    NS_ASSERTION(!mChangeIndexList.empty(), "Only dispatch when there's work to do");
    NS_ASSERTION(mIsWriteScheduled, "Should report write running or scheduled.");

    while (!mChangeIndexList.empty()) {
        if (!mIsOpen) {
            // We've been closed, abort, discarding unwritten changes.
            mIsWriteScheduled = false;
            return NS_ERROR_FAILURE;
        }

        // Process each pending change. We pop the index out of the change
        // list, but leave the BlockChange in mBlockChanges until the change
        // is written to file. This is so that any read which happens while
        // we drop mDataMonitor to write will refer to the data's source in
        // memory, rather than the not-yet up to date data written to file.
        // This also ensures we will insert a new index into mChangeIndexList
        // when this happens.

        // Hold a reference to the change, in case another change
        // overwrites the mBlockChanges entry for this block while we drop
        // mDataMonitor to take mFileMonitor.
        int32_t blockIndex = mChangeIndexList.front();
        mChangeIndexList.pop_front();
        RefPtr<BlockChange> change = mBlockChanges[blockIndex];
        MOZ_ASSERT(change,
                   "Change index list should only contain entries for blocks "
                   "with changes");
        {
            MonitorAutoUnlock unlock(mDataMonitor);
            MonitorAutoLock lock(mFileMonitor);
            if (change->IsWrite()) {
                WriteBlockToFile(blockIndex, change->mData.get());
            } else if (change->IsMove()) {
                MoveBlockInFile(change->mSourceBlockIndex, blockIndex);
            }
        }
        // If a new change has not been made to the block while we dropped
        // mDataMonitor, clear reference to the old change. Otherwise, the old
        // reference has been cleared already.
        if (mBlockChanges[blockIndex] == change) {
            mBlockChanges[blockIndex] = nullptr;
        }
    }

    mIsWriteScheduled = false;

    return NS_OK;
}
nsresult FileBlockCache::MoveBlockInFile(int32_t aSourceBlockIndex,
                                         int32_t aDestBlockIndex)
{
  mFileMonitor.AssertCurrentThreadOwns();

  uint8_t buf[BLOCK_SIZE];
  int32_t bytesRead = 0;
  if (NS_FAILED(ReadFromFile(BlockIndexToOffset(aSourceBlockIndex),
                             buf,
                             BLOCK_SIZE,
                             bytesRead))) {
    return NS_ERROR_FAILURE;
  }
  return WriteBlockToFile(aDestBlockIndex, buf);
}
Пример #3
0
nsresult FileBlockCache::MoveBlockInFile(PRInt32 aSourceBlockIndex,
                                         PRInt32 aDestBlockIndex)
{
  mFileMonitor.AssertCurrentThreadOwns();

  PRUint8 buf[BLOCK_SIZE];
  PRInt32 bytesRead = 0;
  if (NS_FAILED(ReadFromFile(aSourceBlockIndex * BLOCK_SIZE,
                             buf,
                             BLOCK_SIZE,
                             bytesRead))) {
    return NS_ERROR_FAILURE;
  }
  return WriteBlockToFile(aDestBlockIndex, buf);
}