Bug 1135291 - Update chat log entries added to Gloda since bug 955292 to use relative paths. r=aleth,asuth a=rkent
authorNihanth Subramanya <nhnt11@gmail.com>
Mon, 04 May 2015 22:18:45 +0530
changeset 26000 c3e582335241e9cf6c8c6d2769a5584fd40dcd75
parent 25999 6e77ddf85e80421188cc34c2ae304d28183997dd
child 26001 a74742812d519a6dc151f131b91ca1d90a54b5af
push id1850
push userclokep@gmail.com
push dateWed, 08 Mar 2017 19:29:12 +0000
treeherdercomm-esr52@028df196b2d9 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersaleth, asuth, rkent
bugs1135291, 955292
Bug 1135291 - Update chat log entries added to Gloda since bug 955292 to use relative paths. r=aleth,asuth a=rkent
mail/components/im/modules/index_im.js
--- a/mail/components/im/modules/index_im.js
+++ b/mail/components/im/modules/index_im.js
@@ -15,16 +15,18 @@ Cu.import("resource:///modules/iteratorU
 Cu.import("resource:///modules/mailServices.js");
 Cu.import("resource://gre/modules/FileUtils.jsm");
 Cu.import("resource://gre/modules/NetUtil.jsm");
 
 XPCOMUtils.defineLazyModuleGetter(this, "OS", "resource://gre/modules/osfile.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "Task", "resource://gre/modules/Task.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "AsyncShutdown",
                                   "resource://gre/modules/AsyncShutdown.jsm");
+XPCOMUtils.defineLazyModuleGetter(this, "GlodaDatastore",
+                                  "resource:///modules/gloda/datastore.js");
 
 const kCacheFileName = "indexedFiles.json";
 
 const FileInputStream = CC("@mozilla.org/network/file-input-stream;1",
                            "nsIFileInputStream",
                            "init");
 const ScriptableInputStream = CC("@mozilla.org/scriptableinputstream;1",
                                  "nsIScriptableInputStream",
@@ -229,16 +231,17 @@ Gloda.defineAttribute({
   facet: {
     type: "date"
   },
   canQuery: true
 });
 
 var GlodaIMIndexer = {
   name: "index_im",
+  cacheVersion: 1,
   enable: function() {
     Services.obs.addObserver(this, "conversation-closed", false);
     Services.obs.addObserver(this, "new-ui-conversation", false);
     Services.obs.addObserver(this, "ui-conversation-closed", false);
 
     // The shutdown blocker ensures pending saves happen even if the app
     // gets shut down before the timer fires.
     if (this._shutdownBlockerAdded)
@@ -277,16 +280,23 @@ var GlodaIMIndexer = {
     // overwrite it).
     if ("datastoreID" in data &&
         Gloda.datastoreID &&
         data.datastoreID === Gloda.datastoreID) {
       // Ok, the cache's datastoreID matches the one we expected, so it's
       // still valid.
       this._knownFiles = data.knownFiles;
     }
+
+    this.cacheVersion = data.version;
+
+    // If there was no version set on the cache, there is a chance that the index
+    // is affected by bug 1069845. fixEntriesWithAbsolutePaths() sets the version to 1.
+    if (!this.cacheVersion)
+      this.fixEntriesWithAbsolutePaths();
   },
   disable: function() {
     Services.obs.removeObserver(this, "conversation-closed");
     Services.obs.removeObserver(this, "new-ui-conversation");
     Services.obs.removeObserver(this, "ui-conversation-closed");
   },
 
   /* _knownFiles is a tree whose leaves are the last modified times of
@@ -310,16 +320,17 @@ var GlodaIMIndexer = {
     this._cacheSaveTimer = setTimeout(this._saveCacheNow, 5000);
   },
   _saveCacheNow: function() {
     GlodaIMIndexer._cacheSaveTimer = null;
 
     let data = {
       knownFiles: GlodaIMIndexer._knownFiles,
       datastoreID: Gloda.datastoreID,
+      version: GlodaIMIndexer.cacheVersion
     };
 
     // Asynchronously copy the data to the file.
     let path = OS.Path.join(OS.Constants.Path.profileDir, "logs", kCacheFileName);
     return OS.File.writeAtomic(path, JSON.stringify(data),
                                {encoding: "utf-8", tmpPath: path + ".tmp"})
              .catch(aError => Cu.reportError("Failed to write cache file: " + aError));
   },
@@ -651,12 +662,61 @@ var GlodaIMIndexer = {
          worker: this._worker_convFolderSweep
        }]
     ];
   },
 
   initialSweep: function() {
     let job = new IndexingJob("logsFolderSweep", null);
     GlodaIndexer.indexJob(job);
+  },
+
+  // Due to bug 1069845, some logs were indexed against their full paths instead
+  // of their path relative to the logs directory. These entries are updated to
+  // use relative paths below.
+  fixEntriesWithAbsolutePaths: function() {
+    let store = GlodaDatastore;
+    let selectStatement = store._createAsyncStatement(
+      "SELECT id, path FROM imConversations");
+    let updateStatement = store._createAsyncStatement(
+      "UPDATE imConversations SET path = ?1 WHERE id = ?2");
+
+    store._beginTransaction();
+    selectStatement.executeAsync({
+      handleResult: aResultSet => {
+        let row;
+        while ((row = aResultSet.getNextRow())) {
+          // If the path has more than 4 components, it is not relative to
+          // the logs folder. Update it to use only the last 4 components.
+          // The absolute paths were stored as OS-specific paths, so we split
+          // them with OS.Path.split(). It's a safe assumption that nobody
+          // ported their profile folder to a different OS since the regression,
+          // so this should work.
+          let pathComponents = OS.Path.split(row.getString(1)).components;
+          if (pathComponents.length > 4) {
+            updateStatement.bindInt64Parameter(1, row.getInt64(0)); // id
+            updateStatement.bindStringParameter(0,
+              pathComponents.slice(-4).join("/")); // Last 4 path components
+            updateStatement.executeAsync({
+              handleResult: () => {},
+              handleError: aError =>
+                Cu.reportError("Error updating bad entry:\n" + aError),
+              handleCompletion: () => {}
+            });
+          }
+        }
+      },
+
+      handleError: aError =>
+        Cu.reportError("Error looking for bad entries:\n" + aError),
+
+      handleCompletion: () => {
+        store.runPostCommit(() => {
+          this.cacheVersion = 1;
+          this._scheduleCacheSave();
+        });
+        store._commitTransaction();
+      }
+    });
   }
 };
 
 GlodaIndexer.registerIndexer(GlodaIMIndexer);