Bug 604897 - Unable to cache small entries when _CACHE_00[1-3]_ is full; r=mayhemer a=blocking-betaN+
This commit is contained in:
59
netwerk/cache/nsDiskCacheBlockFile.cpp
vendored
59
netwerk/cache/nsDiskCacheBlockFile.cpp
vendored
@@ -46,23 +46,27 @@
|
||||
* nsDiskCacheBlockFile -
|
||||
*****************************************************************************/
|
||||
|
||||
const unsigned short kBitMapBytes = 4096;
|
||||
const unsigned short kBitMapWords = (kBitMapBytes/4);
|
||||
|
||||
/******************************************************************************
|
||||
* Open
|
||||
*****************************************************************************/
|
||||
nsresult
|
||||
nsDiskCacheBlockFile::Open( nsILocalFile * blockFile, PRUint32 blockSize)
|
||||
nsDiskCacheBlockFile::Open(nsILocalFile * blockFile,
|
||||
PRUint32 blockSize,
|
||||
PRUint32 bitMapSize)
|
||||
{
|
||||
if (bitMapSize % 32)
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
|
||||
mBlockSize = blockSize;
|
||||
mBitMapWords = bitMapSize / 32;
|
||||
PRUint32 bitMapBytes = mBitMapWords * 4;
|
||||
|
||||
// open the file - restricted to user, the data could be confidential
|
||||
nsresult rv = blockFile->OpenNSPRFileDesc(PR_RDWR | PR_CREATE_FILE, 00600, &mFD);
|
||||
if (NS_FAILED(rv)) return rv; // unable to open or create file
|
||||
|
||||
// allocate bit map buffer
|
||||
mBitMap = new PRUint32[kBitMapWords];
|
||||
mBitMap = new PRUint32[mBitMapWords];
|
||||
if (!mBitMap) {
|
||||
rv = NS_ERROR_OUT_OF_MEMORY;
|
||||
goto error_exit;
|
||||
@@ -77,24 +81,24 @@ nsDiskCacheBlockFile::Open( nsILocalFile * blockFile, PRUint32 blockSize)
|
||||
}
|
||||
if (mFileSize == 0) {
|
||||
// initialize bit map and write it
|
||||
memset(mBitMap, 0, kBitMapBytes);
|
||||
if (!Write(0, mBitMap, kBitMapBytes))
|
||||
memset(mBitMap, 0, bitMapBytes);
|
||||
if (!Write(0, mBitMap, bitMapBytes))
|
||||
goto error_exit;
|
||||
|
||||
} else if (mFileSize < kBitMapBytes) {
|
||||
} else if ((PRUint32)mFileSize < bitMapBytes) {
|
||||
rv = NS_ERROR_UNEXPECTED; // XXX NS_ERROR_CACHE_INVALID;
|
||||
goto error_exit;
|
||||
|
||||
} else {
|
||||
// read the bit map
|
||||
const PRInt32 bytesRead = PR_Read(mFD, mBitMap, kBitMapBytes);
|
||||
if (bytesRead < kBitMapBytes) {
|
||||
const PRInt32 bytesRead = PR_Read(mFD, mBitMap, bitMapBytes);
|
||||
if ((bytesRead < 0) || ((PRUint32)bytesRead < bitMapBytes)) {
|
||||
rv = NS_ERROR_UNEXPECTED;
|
||||
goto error_exit;
|
||||
}
|
||||
#if defined(IS_LITTLE_ENDIAN)
|
||||
// Swap from network format
|
||||
for (int i = 0; i < kBitMapWords; ++i)
|
||||
for (unsigned int i = 0; i < mBitMapWords; ++i)
|
||||
mBitMap[i] = ntohl(mBitMap[i]);
|
||||
#endif
|
||||
// validate block file size
|
||||
@@ -155,7 +159,7 @@ nsDiskCacheBlockFile::AllocateBlocks(PRInt32 numBlocks)
|
||||
{
|
||||
const int maxPos = 32 - numBlocks;
|
||||
const PRUint32 mask = (0x01 << numBlocks) - 1;
|
||||
for (int i = 0; i < kBitMapWords; ++i) {
|
||||
for (unsigned int i = 0; i < mBitMapWords; ++i) {
|
||||
PRUint32 mapWord = ~mBitMap[i]; // flip bits so free bits are 1
|
||||
if (mapWord) { // At least one free bit
|
||||
// Binary search for first free bit in word
|
||||
@@ -171,7 +175,7 @@ nsDiskCacheBlockFile::AllocateBlocks(PRInt32 numBlocks)
|
||||
if ((mask & mapWord) == mask) {
|
||||
mBitMap[i] |= mask << bit;
|
||||
mBitMapDirty = PR_TRUE;
|
||||
return i * 32 + bit;
|
||||
return (PRInt32)i * 32 + bit;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -189,7 +193,7 @@ nsDiskCacheBlockFile::DeallocateBlocks( PRInt32 startBlock, PRInt32 numBlocks)
|
||||
{
|
||||
if (!mFD) return NS_ERROR_NOT_AVAILABLE;
|
||||
|
||||
if ((startBlock < 0) || (startBlock > kBitMapBytes * 8 - 1) ||
|
||||
if ((startBlock < 0) || ((PRUint32)startBlock > mBitMapWords * 32 - 1) ||
|
||||
(numBlocks < 1) || (numBlocks > 4))
|
||||
return NS_ERROR_ILLEGAL_VALUE;
|
||||
|
||||
@@ -224,10 +228,11 @@ nsDiskCacheBlockFile::WriteBlocks( void * buffer,
|
||||
|
||||
// allocate some blocks in the cache block file
|
||||
*startBlock = AllocateBlocks(numBlocks);
|
||||
NS_ENSURE_STATE(*startBlock >= 0);
|
||||
|
||||
if (*startBlock < 0)
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
|
||||
// seek to block position
|
||||
PRInt32 blockPos = kBitMapBytes + *startBlock * mBlockSize;
|
||||
PRInt32 blockPos = mBitMapWords * 4 + *startBlock * mBlockSize;
|
||||
|
||||
// write the blocks
|
||||
return Write(blockPos, buffer, size) ? NS_OK : NS_ERROR_FAILURE;
|
||||
@@ -250,7 +255,7 @@ nsDiskCacheBlockFile::ReadBlocks( void * buffer,
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
// seek to block position
|
||||
PRInt32 blockPos = kBitMapBytes + startBlock * mBlockSize;
|
||||
PRInt32 blockPos = mBitMapWords * 4 + startBlock * mBlockSize;
|
||||
PRInt32 filePos = PR_Seek(mFD, blockPos, PR_SEEK_SET);
|
||||
if (filePos != blockPos) return NS_ERROR_UNEXPECTED;
|
||||
|
||||
@@ -274,17 +279,21 @@ nsDiskCacheBlockFile::FlushBitMap()
|
||||
if (!mBitMapDirty) return NS_OK;
|
||||
|
||||
#if defined(IS_LITTLE_ENDIAN)
|
||||
PRUint32 bitmap[kBitMapWords];
|
||||
PRUint32 *bitmap = new PRUint32[mBitMapWords];
|
||||
// Copy and swap to network format
|
||||
PRUint32 *p = bitmap;
|
||||
for (int i = 0; i < kBitMapWords; ++i, ++p)
|
||||
for (unsigned int i = 0; i < mBitMapWords; ++i, ++p)
|
||||
*p = htonl(mBitMap[i]);
|
||||
#else
|
||||
PRUint32 *bitmap = mBitMap;
|
||||
#endif
|
||||
|
||||
// write bitmap
|
||||
if (!Write(0, bitmap, kBitMapBytes))
|
||||
bool written = Write(0, bitmap, mBitMapWords * 4);
|
||||
#if defined(IS_LITTLE_ENDIAN)
|
||||
delete [] bitmap;
|
||||
#endif
|
||||
if (!written)
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
|
||||
PRStatus err = PR_Sync(mFD);
|
||||
@@ -307,7 +316,7 @@ nsDiskCacheBlockFile::FlushBitMap()
|
||||
nsresult
|
||||
nsDiskCacheBlockFile::VerifyAllocation( PRInt32 startBlock, PRInt32 numBlocks)
|
||||
{
|
||||
if ((startBlock < 0) || (startBlock > kBitMapBytes * 8 - 1) ||
|
||||
if ((startBlock < 0) || ((PRUint32)startBlock > mBitMapWords * 32 - 1) ||
|
||||
(numBlocks < 1) || (numBlocks > 4))
|
||||
return NS_ERROR_ILLEGAL_VALUE;
|
||||
|
||||
@@ -335,8 +344,8 @@ PRUint32
|
||||
nsDiskCacheBlockFile::CalcBlockFileSize()
|
||||
{
|
||||
// search for last byte in mBitMap with allocated bits
|
||||
PRUint32 estimatedSize = kBitMapBytes;
|
||||
PRInt32 i = kBitMapWords;
|
||||
PRUint32 estimatedSize = mBitMapWords * 4;
|
||||
PRInt32 i = mBitMapWords;
|
||||
while (--i >= 0) {
|
||||
if (mBitMap[i]) break;
|
||||
}
|
||||
@@ -375,7 +384,7 @@ nsDiskCacheBlockFile::Write(PRInt32 offset, const void *buf, PRInt32 amount)
|
||||
const PRInt32 maxPreallocate = 20*1000*1000;
|
||||
if (mFileSize < upTo) {
|
||||
// maximal file size
|
||||
const PRInt32 maxFileSize = kBitMapBytes * (mBlockSize * 8 + 1);
|
||||
const PRInt32 maxFileSize = mBitMapWords * 4 * (mBlockSize * 8 + 1);
|
||||
if (upTo > maxPreallocate) {
|
||||
// grow the file as a multiple of minPreallocate
|
||||
mFileSize = ((upTo + minPreallocate - 1) / minPreallocate) * minPreallocate;
|
||||
|
||||
Reference in New Issue
Block a user