Renaming nsDiskCacheEntry -> nsDiskCacheBindInfo, and reorganize files.
git-svn-id: svn://10.0.0.236/branches/DISKCACHE2_BRANCH@94555 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
10
mozilla/netwerk/cache/src/nsDiskCache.h
vendored
10
mozilla/netwerk/cache/src/nsDiskCache.h
vendored
@@ -26,15 +26,5 @@
|
||||
#ifndef _nsDiskCache_h_
|
||||
#define _nsDiskCache_h_
|
||||
|
||||
#include "prtypes.h"
|
||||
#include "prnetdb.h"
|
||||
#include "nsDebug.h"
|
||||
|
||||
|
||||
|
||||
/*
|
||||
|
||||
|
||||
*/
|
||||
|
||||
#endif // _nsDiskCache_h_
|
||||
|
||||
221
mozilla/netwerk/cache/src/nsDiskCacheBindData.cpp
vendored
Normal file
221
mozilla/netwerk/cache/src/nsDiskCacheBindData.cpp
vendored
Normal file
@@ -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 <beard@netscape.com>
|
||||
* Gordon Sheridan <gordon@netscape.com>
|
||||
*/
|
||||
|
||||
#include <limits.h>
|
||||
|
||||
#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;
|
||||
}
|
||||
188
mozilla/netwerk/cache/src/nsDiskCacheBindData.h
vendored
Normal file
188
mozilla/netwerk/cache/src/nsDiskCacheBindData.h
vendored
Normal file
@@ -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 <gordon@netscape.com>
|
||||
* Patrick C. Beard <beard@netscape.com>
|
||||
*/
|
||||
|
||||
|
||||
#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<nsITransport>& 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<nsITransport> 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_ */
|
||||
126
mozilla/netwerk/cache/src/nsDiskCacheBlockFile.cpp
vendored
126
mozilla/netwerk/cache/src/nsDiskCacheBlockFile.cpp
vendored
@@ -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;
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
590
mozilla/netwerk/cache/src/nsDiskCacheDevice.cpp
vendored
590
mozilla/netwerk/cache/src/nsDiskCacheDevice.cpp
vendored
@@ -259,21 +259,20 @@ static nsresult removeObservers(nsDiskCacheDevice* device)
|
||||
/******************************************************************************
|
||||
* static utility functions
|
||||
*****************************************************************************/
|
||||
static nsDiskCacheEntry*
|
||||
ensureDiskCacheEntry(nsCacheEntry * entry)
|
||||
static nsDiskCacheBindData*
|
||||
ensureDiskCacheBindData(nsCacheEntry * entry)
|
||||
{
|
||||
nsCOMPtr<nsISupports> 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<nsIFileTransportService> 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<nsITransport>& transport = diskEntry->getTransport(mode);
|
||||
nsCOMPtr<nsITransport>& 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<nsIFile> 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<nsICacheEntryInfo> 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<nsIFile> 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<nsIFile> 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<nsIFile> 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<nsIFile> 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<nsISimpleEnumerator> files;
|
||||
rv = mCacheDirectory->GetDirectoryEntries(getter_AddRefs(files));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
nsCOMPtr<nsISupportsArray> 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<nsISupports> next;
|
||||
rv = files->GetNext(getter_AddRefs(next));
|
||||
if (NS_FAILED(rv)) break;
|
||||
nsCOMPtr<nsIFile> 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<nsIInputStream> 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<nsISupports> 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<nsICacheEntryInfo> 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<nsIFile> 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<nsIFile> metaFile;
|
||||
|
||||
34
mozilla/netwerk/cache/src/nsDiskCacheDevice.h
vendored
34
mozilla/netwerk/cache/src/nsDiskCacheDevice.h
vendored
@@ -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<nsIObserver> mPrefsObserver; // XXX ?
|
||||
nsCOMPtr<nsILocalFile> 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<nsIObserver> mPrefsObserver; // XXX ?
|
||||
nsCOMPtr<nsILocalFile> 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
|
||||
};
|
||||
|
||||
|
||||
242
mozilla/netwerk/cache/src/nsDiskCacheEntry.cpp
vendored
242
mozilla/netwerk/cache/src/nsDiskCacheEntry.cpp
vendored
@@ -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 <gordon@netscape.com>
|
||||
* Patrick C. Beard <beard@netscape.com>
|
||||
*/
|
||||
|
||||
#include <limits.h>
|
||||
|
||||
#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;
|
||||
}
|
||||
|
||||
258
mozilla/netwerk/cache/src/nsDiskCacheEntry.h
vendored
258
mozilla/netwerk/cache/src/nsDiskCacheEntry.h
vendored
@@ -17,7 +17,8 @@
|
||||
* Copyright (C) 2001 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Contributor(s):
|
||||
* Gordon Sheridan <gordon@netscape.com>
|
||||
* Patrick C. Beard <beard@netscape.com>
|
||||
*/
|
||||
|
||||
@@ -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<nsITransport>& 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<nsITransport> 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_ */
|
||||
|
||||
12
mozilla/netwerk/cache/src/nsDiskCacheMap.cpp
vendored
12
mozilla/netwerk/cache/src/nsDiskCacheMap.cpp
vendored
@@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
28
mozilla/netwerk/cache/src/nsDiskCacheMap.h
vendored
28
mozilla/netwerk/cache/src/nsDiskCacheMap.h
vendored
@@ -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();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user