Bug 1010221 - Let CacheFileInputStream::ReadSegments loop over all preloaded chunks, r=michal

This commit is contained in:
Honza Bambas 2014-05-15 19:24:55 +02:00
parent 1c1e3abad3
commit 1b6004c6f1
3 changed files with 111 additions and 53 deletions

View File

@ -1362,6 +1362,50 @@ CacheFile::RemoveChunkInternal(CacheFileChunk *aChunk, bool aCacheChunk)
mChunks.Remove(aChunk->Index());
}
int64_t
CacheFile::BytesFromChunk(uint32_t aIndex)
{
AssertOwnsLock();
if (!mDataSize)
return 0;
uint32_t lastChunk = (mDataSize - 1) / kChunkSize;
if (aIndex > lastChunk)
return 0;
uint32_t i;
for (i = aIndex; i <= lastChunk; ++i) {
CacheFileChunk * chunk;
chunk = mChunks.GetWeak(i);
if (chunk) {
MOZ_ASSERT(i == lastChunk || chunk->mDataSize == kChunkSize);
if (chunk->IsReady()) {
continue;
}
// don't search this chunk in cached
break;
}
chunk = mCachedChunks.GetWeak(i);
if (chunk) {
MOZ_ASSERT(i == lastChunk || chunk->mDataSize == kChunkSize);
continue;
}
break;
}
// theoretic bytes in advance
int64_t advance = int64_t(i - aIndex) * kChunkSize;
// real bytes till the end of the file
int64_t tail = mDataSize - (aIndex * kChunkSize);
return std::min(advance, tail);
}
nsresult
CacheFile::RemoveInput(CacheFileInputStream *aInput)
{

View File

@ -140,6 +140,8 @@ private:
nsresult RemoveChunk(CacheFileChunk *aChunk);
void RemoveChunkInternal(CacheFileChunk *aChunk, bool aCacheChunk);
int64_t BytesFromChunk(uint32_t aIndex);
nsresult RemoveInput(CacheFileInputStream *aInput);
nsresult RemoveOutput(CacheFileOutputStream *aOutput);
nsresult NotifyChunkListener(CacheFileChunkListener *aCallback,

View File

@ -89,9 +89,8 @@ CacheFileInputStream::Available(uint64_t *_retval)
*_retval = 0;
if (mChunk) {
int64_t canRead;
const char *buf;
CanRead(&canRead, &buf);
int64_t canRead = mFile->BytesFromChunk(mChunk->Index());
canRead -= (mPos % kChunkSize);
if (canRead > 0)
*_retval = canRead;
@ -188,6 +187,8 @@ CacheFileInputStream::ReadSegments(nsWriteSegmentFun aWriter, void *aClosure,
nsresult rv;
*_retval = 0;
if (mClosed) {
LOG(("CacheFileInputStream::ReadSegments() - Stream is closed. [this=%p, "
"status=0x%08x]", this, mStatus));
@ -195,67 +196,78 @@ CacheFileInputStream::ReadSegments(nsWriteSegmentFun aWriter, void *aClosure,
if NS_FAILED(mStatus)
return mStatus;
*_retval = 0;
return NS_OK;
}
EnsureCorrectChunk(false);
if (NS_FAILED(mStatus))
return mStatus;
if (!mChunk) {
if (mListeningForChunk == -1) {
*_retval = 0;
return NS_OK;
}
else {
return NS_BASE_STREAM_WOULD_BLOCK;
}
}
while (true) {
if (NS_FAILED(mStatus))
return mStatus;
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;
if (!mChunk) {
if (mListeningForChunk == -1) {
return NS_OK;
}
else {
return NS_BASE_STREAM_WOULD_BLOCK;
}
}
EnsureCorrectChunk(!(canRead < aCount && mPos % kChunkSize == 0));
int64_t canRead;
const char *buf;
CanRead(&canRead, &buf);
rv = NS_OK;
}
else {
if (mFile->mOutput)
rv = NS_BASE_STREAM_WOULD_BLOCK;
else {
*_retval = 0;
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);
// We need to release the lock to avoid lock re-entering
#ifdef DEBUG
int64_t oldPos = mPos;
#endif
mInReadSegments = true;
lock.Unlock();
uint32_t read;
rv = aWriter(this, aClosure, buf, 0, toRead, &read);
lock.Lock();
mInReadSegments = false;
#ifdef DEBUG
MOZ_ASSERT(oldPos == mPos);
#endif
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",