Bug 631001 - Password sync: apply records batched and in transactions to avoid fsyncs. r=mconnor a=blocking-fennec
authorPhilipp von Weitershausen <philipp@weitershausen.de>
Tue, 08 Feb 2011 20:37:06 -0800
changeset 62259 8d179f565e1bd9dea506bbb6734efd71db637fb9
parent 62258 80960bc75d8303248c91ccb8024348fd1fa59e5a
child 62260 8af41fd791c1968442ba08fe244306e7a2de5457
child 62261 8214fee0a3556f1c7d8be2558dc24c2e4e84f9c0
push id1
push userroot
push dateTue, 10 Dec 2013 15:46:25 +0000
reviewersmconnor, blocking-fennec
bugs631001
Bug 631001 - Password sync: apply records batched and in transactions to avoid fsyncs. r=mconnor a=blocking-fennec
services/sync/modules/constants.js
services/sync/modules/engines/passwords.js
--- a/services/sync/modules/constants.js
+++ b/services/sync/modules/constants.js
@@ -91,16 +91,17 @@ MASTER_PASSWORD_LOCKED_RETRY_INTERVAL: 1
 // 50 is hardcoded here because of URL length restrictions.
 // (GUIDs can be up to 64 chars long)
 MOBILE_BATCH_SIZE:                     50,
 
 // Default batch size for applying incoming records.
 DEFAULT_STORE_BATCH_SIZE:              1,
 HISTORY_STORE_BATCH_SIZE:              50, // same as MOBILE_BATCH_SIZE
 FORMS_STORE_BATCH_SIZE:                50, // same as MOBILE_BATCH_SIZE
+PASSWORDS_STORE_BATCH_SIZE:            50, // same as MOBILE_BATCH_SIZE
 
 // score thresholds for early syncs
 SINGLE_USER_THRESHOLD:                 1000,
 MULTI_DESKTOP_THRESHOLD:               500,
 MULTI_MOBILE_THRESHOLD:                100,
 
 // File IO Flags
 MODE_RDONLY:                           0x01,
--- a/services/sync/modules/engines/passwords.js
+++ b/services/sync/modules/engines/passwords.js
@@ -37,16 +37,17 @@
  *
  * ***** END LICENSE BLOCK ***** */
 
 const EXPORTED_SYMBOLS = ['PasswordEngine', 'LoginRec'];
 
 const Cu = Components.utils;
 const Cc = Components.classes;
 const Ci = Components.interfaces;
+const Cr = Components.results;
 
 Cu.import("resource://services-sync/record.js");
 Cu.import("resource://services-sync/constants.js");
 Cu.import("resource://services-sync/engines.js");
 Cu.import("resource://services-sync/util.js");
 
 function LoginRec(collection, id) {
   CryptoWrapper.call(this, collection, id);
@@ -63,16 +64,17 @@ Utils.deferGetSet(LoginRec, "cleartext",
 function PasswordEngine() {
   SyncEngine.call(this, "Passwords");
 }
 PasswordEngine.prototype = {
   __proto__: SyncEngine.prototype,
   _storeObj: PasswordStore,
   _trackerObj: PasswordTracker,
   _recordObj: LoginRec,
+  applyIncomingBatchSize: PASSWORDS_STORE_BATCH_SIZE,
 
   _syncFinish: function _syncFinish() {
     SyncEngine.prototype._syncFinish.call(this);
 
     // Delete the weave credentials from the server once
     if (!Svc.Prefs.get("deletePwd", false)) {
       try {
         let ids = Svc.Login.findLogins({}, PWDMGR_HOST, "", "").map(function(info)
@@ -104,16 +106,26 @@ PasswordEngine.prototype = {
         return local.guid;
   }
 };
 
 function PasswordStore(name) {
   Store.call(this, name);
   this._nsLoginInfo = new Components.Constructor(
     "@mozilla.org/login-manager/loginInfo;1", Ci.nsILoginInfo, "init");
+
+  Utils.lazy2(this, "DBConnection", function() {
+    try {
+      return Svc.Login.QueryInterface(Ci.nsIInterfaceRequestor)
+                      .getInterface(Ci.mozIStorageConnection);
+    } catch (ex if (ex.result == Cr.NS_ERROR_NO_INTERFACE)) {
+      // Gecko <2.0 *sadface*
+      return null;
+    }
+  });
 }
 PasswordStore.prototype = {
   __proto__: Store.prototype,
 
   _nsLoginInfoFromRecord: function PasswordStore__nsLoginInfoRec(record) {
     if (record.formSubmitURL &&
         record.httpRealm) {
       this._log.warn("Record " + record.id +
@@ -147,16 +159,26 @@ PasswordStore.prototype = {
       this._log.trace(logins.length + " items matching " + id + " found.");
       return logins[0];
     } else {
       this._log.trace("No items matching " + id + " found. Ignoring");
     }
     return false;
   },
 
+  applyIncomingBatch: function applyIncomingBatch(records) {
+    if (!this.DBConnection) {
+      return Store.prototype.applyIncomingBatch.call(this, records);
+    }
+
+    return Utils.runInTransaction(this.DBConnection, function() {
+      return Store.prototype.applyIncomingBatch.call(this, records);
+    }, this);
+  },
+
   getAllIDs: function PasswordStore__getAllIDs() {
     let items = {};
     let logins = Svc.Login.getAllLogins({});
 
     for (let i = 0; i < logins.length; i++) {
       // Skip over Weave password/passphrase entries
       let metaInfo = logins[i].QueryInterface(Ci.nsILoginMetaInfo);
       if (metaInfo.hostname == PWDMGR_HOST)