Bug 1396655 - Cleanup folder DB cache eviction logic and the debugging output. r=jorgk,rkent a=jorgk
authoraceman <acelists@atlas.sk>
Sat, 09 Sep 2017 08:34:00 +0200
changeset 28211 950c1b4d04ab8e8f14860f9b6c06d9cbdbcbcb67
parent 28210 ae24724700fef59ac37f782f17568ec73a62543b
child 28212 3df0989644bb5fc2df4769bfc5a53d650fd8fe15
push id2068
push usermozilla@jorgk.com
push dateWed, 09 May 2018 22:13:55 +0000
treeherdercomm-esr52@d81c08572750 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjorgk, rkent, jorgk
bugs1396655
Bug 1396655 - Cleanup folder DB cache eviction logic and the debugging output. r=jorgk,rkent a=jorgk
mailnews/base/util/msgDBCacheManager.js
--- a/mailnews/base/util/msgDBCacheManager.js
+++ b/mailnews/base/util/msgDBCacheManager.js
@@ -28,24 +28,29 @@ var DBCACHE_INTERVAL_DEFAULT_MS = 60000;
 var msgDBCacheManager =
 {
   _initialized: false,
 
   _msgDBCacheTimer: null,
 
   _msgDBCacheTimerIntervalMS: DBCACHE_INTERVAL_DEFAULT_MS,
 
+  _dbService: null,
+
   /**
    * This is called on startup
    */
   init: function dbcachemgr_init()
   {
     if (this._initialized)
       return;
 
+    this._dbService = Cc["@mozilla.org/msgDatabase/msgDBService;1"]
+                        .getService(Ci.nsIMsgDBService);
+
     // we listen for "quit-application-granted" instead of
     // "quit-application-requested" because other observers of the
     // latter can cancel the shutdown.
     Services.obs.addObserver(this, "quit-application-granted", false);
 
     this.startPeriodicCheck();
 
     this._initialized = true;
@@ -97,74 +102,74 @@ var msgDBCacheManager =
                                    .createInstance(Ci.nsITimer);
 
       this._dbCacheCheckTimer.initWithCallback(
                                    this._dbCacheCheckTimerCallback,
                                    this._msgDBCacheTimerIntervalMS,
                                    Ci.nsITimer.TYPE_REPEATING_SLACK);
     }
   },
-  checkCachedDBs : function ()
+
+  /**
+   * Checks if any DBs need to be closed due to inactivity or too many of them open.
+   */
+  checkCachedDBs: function()
   {
-    const gDbService = Cc["@mozilla.org/msgDatabase/msgDBService;1"]
-                         .getService(Ci.nsIMsgDBService);
-
     let idleLimit = Services.prefs.getIntPref("mail.db.idle_limit");
     let maxOpenDBs = Services.prefs.getIntPref("mail.db.max_open");
 
     // db.lastUseTime below is in microseconds while Date.now and idleLimit pref
     // is in milliseconds.
     let closeThreshold = (Date.now() - idleLimit) * 1000;
-    let cachedDBs = gDbService.openDBs;
-    log.info("periodic check of cached dbs, count=" + cachedDBs.length);
-    let numOpenDBs = 0;
+    let cachedDBs = this._dbService.openDBs;
+    log.info("Periodic check of cached folder databases (DBs), count=" + cachedDBs.length);
+    // Count databases that are already closed or get closed now due to inactivity.
+    let numClosing = 0;
+    // Count databases whose folder is open in a window.
+    let numOpenInWindow = 0;
+    let dbs = [];
     for (let i = 0; i < cachedDBs.length; i++) {
       let db = cachedDBs.queryElementAt(i, Ci.nsIMsgDatabase);
       if (!db.folder.databaseOpen) {
-        log.debug("skipping cachedDB not open in folder: " + db.folder.name);
+        // The DB isn't really open anymore.
+        log.debug("Skipping, DB not open for folder: " + db.folder.name);
+        numClosing++;
         continue;
       }
 
       if (MailServices.mailSession.IsFolderOpenInWindow(db.folder)) {
-        log.debug("folder open in window, name: " + db.folder.name);
-        numOpenDBs++;
+        // The folder is open in a window so this DB must not be closed.
+        log.debug("Skipping, DB open in window for folder: " + db.folder.name);
+        numOpenInWindow++;
         continue;
       }
+
       if (db.lastUseTime < closeThreshold)
       {
-        log.debug("closing expired msgDatabase for folder: " + db.folder.name);
+        // DB open too log without activity.
+        log.debug("Closing expired DB for folder: " + db.folder.name);
         db.folder.msgDatabase = null;
+        numClosing++;
+        continue;
       }
-      else
-        numOpenDBs++;
+
+      // Database eligible for closing.
+      dbs.push(db);
     }
-    cachedDBs = gDbService.openDBs;
-    log.info("open db count " + numOpenDBs);
-    if (numOpenDBs > maxOpenDBs) {
+    log.info("DBs open in a window: " + numOpenInWindow + ", DBs open: " + dbs.length + ", DBs already closing: " + numClosing);
+    let dbsToClose = Math.max(dbs.length - Math.max(maxOpenDBs - numOpenInWindow, 0), 0);
+    if (dbsToClose > 0) {
       // Close some DBs so that we do not have more than maxOpenDBs.
-      // However, we do not close DB for a folder that is open in a window
+      // However, we skipped DBs for folders that are open in a window
       // so if there are so many windows open, it may be possible for
       // more than maxOpenDBs folders to stay open after this loop.
-      let dbs = [];
-      for (let i = 0; i < cachedDBs.length; i++) {
-        let db = cachedDBs.queryElementAt(i, Ci.nsIMsgDatabase);
-        if (db.folder.databaseOpen)
-          dbs.push(db);
-      }
-      dbs.sort((a, b) => a.lastUseTime > b.lastUseTime);
-      let dbsToClose = dbs.length - maxOpenDBs;
-      if (dbsToClose > 0) {
-        log.info("trying to close " + dbsToClose + " databases");
-        for (let db of dbs) {
-          if (MailServices.mailSession.IsFolderOpenInWindow(db.folder))
-          {
-            log.debug("not closing db open in window, name: " + db.folder.name);
-            continue;
-          }
-          log.debug("closing db for folder: " + db.folder.name);
-          db.folder.msgDatabase = null;
-          if (--dbsToClose == 0)
-            break;
-        }
+      log.info("Need to close " + dbsToClose + " more DBs");
+      // Order databases by lowest lastUseTime (oldest) at the end.
+      dbs.sort((a, b) => b.lastUseTime - a.lastUseTime);
+      while (dbsToClose > 0) {
+        let db = dbs.pop();
+        log.debug("Closing DB for folder: " + db.folder.name);
+        db.folder.msgDatabase = null;
+        dbsToClose--;
       }
     }
   },
 };