From 826ed51db3d35ec1fa0c7d8bc1ace6e4d688380b Mon Sep 17 00:00:00 2001 From: "gordon%netscape.com" Date: Fri, 11 May 2001 01:38:03 +0000 Subject: [PATCH] Renaming nsDiskCacheEntry -> nsDiskCacheBindInfo, and reorganize files. git-svn-id: svn://10.0.0.236/branches/DISKCACHE2_BRANCH@94555 18797224-902f-48f8-a5cc-f745e15eee43 --- mozilla/netwerk/cache/src/nsDiskCache.h | 10 - .../netwerk/cache/src/nsDiskCacheBindData.cpp | 221 +++++++ .../netwerk/cache/src/nsDiskCacheBindData.h | 188 ++++++ .../cache/src/nsDiskCacheBlockFile.cpp | 126 ++-- .../netwerk/cache/src/nsDiskCacheBlockFile.h | 7 +- .../netwerk/cache/src/nsDiskCacheDevice.cpp | 590 +++--------------- mozilla/netwerk/cache/src/nsDiskCacheDevice.h | 34 +- .../netwerk/cache/src/nsDiskCacheEntry.cpp | 242 +++---- mozilla/netwerk/cache/src/nsDiskCacheEntry.h | 258 ++++---- mozilla/netwerk/cache/src/nsDiskCacheMap.cpp | 12 +- mozilla/netwerk/cache/src/nsDiskCacheMap.h | 28 +- 11 files changed, 820 insertions(+), 896 deletions(-) create mode 100644 mozilla/netwerk/cache/src/nsDiskCacheBindData.cpp create mode 100644 mozilla/netwerk/cache/src/nsDiskCacheBindData.h diff --git a/mozilla/netwerk/cache/src/nsDiskCache.h b/mozilla/netwerk/cache/src/nsDiskCache.h index 6bb1da76ea6..1a2bb5788b6 100644 --- a/mozilla/netwerk/cache/src/nsDiskCache.h +++ b/mozilla/netwerk/cache/src/nsDiskCache.h @@ -26,15 +26,5 @@ #ifndef _nsDiskCache_h_ #define _nsDiskCache_h_ -#include "prtypes.h" -#include "prnetdb.h" -#include "nsDebug.h" - - - -/* - - -*/ #endif // _nsDiskCache_h_ diff --git a/mozilla/netwerk/cache/src/nsDiskCacheBindData.cpp b/mozilla/netwerk/cache/src/nsDiskCacheBindData.cpp new file mode 100644 index 00000000000..f8126c613b9 --- /dev/null +++ b/mozilla/netwerk/cache/src/nsDiskCacheBindData.cpp @@ -0,0 +1,221 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is nsDiskCacheBindData.cpp, released May 10, 2001. + * + * The Initial Developer of the Original Code is Netscape Communications + * Corporation. Portions created by Netscape are + * Copyright (C) 2001 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * Patrick C. Beard + * Gordon Sheridan + */ + +#include + +#include "nsDiskCacheBindData.h" + +/****************************************************************************** + * nsDiskCacheBindData + *****************************************************************************/ + +NS_IMPL_THREADSAFE_ISUPPORTS0(nsDiskCacheBindData); + +PLDHashNumber +nsDiskCacheBindData::Hash(const char* key) +{ + PLDHashNumber h = 0; + for (const PRUint8* s = (PRUint8*) key; *s != '\0'; ++s) + h = (h >> (PL_DHASH_BITS - 4)) ^ (h << 4) ^ *s; + return (h == 0 ? ULONG_MAX : h); +} + + +/****************************************************************************** + * nsDiskCacheHashTable + *****************************************************************************/ + +PLDHashTableOps nsDiskCacheHashTable::ops = +{ + PL_DHashAllocTable, + PL_DHashFreeTable, + GetKey, + HashKey, + MatchEntry, + MoveEntry, + ClearEntry, + Finalize +}; + + +nsDiskCacheHashTable::nsDiskCacheHashTable() + : initialized(PR_FALSE) +{ +} + + +nsDiskCacheHashTable::~nsDiskCacheHashTable() +{ + if (initialized) + PL_DHashTableFinish(&table); +} + + +nsresult +nsDiskCacheHashTable::Init() +{ + nsresult rv = NS_OK; + initialized = PL_DHashTableInit(&table, &ops, nsnull, + sizeof(HashTableEntry), 512); + + if (!initialized) rv = NS_ERROR_OUT_OF_MEMORY; + + return rv; +} + + +nsDiskCacheBindData * +nsDiskCacheHashTable::GetEntry(const char * key) +{ + return GetEntry(nsDiskCacheBindData::Hash(key)); +} + + +nsDiskCacheBindData * +nsDiskCacheHashTable::GetEntry(PLDHashNumber key) +{ + nsDiskCacheBindData * result = nsnull; + NS_ASSERTION(initialized, "nsDiskCacheHashTable not initialized"); + HashTableEntry * hashEntry; + hashEntry = (HashTableEntry*) PL_DHashTableOperate(&table, (void*) key, PL_DHASH_LOOKUP); + if (PL_DHASH_ENTRY_IS_BUSY(hashEntry)) { + result = hashEntry->mDiskCacheBindData; + } + return result; +} + + +nsresult +nsDiskCacheHashTable::AddEntry(nsDiskCacheBindData * entry) +{ + NS_ENSURE_ARG_POINTER(entry); + NS_ASSERTION(initialized, "nsDiskCacheHashTable not initialized"); + + HashTableEntry * hashEntry; + hashEntry = (HashTableEntry *) PL_DHashTableOperate(&table, + (void*) entry->getHashNumber(), + PL_DHASH_ADD); + if (!hashEntry) return NS_ERROR_OUT_OF_MEMORY; + + NS_ADDREF(hashEntry->mDiskCacheBindData = entry); + + return NS_OK; +} + + +void +nsDiskCacheHashTable::RemoveEntry(nsDiskCacheBindData * entry) +{ + NS_ASSERTION(initialized, "nsDiskCacheHashTable not initialized"); + NS_ASSERTION(entry, "### cacheEntry == nsnull"); + + (void) PL_DHashTableOperate(&table, (void*) entry->getHashNumber(), PL_DHASH_REMOVE); +} + + +void +nsDiskCacheHashTable::VisitEntries(Visitor *visitor) +{ + PL_DHashTableEnumerate(&table, VisitEntry, visitor); +} + + +PLDHashOperator PR_CALLBACK +nsDiskCacheHashTable::VisitEntry(PLDHashTable * table, + PLDHashEntryHdr * header, + PRUint32 number, + void * arg) +{ + HashTableEntry* hashEntry = (HashTableEntry *) header; + Visitor *visitor = (Visitor*) arg; + return (visitor->VisitEntry(hashEntry->mDiskCacheBindData) ? PL_DHASH_NEXT : PL_DHASH_STOP); +} + +/** + * hash table operation callback functions + */ +const void * PR_CALLBACK +nsDiskCacheHashTable::GetKey(PLDHashTable * /*table*/, PLDHashEntryHdr * header) +{ + HashTableEntry * hashEntry = (HashTableEntry *) header; + return (void*) hashEntry->mDiskCacheBindData->getHashNumber(); +} + + +PLDHashNumber PR_CALLBACK +nsDiskCacheHashTable::HashKey( PLDHashTable *table, const void *key) +{ + return (PLDHashNumber) key; +} + + +PRBool PR_CALLBACK +nsDiskCacheHashTable::MatchEntry(PLDHashTable * /* table */, + const PLDHashEntryHdr * header, + const void * key) +{ + HashTableEntry * hashEntry = (HashTableEntry *) header; + return (hashEntry->mDiskCacheBindData->getHashNumber() == (PLDHashNumber) key); +} + +void PR_CALLBACK +nsDiskCacheHashTable::MoveEntry(PLDHashTable * /* table */, + const PLDHashEntryHdr * fromHeader, + PLDHashEntryHdr * toHeader) +{ + HashTableEntry * fromEntry = (HashTableEntry *) fromHeader; + HashTableEntry * toEntry = (HashTableEntry *) toHeader; + toEntry->keyHash = fromEntry->keyHash; + toEntry->mDiskCacheBindData = fromEntry->mDiskCacheBindData; + fromEntry->mDiskCacheBindData = nsnull; +} + + +void PR_CALLBACK +nsDiskCacheHashTable::ClearEntry(PLDHashTable * /* table */, + PLDHashEntryHdr * header) +{ + HashTableEntry* hashEntry = (HashTableEntry *) header; + hashEntry->keyHash = 0; + NS_IF_RELEASE(hashEntry->mDiskCacheBindData); +} + + +void PR_CALLBACK +nsDiskCacheHashTable::Finalize(PLDHashTable * table) +{ + (void) PL_DHashTableEnumerate(table, FreeCacheEntries, nsnull); +} + + +PLDHashOperator PR_CALLBACK +nsDiskCacheHashTable::FreeCacheEntries(PLDHashTable * /* table */, + PLDHashEntryHdr * header, + PRUint32 number, + void * arg) +{ + HashTableEntry *entry = (HashTableEntry *) header; + NS_IF_RELEASE(entry->mDiskCacheBindData); + return PL_DHASH_NEXT; +} diff --git a/mozilla/netwerk/cache/src/nsDiskCacheBindData.h b/mozilla/netwerk/cache/src/nsDiskCacheBindData.h new file mode 100644 index 00000000000..46114461df6 --- /dev/null +++ b/mozilla/netwerk/cache/src/nsDiskCacheBindData.h @@ -0,0 +1,188 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is nsDiskCacheBindData.h, released May 10, 2001. + * + * The Initial Developer of the Original Code is Netscape Communications + * Corporation. Portions created by Netscape are + * Copyright (C) 2001 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + * Gordon Sheridan + * Patrick C. Beard + */ + + +#ifndef _nsDiskCacheBindData_h_ +#define _nsDiskCacheBindData_h_ + +#include "nspr.h" +#include "pldhash.h" + +#include "nsISupports.h" +#include "nsCacheEntry.h" + +#ifdef MOZ_NEW_CACHE_REUSE_TRANSPORTS +#include "nsITransport.h" +#endif + + +/****************************************************************************** + * nsDiskCacheBindData + * + * Created for disk cache specific data and stored in nsCacheEntry.mData as + * an nsISupports. Also stored in nsDiskCacheHashTable, with collisions + * linked by the PRCList. + * + *****************************************************************************/ + +class nsDiskCacheBindData : public nsISupports, public PRCList { +public: + NS_DECL_ISUPPORTS + + nsDiskCacheBindData(nsCacheEntry* entry) + : mCacheEntry(entry), + mGeneration(0) + { + NS_INIT_ISUPPORTS(); + PR_INIT_CLIST(this); + mHashNumber = Hash(entry->Key()->get()); + } + + virtual ~nsDiskCacheBindData() + { + PR_REMOVE_LINK(this); + } + +#ifdef MOZ_NEW_CACHE_REUSE_TRANSPORTS + /** + * Maps a cache access mode to a cached nsITransport for that access + * mode. We keep these cached to avoid repeated trips to the + * file transport service. + */ + nsCOMPtr& getTransport(nsCacheAccessMode mode) + { + return mTransports[mode - 1]; + } +#endif + + nsCacheEntry* getCacheEntry() + { + return mCacheEntry; + } + + PRUint32 getGeneration() + { + return mGeneration; + } + + void setGeneration(PRUint32 generation) + { + mGeneration = generation; + } + + PLDHashNumber getHashNumber() + { + return mHashNumber; + } + + nsrefcnt getRefCount() + { + return mRefCnt; + } + + static PLDHashNumber Hash(const char* key); + +private: +#ifdef MOZ_NEW_CACHE_REUSE_TRANSPORTS + nsCOMPtr mTransports[3]; +#endif + nsCacheEntry* mCacheEntry; // back pointer to parent nsCacheEntry + PRUint32 mGeneration; // XXX part of nsDiskCacheRecord + PLDHashNumber mHashNumber; // XXX part of nsDiskCacheRecord +// XXX nsDiskCacheRecord mMapRecord; +}; + + +/****************************************************************************** + * nsDiskCacheHashTable + * + * Used to keep track of nsDiskCacheEntries associated with active/bound (and + * possibly doomed) entries. Lookups on 4 byte disk hash to find collisions + * (which need to be doomed, instead of just evicted. Collisions are linked + * using a PRCList to keep track of current generation number. + * + *****************************************************************************/ + +class nsDiskCacheHashTable { +public: + nsDiskCacheHashTable(); + ~nsDiskCacheHashTable(); + + nsresult Init(); + + nsDiskCacheBindData * GetEntry(const char * key); + nsDiskCacheBindData * GetEntry(PLDHashNumber key); + nsresult AddEntry(nsDiskCacheBindData * entry); + void RemoveEntry(nsDiskCacheBindData * entry); + + class Visitor { + public: + virtual PRBool VisitEntry(nsDiskCacheBindData * entry) = 0; + }; + + void VisitEntries(Visitor * visitor); + +private: + struct HashTableEntry : PLDHashEntryHdr { + nsDiskCacheBindData * mDiskCacheBindData; // STRONG ref? + }; + + // PLDHashTable operation callbacks + static const void * PR_CALLBACK GetKey(PLDHashTable * table, + PLDHashEntryHdr * entry); + + static PLDHashNumber PR_CALLBACK HashKey(PLDHashTable * table, + const void * key); + + static PRBool PR_CALLBACK MatchEntry(PLDHashTable * table, + const PLDHashEntryHdr * entry, + const void * key); + + static void PR_CALLBACK MoveEntry(PLDHashTable * table, + const PLDHashEntryHdr * from, + PLDHashEntryHdr * to); + + static void PR_CALLBACK ClearEntry(PLDHashTable * table, + PLDHashEntryHdr * entry); + + static void PR_CALLBACK Finalize(PLDHashTable *table); + + static + PLDHashOperator PR_CALLBACK FreeCacheEntries(PLDHashTable * table, + PLDHashEntryHdr * hdr, + PRUint32 number, + void * arg); + static + PLDHashOperator PR_CALLBACK VisitEntry(PLDHashTable * table, + PLDHashEntryHdr * hdr, + PRUint32 number, + void * arg); + + // member variables + static PLDHashTableOps ops; + PLDHashTable table; + PRBool initialized; +}; + +#endif /* _nsDiskCacheBindData_h_ */ \ No newline at end of file diff --git a/mozilla/netwerk/cache/src/nsDiskCacheBlockFile.cpp b/mozilla/netwerk/cache/src/nsDiskCacheBlockFile.cpp index 5a5d3332439..94a86cde4b5 100644 --- a/mozilla/netwerk/cache/src/nsDiskCacheBlockFile.cpp +++ b/mozilla/netwerk/cache/src/nsDiskCacheBlockFile.cpp @@ -35,19 +35,12 @@ nsresult nsDiskCacheBlockFile::Open( nsILocalFile * blockFile, PRUint32 blockSize) { - // create the stream + PRStatus err = PR_SUCCESS; mBlockSize = blockSize; - mStream = new nsANSIFileStream; - if (!mStream) return NS_ERROR_OUT_OF_MEMORY; - NS_ADDREF(mStream); - // open the stream - nsresult rv = mStream->Open(blockFile); - if (NS_FAILED(rv)) { - NS_RELEASE(mStream); - mStream = nsnull; - return rv; - } + // open the file + nsresult rv = blockFile->OpenNSPRFileDesc(PR_RDWR | PR_CREATE_FILE, 00666, &mFD); + if (NS_FAILED(rv)) return rv; // unable to open or create file // allocate bit map buffer mBitMap = new PRUint8[kBitMapBytes]; @@ -57,17 +50,18 @@ nsDiskCacheBlockFile::Open( nsILocalFile * blockFile, PRUint32 blockSize) } // check if we just creating the file - rv = mStream->Available(&mEndOfFile); + PRInt32 fileSize = PR_Available(mFD); + if (fileSize < 0) { + // XXX an error occurred. We could call PR_GetError(), but how would that help? + rv = NS_ERROR_UNEXPECTED; + goto error_exit; + } + mEndOfFile = fileSize; if (mEndOfFile == 0) { // initialize bit map and write it nsCRT::zero(mBitMap, kBitMapBytes); - PRUint32 bytesWritten = 0; - rv = mStream->Write((char *)mBitMap, kBitMapBytes, &bytesWritten); - if (NS_FAILED(rv)) goto error_exit; - if (kBitMapBytes != bytesWritten) { - rv = NS_ERROR_UNEXPECTED; - goto error_exit; - } + PRInt32 bytesWritten = PR_Write(mFD, mBitMap, kBitMapBytes); + if (bytesWritten < kBitMapBytes) goto error_exit; mEndOfFile = kBitMapBytes; } else if (mEndOfFile < kBitMapBytes) { @@ -76,10 +70,8 @@ nsDiskCacheBlockFile::Open( nsILocalFile * blockFile, PRUint32 blockSize) } else { // read the bit map - PRUint32 bytesRead = 0; - rv = mStream->Read((char *)mBitMap, kBitMapBytes, &bytesRead); - if (NS_FAILED(rv)) goto error_exit; - if (kBitMapBytes != bytesRead) { + PRInt32 bytesRead = PR_Read(mFD, mBitMap, kBitMapBytes); + if (bytesRead < kBitMapBytes) { rv = NS_ERROR_UNEXPECTED; goto error_exit; } @@ -92,10 +84,9 @@ nsDiskCacheBlockFile::Open( nsILocalFile * blockFile, PRUint32 blockSize) return NS_OK; error_exit: - if (mStream) { - (void) mStream->Close(); - NS_RELEASE(mStream); - mStream = nsnull; + if (mFD) { + (void) PR_Close(mFD); + mFD = nsnull; } if (mBitMap) { @@ -112,19 +103,21 @@ error_exit: nsresult nsDiskCacheBlockFile::Close() { - if (!mStream) return NS_OK; + if (!mFD) return NS_OK; - nsresult rv = FlushBitMap(); - - nsresult rv2 = mStream->Close(); - NS_RELEASE(mStream); - mStream = nsnull; + nsresult rv = FlushBitMap(); + PRStatus err = PR_Close(mFD); + mFD = nsnull; if (mBitMap) { delete [] mBitMap; mBitMap = nsnull; } - return rv ? rv : rv2; + + if (NS_SUCCEEDED(rv) && (err != PR_SUCCESS)) + rv = NS_ERROR_UNEXPECTED; + + return rv; } @@ -153,7 +146,7 @@ nsDiskCacheBlockFile::Trim() PRInt32 nsDiskCacheBlockFile::AllocateBlocks(PRInt32 numBlocks) { - if (!mStream) return -1; // NS_ERROR_NOT_AVAILABLE; + if (!mFD) return -1; // NS_ERROR_NOT_AVAILABLE; // return -1 if unable to allocate blocks // PRUint8 mask = (0x01 << numBlocks) - 1; int i = 0; @@ -233,7 +226,7 @@ nsDiskCacheBlockFile::AllocateBlocks(PRInt32 numBlocks) nsresult nsDiskCacheBlockFile::DeallocateBlocks( PRInt32 startBlock, PRInt32 numBlocks) { - if (!mStream) return NS_ERROR_NOT_AVAILABLE; + if (!mFD) return NS_ERROR_NOT_AVAILABLE; if ((startBlock < 0) || (startBlock > kBitMapBytes * 8 - 1) || (numBlocks < 1) || (numBlocks > 4)) return NS_ERROR_ILLEGAL_VALUE; @@ -266,24 +259,22 @@ nsDiskCacheBlockFile::WriteBlocks( char * buffer, PRInt32 numBlocks) { // presume buffer != nsnull - if (!mStream) return NS_ERROR_NOT_AVAILABLE; + if (!mFD) return NS_ERROR_NOT_AVAILABLE; nsresult rv = VerifyAllocation(startBlock, numBlocks); if (NS_FAILED(rv)) return rv; // seek to block position PRInt32 blockPos = kBitMapBytes + startBlock * mBlockSize; - rv = mStream->Seek(nsISeekableStream::NS_SEEK_SET, blockPos); - if (NS_FAILED(rv)) return rv; + PRInt32 filePos = PR_Seek(mFD, blockPos, PR_SEEK_SET); + if (filePos != blockPos) return NS_ERROR_UNEXPECTED; if (mEndOfFile < (blockPos + numBlocks * mBlockSize)) mEndOfFile = (blockPos + numBlocks * mBlockSize); // write the blocks - PRUint32 bytesToWrite = numBlocks * mBlockSize; - PRUint32 bytesWritten = 0; - rv = mStream->Write(buffer, bytesToWrite, &bytesWritten); - if (NS_FAILED(rv)) return rv; - if (bytesWritten != bytesToWrite) return NS_ERROR_UNEXPECTED; + PRInt32 bytesToWrite = numBlocks * mBlockSize; + PRInt32 bytesWritten = PR_Write(mFD, buffer, bytesToWrite); + if (bytesWritten < bytesToWrite) return NS_ERROR_UNEXPECTED; // write the bit map and flush the file rv = FlushBitMap(); @@ -300,21 +291,19 @@ nsDiskCacheBlockFile::ReadBlocks( char * buffer, PRInt32 numBlocks) { // presume buffer != nsnull - if (!mStream) return NS_ERROR_NOT_AVAILABLE; + if (!mFD) return NS_ERROR_NOT_AVAILABLE; nsresult rv = VerifyAllocation(startBlock, numBlocks); if (NS_FAILED(rv)) return rv; // seek to block position PRInt32 blockPos = kBitMapBytes + startBlock * mBlockSize; - rv = mStream->Seek(nsISeekableStream::NS_SEEK_SET, blockPos); - if (NS_FAILED(rv)) return rv; + PRInt32 filePos = PR_Seek(mFD, blockPos, PR_SEEK_SET); + if (filePos != blockPos) return NS_ERROR_UNEXPECTED; // read the blocks - PRUint32 bytesToRead = numBlocks * mBlockSize; - PRUint32 bytesRead = 0; - rv = mStream->Read(buffer, bytesToRead, &bytesRead); - if (NS_FAILED(rv)) return rv; - if (bytesRead != bytesToRead) return NS_ERROR_UNEXPECTED; + PRInt32 bytesToRead = numBlocks * mBlockSize; + PRInt32 bytesRead = PR_Read(mFD, buffer, bytesToRead); + if (bytesRead < bytesToRead) return NS_ERROR_UNEXPECTED; return rv; } @@ -329,19 +318,15 @@ nsDiskCacheBlockFile::FlushBitMap() if (!mBitMapDirty) return NS_OK; // seek to bitmap - nsresult rv = mStream->Seek(nsISeekableStream::NS_SEEK_SET, 0); - if (NS_FAILED(rv)) return rv; + PRInt32 filePos = PR_Seek(mFD, 0, PR_SEEK_SET); + if (filePos != 0) return NS_ERROR_UNEXPECTED; // write bitmap - PRUint32 bytesWritten = 0; - rv = mStream->Write((char *)mBitMap, kBitMapBytes, &bytesWritten); - if (NS_FAILED(rv)) return rv; - if (kBitMapBytes != bytesWritten) { - return NS_ERROR_UNEXPECTED; - } - - rv = mStream->Flush(); - if (NS_FAILED(rv)) return rv; + PRInt32 bytesWritten = PR_Write(mFD, mBitMap, kBitMapBytes); + if (bytesWritten < kBitMapBytes) return NS_ERROR_UNEXPECTED; + + PRStatus err = PR_Sync(mFD); + if (err != PR_SUCCESS) return NS_ERROR_UNEXPECTED; mBitMapDirty = PR_FALSE; return NS_OK; @@ -357,20 +342,17 @@ nsDiskCacheBlockFile::FlushBitMap() nsresult nsDiskCacheBlockFile::ValidateFile() { - PRUint32 estimatedSize = kBitMapBytes; + PRInt32 estimatedSize = kBitMapBytes; PRInt32 lastBlock = LastBlock(); if (lastBlock >= 0) estimatedSize += (lastBlock + 1) * mBlockSize; - - PRUint32 fileSize = 0; - + // seek to beginning - nsresult rv = mStream->Seek(nsISeekableStream::NS_SEEK_SET, 0); - if (NS_FAILED(rv)) return rv; - - rv = mStream->Available(&fileSize); - if (NS_FAILED(rv)) return rv; + PRInt32 filePos = PR_Seek(mFD, 0, PR_SEEK_SET); + if (filePos != 0) return NS_ERROR_UNEXPECTED; + PRInt32 fileSize = PR_Available(mFD); + if (estimatedSize > fileSize) return NS_ERROR_UNEXPECTED; diff --git a/mozilla/netwerk/cache/src/nsDiskCacheBlockFile.h b/mozilla/netwerk/cache/src/nsDiskCacheBlockFile.h index c8b32b76455..868f7443b2f 100644 --- a/mozilla/netwerk/cache/src/nsDiskCacheBlockFile.h +++ b/mozilla/netwerk/cache/src/nsDiskCacheBlockFile.h @@ -24,7 +24,8 @@ #ifndef _nsDiskCacheBlockFile_h_ #define _nsDiskCacheBlockFile_h_ -#include "nsANSIFileStreams.h" +#include "nsILocalFile.h" +#include "nspr.h" enum { kBitMapBytes = 4096 }; @@ -48,7 +49,7 @@ typedef struct BlockFile { class nsDiskCacheBlockFile { public: nsDiskCacheBlockFile() - : mStream(nsnull) + : mFD(nsnull) , mBlockSize(0) , mEndOfFile(0) , mBitMap(nsnull) @@ -73,7 +74,7 @@ public: /** * Data members */ - nsANSIFileStream * mStream; + PRFileDesc * mFD; PRUint32 mBlockSize; PRUint32 mEndOfFile; PRUint8 * mBitMap; // XXX future: array of bit map blocks diff --git a/mozilla/netwerk/cache/src/nsDiskCacheDevice.cpp b/mozilla/netwerk/cache/src/nsDiskCacheDevice.cpp index aaa665653d4..2e0b4990ab3 100644 --- a/mozilla/netwerk/cache/src/nsDiskCacheDevice.cpp +++ b/mozilla/netwerk/cache/src/nsDiskCacheDevice.cpp @@ -259,21 +259,20 @@ static nsresult removeObservers(nsDiskCacheDevice* device) /****************************************************************************** * static utility functions *****************************************************************************/ -static nsDiskCacheEntry* -ensureDiskCacheEntry(nsCacheEntry * entry) +static nsDiskCacheBindData* +ensureDiskCacheBindData(nsCacheEntry * entry) { nsCOMPtr data; nsresult rv = entry->GetData(getter_AddRefs(data)); if (NS_SUCCEEDED(rv) && !data) { - nsDiskCacheEntry* diskEntry = new nsDiskCacheEntry(entry); - data = diskEntry; + nsDiskCacheBindData* bindData = new nsDiskCacheBindData(entry); + data = bindData; if (NS_SUCCEEDED(rv) && data) entry->SetData(data.get()); } - return (nsDiskCacheEntry*) (nsISupports*) data.get(); + return (nsDiskCacheBindData*) (nsISupports*) data.get(); } - /****************************************************************************** * nsDiskCacheDeviceInfo *****************************************************************************/ @@ -355,302 +354,9 @@ NS_IMETHODIMP nsDiskCacheDeviceInfo::GetMaximumSize(PRUint32 *aMaximumSize) } -/****************************************************************************** - * MetaData - *****************************************************************************/ -struct MetaDataHeader { - PRUint32 mHeaderSize; -// PRUint32 mHashNumber; // XXX -// PRUint32 mMetaLocation; // XXX - PRInt32 mFetchCount; - PRUint32 mLastFetched; - PRUint32 mLastModified; - PRUint32 mExpirationTime; - PRUint32 mDataSize; - PRUint32 mKeySize; - PRUint32 mMetaDataSize; -// void * mKeyPtrSpace; // XXX don't need this -// void * mMetaDataPtrSpace; // XXX don't need this, we'll calculate it when necessary - // followed by null-terminated key and metadata string values. - - MetaDataHeader() - : mHeaderSize(sizeof(MetaDataHeader)), - mFetchCount(0), - mLastFetched(0), - mLastModified(0), - mExpirationTime(0), - mDataSize(0), - mKeySize(0), - mMetaDataSize(0) - { - } - - MetaDataHeader(nsCacheEntry* entry) - : mHeaderSize(sizeof(MetaDataHeader)), - mFetchCount(entry->FetchCount()), - mLastFetched(entry->LastFetched()), - mLastModified(entry->LastModified()), - mExpirationTime(entry->ExpirationTime()), - mDataSize(entry->DataSize()), - mKeySize(entry->Key()->Length() + 1), - mMetaDataSize(0) - { - } - - void Swap() - { -#if defined(IS_LITTLE_ENDIAN) - mHeaderSize = ::PR_htonl(mHeaderSize); - mFetchCount = ::PR_htonl(mFetchCount); - mLastFetched = ::PR_htonl(mLastFetched); - mLastModified = ::PR_htonl(mLastModified); - mExpirationTime = ::PR_htonl(mExpirationTime); - mDataSize = ::PR_htonl(mDataSize); - mKeySize = ::PR_htonl(mKeySize); - mMetaDataSize = ::PR_htonl(mMetaDataSize); -#endif - } - - void Unswap() - { -#if defined(IS_LITTLE_ENDIAN) - mHeaderSize = ::PR_ntohl(mHeaderSize); - mFetchCount = ::PR_ntohl(mFetchCount); - mLastFetched = ::PR_ntohl(mLastFetched); - mLastModified = ::PR_ntohl(mLastModified); - mExpirationTime = ::PR_ntohl(mExpirationTime); - mDataSize = ::PR_ntohl(mDataSize); - mKeySize = ::PR_ntohl(mKeySize); - mMetaDataSize = ::PR_ntohl(mMetaDataSize); -#endif - } -}; - -struct MetaDataFile : MetaDataHeader { - char* mKey; - char* mMetaData; - - MetaDataFile() - : mKey(nsnull), mMetaData(nsnull) - { - } - - MetaDataFile(nsCacheEntry* entry) - : MetaDataHeader(entry), - mKey(nsnull), mMetaData(nsnull) - { - } - - ~MetaDataFile() - { - delete[] mKey; - delete[] mMetaData; - } - - nsresult Init(nsCacheEntry* entry) - { - PRUint32 size = 1 + entry->Key()->Length(); - mKey = new char[size]; - if (!mKey) return NS_ERROR_OUT_OF_MEMORY; - nsCRT::memcpy(mKey, entry->Key()->get(), size); - return entry->FlattenMetaData(&mMetaData, &mMetaDataSize); - } - - nsresult Read(nsIInputStream* input); - nsresult Write(nsIOutputStream* output); -}; - -nsresult MetaDataFile::Read(nsIInputStream* input) -{ - nsresult rv; - PRUint32 count; - - // XXX Is it less expensive to read the file in multiple parts, or - // XXX get the size and read it in one chunk? - // read in the file header. - rv = input->Read((char*)&mHeaderSize, sizeof(MetaDataHeader), &count); - if (NS_FAILED(rv)) return rv; - Unswap(); - - // make sure it is self-consistent. - if (mHeaderSize != sizeof(MetaDataHeader)) { - NS_ERROR("### CACHE FORMAT CHANGED!!! PLEASE DELETE YOUR NewCache DIRECTORY!!! ###"); - return NS_ERROR_ILLEGAL_VALUE; - } - - // read in the key. - delete[] mKey; - mKey = new char[mKeySize]; - if (!mKey) return NS_ERROR_OUT_OF_MEMORY; - rv = input->Read(mKey, mKeySize, &count); - if (NS_FAILED(rv)) return rv; - - // read in the metadata. - delete mMetaData; - mMetaData = nsnull; - if (mMetaDataSize) { - mMetaData = new char[mMetaDataSize]; - if (!mMetaData) return NS_ERROR_OUT_OF_MEMORY; - rv = input->Read(mMetaData, mMetaDataSize, &count); - if (NS_FAILED(rv)) return rv; - } - - return NS_OK; -} - -nsresult MetaDataFile::Write(nsIOutputStream* output) -{ - nsresult rv; - PRUint32 count; - - // write the header to the file. - Swap(); - rv = output->Write((char*)&mHeaderSize, sizeof(MetaDataHeader), &count); - Unswap(); - if (NS_FAILED(rv)) return rv; - - // write the key to the file. - rv = output->Write(mKey, mKeySize, &count); - if (NS_FAILED(rv)) return rv; - - // write the flattened metadata to the file. - if (mMetaDataSize) { - rv = output->Write(mMetaData, mMetaDataSize, &count); - if (NS_FAILED(rv)) return rv; - } - - return NS_OK; -} - - -/****************************************************************************** - * nsDiskCacheEntryInfo - *****************************************************************************/ -class nsDiskCacheEntryInfo : public nsICacheEntryInfo { -public: - NS_DECL_ISUPPORTS - NS_DECL_NSICACHEENTRYINFO - - nsDiskCacheEntryInfo() - { - NS_INIT_ISUPPORTS(); - } - - virtual ~nsDiskCacheEntryInfo() {} - - nsresult Read(nsIInputStream * input) - { - return mMetaDataFile.Read(input); - } - - const char* Key() { return mMetaDataFile.mKey; } - -private: - MetaDataFile mMetaDataFile; -}; -NS_IMPL_ISUPPORTS1(nsDiskCacheEntryInfo, nsICacheEntryInfo); - -NS_IMETHODIMP nsDiskCacheEntryInfo::GetClientID(char ** clientID) -{ - NS_ENSURE_ARG_POINTER(clientID); - return ClientIDFromCacheKey(nsLiteralCString(mMetaDataFile.mKey), clientID); -} - - -NS_IMETHODIMP nsDiskCacheEntryInfo::GetDeviceID(char ** deviceID) -{ - NS_ENSURE_ARG_POINTER(deviceID); - *deviceID = nsCRT::strdup(DISK_CACHE_DEVICE_ID); - return *deviceID ? NS_OK : NS_ERROR_OUT_OF_MEMORY; -} - - -NS_IMETHODIMP nsDiskCacheEntryInfo::GetKey(char ** clientKey) -{ - NS_ENSURE_ARG_POINTER(clientKey); - return ClientKeyFromCacheKey(nsLiteralCString(mMetaDataFile.mKey), clientKey); -} - -NS_IMETHODIMP nsDiskCacheEntryInfo::GetFetchCount(PRInt32 *aFetchCount) -{ - return *aFetchCount = mMetaDataFile.mFetchCount; - return NS_OK; -} - -NS_IMETHODIMP nsDiskCacheEntryInfo::GetLastFetched(PRUint32 *aLastFetched) -{ - *aLastFetched = mMetaDataFile.mLastFetched; - return NS_OK; -} - -NS_IMETHODIMP nsDiskCacheEntryInfo::GetLastModified(PRUint32 *aLastModified) -{ - *aLastModified = mMetaDataFile.mLastModified; - return NS_OK; -} - -NS_IMETHODIMP nsDiskCacheEntryInfo::GetExpirationTime(PRUint32 *aExpirationTime) -{ - *aExpirationTime = mMetaDataFile.mExpirationTime; - return NS_OK; -} - -NS_IMETHODIMP nsDiskCacheEntryInfo::IsStreamBased(PRBool *aStreamBased) -{ - *aStreamBased = PR_TRUE; - return NS_OK; -} - -NS_IMETHODIMP nsDiskCacheEntryInfo::GetDataSize(PRUint32 *aDataSize) -{ - *aDataSize = mMetaDataFile.mDataSize; - return NS_OK; -} - - -/****************************************************************************** - * do_QueryElementAt - *****************************************************************************/ -#if 0 -/** - * Helper class for implementing do_QueryElementAt() pattern. Thanks scc! - * Eventually this should become part of nsICollection.idl. - */ -class do_QueryElementAt : public nsCOMPtr_helper { -public: - do_QueryElementAt(nsICollection* aCollection, PRUint32 aIndex, nsresult* aErrorPtr = 0) - : mCollection(aCollection), - mIndex(aIndex), - mErrorPtr(aErrorPtr) - { - // nothing else to do here - } - - virtual nsresult operator()( const nsIID& aIID, void** aResult) const - { - nsresult status; - if ( mCollection ) { - if ( !NS_SUCCEEDED(status = mCollection->QueryElementAt(mIndex, aIID, aResult)) ) - *aResult = 0; - } else - status = NS_ERROR_NULL_POINTER; - if ( mErrorPtr ) - *mErrorPtr = status; - return status; - } - -private: - nsICollection* mCollection; - PRUint32 mIndex; - nsresult* mErrorPtr; -}; -#endif - - /****************************************************************************** * nsDiskCacheDevice *****************************************************************************/ - static nsCOMPtr gFileTransportService; nsDiskCacheDevice::nsDiskCacheDevice() @@ -701,7 +407,7 @@ nsDiskCacheDevice::Init() // no cache directory has ever existed before. rv = readCacheMap(); if (NS_FAILED(rv) || mCacheMap->IsDirty()) { - rv = clobberDiskCache(); // XXX initializeCacheDirectory() + rv = InitializeCacheDirectory(); // XXX initializeCacheDirectory() if (NS_FAILED(rv)) return rv; } @@ -766,23 +472,23 @@ nsDiskCacheDevice::FindEntry(nsCString * key) // XXX look in entry hashtable first, if not found, then look on // disk, to see if we have a disk cache entry that maches. nsCacheEntry * entry = nsnull; - nsDiskCacheEntry * diskEntry = nsnull; + nsDiskCacheBindData * bindData = nsnull; // XXX checking the bound hash table should only be a debug check // XXX - the cache service shouldn't bother calling the device // XXX - if the entry is already active (bound or not). // XXX change to #if DEBUG, because we shouldn't be called for active entries - diskEntry = mBoundEntries.GetEntry(key->get()); - NS_ASSERTION(!diskEntry, "### FindEntry() called for a bound entry."); + bindData = mBoundEntries.GetEntry(key->get()); + NS_ASSERTION(!bindData, "### FindEntry() called for a bound entry."); // XXX #endif - if (!diskEntry) { - PLDHashNumber hashNumber = nsDiskCacheEntry::Hash(key->get()); + if (!bindData) { + PLDHashNumber hashNumber = nsDiskCacheBindData::Hash(key->get()); nsDiskCacheRecord* record = mCacheMap->GetRecord(hashNumber); if (record->HashNumber() == hashNumber) { - nsresult rv = readDiskCacheEntry(key->get(), &diskEntry); + nsresult rv = readDiskCacheEntry(key->get(), &bindData); if (NS_FAILED(rv)) return nsnull; - entry = diskEntry->getCacheEntry(); - rv = mBoundEntries.AddEntry(diskEntry); + entry = bindData->getCacheEntry(); + rv = mBoundEntries.AddEntry(bindData); if (NS_FAILED(rv)) { delete entry; return nsnull; @@ -791,7 +497,7 @@ nsDiskCacheDevice::FindEntry(nsCString * key) } else { // XXX need to make sure this is an exact match, not just // a hash code match. - entry = diskEntry->getCacheEntry(); + entry = bindData->getCacheEntry(); if (nsCRT::strcmp(entry->Key()->get(), key->get()) != 0) return nsnull; } @@ -803,24 +509,24 @@ nsresult nsDiskCacheDevice::DeactivateEntry(nsCacheEntry * entry) { // XXX if entry->mData is null, it's an error. - nsDiskCacheEntry* diskEntry = ensureDiskCacheEntry(entry); - if (mBoundEntries.GetEntry(diskEntry->getHashNumber()) == diskEntry) { + nsDiskCacheBindData* bindData = ensureDiskCacheBindData(entry); + if (mBoundEntries.GetEntry(bindData->getHashNumber()) == bindData) { // XXX eventually, as a performance enhancement, keep entries around for a while before deleting them. // XXX right now, to prove correctness, destroy the entries eagerly. - mBoundEntries.RemoveEntry(diskEntry); + mBoundEntries.RemoveEntry(bindData); } if (!entry->IsDoomed()) { // commit any changes about this entry to disk. - updateDiskCacheEntry(diskEntry); + updateDiskCacheEntry(bindData); // XXX if this entry collided with other concurrently bound entries, then its // generation count will be non-zero. The other entries that came before it // will be linked to it and doomed. deletion of the entry can only be done // when all of the other doomed entries are deactivated, so that the final live entry // can have its generation number reset to zero. - if (diskEntry->getGeneration() != 0) - scavengeDiskCacheEntries(diskEntry); + if (bindData->getGeneration() != 0) + scavengeDiskCacheEntries(bindData); else delete entry; } else { @@ -828,13 +534,13 @@ nsDiskCacheDevice::DeactivateEntry(nsCacheEntry * entry) mCacheMap->DataSize() -= entry->DataSize(); // obliterate all knowledge of this entry on disk. - deleteDiskCacheEntry(diskEntry); + deleteDiskCacheEntry(bindData); // XXX if this entry resides on a list, then there must have been a collision // during the entry's lifetime. use this deactivation as a trigger to scavenge // generation numbers, and reset the live entry's generation to zero. - if (!PR_CLIST_IS_EMPTY(diskEntry)) { - scavengeDiskCacheEntries(diskEntry); + if (!PR_CLIST_IS_EMPTY(bindData)) { + scavengeDiskCacheEntries(bindData); } // delete entry from memory. @@ -850,42 +556,42 @@ nsDiskCacheDevice::BindEntry(nsCacheEntry * newEntry) { nsresult rv; - // Make sure this entry has its associated nsDiskCacheEntry data attached. - nsDiskCacheEntry* newDiskEntry = ensureDiskCacheEntry(newEntry); - NS_ASSERTION(newDiskEntry, "nsDiskCacheDevice::BindEntry"); - if (!newDiskEntry) return NS_ERROR_OUT_OF_MEMORY; + // Make sure this entry has its associated nsDiskCacheBindData attached. + nsDiskCacheBindData* newBindData = ensureDiskCacheBindData(newEntry); + NS_ASSERTION(newBindData, "nsDiskCacheDevice::BindEntry"); + if (!newBindData) return NS_ERROR_OUT_OF_MEMORY; // XXX check for cache collision. if an entry exists on disk that has the same // hash code as this newly bound entry, AND there is already a bound entry for // that key, we need to ask the cache service to doom that entry, since two // simultaneous entries that have the same hash code aren't allowed until // some sort of chaining mechanism is implemented. - nsDiskCacheEntry* oldDiskEntry = mBoundEntries.GetEntry(newEntry->Key()->get()); - if (oldDiskEntry) { + nsDiskCacheBindData* oldBindData = mBoundEntries.GetEntry(newEntry->Key()->get()); + if (oldBindData) { // XXX Hacky liveness test, remove when we've figured this all out. - if (oldDiskEntry->getRefCount() > 1) { + if (oldBindData->getRefCount() > 1) { // set the generation count on the newly bound entry, // so that files created will be unique and won't conflict // with the doomed entries that are still active. - newDiskEntry->setGeneration(oldDiskEntry->getGeneration() + 1); - PR_APPEND_LINK(newDiskEntry, oldDiskEntry); + newBindData->setGeneration(oldBindData->getGeneration() + 1); + PR_APPEND_LINK(newBindData, oldBindData); // XXX Whom do we tell about this impending doom? - nsCacheEntry* oldEntry = oldDiskEntry->getCacheEntry(); + nsCacheEntry* oldEntry = oldBindData->getCacheEntry(); // XXX Yes Virginia, a doomed entry can be bound. // NS_ASSERTION(!oldEntry->IsDoomed(), "a bound entry is doomed!"); if (!oldEntry->IsDoomed()) nsCacheService::GlobalInstance()->DoomEntry_Locked(oldEntry); else - mBoundEntries.RemoveEntry(oldDiskEntry); + mBoundEntries.RemoveEntry(oldBindData); } else { // XXX somehow we didn't hear about the entry going away. Ask gordon. NS_NOTREACHED("bound disk cache entry with no corresponding cache entry."); - mBoundEntries.RemoveEntry(oldDiskEntry); + mBoundEntries.RemoveEntry(oldBindData); } } - rv = mBoundEntries.AddEntry(newDiskEntry); + rv = mBoundEntries.AddEntry(newBindData); if (NS_FAILED(rv)) return rv; @@ -897,7 +603,7 @@ nsDiskCacheDevice::BindEntry(nsCacheEntry * newEntry) // this probably isn't needed while the entry is bound, // only when the entry is deactivated. this could be // the reason disk cache performance suffers. - return updateDiskCacheEntry(newDiskEntry); + return updateDiskCacheEntry(newBindData); } @@ -906,8 +612,8 @@ nsDiskCacheDevice::DoomEntry(nsCacheEntry * entry) { // so it can't be seen by FindEntry() ever again. // XXX if entry->mData is null, it's an error - nsDiskCacheEntry* diskEntry = ensureDiskCacheEntry(entry); - mBoundEntries.RemoveEntry(diskEntry); + nsDiskCacheBindData* bindData = ensureDiskCacheBindData(entry); + mBoundEntries.RemoveEntry(bindData); // XXX clear this entry out of the cache map. // this is done in deleteDiskCacheEntry(). @@ -922,11 +628,11 @@ nsDiskCacheDevice::GetTransportForEntry(nsCacheEntry * entry, NS_ENSURE_ARG_POINTER(entry); NS_ENSURE_ARG_POINTER(result); - nsDiskCacheEntry* diskEntry = ensureDiskCacheEntry(entry); - if (!diskEntry) return NS_ERROR_OUT_OF_MEMORY; + nsDiskCacheBindData* bindData = ensureDiskCacheBindData(entry); + if (!bindData) return NS_ERROR_OUT_OF_MEMORY; #ifdef MOZ_NEW_CACHE_REUSE_TRANSPORTS - nsCOMPtr& transport = diskEntry->getTransport(mode); + nsCOMPtr& transport = bindData->getTransport(mode); if (transport) { NS_ADDREF(*result = transport); return NS_OK; @@ -938,7 +644,7 @@ nsDiskCacheDevice::GetTransportForEntry(nsCacheEntry * entry, // XXX generate the name of the cache entry from the hash code of its key, // modulo the number of files we're willing to keep cached. nsCOMPtr dataFile; - nsresult rv = getFileForDiskCacheEntry(diskEntry, PR_FALSE, + nsresult rv = getFileForDiskCacheEntry(bindData, PR_FALSE, getter_AddRefs(dataFile)); if (NS_SUCCEEDED(rv)) { rv = getTransportForFile(dataFile, mode, getter_AddRefs(transport)); @@ -953,9 +659,9 @@ nsresult nsDiskCacheDevice::GetFileForEntry(nsCacheEntry * entry, nsIFile ** result) { - nsDiskCacheEntry* diskEntry = ensureDiskCacheEntry(entry); - if (!diskEntry) return NS_ERROR_OUT_OF_MEMORY; - return getFileForDiskCacheEntry(diskEntry, PR_FALSE, result); + nsDiskCacheBindData* bindData = ensureDiskCacheBindData(entry); + if (!bindData) return NS_ERROR_OUT_OF_MEMORY; + return getFileForDiskCacheEntry(bindData, PR_FALSE, result); } /** @@ -990,6 +696,7 @@ nsDiskCacheDevice::Visit(nsICacheVisitor * visitor) return NS_OK; } + nsresult nsDiskCacheDevice::EvictEntries(const char * clientID) { @@ -1019,9 +726,9 @@ nsDiskCacheDevice::EvictEntries(const char * clientID) nsDiskCacheRecord* record = &records[j]; // if the entry is currently in use, then doom it rather than evicting right here. - nsDiskCacheEntry* diskEntry = mBoundEntries.GetEntry(record->HashNumber()); - if (diskEntry) { - nsCacheService::GlobalInstance()->DoomEntry_Locked(diskEntry->getCacheEntry()); + nsDiskCacheBindData* bindData = mBoundEntries.GetEntry(record->HashNumber()); + if (bindData) { + nsCacheService::GlobalInstance()->DoomEntry_Locked(bindData->getCacheEntry()); continue; } @@ -1159,14 +866,14 @@ nsresult nsDiskCacheDevice::getFileForHashNumber(PLDHashNumber hashNumber, PRBoo nsresult nsDiskCacheDevice::getFileForKey(const char* key, PRBool meta, PRUint32 generation, nsIFile ** result) { - PLDHashNumber hash = nsDiskCacheEntry::Hash(key); + PLDHashNumber hash = nsDiskCacheBindData::Hash(key); return getFileForHashNumber(hash, meta, generation, result); } -nsresult nsDiskCacheDevice::getFileForDiskCacheEntry(nsDiskCacheEntry * diskEntry, PRBool meta, +nsresult nsDiskCacheDevice::getFileForDiskCacheEntry(nsDiskCacheBindData * bindData, PRBool meta, nsIFile ** result) { - return getFileForHashNumber(diskEntry->getHashNumber(), meta, diskEntry->getGeneration(), result); + return getFileForHashNumber(bindData->getHashNumber(), meta, bindData->getGeneration(), result); } nsresult nsDiskCacheDevice::getTransportForFile(nsIFile* file, nsCacheAccessMode mode, nsITransport ** result) @@ -1239,7 +946,7 @@ nsresult nsDiskCacheDevice::visitEntries(nsICacheVisitor * visitor) rv = updateDiskCacheEntries(); if (NS_FAILED(rv)) return rv; - nsDiskCacheEntryInfo* entryInfo = new nsDiskCacheEntryInfo(); + nsDiskCacheEntryInfo* entryInfo = new nsDiskCacheEntryInfo(DISK_CACHE_DEVICE_ID); if (!entryInfo) return NS_ERROR_OUT_OF_MEMORY; nsCOMPtr ref(entryInfo); @@ -1278,14 +985,14 @@ nsresult nsDiskCacheDevice::visitEntries(nsICacheVisitor * visitor) return NS_OK; } -class UpdateEntryVisitor : public nsDiskCacheEntryHashTable::Visitor { +class UpdateEntryVisitor : public nsDiskCacheHashTable::Visitor { nsDiskCacheDevice* mDevice; public: UpdateEntryVisitor(nsDiskCacheDevice * device) : mDevice(device) {} - virtual PRBool VisitEntry(nsDiskCacheEntry * diskEntry) + virtual PRBool VisitEntry(nsDiskCacheBindData * bindData) { - mDevice->updateDiskCacheEntry(diskEntry); + mDevice->updateDiskCacheEntry(bindData); return PR_TRUE; } }; @@ -1297,17 +1004,17 @@ nsresult nsDiskCacheDevice::updateDiskCacheEntries() return NS_OK; } -nsresult nsDiskCacheDevice::updateDiskCacheEntry(nsDiskCacheEntry* diskEntry) +nsresult nsDiskCacheDevice::updateDiskCacheEntry(nsDiskCacheBindData* bindData) { nsresult rv; - nsCacheEntry* entry = diskEntry->getCacheEntry(); + nsCacheEntry* entry = bindData->getCacheEntry(); if (entry->IsMetaDataDirty() || entry->IsEntryDirty() || entry->IsDataDirty()) { // make sure this disk entry is known to the cache map. - rv = updateCacheMap(diskEntry); + rv = updateCacheMap(bindData); if (NS_FAILED(rv)) return rv; nsCOMPtr file; - rv = getFileForDiskCacheEntry(diskEntry, PR_TRUE, + rv = getFileForDiskCacheEntry(bindData, PR_TRUE, getter_AddRefs(file)); if (NS_FAILED(rv)) return rv; @@ -1332,7 +1039,7 @@ nsresult nsDiskCacheDevice::updateDiskCacheEntry(nsDiskCacheEntry* diskEntry) } -nsresult nsDiskCacheDevice::readDiskCacheEntry(const char * key, nsDiskCacheEntry ** result) +nsresult nsDiskCacheDevice::readDiskCacheEntry(const char * key, nsDiskCacheBindData ** result) { // result should be nsull on cache miss. *result = nsnull; @@ -1377,7 +1084,7 @@ nsresult nsDiskCacheDevice::readDiskCacheEntry(const char * key, nsDiskCacheEntr } // celebrate! - *result = ensureDiskCacheEntry(entry); + *result = ensureDiskCacheBindData(entry); if (!*result) goto error; return NS_OK; @@ -1387,13 +1094,13 @@ error: return NS_ERROR_NOT_AVAILABLE; } -nsresult nsDiskCacheDevice::deleteDiskCacheEntry(nsDiskCacheEntry * diskEntry) +nsresult nsDiskCacheDevice::deleteDiskCacheEntry(nsDiskCacheBindData * bindData) { nsresult rv; // delete the metadata file. nsCOMPtr metaFile; - rv = getFileForDiskCacheEntry(diskEntry, PR_TRUE, + rv = getFileForDiskCacheEntry(bindData, PR_TRUE, getter_AddRefs(metaFile)); if (NS_SUCCEEDED(rv)) { rv = metaFile->Delete(PR_FALSE); @@ -1402,7 +1109,7 @@ nsresult nsDiskCacheDevice::deleteDiskCacheEntry(nsDiskCacheEntry * diskEntry) // delete the data file nsCOMPtr dataFile; - rv = getFileForDiskCacheEntry(diskEntry, PR_FALSE, + rv = getFileForDiskCacheEntry(bindData, PR_FALSE, getter_AddRefs(dataFile)); if (NS_SUCCEEDED(rv)) { rv = dataFile->Delete(PR_FALSE); @@ -1410,14 +1117,14 @@ nsresult nsDiskCacheDevice::deleteDiskCacheEntry(nsDiskCacheEntry * diskEntry) } // remove from cache map. - nsDiskCacheRecord* record = mCacheMap->GetRecord(diskEntry->getHashNumber()); - if (record->HashNumber() == diskEntry->getHashNumber() && record->FileGeneration() == diskEntry->getGeneration()) + nsDiskCacheRecord* record = mCacheMap->GetRecord(bindData->getHashNumber()); + if (record->HashNumber() == bindData->getHashNumber() && record->FileGeneration() == bindData->getGeneration()) mCacheMap->DeleteRecord(record); return NS_OK; } -nsresult nsDiskCacheDevice::scavengeDiskCacheEntries(nsDiskCacheEntry * diskEntry) +nsresult nsDiskCacheDevice::scavengeDiskCacheEntries(nsDiskCacheBindData * bindData) { nsresult rv; @@ -1426,22 +1133,22 @@ nsresult nsDiskCacheDevice::scavengeDiskCacheEntries(nsDiskCacheEntry * diskEntr // the liveEntry, if inactive, can have its generation reset // to zero. PRUint32 doomedEntryCount = 0; - nsDiskCacheEntry * youngestDiskEntry = diskEntry; - nsCacheEntry * youngestEntry = diskEntry->getCacheEntry(); - nsDiskCacheEntry * nextDiskEntry = NS_STATIC_CAST(nsDiskCacheEntry*, PR_NEXT_LINK(diskEntry)); - while (nextDiskEntry != diskEntry) { - nsCacheEntry* nextEntry = nextDiskEntry->getCacheEntry(); + nsDiskCacheBindData * youngestBindData = bindData; + nsCacheEntry * youngestEntry = bindData->getCacheEntry(); + nsDiskCacheBindData * nextBindData = NS_STATIC_CAST(nsDiskCacheBindData*, PR_NEXT_LINK(bindData)); + while (nextBindData != bindData) { + nsCacheEntry* nextEntry = nextBindData->getCacheEntry(); if (nextEntry->IsDoomed()) { ++doomedEntryCount; - } else if (nextDiskEntry->getGeneration() > youngestDiskEntry->getGeneration()) { + } else if (nextBindData->getGeneration() > youngestBindData->getGeneration()) { youngestEntry = nextEntry; - youngestDiskEntry = nextDiskEntry; + youngestBindData = nextBindData; } - nextDiskEntry = NS_STATIC_CAST(nsDiskCacheEntry*, PR_NEXT_LINK(nextDiskEntry)); + nextBindData = NS_STATIC_CAST(nsDiskCacheBindData*, PR_NEXT_LINK(nextBindData)); } if (doomedEntryCount == 0 && !youngestEntry->IsDoomed() && !youngestEntry->IsActive()) { - PRUint32 generation = youngestDiskEntry->getGeneration(); + PRUint32 generation = youngestBindData->getGeneration(); // XXX reset generation number. const char* key = youngestEntry->Key()->get(); nsCOMPtr oldFile, newFile; @@ -1472,107 +1179,8 @@ nsresult nsDiskCacheDevice::scavengeDiskCacheEntries(nsDiskCacheEntry * diskEntr return NS_OK; } -nsresult nsDiskCacheDevice::scanDiskCacheEntries(nsISupportsArray ** result) -{ -#if 0 - nsresult rv; - - // XXX make sure meta data is up to date. - rv = updateDiskCacheEntries(); - if (NS_FAILED(rv)) return rv; - nsCOMPtr files; - rv = mCacheDirectory->GetDirectoryEntries(getter_AddRefs(files)); - if (NS_FAILED(rv)) return rv; - - nsCOMPtr entries = do_CreateInstance(NS_SUPPORTSARRAY_CONTRACTID, &rv); - if (NS_FAILED(rv)) return rv; - - PRUint32 newCacheSize = 0; - - for (PRBool more; NS_SUCCEEDED(files->HasMoreElements(&more)) && more;) { - nsCOMPtr next; - rv = files->GetNext(getter_AddRefs(next)); - if (NS_FAILED(rv)) break; - nsCOMPtr file(do_QueryInterface(next, &rv)); - if (NS_FAILED(rv)) break; - nsXPIDLCString name; - rv = file->GetLeafName(getter_Copies(name)); - if (isMetaDataFile(name)) { - // this must be a metadata file. - nsCOMPtr input; - rv = openInputStream(file, getter_AddRefs(input)); - if (NS_FAILED(rv)) continue; - - nsDiskCacheEntryInfo* entryInfo = new nsDiskCacheEntryInfo(); - if (!entryInfo) return NS_ERROR_OUT_OF_MEMORY; - nsCOMPtr ref(entryInfo); - rv = entryInfo->Read(input); - input->Close(); - if (NS_FAILED(rv)) return rv; - - // update the cache size. - PRUint32 dataSize; - entryInfo->GetDataSize(&dataSize); - newCacheSize += dataSize; - - // update the cache map. - PLDHashNumber hashNumber = nsDiskCacheEntry::Hash(entryInfo->Key()); - nsDiskCacheRecord* record = mCacheMap->GetRecord(hashNumber); - record->SetHashNumber(hashNumber); - record->SetEvictionRank(0); - record->SetFileGeneration(0); - - // sort entries by modification time. - PRUint32 count; - entries->Count(&count); - if (count == 0) { - rv = entries->AppendElement(entryInfo); - if (NS_FAILED(rv)) return rv; - continue; - } - PRUint32 modTime; - entryInfo->GetLastModified(&modTime); - PRInt32 low = 0, high = count - 1; - for (;;) { - PRInt32 middle = (low + high) / 2; - nsCOMPtr info = do_QueryElementAt(entries, middle, &rv); - if (NS_FAILED(rv)) return rv; - PRUint32 modTime1; - info->GetLastModified(&modTime1); - if (low >= high) { - if (modTime <= modTime1) - rv = entries->InsertElementAt(entryInfo, middle); - else - rv = entries->InsertElementAt(entryInfo, middle + 1); - if (NS_FAILED(rv)) return rv; - break; - } else { - if (modTime < modTime1) { - high = middle - 1; - } else if (modTime > modTime1) { - low = middle + 1; - } else { - rv = entries->InsertElementAt(entryInfo, middle); - if (NS_FAILED(rv)) return rv; - break; - } - } - } - } - } - - NS_ADDREF(*result = entries); - - // we've successfully totaled the cache size. - mCacheMap->DataSize() = newCacheSize; - entries->Count(&mCacheMap->EntryCount()); -#endif - return NS_OK; -} - - -nsresult nsDiskCacheDevice::clobberDiskCache() +nsresult nsDiskCacheDevice::InitializeCacheDirectory() { nsresult rv; @@ -1677,8 +1285,8 @@ nsresult nsDiskCacheDevice::evictDiskCacheEntries() // XXX if this entry is currently active, then leave it alone, // as it is likely to be modified very soon. - nsDiskCacheEntry* diskEntry = mBoundEntries.GetEntry(record->HashNumber()); - if (diskEntry) continue; + nsDiskCacheBindData* bindData = mBoundEntries.GetEntry(record->HashNumber()); + if (bindData) continue; // delete the metadata file. nsCOMPtr metaFile; @@ -1715,6 +1323,10 @@ nsresult nsDiskCacheDevice::evictDiskCacheEntries() return NS_OK; } + +/** + * openCacheMap : called by InitializeCacheDirectory, readCacheMap, writeCacheMap, updateCacheMap + */ nsresult nsDiskCacheDevice::openCacheMap() { nsresult rv; @@ -1738,7 +1350,7 @@ nsresult nsDiskCacheDevice::openCacheMap() return NS_OK; } -nsresult nsDiskCacheDevice::readCacheMap() +nsresult nsDiskCacheDevice::readCacheMap() // only called by Init() { nsresult rv; if (!mCacheStream) { @@ -1749,7 +1361,7 @@ nsresult nsDiskCacheDevice::readCacheMap() return rv; } -nsresult nsDiskCacheDevice::writeCacheMap() +nsresult nsDiskCacheDevice::writeCacheMap() // only called by Shutdown() { nsresult rv; if (!mCacheStream) { @@ -1760,14 +1372,18 @@ nsresult nsDiskCacheDevice::writeCacheMap() return rv; } -nsresult nsDiskCacheDevice::updateCacheMap(nsDiskCacheEntry * diskEntry) + +/** + * updateCacheMap : called by updateDiskCacheEntry + */ +nsresult nsDiskCacheDevice::updateCacheMap(nsDiskCacheBindData * bindData) { nsresult rv; // get a record from the cache map, and use the fetch time for eviction ranking. PRBool commitBucket = PR_TRUE; - nsDiskCacheRecord* record = mCacheMap->GetRecord(diskEntry->getHashNumber()); - if (record->HashNumber() != diskEntry->getHashNumber()) { + nsDiskCacheRecord* record = mCacheMap->GetRecord(bindData->getHashNumber()); + if (record->HashNumber() != bindData->getHashNumber()) { if (record->HashNumber() != 0) { // eviction of eldest entry in this bucket. evictDiskCacheRecord(record); @@ -1775,14 +1391,14 @@ nsresult nsDiskCacheDevice::updateCacheMap(nsDiskCacheEntry * diskEntry) mCacheMap->EntryCount() += 1; } // newly bound record. fill in the blanks. - record->SetHashNumber(diskEntry->getHashNumber()); + record->SetHashNumber(bindData->getHashNumber()); record->SetEvictionRank(0); - record->SetFileGeneration(diskEntry->getGeneration()); - } else if (record->FileGeneration() != diskEntry->getGeneration()) { + record->SetFileGeneration(bindData->getGeneration()); + } else if (record->FileGeneration() != bindData->getGeneration()) { // a collision has occurred - record->SetHashNumber(diskEntry->getHashNumber()); + record->SetHashNumber(bindData->getHashNumber()); record->SetEvictionRank(0); - record->SetFileGeneration(diskEntry->getGeneration()); + record->SetFileGeneration(bindData->getGeneration()); } else { commitBucket = PR_FALSE; record->SetEvictionRank(record->EvictionRank() + 1); @@ -1816,9 +1432,9 @@ nsresult nsDiskCacheDevice::evictDiskCacheRecord(nsDiskCacheRecord * record) nsresult rv; // if the entry is currently in use, then doom it rather than evicting right here. - nsDiskCacheEntry* diskEntry = mBoundEntries.GetEntry(record->HashNumber()); - if (diskEntry) - return nsCacheService::GlobalInstance()->DoomEntry_Locked(diskEntry->getCacheEntry()); + nsDiskCacheBindData* bindData = mBoundEntries.GetEntry(record->HashNumber()); + if (bindData) + return nsCacheService::GlobalInstance()->DoomEntry_Locked(bindData->getCacheEntry()); // delete the metadata file. nsCOMPtr metaFile; diff --git a/mozilla/netwerk/cache/src/nsDiskCacheDevice.h b/mozilla/netwerk/cache/src/nsDiskCacheDevice.h index af136d40351..fc539f1851a 100644 --- a/mozilla/netwerk/cache/src/nsDiskCacheDevice.h +++ b/mozilla/netwerk/cache/src/nsDiskCacheDevice.h @@ -26,12 +26,13 @@ #define _nsDiskCacheDevice_h_ #include "nsCacheDevice.h" +#include "nsDiskCacheBindData.h" #include "nsDiskCacheEntry.h" #include "nsILocalFile.h" #include "nsIObserver.h" -class nsDiskCacheEntry; +class nsDiskCacheBindData; class nsDiskCacheMap; class nsDiskCacheRecord; @@ -81,42 +82,41 @@ public: nsresult getFileForHashNumber(PLDHashNumber hashNumber, PRBool meta, PRUint32 generation, nsIFile ** result); nsresult getFileForKey(const char* key, PRBool meta, PRUint32 generation, nsIFile ** result); - nsresult getFileForDiskCacheEntry(nsDiskCacheEntry * diskEntry, PRBool meta, nsIFile ** result); + nsresult getFileForDiskCacheEntry(nsDiskCacheBindData * bindData, PRBool meta, nsIFile ** result); static nsresult getTransportForFile(nsIFile* file, nsCacheAccessMode mode, nsITransport ** result); static nsresult openInputStream(nsIFile* file, nsIInputStream ** result); static nsresult openOutputStream(nsIFile* file, nsIOutputStream ** result); - nsresult visitEntries(nsICacheVisitor * visitory); + nsresult visitEntries(nsICacheVisitor * visitor); - nsresult readDiskCacheEntry(const char * key, nsDiskCacheEntry ** diskEntry); + nsresult readDiskCacheEntry(const char * key, nsDiskCacheBindData ** bindData); nsresult updateDiskCacheEntries(); - nsresult updateDiskCacheEntry(nsDiskCacheEntry * diskEntry); - nsresult deleteDiskCacheEntry(nsDiskCacheEntry * diskEntry); + nsresult updateDiskCacheEntry(nsDiskCacheBindData * bindData); + nsresult deleteDiskCacheEntry(nsDiskCacheBindData * bindData); - nsresult scavengeDiskCacheEntries(nsDiskCacheEntry * diskEntry); + nsresult scavengeDiskCacheEntries(nsDiskCacheBindData * bindData); - nsresult scanDiskCacheEntries(nsISupportsArray ** result); nsresult evictDiskCacheEntries(); - nsresult clobberDiskCache(); + nsresult InitializeCacheDirectory(); nsresult openCacheMap(); nsresult readCacheMap(); nsresult writeCacheMap(); - nsresult updateCacheMap(nsDiskCacheEntry * diskEntry); + nsresult updateCacheMap(nsDiskCacheBindData * bindData); nsresult evictDiskCacheRecord(nsDiskCacheRecord * record); private: - PRBool mInitialized; - nsCOMPtr mPrefsObserver; // XXX ? - nsCOMPtr mCacheDirectory; - nsDiskCacheEntryHashTable mBoundEntries; // XXX rename to refer to active entries - PRUint32 mCacheCapacity; // XXX need soft/hard limits, currentTotal - nsDiskCacheMap* mCacheMap; - nsANSIFileStream* mCacheStream; // XXX should be owned by cache map + PRBool mInitialized; + nsCOMPtr mPrefsObserver; // XXX ? + nsCOMPtr mCacheDirectory; + nsDiskCacheHashTable mBoundEntries; // XXX rename to refer to active entries + PRUint32 mCacheCapacity; // XXX need soft/hard limits, currentTotal + nsDiskCacheMap* mCacheMap; + nsANSIFileStream* mCacheStream; // XXX should be owned by cache map // XXX need array of cache block files }; diff --git a/mozilla/netwerk/cache/src/nsDiskCacheEntry.cpp b/mozilla/netwerk/cache/src/nsDiskCacheEntry.cpp index f36297f682b..7a3adc0203b 100644 --- a/mozilla/netwerk/cache/src/nsDiskCacheEntry.cpp +++ b/mozilla/netwerk/cache/src/nsDiskCacheEntry.cpp @@ -10,7 +10,7 @@ * implied. See the License for the specific language governing * rights and limitations under the License. * - * The Original Code is nsMemoryCacheDevice.cpp, released February 22, 2001. + * The Original Code is nsDiskCacheEntry.cpp, released May 10, 2001. * * The Initial Developer of the Original Code is Netscape Communications * Corporation. Portions created by Netscape are @@ -18,196 +18,132 @@ * Rights Reserved. * * Contributor(s): + * Gordon Sheridan * Patrick C. Beard */ -#include - #include "nsDiskCacheEntry.h" +#include "nsCache.h" -NS_IMPL_THREADSAFE_ISUPPORTS0(nsDiskCacheEntry); -PLDHashNumber -nsDiskCacheEntry::Hash(const char* key) +nsresult MetaDataFile::Read(nsIInputStream* input) { - PLDHashNumber h = 0; - for (const PRUint8* s = (PRUint8*) key; *s != '\0'; ++s) - h = (h >> (PL_DHASH_BITS - 4)) ^ (h << 4) ^ *s; - return (h == 0 ? ULONG_MAX : h); -} - -/****************************************************************************** - * nsCacheEntryHashTable - *****************************************************************************/ - -PLDHashTableOps nsDiskCacheEntryHashTable::ops = -{ - PL_DHashAllocTable, - PL_DHashFreeTable, - GetKey, - HashKey, - MatchEntry, - MoveEntry, - ClearEntry, - Finalize -}; - -nsDiskCacheEntryHashTable::nsDiskCacheEntryHashTable() - : initialized(PR_FALSE) -{ -} - - -nsDiskCacheEntryHashTable::~nsDiskCacheEntryHashTable() -{ - if (initialized) - PL_DHashTableFinish(&table); -} - - -nsresult -nsDiskCacheEntryHashTable::Init() -{ - nsresult rv = NS_OK; - initialized = PL_DHashTableInit(&table, &ops, nsnull, - sizeof(HashTableEntry), 512); - - if (!initialized) rv = NS_ERROR_OUT_OF_MEMORY; + nsresult rv; + PRUint32 count; - return rv; -} - - -nsDiskCacheEntry * -nsDiskCacheEntryHashTable::GetEntry(const char * key) -{ - return GetEntry(nsDiskCacheEntry::Hash(key)); -} - - -nsDiskCacheEntry * -nsDiskCacheEntryHashTable::GetEntry(PLDHashNumber key) -{ - nsDiskCacheEntry * result = nsnull; - NS_ASSERTION(initialized, "nsDiskCacheEntryHashTable not initialized"); - HashTableEntry * hashEntry; - hashEntry = (HashTableEntry*) PL_DHashTableOperate(&table, (void*) key, PL_DHASH_LOOKUP); - if (PL_DHASH_ENTRY_IS_BUSY(hashEntry)) { - result = hashEntry->mDiskCacheEntry; + // XXX Is it less expensive to read the file in multiple parts, or + // XXX get the size and read it in one chunk? + // read in the file header. + rv = input->Read((char*)&mHeaderSize, sizeof(MetaDataHeader), &count); + if (NS_FAILED(rv)) return rv; + Unswap(); + + // make sure it is self-consistent. + if (mHeaderSize != sizeof(MetaDataHeader)) { + NS_ERROR("### CACHE FORMAT CHANGED!!! PLEASE DELETE YOUR NewCache DIRECTORY!!! ###"); + return NS_ERROR_ILLEGAL_VALUE; } - return result; + + // read in the key. + delete[] mKey; + mKey = new char[mKeySize]; + if (!mKey) return NS_ERROR_OUT_OF_MEMORY; + rv = input->Read(mKey, mKeySize, &count); + if (NS_FAILED(rv)) return rv; + + // read in the metadata. + delete mMetaData; + mMetaData = nsnull; + if (mMetaDataSize) { + mMetaData = new char[mMetaDataSize]; + if (!mMetaData) return NS_ERROR_OUT_OF_MEMORY; + rv = input->Read(mMetaData, mMetaDataSize, &count); + if (NS_FAILED(rv)) return rv; + } + + return NS_OK; } - -nsresult -nsDiskCacheEntryHashTable::AddEntry(nsDiskCacheEntry * entry) +nsresult MetaDataFile::Write(nsIOutputStream* output) { - NS_ENSURE_ARG_POINTER(entry); - NS_ASSERTION(initialized, "nsDiskCacheEntryHashTable not initialized"); - - HashTableEntry * hashEntry; - hashEntry = (HashTableEntry *) PL_DHashTableOperate(&table, - (void*) entry->getHashNumber(), - PL_DHASH_ADD); - if (!hashEntry) return NS_ERROR_OUT_OF_MEMORY; + nsresult rv; + PRUint32 count; + + // write the header to the file. + Swap(); + rv = output->Write((char*)&mHeaderSize, sizeof(MetaDataHeader), &count); + Unswap(); + if (NS_FAILED(rv)) return rv; + + // write the key to the file. + rv = output->Write(mKey, mKeySize, &count); + if (NS_FAILED(rv)) return rv; + + // write the flattened metadata to the file. + if (mMetaDataSize) { + rv = output->Write(mMetaData, mMetaDataSize, &count); + if (NS_FAILED(rv)) return rv; + } - NS_ADDREF(hashEntry->mDiskCacheEntry = entry); - return NS_OK; } -void -nsDiskCacheEntryHashTable::RemoveEntry(nsDiskCacheEntry * entry) -{ - NS_ASSERTION(initialized, "nsDiskCacheEntryHashTable not initialized"); - NS_ASSERTION(entry, "### cacheEntry == nsnull"); +NS_IMPL_ISUPPORTS1(nsDiskCacheEntryInfo, nsICacheEntryInfo); - (void) PL_DHashTableOperate(&table, (void*) entry->getHashNumber(), PL_DHASH_REMOVE); +NS_IMETHODIMP nsDiskCacheEntryInfo::GetClientID(char ** clientID) +{ + NS_ENSURE_ARG_POINTER(clientID); + return ClientIDFromCacheKey(nsLiteralCString(mMetaDataFile.mKey), clientID); +} + +extern const char DISK_CACHE_DEVICE_ID[]; +NS_IMETHODIMP nsDiskCacheEntryInfo::GetDeviceID(char ** deviceID) +{ + NS_ENSURE_ARG_POINTER(deviceID); + *deviceID = nsCRT::strdup(mDeviceID); + return *deviceID ? NS_OK : NS_ERROR_OUT_OF_MEMORY; } -void -nsDiskCacheEntryHashTable::VisitEntries(Visitor *visitor) +NS_IMETHODIMP nsDiskCacheEntryInfo::GetKey(char ** clientKey) { - PL_DHashTableEnumerate(&table, VisitEntry, visitor); + NS_ENSURE_ARG_POINTER(clientKey); + return ClientKeyFromCacheKey(nsLiteralCString(mMetaDataFile.mKey), clientKey); } - -PLDHashOperator PR_CALLBACK -nsDiskCacheEntryHashTable::VisitEntry(PLDHashTable * table, - PLDHashEntryHdr * header, - PRUint32 number, - void * arg) +NS_IMETHODIMP nsDiskCacheEntryInfo::GetFetchCount(PRInt32 *aFetchCount) { - HashTableEntry* hashEntry = (HashTableEntry *) header; - Visitor *visitor = (Visitor*) arg; - return (visitor->VisitEntry(hashEntry->mDiskCacheEntry) ? PL_DHASH_NEXT : PL_DHASH_STOP); + return *aFetchCount = mMetaDataFile.mFetchCount; + return NS_OK; } -/** - * hash table operation callback functions - */ -const void * PR_CALLBACK -nsDiskCacheEntryHashTable::GetKey(PLDHashTable * /*table*/, PLDHashEntryHdr * header) +NS_IMETHODIMP nsDiskCacheEntryInfo::GetLastFetched(PRUint32 *aLastFetched) { - HashTableEntry * hashEntry = (HashTableEntry *) header; - return (void*) hashEntry->mDiskCacheEntry->getHashNumber(); + *aLastFetched = mMetaDataFile.mLastFetched; + return NS_OK; } - -PLDHashNumber PR_CALLBACK -nsDiskCacheEntryHashTable::HashKey( PLDHashTable *table, const void *key) +NS_IMETHODIMP nsDiskCacheEntryInfo::GetLastModified(PRUint32 *aLastModified) { - return (PLDHashNumber) key; + *aLastModified = mMetaDataFile.mLastModified; + return NS_OK; } -PRBool PR_CALLBACK -nsDiskCacheEntryHashTable::MatchEntry(PLDHashTable * /* table */, - const PLDHashEntryHdr * header, - const void * key) +NS_IMETHODIMP nsDiskCacheEntryInfo::GetExpirationTime(PRUint32 *aExpirationTime) { - HashTableEntry * hashEntry = (HashTableEntry *) header; - return (hashEntry->mDiskCacheEntry->getHashNumber() == (PLDHashNumber) key); + *aExpirationTime = mMetaDataFile.mExpirationTime; + return NS_OK; } -void PR_CALLBACK -nsDiskCacheEntryHashTable::MoveEntry(PLDHashTable * /* table */, - const PLDHashEntryHdr * fromHeader, - PLDHashEntryHdr * toHeader) +NS_IMETHODIMP nsDiskCacheEntryInfo::IsStreamBased(PRBool *aStreamBased) { - HashTableEntry * fromEntry = (HashTableEntry *) fromHeader; - HashTableEntry * toEntry = (HashTableEntry *) toHeader; - toEntry->keyHash = fromEntry->keyHash; - toEntry->mDiskCacheEntry = fromEntry->mDiskCacheEntry; - fromEntry->mDiskCacheEntry = nsnull; + *aStreamBased = PR_TRUE; + return NS_OK; } - -void PR_CALLBACK -nsDiskCacheEntryHashTable::ClearEntry(PLDHashTable * /* table */, - PLDHashEntryHdr * header) +NS_IMETHODIMP nsDiskCacheEntryInfo::GetDataSize(PRUint32 *aDataSize) { - HashTableEntry* hashEntry = (HashTableEntry *) header; - hashEntry->keyHash = 0; - NS_IF_RELEASE(hashEntry->mDiskCacheEntry); -} - - -void PR_CALLBACK -nsDiskCacheEntryHashTable::Finalize(PLDHashTable * table) -{ - (void) PL_DHashTableEnumerate(table, FreeCacheEntries, nsnull); -} - - -PLDHashOperator PR_CALLBACK -nsDiskCacheEntryHashTable::FreeCacheEntries(PLDHashTable * /* table */, - PLDHashEntryHdr * header, - PRUint32 number, - void * arg) -{ - HashTableEntry *entry = (HashTableEntry *) header; - NS_IF_RELEASE(entry->mDiskCacheEntry); - return PL_DHASH_NEXT; + *aDataSize = mMetaDataFile.mDataSize; + return NS_OK; } diff --git a/mozilla/netwerk/cache/src/nsDiskCacheEntry.h b/mozilla/netwerk/cache/src/nsDiskCacheEntry.h index 8031b790c0b..a93350c34f9 100644 --- a/mozilla/netwerk/cache/src/nsDiskCacheEntry.h +++ b/mozilla/netwerk/cache/src/nsDiskCacheEntry.h @@ -17,7 +17,8 @@ * Copyright (C) 2001 Netscape Communications Corporation. All * Rights Reserved. * - * Contributor(s): + * Contributor(s): + * Gordon Sheridan * Patrick C. Beard */ @@ -25,162 +26,149 @@ #define _nsDiskCacheEntry_h_ #include "nspr.h" -#include "pldhash.h" +#include "nscore.h" +#include "nsError.h" + +#include "nsIInputStream.h" +#include "nsIOutputStream.h" +#include "nsICacheVisitor.h" -#include "nsISupports.h" #include "nsCacheEntry.h" -#ifdef MOZ_NEW_CACHE_REUSE_TRANSPORTS -#include "nsITransport.h" + +/****************************************************************************** + * MetaData + *****************************************************************************/ +struct MetaDataHeader { + PRUint32 mHeaderSize; +// PRUint32 mHashNumber; // XXX +// PRUint32 mMetaLocation; // XXX + PRInt32 mFetchCount; + PRUint32 mLastFetched; + PRUint32 mLastModified; + PRUint32 mExpirationTime; + PRUint32 mDataSize; + PRUint32 mKeySize; + PRUint32 mMetaDataSize; +// void * mKeyPtrSpace; // XXX don't need this +// void * mMetaDataPtrSpace; // XXX don't need this, we'll calculate it when necessary + // followed by null-terminated key and metadata string values. + + MetaDataHeader() + : mHeaderSize(sizeof(MetaDataHeader)), + mFetchCount(0), + mLastFetched(0), + mLastModified(0), + mExpirationTime(0), + mDataSize(0), + mKeySize(0), + mMetaDataSize(0) + { + } + + MetaDataHeader(nsCacheEntry* entry) + : mHeaderSize(sizeof(MetaDataHeader)), + mFetchCount(entry->FetchCount()), + mLastFetched(entry->LastFetched()), + mLastModified(entry->LastModified()), + mExpirationTime(entry->ExpirationTime()), + mDataSize(entry->DataSize()), + mKeySize(entry->Key()->Length() + 1), + mMetaDataSize(0) + { + } + + void Swap() + { +#if defined(IS_LITTLE_ENDIAN) + mHeaderSize = ::PR_htonl(mHeaderSize); + mFetchCount = ::PR_htonl(mFetchCount); + mLastFetched = ::PR_htonl(mLastFetched); + mLastModified = ::PR_htonl(mLastModified); + mExpirationTime = ::PR_htonl(mExpirationTime); + mDataSize = ::PR_htonl(mDataSize); + mKeySize = ::PR_htonl(mKeySize); + mMetaDataSize = ::PR_htonl(mMetaDataSize); #endif + } + + void Unswap() + { +#if defined(IS_LITTLE_ENDIAN) + mHeaderSize = ::PR_ntohl(mHeaderSize); + mFetchCount = ::PR_ntohl(mFetchCount); + mLastFetched = ::PR_ntohl(mLastFetched); + mLastModified = ::PR_ntohl(mLastModified); + mExpirationTime = ::PR_ntohl(mExpirationTime); + mDataSize = ::PR_ntohl(mDataSize); + mKeySize = ::PR_ntohl(mKeySize); + mMetaDataSize = ::PR_ntohl(mMetaDataSize); +#endif + } +}; + +struct MetaDataFile : MetaDataHeader { + char* mKey; + char* mMetaData; + + MetaDataFile() + : mKey(nsnull), mMetaData(nsnull) + { + } + + MetaDataFile(nsCacheEntry* entry) + : MetaDataHeader(entry), + mKey(nsnull), mMetaData(nsnull) + { + } + + ~MetaDataFile() + { + delete[] mKey; + delete[] mMetaData; + } + + nsresult Init(nsCacheEntry* entry) + { + PRUint32 size = 1 + entry->Key()->Length(); + mKey = new char[size]; + if (!mKey) return NS_ERROR_OUT_OF_MEMORY; + nsCRT::memcpy(mKey, entry->Key()->get(), size); + return entry->FlattenMetaData(&mMetaData, &mMetaDataSize); + } + + nsresult Read(nsIInputStream* input); + nsresult Write(nsIOutputStream* output); +}; /****************************************************************************** - * nsDiskCacheEntry - * - * Created for disk cache specific data and stored in nsCacheEntry.mData as - * an nsISupports. Also stored in nsDiscCacheEntryHashTable, with collisions - * linked by the PRCList. - * + * nsDiskCacheEntryInfo *****************************************************************************/ - -class nsDiskCacheEntry : public nsISupports, public PRCList { +class nsDiskCacheEntryInfo : public nsICacheEntryInfo { public: NS_DECL_ISUPPORTS + NS_DECL_NSICACHEENTRYINFO - nsDiskCacheEntry(nsCacheEntry* entry) - : mCacheEntry(entry), - mGeneration(0) + nsDiskCacheEntryInfo(const char * deviceID) + : mDeviceID(deviceID) { NS_INIT_ISUPPORTS(); - PR_INIT_CLIST(this); - mHashNumber = Hash(entry->Key()->get()); } - virtual ~nsDiskCacheEntry() - { - PR_REMOVE_LINK(this); - } - -#ifdef MOZ_NEW_CACHE_REUSE_TRANSPORTS - /** - * Maps a cache access mode to a cached nsITransport for that access - * mode. We keep these cached to avoid repeated trips to the - * file transport service. - */ - nsCOMPtr& getTransport(nsCacheAccessMode mode) - { - return mTransports[mode - 1]; - } -#endif + virtual ~nsDiskCacheEntryInfo() {} - nsCacheEntry* getCacheEntry() + nsresult Read(nsIInputStream * input) { - return mCacheEntry; + return mMetaDataFile.Read(input); } - PRUint32 getGeneration() - { - return mGeneration; - } - - void setGeneration(PRUint32 generation) - { - mGeneration = generation; - } - - PLDHashNumber getHashNumber() - { - return mHashNumber; - } - - nsrefcnt getRefCount() - { - return mRefCnt; - } - - static PLDHashNumber Hash(const char* key); + const char* Key() { return mMetaDataFile.mKey; } private: -#ifdef MOZ_NEW_CACHE_REUSE_TRANSPORTS - nsCOMPtr mTransports[3]; -#endif - nsCacheEntry* mCacheEntry; // back pointer to parent nsCacheEntry - PRUint32 mGeneration; // XXX part of nsDiskCacheRecord - PLDHashNumber mHashNumber; // XXX part of nsDiskCacheRecord -// XXX nsDiskCacheRecord mMapRecord; + const char * mDeviceID; + MetaDataFile mMetaDataFile; }; -/****************************************************************************** - * nsDiskCacheEntryHashTable - * - * Used to keep track of nsDiskCacheEntries associated with active/bound (and - * possibly doomed) entries. Lookups on 4 byte disk hash to find collisions - * (which need to be doomed, instead of just evicted. Collisions are linked - * using a PRCList to keep track of current generation number. - * - *****************************************************************************/ - -class nsDiskCacheEntryHashTable { -public: - nsDiskCacheEntryHashTable(); - ~nsDiskCacheEntryHashTable(); - - nsresult Init(); - - nsDiskCacheEntry * GetEntry(const char * key); - nsDiskCacheEntry * GetEntry(PLDHashNumber key); - nsresult AddEntry(nsDiskCacheEntry * entry); - void RemoveEntry(nsDiskCacheEntry * entry); - - class Visitor { - public: - virtual PRBool VisitEntry(nsDiskCacheEntry * entry) = 0; - }; - - void VisitEntries(Visitor * visitor); - -private: - struct HashTableEntry : PLDHashEntryHdr { - nsDiskCacheEntry * mDiskCacheEntry; // STRONG ref? - }; - - // PLDHashTable operation callbacks - static const void * PR_CALLBACK GetKey(PLDHashTable * table, - PLDHashEntryHdr * entry); - - static PLDHashNumber PR_CALLBACK HashKey(PLDHashTable * table, - const void * key); - - static PRBool PR_CALLBACK MatchEntry(PLDHashTable * table, - const PLDHashEntryHdr * entry, - const void * key); - - static void PR_CALLBACK MoveEntry(PLDHashTable * table, - const PLDHashEntryHdr * from, - PLDHashEntryHdr * to); - - static void PR_CALLBACK ClearEntry(PLDHashTable * table, - PLDHashEntryHdr * entry); - - static void PR_CALLBACK Finalize(PLDHashTable *table); - - static - PLDHashOperator PR_CALLBACK FreeCacheEntries(PLDHashTable * table, - PLDHashEntryHdr * hdr, - PRUint32 number, - void * arg); - static - PLDHashOperator PR_CALLBACK VisitEntry(PLDHashTable * table, - PLDHashEntryHdr * hdr, - PRUint32 number, - void * arg); - - // member variables - static PLDHashTableOps ops; - PLDHashTable table; - PRBool initialized; -}; - #endif /* _nsDiskCacheEntry_h_ */ diff --git a/mozilla/netwerk/cache/src/nsDiskCacheMap.cpp b/mozilla/netwerk/cache/src/nsDiskCacheMap.cpp index 5441046d257..71642fac923 100644 --- a/mozilla/netwerk/cache/src/nsDiskCacheMap.cpp +++ b/mozilla/netwerk/cache/src/nsDiskCacheMap.cpp @@ -130,7 +130,7 @@ nsDiskCacheMap::Close() // XXX dealloc cache map memory? - // XXX return rv ? rv : rv2; +// return rv ? rv : rv2; return rv2; } @@ -139,14 +139,14 @@ nsresult nsDiskCacheMap::AddRecord( nsDiskCacheRecord * mapRecord, nsDiskCacheRecord * oldRecord) { - return NS_OK; + } nsresult nsDiskCacheMap::UpdateRecord( nsDiskCacheRecord * mapRecord) { - return NS_OK; + } @@ -159,7 +159,7 @@ nsDiskCacheMap::FindRecord( PRUint32 hashNumber, nsDiskCacheRecord * mapRecord for (int i = 0; i < kRecordsPerBucket; ++i) { if (bucket->mRecords[i].HashNumber() == 0) break; - if (bucket->mRecords[i].HashNumber() == hashNumber) { + if (bucket->mRecords[i].HashNumber() == mapRecord->HashNumber()) { *mapRecord = bucket->mRecords[i]; // copy the record return NS_OK; } @@ -212,8 +212,8 @@ void nsDiskCacheMap::Reset() mHeader.mIsDirty = PR_TRUE; for (PRUint32 b = 0; b < kBucketsPerTable; ++b) { - nsDiskCacheBucket& bucket = mBuckets[b]; - ::memset(&bucket, 0, sizeof(nsDiskCacheBucket)); + nsDiskCacheBucket * bucket = &mBuckets[b]; + ::memset(bucket, 0, sizeof(nsDiskCacheBucket)); } } diff --git a/mozilla/netwerk/cache/src/nsDiskCacheMap.h b/mozilla/netwerk/cache/src/nsDiskCacheMap.h index aebc410cba0..67b210fb4d4 100644 --- a/mozilla/netwerk/cache/src/nsDiskCacheMap.h +++ b/mozilla/netwerk/cache/src/nsDiskCacheMap.h @@ -25,13 +25,12 @@ #ifndef _nsDiskCacheMap_h_ #define _nsDiskCacheMap_h_ -#include "nsANSIFileStreams.h" - #include "prtypes.h" #include "prnetdb.h" #include "nsDebug.h" #include "nsError.h" #include "nsILocalFile.h" +#include "nsANSIFileStreams.h" class nsIInputStream; class nsIOutputStream; @@ -193,10 +192,9 @@ class nsDiskCacheRecordVisitor { /****************************************************************************** * nsDiskCacheBucket *****************************************************************************/ - enum { - kRecordsPerBucket = 256, - kBucketsPerTable = (1 << 5) // must be a power of 2! - }; +enum { + kRecordsPerBucket = 256 +}; struct nsDiskCacheBucket { nsDiskCacheRecord mRecords[kRecordsPerBucket]; @@ -206,10 +204,9 @@ struct nsDiskCacheBucket { /****************************************************************************** * nsDiskCacheHeader *****************************************************************************/ - enum { kCurrentVersion = 0x00010002 }; +enum { kCurrentVersion = 0x00010002 }; struct nsDiskCacheHeader { - PRUint32 mVersion; // cache version. PRUint32 mDataSize; // size of cache in bytes. PRUint32 mEntryCount; // number of entries stored in cache. @@ -247,15 +244,20 @@ struct nsDiskCacheHeader { } }; -enum { kCacheMapSize = sizeof(nsDiskCacheHeader) + - kBucketsPerTable * sizeof(nsDiskCacheBucket) -}; /****************************************************************************** * nsDiskCacheMap * * // XXX initial capacity, enough for 8192 distinct entries. *****************************************************************************/ + +enum { + kBucketsPerTable = (1 << 5), // must be a power of 2! + kCacheMapSize = sizeof(nsDiskCacheHeader) + + kBucketsPerTable * sizeof(nsDiskCacheBucket) +}; + + class nsDiskCacheMap { public: nsDiskCacheMap(); @@ -281,11 +283,11 @@ public: nsresult AddRecord( nsDiskCacheRecord * mapRecord, nsDiskCacheRecord * oldRecord); nsresult UpdateRecord( nsDiskCacheRecord * mapRecord); nsresult FindRecord( PRUint32 hashNumber, nsDiskCacheRecord * mapRecord); - - nsresult GetRecord2( nsDiskCacheRecord * mapRecord); nsresult DeleteRecord2( nsDiskCacheRecord * mapRecord); nsresult EvictRecords( nsDiskCacheRecordVisitor * visitor); +//private: + void Reset();