Bug 503964 - Have per-engine versioning to avoid wiping all engine data [r=mconnor]

Add an engines object to meta/global to track version and syncID for each engine. If the server is outdated, wipe the data and set a new version and syncID. If the client is oudated, ask for an upgrade. Differing syncIDs cause a reupload. All engines are right now the default version 1.
This commit is contained in:
Edward Lee 2010-03-25 10:05:21 -07:00
parent 1cd3c07303
commit e0f3625f3c
2 changed files with 62 additions and 5 deletions

View File

@ -295,8 +295,8 @@ function SyncEngine(name) {
}
SyncEngine.prototype = {
__proto__: Engine.prototype,
_recordObj: CryptoWrapper,
version: 1,
get storageURL() Svc.Prefs.get("clusterURL") + Svc.Prefs.get("storageAPI") +
"/" + ID.get("WeaveID").username + "/storage/",
@ -305,6 +305,17 @@ SyncEngine.prototype = {
get cryptoMetaURL() this.storageURL + "crypto/" + this.name,
get metaURL() this.storageURL + "meta/global",
get syncID() {
// Generate a random syncID if we don't have one
let syncID = Svc.Prefs.get(this.name + ".syncID", "");
return syncID == "" ? this.syncID = Utils.makeGUID() : syncID;
},
set syncID(value) {
Svc.Prefs.set(this.name + ".syncID", value);
},
get lastSync() {
return parseFloat(Svc.Prefs.get(this.name + ".lastSync", "0"));
},
@ -346,6 +357,42 @@ SyncEngine.prototype = {
_syncStartup: function SyncEngine__syncStartup() {
this._log.trace("Ensuring server crypto records are there");
// Determine if we need to wipe on outdated versions
let wipeServerData = false;
let metaGlobal = Records.get(this.metaURL);
let engines = metaGlobal.payload.engines || {};
let engineData = engines[this.name] || {};
// Assume missing versions are 0 and wipe the server
if ((engineData.version || 0) < this.version) {
this._log.debug("Old engine data: " + [engineData.version, this.version]);
// Prepare to clear the server and upload everything
wipeServerData = true;
this.syncID = "";
// Set the newer version and newly generated syncID
engineData.version = this.version;
engineData.syncID = this.syncID;
// Put the new data back into meta/global and mark for upload
engines[this.name] = engineData;
metaGlobal.payload.engines = engines;
metaGlobal.changed = true;
}
// Don't sync this engine if the server has newer data
else if (engineData.version > this.version) {
let error = new String("New data: " + [engineData.version, this.version]);
error.failureCode = VERSION_OUT_OF_DATE;
throw error;
}
// Changes to syncID mean we'll need to upload everything
else if (engineData.syncID != this.syncID) {
this._log.debug("Engine syncIDs: " + [engineData.syncID, this.syncID]);
this.syncID = engineData.syncID;
this._resetClient();
};
// Try getting/unwrapping the crypto record
let meta = CryptoMetas.get(this.cryptoMetaURL);
if (meta) {
@ -355,16 +402,20 @@ SyncEngine.prototype = {
meta.getKey(privkey, ID.get("WeaveCryptoID"));
}
catch(ex) {
// Remove traces of this bad cryptometa
// Remove traces of this bad cryptometa and tainted data
this._log.debug("Purging bad data after failed unwrap crypto: " + ex);
CryptoMetas.del(this.cryptoMetaURL);
meta = null;
// Remove any potentially tained data
new Resource(this.engineURL).delete();
wipeServerData = true;
}
}
// Delete all server data and reupload on bad version or meta
if (wipeServerData) {
new Resource(this.engineURL).delete();
this._resetClient();
}
// Generate a new crypto record
if (!meta) {
let symkey = Svc.Crypto.generateRandomKey();

View File

@ -1172,6 +1172,11 @@ WeaveSvc.prototype = {
}
}
// Upload meta/global if any engines changed anything
let meta = Records.get(this.metaURL);
if (meta.changed)
new Resource(meta.uri).put(meta);
if (this._syncError)
throw "Some engines did not sync correctly";
else {
@ -1246,6 +1251,7 @@ WeaveSvc.prototype = {
let resp = new Resource(meta.uri).put(meta);
if (!resp.success)
throw resp;
Records.set(meta.uri, meta);
// Wipe everything we know about except meta because we just uploaded it
let collections = [Clients].concat(Engines.getAll()).map(function(engine) {