diff --git a/mozilla/network/cache/nu/src/CacheStubs.cpp b/mozilla/network/cache/nu/src/CacheStubs.cpp index f2aac9b5eff..98fa050c7ed 100644 --- a/mozilla/network/cache/nu/src/CacheStubs.cpp +++ b/mozilla/network/cache/nu/src/CacheStubs.cpp @@ -31,8 +31,7 @@ void Cache_Init(void) { - /* Most of the initilization gets done in the constructor for the - * nsCacheManager class. */ + CACHEMGR->Init(); } void diff --git a/mozilla/network/cache/nu/src/makefile.win b/mozilla/network/cache/nu/src/makefile.win index d4ca8e11e71..5c3475612da 100644 --- a/mozilla/network/cache/nu/src/makefile.win +++ b/mozilla/network/cache/nu/src/makefile.win @@ -33,6 +33,7 @@ LLIBS = \ $(DIST)\lib\libplc21.lib \ $(DIST)\lib\dbm32.lib \ $(DIST)\lib\xpcom32.lib \ + $(DIST)\lib\libpref.lib \ $(NULL) MISCDEP = $(LLIBS) @@ -55,13 +56,12 @@ OBJS = \ .\$(OBJDIR)\nsMemStream.obj \ $(NULL) -# .\$(OBJDIR)\nsHash.obj \ - LINCS = \ -I$(PUBLIC)\xpcom \ -I$(PUBLIC)\dbm \ -I$(PUBLIC)\pref \ - -I..\public \ + -I$(PUBLIC)\js \ + -I..\public \ -I..\include \ $(NULL) diff --git a/mozilla/network/cache/nu/src/nsCacheManager.cpp b/mozilla/network/cache/nu/src/nsCacheManager.cpp index eef2c2fdccd..5a64e976f30 100644 --- a/mozilla/network/cache/nu/src/nsCacheManager.cpp +++ b/mozilla/network/cache/nu/src/nsCacheManager.cpp @@ -38,24 +38,31 @@ static nsCacheManager TheManager; PRUint32 NumberOfObjects(void); -nsCacheManager::nsCacheManager(): m_pFirstModule(0), m_bOffline(PR_FALSE) +nsCacheManager::nsCacheManager(): + m_pFirstModule(0), + m_bOffline(PR_FALSE), + m_pPrefs(0) { - Init(); } nsCacheManager::~nsCacheManager() { - if (m_pBkgThd) + if (m_pPrefs) { - m_pBkgThd->Stop(); - delete m_pBkgThd; - m_pBkgThd = 0; + delete m_pPrefs; + m_pPrefs = 0; } if (m_pFirstModule) { delete m_pFirstModule; m_pFirstModule = 0; } + if (m_pBkgThd) + { + m_pBkgThd->Stop(); + delete m_pBkgThd; + m_pBkgThd = 0; + } } nsCacheManager* @@ -205,6 +212,11 @@ void nsCacheManager::Init() { MonitorLocker ml(this); + + //Init prefs + if (!m_pPrefs) + m_pPrefs = new nsCachePref(); + if (m_pFirstModule) delete m_pFirstModule; diff --git a/mozilla/network/cache/nu/src/nsCacheModule.cpp b/mozilla/network/cache/nu/src/nsCacheModule.cpp index 5f8c5401a77..3b80c0d8ea6 100644 --- a/mozilla/network/cache/nu/src/nsCacheModule.cpp +++ b/mozilla/network/cache/nu/src/nsCacheModule.cpp @@ -32,6 +32,7 @@ nsCacheModule::nsCacheModule(const PRUint32 i_size=DEFAULT_SIZE): m_Size(i_size), + m_SizeInUse(0), m_pEnumeration(0), m_pNext(0), m_Entries(0) diff --git a/mozilla/network/cache/nu/src/nsCachePref.cpp b/mozilla/network/cache/nu/src/nsCachePref.cpp index 838673c5d10..e745e761586 100644 --- a/mozilla/network/cache/nu/src/nsCachePref.cpp +++ b/mozilla/network/cache/nu/src/nsCachePref.cpp @@ -17,17 +17,30 @@ */ #include "nsCachePref.h" -//#include "prefapi.h" +#include "xp.h" +#include "prefapi.h" +#include "prmem.h" +#include "nsCacheManager.h" +#include "plstr.h" static const PRUint32 MEM_CACHE_SIZE_DEFAULT = 1024*1024; static const PRUint32 DISK_CACHE_SIZE_DEFAULT = 5*MEM_CACHE_SIZE_DEFAULT; -static const PRUint32 BKG_THREAD_SLEEP = 15*60; /*in seconds, 15 minutes */ +static const PRUint32 BKG_THREAD_SLEEP = 60;//TODO- Testing 15*60; /*in seconds, 15 minutes */ static const PRUint16 BUGS_FOUND_SO_FAR = 0; + +//Preferences +static const char* MEM_CACHE_PREF = "browser.cache.memory_cache_size"; +static const char* DISK_CACHE_PREF = "browser.cache.disk_cache_size"; +static const char* CACHE_DIR_PREF = "browser.cache.directory"; +static const char* FREQ_PREF = "browser.cache.check_doc_frequency"; + /* Find a bug in NU_CACHE, get these many chocolates */ static const PRUint16 CHOCOLATES_PER_BUG_FOUND = 2^BUGS_FOUND_SO_FAR; -/* TODO move this to InitNetLib */ -static nsCachePref ThePrefs; +int PR_CALLBACK Cache_PrefChangedFunc(const char *pref, void *data) { + nsCachePref::GetInstance()->SetupPrefs(pref); + return PR_TRUE; +} nsCachePref::nsCachePref(void): m_BkgSleepTime(BKG_THREAD_SLEEP), @@ -37,15 +50,85 @@ nsCachePref::nsCachePref(void): m_MemCacheSize(MEM_CACHE_SIZE_DEFAULT), m_RefreshFreq(ONCE) { - //Read all the stuff from pref here. - //If this changes to nsPref, here is all that needs to be changed. - //PRUint32 nTemp; - //PREF_GetIntPref("browser.cache.memory_cache_size",&nTemp); - //*1024 + PREF_RegisterCallback("browser.cache",Cache_PrefChangedFunc,0); + SetupPrefs(0); } nsCachePref::~nsCachePref() { + if (m_DiskCacheFolder) + { + delete m_DiskCacheFolder; + m_DiskCacheFolder = 0; + } +} + +//Read all the stuff from pref here. +void +nsCachePref::SetupPrefs(const char* i_Pref) +{ + PRBool bSetupAll = PR_FALSE; + + long nTemp; + char* tempPref=0; + + if (!i_Pref) + bSetupAll = PR_TRUE; + + if (bSetupAll || !PL_strcmp(i_Pref,MEM_CACHE_PREF)) + { + if (PREF_OK == PREF_GetIntPref(MEM_CACHE_PREF,&nTemp)) + m_MemCacheSize = 1024*nTemp; + else + m_MemCacheSize = MEM_CACHE_SIZE_DEFAULT; + } + + if (bSetupAll || !PL_strcmp(i_Pref,DISK_CACHE_PREF)) + { + if (PREF_OK == PREF_GetIntPref(DISK_CACHE_PREF,&nTemp)) + m_DiskCacheSize = 1024*nTemp; + else + m_DiskCacheSize = DISK_CACHE_SIZE_DEFAULT; + } + + if (bSetupAll || !PL_strcmp(i_Pref,FREQ_PREF)) + { + if (PREF_OK == PREF_GetIntPref(FREQ_PREF,&nTemp)) + { + m_RefreshFreq = (nsCachePref::Refresh)nTemp; + } + else + m_RefreshFreq = ONCE; + } + + if (bSetupAll || !PL_strcmp(i_Pref,CACHE_DIR_PREF)) + { + if (PREF_OK == PREF_CopyCharPref(CACHE_DIR_PREF,&tempPref)) + { + PR_ASSERT(tempPref); + if (m_DiskCacheFolder) + delete m_DiskCacheFolder; + m_DiskCacheFolder = new char[PL_strlen(tempPref)+1]; + if (!m_DiskCacheFolder) + { + if (tempPref) + PR_Free(tempPref); + return; + } + PL_strcpy(m_DiskCacheFolder, tempPref); + } + else //TODO set to temp folder + { + m_DiskCacheFolder = new char [1]; + if (!m_DiskCacheFolder) + return; + *m_DiskCacheFolder = '\0'; + } + + } + + if (tempPref) + PR_Free(tempPref); } const PRUint32 @@ -81,12 +164,13 @@ const char* nsCachePref::DiskCacheDBFilename(void) const char* nsCachePref::DiskCacheFolder(void) { - return 0; + return ""; } nsCachePref* nsCachePref::GetInstance() { - return &ThePrefs; + PR_ASSERT(nsCacheManager::GetInstance()->GetPrefs()); + return nsCacheManager::GetInstance()->GetPrefs(); } PRUint32 nsCachePref::MemCacheSize() diff --git a/mozilla/network/cache/nu/src/nsDiskModule.cpp b/mozilla/network/cache/nu/src/nsDiskModule.cpp index 44205771e4d..25cfbf2b191 100644 --- a/mozilla/network/cache/nu/src/nsDiskModule.cpp +++ b/mozilla/network/cache/nu/src/nsDiskModule.cpp @@ -46,15 +46,29 @@ PR_ASSERT(res); \ } -typedef struct { +struct recentlyUsedObject { PRCList link; nsCacheObject* cacheObject; -} recentlyUsedObject; +}; + +/* Find pointer to recentlyUsedObject struct + * from the list linkaged embedded in it + */ +#define OBJECT_PTR(_link) \ + ((recentlyUsedObject*) ((char*) (_link) - offsetof(recentlyUsedObject,link))) //File static list of recently used cache objects static PRCList g_RecentlyUsedList; + static char* g_FullFilename=0; -const static PRUint16 MAX_FILENAME_LEN = 512; +const static int MAX_FILENAME_LEN = 512; + +// Every time we cleanup we cleanup to 75% of the max available size. +// This should ideally change to a more const number than a percentage. +// Since someone may have a bigger cache size, so we don't really want to +// be cleaning up 5 megs if some one has a 20 megs cache size. +// I will revisit this issue once the basic architecture is up and running. +#define CLEANUP_FACTOR 0.75 char* FullFilename(const char* i_Filename); // @@ -64,7 +78,6 @@ nsDiskModule::nsDiskModule(const PRUint32 size): nsCacheModule(size), m_pDB(0) { - /* initialize the list recently used urls*/ PR_INIT_CLIST(&g_RecentlyUsedList); } @@ -76,15 +89,24 @@ nsDiskModule::~nsDiskModule() (*m_pDB->close)(m_pDB); m_pDB = 0; } + + /* Clean up the recently used list */ recentlyUsedObject* obj; while (!PR_CLIST_IS_EMPTY(&g_RecentlyUsedList)) { obj = (recentlyUsedObject*) PR_LIST_HEAD(&g_RecentlyUsedList); - PR_FREEIF(obj->cacheObject); + if (obj->cacheObject) + delete obj->cacheObject; PR_REMOVE_LINK(&obj->link); - PR_DELETE(obj); } + PR_ASSERT(PR_CLIST_IS_EMPTY(&g_RecentlyUsedList)); + + if (g_FullFilename) + { + delete[] g_FullFilename; + g_FullFilename = 0; + } } PRBool nsDiskModule::AddObject(nsCacheObject* io_pObject) @@ -119,6 +141,8 @@ PRBool nsDiskModule::AddObject(nsCacheObject* io_pObject) { // if (m_Sync == EVERYTIME) status = (*m_pDB->sync)(m_pDB, 0); + m_Entries++; + m_SizeInUse += io_pObject->Size(); } PR_Free(key); PR_Free(data); @@ -129,8 +153,6 @@ PRBool nsDiskModule::AddObject(nsCacheObject* io_pObject) PRBool nsDiskModule::Contains(nsCacheObject* io_pObject) const { - //return Contains(io_oObject->Address()); - ENSURE_INIT; if (!m_pDB || !io_pObject) @@ -139,7 +161,8 @@ PRBool nsDiskModule::Contains(nsCacheObject* io_pObject) const nsCacheObject* pTemp = GetObject(io_pObject->Address()); if (pTemp) { - io_pObject = pTemp; /*bug */ + PR_ASSERT(io_pObject == pTemp); + // until I do a copyFrom function return PR_TRUE; } return PR_FALSE; @@ -167,6 +190,9 @@ PRBool nsDiskModule::Contains(const char* i_url) const void nsDiskModule::GarbageCollect(void) { MonitorLocker ml(this); + ReduceSizeTo((PRUint32)(CLEANUP_FACTOR*m_Size)); + // TODO + // if the recentlyusedlist has grown too big, trim some objects from there as well } nsCacheObject* nsDiskModule::GetObject(const PRUint32 i_index) const @@ -181,11 +207,27 @@ nsCacheObject* nsDiskModule::GetObject(const PRUint32 i_index) const nsCacheObject* nsDiskModule::GetObject(const char* i_url) const { ENSURE_INIT; + MonitorLocker ml((nsDiskModule*)this); if (!m_pDB || !i_url || !*i_url) return 0; - //TODO check from recently used list. + /* Check amongst recently used objects */ + recentlyUsedObject* obj; + PRCList* list = &g_RecentlyUsedList; + if (!PR_CLIST_IS_EMPTY(&g_RecentlyUsedList)) + { + list = g_RecentlyUsedList.next; + nsCacheObject* pObj; + while (list != &g_RecentlyUsedList) + { + obj = OBJECT_PTR(list); + pObj = obj->cacheObject; + if (0 == PL_strcasecmp(i_url, pObj->Address())) //todo also validate + return pObj; + list = list->next; + } + } DBT key, data; @@ -196,8 +238,9 @@ nsCacheObject* nsDiskModule::GetObject(const char* i_url) const { nsCacheObject* pTemp = new nsCacheObject(); pTemp->Info(data.data); - recentlyUsedObject* pNode = PR_NEW(recentlyUsedObject); + recentlyUsedObject* pNode = PR_NEWZAP(recentlyUsedObject); PR_APPEND_LINK(&pNode->link, &g_RecentlyUsedList); + pNode->cacheObject = pTemp; return pTemp; } @@ -283,20 +326,87 @@ PRBool nsDiskModule::InitDB(void) PRBool nsDiskModule::ReduceSizeTo(const PRUint32 i_NewSize) { - //TODO - return PR_TRUE; + return PR_FALSE; //TODO Fix this. + PRInt32 needToFree = m_SizeInUse - i_NewSize; + if (needToFree > 0) + { + PRUint32 avg = AverageSize(); + if (avg==0) + return PR_FALSE; + + PRUint32 nObjectsToFree = needToFree/AverageSize(); + if (nObjectsToFree < 1) + nObjectsToFree = 1; + + //TODO + + /* + DBT key, data; + + key.data = (void*) i_url; + key.size = PL_strlen(i_url); + + if (0 == (*m_pDB->get)(m_pDB, &key, &data, 0)) + { + nsCacheObject* pTemp = new nsCacheObject(); + pTemp->Info(data.data); + recentlyUsedObject* pNode = PR_NEWZAP(recentlyUsedObject); + PR_APPEND_LINK(&pNode->link, &g_RecentlyUsedList); + pNode->cacheObject = pTemp; + return pTemp; + } + */ + + return PR_TRUE; + } + + return PR_FALSE; } PRBool nsDiskModule::Remove(const char* i_url) { ENSURE_INIT; - //TODO - // Also remove the file corresponding to this item. + nsCacheObject* pObject = GetObject(i_url); + if (pObject) + { + return Remove(pObject); + } return PR_FALSE; } +PRBool nsDiskModule::Remove(nsCacheObject* pObject) +{ + MonitorLocker ml(this); + + if (!pObject) + return PR_FALSE; + //PR_ASSERT(Contains(pObject); + + //Remove it from the index + DBT key; + key.data = (void*) pObject->Address(); + key.size = PL_strlen(pObject->Address()); + if (0 == (*m_pDB->del)(m_pDB, &key, 0)) + { + --m_Entries; + m_SizeInUse -= pObject->Size(); + } + //Remove it from the recently used list + //TODO till done I am not removing it from here + + //Remove it from the disk + + //Remove file FullFilename(pObject->Filename()); + + //Finally delete it + //delete pObject; //Currently recentlyused will delete these. + //pObject = 0; + return PR_TRUE; + +} PRBool nsDiskModule::Remove(const PRUint32 i_index) { + //This will probably go away. ENSURE_INIT; //TODO // Also remove the file corresponding to this item. @@ -316,7 +426,7 @@ void nsDiskModule::SetSize(const PRUint32 i_Size) m_Size = i_Size; if (m_Size >0) { - ReduceSizeTo(m_Size); + ReduceSizeTo((PRUint32)(CLEANUP_FACTOR*m_Size)); } else { @@ -329,6 +439,7 @@ char* FullFilename(const char* i_Filename) if (0 == g_FullFilename) { g_FullFilename = new char[MAX_FILENAME_LEN]; + *g_FullFilename = '\0'; if (0 == g_FullFilename) return 0; }