// nsISeekableStream NS_IMETHODIMP CacheFileInputStream::Seek(int32_t whence, int64_t offset) { CacheFileAutoLock lock(mFile); MOZ_ASSERT(!mInReadSegments); LOG(("CacheFileInputStream::Seek() [this=%p, whence=%d, offset=%lld]", this, whence, offset)); if (mClosed) { LOG(("CacheFileInputStream::Seek() - Stream is closed. [this=%p]", this)); return NS_BASE_STREAM_CLOSED; } int64_t newPos = offset; switch (whence) { case NS_SEEK_SET: break; case NS_SEEK_CUR: newPos += mPos; break; case NS_SEEK_END: newPos += mFile->mDataSize; break; default: NS_ERROR("invalid whence"); return NS_ERROR_INVALID_ARG; } mPos = newPos; EnsureCorrectChunk(true); LOG(("CacheFileInputStream::Seek() [this=%p, pos=%lld]", this, mPos)); return NS_OK; }
NS_IMETHODIMP CacheFileInputStream::AsyncWait(nsIInputStreamCallback *aCallback, uint32_t aFlags, uint32_t aRequestedCount, nsIEventTarget *aEventTarget) { CacheFileAutoLock lock(mFile); MOZ_ASSERT(!mInReadSegments); LOG(("CacheFileInputStream::AsyncWait() [this=%p, callback=%p, flags=%d, " "requestedCount=%d, eventTarget=%p]", this, aCallback, aFlags, aRequestedCount, aEventTarget)); mCallback = aCallback; mCallbackFlags = aFlags; if (!mCallback) { if (mWaitingForUpdate) { mChunk->CancelWait(this); mWaitingForUpdate = false; } return NS_OK; } if (mClosed) { NotifyListener(); return NS_OK; } EnsureCorrectChunk(false); MaybeNotifyListener(); return NS_OK; }
NS_IMETHODIMP CacheFileInputStream::ReadSegments(nsWriteSegmentFun aWriter, void *aClosure, uint32_t aCount, uint32_t *_retval) { CacheFileAutoLock lock(mFile); MOZ_ASSERT(!mInReadSegments); LOG(("CacheFileInputStream::ReadSegments() [this=%p, count=%d]", this, aCount)); nsresult rv; if (mClosed) { LOG(("CacheFileInputStream::ReadSegments() - Stream is closed. [this=%p, " "status=0x%08x]", this, mStatus)); if NS_FAILED(mStatus) return mStatus; *_retval = 0; return NS_OK; } EnsureCorrectChunk(false); if (!mChunk) { if (mListeningForChunk == -1) { *_retval = 0; return NS_OK; } else { return NS_BASE_STREAM_WOULD_BLOCK; } } int64_t canRead; const char *buf; CanRead(&canRead, &buf); if (canRead < 0) { // file was truncated ??? MOZ_ASSERT(false, "SetEOF is currenty not implemented?!"); *_retval = 0; rv = NS_OK; } else if (canRead > 0) { uint32_t toRead = std::min(static_cast<uint32_t>(canRead), aCount); // We need to release the lock to avoid lock re-entering #ifdef DEBUG int64_t oldPos = mPos; #endif mInReadSegments = true; lock.Unlock(); rv = aWriter(this, aClosure, buf, 0, toRead, _retval); lock.Lock(); mInReadSegments = false; #ifdef DEBUG MOZ_ASSERT(oldPos == mPos); #endif if (NS_SUCCEEDED(rv)) { MOZ_ASSERT(*_retval <= toRead, "writer should not write more than we asked it to write"); mPos += *_retval; } EnsureCorrectChunk(!(canRead < aCount && mPos % kChunkSize == 0)); rv = NS_OK; } else { if (mFile->mOutput) rv = NS_BASE_STREAM_WOULD_BLOCK; else { *_retval = 0; rv = NS_OK; } } LOG(("CacheFileInputStream::ReadSegments() [this=%p, rv=0x%08x, retval=%d", this, rv, *_retval)); return rv; }
NS_IMETHODIMP CacheFileInputStream::ReadSegments(nsWriteSegmentFun aWriter, void *aClosure, uint32_t aCount, uint32_t *_retval) { CacheFileAutoLock lock(mFile); LOG(("CacheFileInputStream::ReadSegments() [this=%p, count=%d]", this, aCount)); nsresult rv; *_retval = 0; if (mClosed) { LOG(("CacheFileInputStream::ReadSegments() - Stream is closed. [this=%p, " "status=0x%08x]", this, mStatus)); if NS_FAILED(mStatus) return mStatus; return NS_OK; } EnsureCorrectChunk(false); while (true) { if (NS_FAILED(mStatus)) return mStatus; if (!mChunk) { if (mListeningForChunk == -1) { return NS_OK; } else { return NS_BASE_STREAM_WOULD_BLOCK; } } int64_t canRead; const char *buf; CanRead(&canRead, &buf); if (NS_FAILED(mStatus)) { return mStatus; } if (canRead < 0) { // file was truncated ??? MOZ_ASSERT(false, "SetEOF is currenty not implemented?!"); rv = NS_OK; } else if (canRead > 0) { uint32_t toRead = std::min(static_cast<uint32_t>(canRead), aCount); uint32_t read; rv = aWriter(this, aClosure, buf, *_retval, toRead, &read); if (NS_SUCCEEDED(rv)) { MOZ_ASSERT(read <= toRead, "writer should not write more than we asked it to write"); *_retval += read; mPos += read; aCount -= read; // The last chunk is released after the caller closes this stream. EnsureCorrectChunk(false); if (mChunk && aCount) { // We have the next chunk! Go on. continue; } } rv = NS_OK; } else { if (mFile->mOutput) rv = NS_BASE_STREAM_WOULD_BLOCK; else { rv = NS_OK; } } break; } LOG(("CacheFileInputStream::ReadSegments() [this=%p, rv=0x%08x, retval=%d]", this, rv, *_retval)); return rv; }