Land DISKCACHE1_BRANCH, implementing first draft of cache map file for more efficient eviction and cache miss detection. Fixed some problems with overeager setting of lastModified time stamp. Read cache enable prefs on startup. r=beard, sr=darin.

git-svn-id: svn://10.0.0.236/trunk@90752 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
gordon%netscape.com
2001-03-29 05:54:58 +00:00
parent 0484dbbaf3
commit 473ba08356
21 changed files with 1062 additions and 520 deletions

View File

@@ -22,8 +22,9 @@
*/
#include "nsDiskCacheMap.h"
#include "nsIInputStream.h"
#include "nsIOutputStream.h"
#include "nsIFileStreams.h"
#include <string.h>
nsDiskCacheMap::nsDiskCacheMap()
{
@@ -35,33 +36,74 @@ nsDiskCacheMap::~nsDiskCacheMap()
nsDiskCacheRecord* nsDiskCacheMap::GetRecord(PRUint32 hashNumber)
{
PRUint32 index = (hashNumber & (kBucketsPerTable - 1));
nsDiskCacheBucket& bucket = mBuckets[index];
nsDiskCacheBucket& bucket = mBuckets[(hashNumber & (kBucketsPerTable - 1))];
nsDiskCacheRecord* oldestRecord = &bucket.mRecords[0];
for (int i = 0; i < kRecordsPerBucket; ++i) {
nsDiskCacheRecord* record = &bucket.mRecords[i];
for (int r = 0; r < kRecordsPerBucket; ++r) {
nsDiskCacheRecord* record = &bucket.mRecords[r];
if (record->HashNumber() == 0 || record->HashNumber() == hashNumber)
return record;
if (record->EvictionRank() > oldestRecord->EvictionRank())
if (record->EvictionRank() < oldestRecord->EvictionRank())
oldestRecord = record;
}
// record not found, so must evict a record.
oldestRecord->SetHashNumber(0);
oldestRecord->SetEvictionRank(0);
// if we don't find an empty record, return the oldest record for eviction.
return oldestRecord;
}
void nsDiskCacheMap::DeleteRecord(PRUint32 hashNumber)
{
nsDiskCacheBucket& bucket = mBuckets[(hashNumber & (kBucketsPerTable - 1))];
for (int r = 0; r < kRecordsPerBucket; ++r) {
nsDiskCacheRecord* record = &bucket.mRecords[r];
if (record->HashNumber() == hashNumber) {
nsDiskCacheRecord* deletedRecord = record;
nsDiskCacheRecord* lastRecord = nsnull;
// XXX use binary search to find the end, much quicker.
// find the last record, to fill in the deleted record.
for (int j = r + 1; j < kRecordsPerBucket; ++j) {
record = &bucket.mRecords[j];
if (record->HashNumber() == 0) {
lastRecord = record - 1;
break;
}
}
// copy the last record, to the newly deleted record.
if (lastRecord && deletedRecord != lastRecord) {
*deletedRecord = *lastRecord;
deletedRecord = lastRecord;
}
// mark record as free.
deletedRecord->SetHashNumber(0);
break;
}
}
}
nsresult nsDiskCacheMap::Read(nsIInputStream* input)
{
// XXX need a header, etc.
nsresult rv;
PRUint32 count;
nsresult rv = input->Read((char*)&mBuckets, sizeof(mBuckets), &count);
// read the header.
rv = input->Read((char*)&mHeader, sizeof(mHeader), &count);
if (NS_FAILED(rv)) return rv;
mHeader.Unswap();
// validate the version.
if (mHeader.mVersion != nsDiskCacheHeader::kCurrentVersion) return NS_ERROR_FAILURE;
// seek to beginning of first bucket.
nsCOMPtr<nsISeekableStream> seekable = do_QueryInterface(input, &rv);
if (NS_FAILED(rv)) return rv;
rv = seekable->Seek(nsISeekableStream::NS_SEEK_SET, sizeof(nsDiskCacheBucket));
if (NS_FAILED(rv)) return rv;
// read the buckets.
rv = input->Read((char*)&mBuckets[1], sizeof(mBuckets) - sizeof(nsDiskCacheBucket), &count);
if (NS_FAILED(rv)) return rv;
// unswap all of the active records.
for (int b = 0; b < kBucketsPerTable; ++b) {
for (int b = 1; b < kBucketsPerTable; ++b) {
nsDiskCacheBucket& bucket = mBuckets[b];
for (int r = 0; r < kRecordsPerBucket; ++r) {
nsDiskCacheRecord* record = &bucket.mRecords[r];
@@ -76,8 +118,12 @@ nsresult nsDiskCacheMap::Read(nsIInputStream* input)
nsresult nsDiskCacheMap::Write(nsIOutputStream* output)
{
nsresult rv;
PRUint32 count;
int b;
// swap all of the active records.
for (int b = 0; b < kBucketsPerTable; ++b) {
for (b = 1; b < kBucketsPerTable; ++b) {
nsDiskCacheBucket& bucket = mBuckets[b];
for (int r = 0; r < kRecordsPerBucket; ++r) {
nsDiskCacheRecord* record = &bucket.mRecords[r];
@@ -87,12 +133,11 @@ nsresult nsDiskCacheMap::Write(nsIOutputStream* output)
}
}
// XXX need a header, etc.
PRUint32 count;
nsresult rv = output->Write((char*)&mBuckets, sizeof(mBuckets), &count);
// write the buckets.
rv = output->Write((char*)&mBuckets, sizeof(mBuckets), &count);
// unswap all of the active records.
for (int b = 0; b < kBucketsPerTable; ++b) {
for (b = 1; b < kBucketsPerTable; ++b) {
nsDiskCacheBucket& bucket = mBuckets[b];
for (int r = 0; r < kRecordsPerBucket; ++r) {
nsDiskCacheRecord* record = &bucket.mRecords[r];
@@ -101,6 +146,18 @@ nsresult nsDiskCacheMap::Write(nsIOutputStream* output)
record->Unswap();
}
}
if (NS_FAILED(rv)) return rv;
// seek back to beginning of file.
nsCOMPtr<nsISeekableStream> seekable = do_QueryInterface(output, &rv);
if (NS_FAILED(rv)) return rv;
rv = seekable->Seek(nsISeekableStream::NS_SEEK_SET, 0);
if (NS_FAILED(rv)) return rv;
// write the header.
mHeader.Swap();
rv = output->Write((char*)&mHeader, sizeof(mHeader), &count);
mHeader.Unswap();
return rv;
}