backing out earlier changes for 53312

This commit is contained in:
dprice%netscape.com 2000-10-14 01:15:24 +00:00
parent d1f12ec2e5
commit dabe025a7e
2 changed files with 28 additions and 127 deletions

View File

@ -148,7 +148,7 @@ DeleteManifestEntry(nsHashKey* aKey, void* aData, void* closure)
// The following initialization makes a guess of 10 entries per jarfile.
nsJAR::nsJAR(): mManifestData(nsnull, nsnull, DeleteManifestEntry, nsnull, 10),
mParsedManifest(PR_FALSE), mGlobalStatus(nsIZipReader::NOT_SIGNED),
mReleaseTime(PR_INTERVAL_NO_TIMEOUT), mCache(nsnull), mLock(nsnull)
mReleaseTime(0), mCache(nsnull), mLock(nsnull)
{
NS_INIT_REFCNT();
}
@ -1101,18 +1101,17 @@ nsJARItem::GetCRC32(PRUint32 *aCrc32)
////////////////////////////////////////////////////////////////////////////////
// nsIZipReaderCache
NS_IMPL_THREADSAFE_ISUPPORTS2(nsZipReaderCache, nsIZipReaderCache, nsIObserver)
NS_IMPL_THREADSAFE_ISUPPORTS1(nsZipReaderCache, nsIZipReaderCache)
nsZipReaderCache::nsZipReaderCache()
: mLock(nsnull),
mZips(16)
mZips(16),
#ifdef ZIP_CACHE_HIT_RATE
,
mZipCacheLookups(0),
mZipCacheHits(0),
mZipCacheFlushes(0),
mZipSyncMisses(0)
#endif
mFreeCount(0)
{
NS_INIT_REFCNT();
}
@ -1120,23 +1119,13 @@ nsZipReaderCache::nsZipReaderCache()
NS_IMETHODIMP
nsZipReaderCache::Init(PRUint32 cacheSize)
{
nsresult rv;
#ifdef xDEBUG_warren
mCacheSize = 1;//cacheSize; // XXX hack
#else
mCacheSize = cacheSize;
mCacheSize = cacheSize;
#endif
// Register as a memory pressure observer
NS_WITH_SERVICE(nsIObserverService, os, NS_OBSERVERSERVICE_CONTRACTID, &rv);
if (NS_SUCCEEDED(rv)) {
rv = os->AddObserver(this, NS_MEMORY_PRESSURE_TOPIC);
}
// ignore failure of the observer registration.
mLock = PR_NewLock();
return mLock ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
}
static PRBool PR_CALLBACK
@ -1149,21 +1138,14 @@ DropZipReaderCache(nsHashKey *aKey, void *aData, void* closure)
nsZipReaderCache::~nsZipReaderCache()
{
nsresult rv;
if (mLock)
PR_DestroyLock(mLock);
mZips.Enumerate(DropZipReaderCache, nsnull);
// Unregister this memory pressure observer
NS_WITH_SERVICE(nsIObserverService, os, NS_OBSERVERSERVICE_CONTRACTID, &rv);
if (NS_SUCCEEDED(rv)) {
rv = os->RemoveObserver(this, NS_MEMORY_PRESSURE_TOPIC);
}
#ifdef ZIP_CACHE_HIT_RATE
printf("nsZipReaderCache size=%d hits=%d lookups=%d rate=%f%% flushes=%d missed %d\n",
mCacheSize, mZipCacheHits, mZipCacheLookups,
(float)mZipCacheHits / mZipCacheLookups,
mZipCacheFlushes, mZipSyncMisses);
printf("nsZipReaderCache size=%d hits=%d lookups=%d rate=%f%% flushes=%d\n",
mZipCacheHits, mZipCacheLookups, (float)mZipCacheHits / mZipCacheLookups,
mZipCacheFlushes);
#endif
}
@ -1202,7 +1184,11 @@ nsZipReaderCache::GetZip(nsIFile* zipFile, nsIZipReader* *result)
#ifdef ZIP_CACHE_HIT_RATE
mZipCacheHits++;
#endif
zip->ClearReleaseTime();
if (zip->GetReleaseTime() != PR_INTERVAL_NO_TIMEOUT) {
// this was an otherwise-free entry, so decrement our free counter
NS_ASSERTION(mFreeCount > 0, "mFreeCount screwed up");
mFreeCount--;
}
}
else {
zip = new nsJAR();
@ -1245,72 +1231,32 @@ FindOldestZip(nsHashKey *aKey, void *aData, void* closure)
return PR_TRUE;
}
struct ZipFindData {nsJAR* zip; PRBool found;};
static PRBool PR_CALLBACK
FindZip(nsHashKey *aKey, void *aData, void* closure)
{
ZipFindData* find_data = (ZipFindData*)closure;
if (find_data->zip == (nsJAR*)aData) {
find_data->found = PR_TRUE;
return PR_FALSE;
}
return PR_TRUE;
}
nsresult
nsZipReaderCache::ReleaseZip(nsJAR* zip)
{
nsresult rv;
nsAutoLock lock(mLock);
// It is possible that two thread compete for this zip. The dangerous
// case is where one thread Releases the zip and discovers that the ref
// count has gone to one. Before it can call this ReleaseZip method
// another thread calls our GetZip method. The ref count goes to two. That
// second thread then Releases the zip and the ref coutn goes to one. It
// Then tries to enter this ReleaseZip method and blocks while the first
// thread is still here. The first thread continues and remove the zip from
// the cache and calls its Release method sending the ref count to 0 and
// deleting the zip. However, the second thread is still blocked at the
// start of ReleaseZip, but the 'zip' param now hold a reference to a
// deleted zip!
//
// So, we are going to try safegaurding here by searching our hashtable while
// locked here for the zip. We return fast if it is not found.
ZipFindData find_data = {zip, PR_FALSE};
mZips.Enumerate(FindZip, &find_data);
if (!find_data.found) {
#ifdef ZIP_CACHE_HIT_RATE
mZipSyncMisses++;
#endif
return NS_OK;
}
zip->SetReleaseTime();
mFreeCount++;
if (mZips.Count() <= mCacheSize)
return NS_OK;
nsJAR* oldest = nsnull;
mZips.Enumerate(FindOldestZip, &oldest);
// Because of the craziness above it is possible that there is no zip that
// needs removing.
if (!oldest)
return NS_OK;
if (mFreeCount == 1) {
// then this is our guy -- no need to search for the oldest
oldest = zip;
}
else {
mZips.Enumerate(FindOldestZip, &oldest);
}
NS_ASSERTION(oldest, "wacked");
#ifdef ZIP_CACHE_HIT_RATE
mZipCacheFlushes++;
#endif
// Clear the cache pointer in case we gave out this oldest guy while
// his Release call was being made. Otherwise we could nest on ReleaseZip
// when the second owner calls Release and we are still here in this lock.
oldest->SetZipReaderCache(nsnull);
// remove from hashtable
nsCOMPtr<nsIFile> zipFile;
rv = oldest->GetFile(getter_AddRefs(zipFile));
@ -1324,48 +1270,6 @@ nsZipReaderCache::ReleaseZip(nsJAR* zip)
PRBool removed = mZips.Remove(&key); // Releases
NS_ASSERTION(removed, "botched");
#ifdef xDEBUG_jband
printf("dumped %s from the jar cache\n", (const char*) path);
#endif
return NS_OK;
}
static PRBool PR_CALLBACK
FindUnreferencedZip(nsHashKey *aKey, void *aData, void* closure)
{
nsHashKey** unrefKeyPtr = (nsHashKey**)closure;
nsJAR* current = (nsJAR*)aData;
if (current->GetReleaseTime() != PR_INTERVAL_NO_TIMEOUT) {
*unrefKeyPtr = aKey;
current->SetZipReaderCache(nsnull);
return PR_FALSE;
}
return PR_TRUE;
}
NS_IMETHODIMP
nsZipReaderCache::Observe(nsISupports *aSubject,
const PRUnichar *aTopic,
const PRUnichar *aSomeData)
{
nsAutoLock lock(mLock);
while (PR_TRUE)
{
nsHashKey* unreferenced = nsnull;
mZips.Enumerate(FindUnreferencedZip, &unreferenced);
if ( ! unreferenced )
break;
PRBool removed = mZips.Remove(unreferenced); // Releases
NS_ASSERTION(removed, "botched");
#ifdef xDEBUG_jband
printf("flushed something from the jar cache\n");
#endif
}
return NS_OK;
}

View File

@ -54,7 +54,6 @@
#include "zipfile.h"
#include "nsIPrincipal.h"
#include "nsISignatureVerifier.h"
#include "nsIObserverService.h"
class nsIInputStream;
class nsJARManifestItem;
@ -85,11 +84,10 @@ class nsJAR : public nsIZipReader
Create(nsISupports *aOuter, REFNSIID aIID, void **aResult);
PRIntervalTime GetReleaseTime() {
if (mRefCnt == 1)
return mReleaseTime;
}
PRBool IsReleased() {
return mReleaseTime != PR_INTERVAL_NO_TIMEOUT;
else
return PR_INTERVAL_NO_TIMEOUT;
}
void SetReleaseTime() {
@ -182,16 +180,15 @@ protected:
////////////////////////////////////////////////////////////////////////////////
#if defined(DEBUG_warren) || defined(DEBUG_jband)
#ifdef DEBUG_warren
#define ZIP_CACHE_HIT_RATE
#endif
class nsZipReaderCache : public nsIZipReaderCache, public nsIObserver
class nsZipReaderCache : public nsIZipReaderCache
{
public:
NS_DECL_ISUPPORTS
NS_DECL_NSIZIPREADERCACHE
NS_DECL_NSIOBSERVER
nsZipReaderCache();
virtual ~nsZipReaderCache();
@ -205,12 +202,12 @@ protected:
PRLock* mLock;
PRInt32 mCacheSize;
nsSupportsHashtable mZips;
PRUint32 mFreeCount;
#ifdef ZIP_CACHE_HIT_RATE
PRUint32 mZipCacheLookups;
PRUint32 mZipCacheHits;
PRUint32 mZipCacheFlushes;
PRUint32 mZipSyncMisses;
#endif
};