re-enable tracker in the first-sync case just to add all the guids; add some debugging messages; when reconciling throw out records which are identical on the client and server (even if we thought they had changed)
authorDan Mills <thunder@mozilla.com>
Fri, 05 Dec 2008 03:28:17 -0800
changeset 45084 63bc16770eba3b3f6ddbb297380e3ffe290037c0
parent 45083 e1d3a8cfd970ec17fdf9c195ddb07e5b81c4db45
child 45085 c94b8dad69eca2c395e3cd1cac52feeaba4138e2
push idunknown
push userunknown
push dateunknown
re-enable tracker in the first-sync case just to add all the guids; add some debugging messages; when reconciling throw out records which are identical on the client and server (even if we thought they had changed)
services/sync/modules/engines.js
--- a/services/sync/modules/engines.js
+++ b/services/sync/modules/engines.js
@@ -399,18 +399,21 @@ SyncEngine.prototype = {
     let self = yield;
 
     this._log.debug("Calculating client changes");
 
     // first sync special case: upload all items
     if (!this.lastSync) {
       this._log.info("First sync, uploading all items");
       let all = yield this._getAllIDs.async(this, self.cb);
-      for (let key in all)
+      this._tracker.enable();
+      for (let key in all) {
         this._tracker.addChangedID(key);
+      }
+      this._tracker.disable();
     }
 
     // generate queue from changed items list
     // NOTE we want changed items -> outgoing -> server to be as atomic as
     // possible, so we clear the changed IDs after we upload the changed records
     // NOTE2 don't encrypt, we'll do that before uploading instead
     for (let id in this._tracker.changedIDs) {
       this.outgoing.push(yield this._createRecord.async(this, self.cb, id, false));
@@ -476,26 +479,36 @@ SyncEngine.prototype = {
   // bookmarks imported, every bookmark will match this condition.
   // When two items with different IDs are "the same" we change the local ID to
   // match the remote one.
   _reconcile: function SyncEngine__reconcile() {
     let self = yield;
 
     this._log.debug("Reconciling server/client changes");
 
+    this._log.debug(this.incoming.length + " items coming in, " +
+                    this.outgoing.length + " items going out");
+
     // Check for the same item (same ID) on both incoming & outgoing queues
     let conflicts = [];
     for (let i = 0; i < this.incoming.length; i++) {
-      for each (let out in this.outgoing) {
-        if (this.incoming[i].id == out.id) {
-          conflicts.push({in: this.incoming[i], out: out});
+      for (let o = 0; o < this.outgoing.length; o++) {
+        if (this.incoming[i].id == this.outgoing[o].id) {
+          // Only consider it a conflict if there are actual differences
+          // otherwise, just remove the outgoing record as well
+          if (!Utils.deepEquals(this.incoming[i].cleartext,
+                                this.outgoing[o].cleartext))
+            conflicts.push({in: this.incoming[i], out: this.outgoing[o]});
+          else
+            delete this.outgoing[o];
           delete this.incoming[i];
           break;
         }
       }
+      this._outgoing = this.outgoing.filter(function(n) n); // removes any holes
     }
     this._incoming = this.incoming.filter(function(n) n); // removes any holes
     if (conflicts.length)
       this._log.debug("Conflicts found.  Conflicting server changes discarded");
 
     // Check for items with different IDs which we think are the same one
     for (let i = 0; i < this.incoming.length; i++) {
       for (let o = 0; o < this.outgoing.length; o++) {
@@ -511,16 +524,20 @@ SyncEngine.prototype = {
           delete this.incoming[i];
           delete this.outgoing[o];
           break;
         }
       }
       this._outgoing = this.outgoing.filter(function(n) n); // removes any holes
     }
     this._incoming = this.incoming.filter(function(n) n); // removes any holes
+
+    this._log.debug("Reconciliation complete");
+    this._log.debug(this.incoming.length + " items coming in, " +
+                    this.outgoing.length + " items going out");
   },
 
   // Apply incoming records
   _applyIncoming: function SyncEngine__applyIncoming() {
     let self = yield;
     if (this.incoming.length) {
       this._log.debug("Applying server changes");
       let inc;
@@ -547,17 +564,17 @@ SyncEngine.prototype = {
       if (up.data.modified > this.lastSync)
         this.lastSync = up.data.modified;
     }
     this._tracker.clearChangedIDs();
   },
 
   // Any cleanup necessary.
   // Save the current snapshot so as to calculate changes at next sync
-  _syncFinish: function SyncEngine__syncFinish() {
+  _syncFinish: function SyncEngine__syncFinish(error) {
     let self = yield;
     this._log.debug("Finishing up sync");
     this._tracker.resetScore();
     this._tracker.enable();
   },
 
   _sync: function SyncEngine__sync() {
     let self = yield;
@@ -571,22 +588,25 @@ SyncEngine.prototype = {
 
       // Decrypt and sort incoming records, then reconcile
       yield this._processIncoming.async(this, self.cb);
       yield this._reconcile.async(this, self.cb);
 
       // Apply incoming records, upload outgoing records
       yield this._applyIncoming.async(this, self.cb);
       yield this._uploadOutgoing.async(this, self.cb);
+
+      yield this._syncFinish.async(this, self.cb);
     }
     catch (e) {
+      this._log.warn("Sync failed");
       throw e;
     }
     finally {
-      yield this._syncFinish.async(this, self.cb);
+      this._tracker.enable();
     }
   },
 
   _resetServer: function SyncEngine__resetServer() {
     let self = yield;
     let all = new Resource(this.engineURL);
     yield all.delete(self.cb);
   }