Bug 616090 - Optimize timer in nsDOMStorageDBWrapper. r=honzab a=blocking-fennec
--- a/dom/src/storage/nsDOMStorage.cpp
+++ b/dom/src/storage/nsDOMStorage.cpp
@@ -436,16 +436,18 @@ nsDOMStorageManager::Observe(nsISupports
return DOMStorageImpl::gStorageDB->DropSessionOnlyStoragesForHost(host);
#endif
}
} else if (!strcmp(aTopic, "timer-callback")) {
nsCOMPtr<nsIObserverService> obsserv = mozilla::services::GetObserverService();
if (obsserv)
obsserv->NotifyObservers(nsnull, NS_DOMSTORAGE_FLUSH_TIMER_OBSERVER, nsnull);
+ if (!UnflushedDataExists())
+ DOMStorageImpl::gStorageDB->StopTempTableFlushTimer();
} else if (!strcmp(aTopic, "browser:purge-domain-data")) {
// Convert the domain name to the ACE format
nsCAutoString aceDomain;
nsresult rv;
nsCOMPtr<nsIIDNService> converter = do_GetService(NS_IDNSERVICE_CONTRACTID);
if (converter) {
rv = converter->ConvertUTF8toACE(NS_ConvertUTF16toUTF8(aData), aceDomain);
NS_ENSURE_SUCCESS(rv, rv);
@@ -532,16 +534,36 @@ nsDOMStorageManager::AddToStoragesHash(D
void
nsDOMStorageManager::RemoveFromStoragesHash(DOMStorageImpl* aStorage)
{
nsDOMStorageEntry* entry = mStorages.GetEntry(aStorage);
if (entry)
mStorages.RemoveEntry(aStorage);
}
+static PLDHashOperator
+CheckUnflushedData(nsDOMStorageEntry* aEntry, void* userArg)
+{
+ if (aEntry->mStorage->WasTemporaryTableLoaded()) {
+ PRBool *unflushedData = (PRBool*)userArg;
+ *unflushedData = PR_TRUE;
+ return PL_DHASH_STOP;
+ }
+
+ return PL_DHASH_NEXT;
+}
+
+PRBool
+nsDOMStorageManager::UnflushedDataExists()
+{
+ PRBool unflushedData = PR_FALSE;
+ mStorages.EnumerateEntries(CheckUnflushedData, &unflushedData);
+ return unflushedData;
+}
+
//
// nsDOMStorage
//
#ifdef MOZ_STORAGE
nsDOMStorageDBWrapper* DOMStorageImpl::gStorageDB = nsnull;
#endif
@@ -1050,16 +1072,18 @@ DOMStorageImpl::WasTemporaryTableLoaded(
void
DOMStorageImpl::SetTemporaryTableLoaded(bool loaded)
{
if (loaded) {
mLastTemporaryTableAccessTime = TimeStamp::Now();
if (!mLoadedTemporaryTable)
mTemporaryTableAge = mLastTemporaryTableAccessTime;
+
+ gStorageDB->EnsureTempTableFlushTimer();
}
mLoadedTemporaryTable = loaded;
}
NS_IMETHODIMP
DOMStorageImpl::Observe(nsISupports *subject,
const char *topic,
--- a/dom/src/storage/nsDOMStorage.h
+++ b/dom/src/storage/nsDOMStorage.h
@@ -131,16 +131,21 @@ public:
nsresult ClearAllStorages();
PRBool InPrivateBrowsingMode() { return mInPrivateBrowsing; }
static nsresult Initialize();
static nsDOMStorageManager* GetInstance();
static void Shutdown();
+ /**
+ * Checks whether there is any data waiting to be flushed from a temp table.
+ */
+ PRBool UnflushedDataExists();
+
static nsDOMStorageManager* gStorageManager;
protected:
nsTHashtable<nsDOMStorageEntry> mStorages;
PRBool mInPrivateBrowsing;
};
--- a/dom/src/storage/nsDOMStorageDBWrapper.cpp
+++ b/dom/src/storage/nsDOMStorageDBWrapper.cpp
@@ -70,19 +70,17 @@ void ReverseString(const nsCSubstring& s
}
nsDOMStorageDBWrapper::nsDOMStorageDBWrapper()
{
}
nsDOMStorageDBWrapper::~nsDOMStorageDBWrapper()
{
- if (mFlushTimer) {
- mFlushTimer->Cancel();
- }
+ StopTempTableFlushTimer();
}
nsresult
nsDOMStorageDBWrapper::Init()
{
nsresult rv;
rv = mPersistentDB.Init(NS_LITERAL_STRING("webappsstore.sqlite"));
@@ -92,23 +90,16 @@ nsDOMStorageDBWrapper::Init()
NS_ENSURE_SUCCESS(rv, rv);
rv = mSessionOnlyDB.Init(&mPersistentDB);
NS_ENSURE_SUCCESS(rv, rv);
rv = mPrivateBrowsingDB.Init();
NS_ENSURE_SUCCESS(rv, rv);
- mFlushTimer = do_CreateInstance(NS_TIMER_CONTRACTID, &rv);
- NS_ENSURE_SUCCESS(rv, rv);
-
- rv = mFlushTimer->Init(nsDOMStorageManager::gStorageManager, 5000,
- nsITimer::TYPE_REPEATING_SLACK);
- NS_ENSURE_SUCCESS(rv, rv);
-
return NS_OK;
}
nsresult
nsDOMStorageDBWrapper::EnsureLoadTemporaryTableForStorage(DOMStorageImpl* aStorage)
{
if (aStorage->CanUseChromePersist())
return mChromePersistentDB.EnsureLoadTemporaryTableForStorage(aStorage);
@@ -447,8 +438,35 @@ nsDOMStorageDBWrapper::GetDomainFromScop
{
nsCAutoString reverseDomain, scope;
scope = aScope;
scope.Left(reverseDomain, scope.FindChar(':')-1);
ReverseString(reverseDomain, aDomain);
return NS_OK;
}
+
+void
+nsDOMStorageDBWrapper::EnsureTempTableFlushTimer()
+{
+ if (!mTempTableFlushTimer) {
+ nsresult rv;
+ mTempTableFlushTimer = do_CreateInstance(NS_TIMER_CONTRACTID, &rv);
+
+ if (!NS_SUCCEEDED(rv)) {
+ mTempTableFlushTimer = nsnull;
+ return;
+ }
+
+ mTempTableFlushTimer->Init(nsDOMStorageManager::gStorageManager, 5000,
+ nsITimer::TYPE_REPEATING_SLACK);
+ }
+}
+
+void
+nsDOMStorageDBWrapper::StopTempTableFlushTimer()
+{
+ if (mTempTableFlushTimer) {
+ mTempTableFlushTimer->Cancel();
+ mTempTableFlushTimer = nsnull;
+ }
+}
+
--- a/dom/src/storage/nsDOMStorageDBWrapper.h
+++ b/dom/src/storage/nsDOMStorageDBWrapper.h
@@ -216,18 +216,29 @@ public:
*/
static nsresult CreateQuotaDomainDBKey(const nsACString& aAsciiDomain,
PRBool aIncludeSubDomains, PRBool aETLDplus1Only,
nsACString& aKey);
static nsresult GetDomainFromScopeKey(const nsACString& aScope,
nsACString& aDomain);
+ /**
+ * Ensures the temp table flush timer is running. This is called when we add
+ * data that will need to be flushed.
+ */
+ void EnsureTempTableFlushTimer();
+
+ /**
+ * Stops the temp table flush timer.
+ */
+ void StopTempTableFlushTimer();
+
protected:
nsDOMStoragePersistentDB mChromePersistentDB;
nsDOMStoragePersistentDB mPersistentDB;
nsDOMStorageMemoryDB mSessionOnlyDB;
nsDOMStorageMemoryDB mPrivateBrowsingDB;
- nsCOMPtr<nsITimer> mFlushTimer;
+ nsCOMPtr<nsITimer> mTempTableFlushTimer;
};
#endif /* nsDOMStorageDB_h___ */