author | Gregory Szorc <gps@mozilla.com> |
Fri, 09 Sep 2011 10:34:58 -0700 | |
changeset 78565 | cebcf93501983c32332ef712b32dcf271295b382 |
parent 78564 | 5e7a991c8305cc5a2f895923362e2832de5c414d |
child 78566 | cb70379936f3ecc1e598697400fd6c3b5ffe652a |
push id | 78 |
push user | clegnitto@mozilla.com |
push date | Fri, 16 Dec 2011 17:32:24 +0000 |
treeherder | mozilla-release@79d24e644fdd [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | philikon |
bugs | 685757 |
milestone | 9.0a1 |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
--- a/services/sync/modules/engines.js +++ b/services/sync/modules/engines.js @@ -176,19 +176,34 @@ Tracker.prototype = { this._log.trace("Clearing changed ID list"); this.changedIDs = {}; this.saveChangedIDs(); } }; -/* - * Data Stores - * These can wrap, serialize items and apply commands +/** + * The Store serves as the interface between Sync and stored data. + * + * The name "store" is slightly a misnomer because it doesn't actually "store" + * anything. Instead, it serves as a gateway to something that actually does + * the "storing." + * + * The store is responsible for record management inside an engine. It tells + * Sync what items are available for Sync, converts items to and from Sync's + * record format, and applies records from Sync into changes on the underlying + * store. + * + * Store implementations require a number of functions to be implemented. These + * are all documented below. + * + * For stores that deal with many records or which have expensive store access + * routines, it is highly recommended to implement a custom applyIncomingBatch + * and/or applyIncoming function on top of the basic APIs. */ function Store(name) { name = name || "Unnamed"; this.name = name.toLowerCase(); this._log = Log4Moz.repository.getLogger("Sync.Store." + name); let level = Svc.Prefs.get("log.logger.engine." + this.name, "Debug"); @@ -201,16 +216,31 @@ function Store(name) { Store.prototype = { _sleep: function _sleep(delay) { let cb = Async.makeSyncCallback(); this._timer.initWithCallback(cb, delay, Ci.nsITimer.TYPE_ONE_SHOT); Async.waitForSyncCallback(cb); }, + /** + * Apply multiple incoming records against the store. + * + * This is called with a set of incoming records to process. The function + * should look at each record, reconcile with the current local state, and + * make the local changes required to bring its state in alignment with the + * record. + * + * The default implementation simply iterates over all records and calls + * applyIncoming(). Store implementations may overwrite this function + * if desired. + * + * @param records Array of records to apply + * @return Array of record IDs which did not apply cleanly + */ applyIncomingBatch: function applyIncomingBatch(records) { let failed = []; for each (let record in records) { try { this.applyIncoming(record); } catch (ex if (ex.code == Engine.prototype.eEngineAbortApplyIncoming)) { // This kind of exception should have a 'cause' attribute, which is an // originating exception. @@ -220,55 +250,143 @@ Store.prototype = { this._log.warn("Failed to apply incoming record " + record.id); this._log.warn("Encountered exception: " + Utils.exceptionStr(ex)); failed.push(record.id); } }; return failed; }, + /** + * Apply a single record against the store. + * + * This takes a single record and makes the local changes required so the + * local state matches what's in the record. + * + * The default implementation calls one of remove(), create(), or update() + * depending on the state obtained from the store itself. Store + * implementations may overwrite this function if desired. + * + * @param record + * Record to apply + */ applyIncoming: function Store_applyIncoming(record) { if (record.deleted) this.remove(record); else if (!this.itemExists(record.id)) this.create(record); else this.update(record); }, // override these in derived objects + /** + * Create an item in the store from a record. + * + * This is called by the default implementation of applyIncoming(). If using + * applyIncomingBatch(), this won't be called unless your store calls it. + * + * @param record + * The store record to create an item from + */ create: function Store_create(record) { throw "override create in a subclass"; }, + /** + * Remove an item in the store from a record. + * + * This is called by the default implementation of applyIncoming(). If using + * applyIncomingBatch(), this won't be called unless your store calls it. + * + * @param record + * The store record to delete an item from + */ remove: function Store_remove(record) { throw "override remove in a subclass"; }, + /** + * Update an item from a record. + * + * This is called by the default implementation of applyIncoming(). If using + * applyIncomingBatch(), this won't be called unless your store calls it. + * + * @param record + * The record to use to update an item from + */ update: function Store_update(record) { throw "override update in a subclass"; }, + /** + * Determine whether a record with the specified ID exists. + * + * Takes a string record ID and returns a booleans saying whether the record + * exists. + * + * @param id + * string record ID + * @return boolean indicating whether record exists locally + */ itemExists: function Store_itemExists(id) { throw "override itemExists in a subclass"; }, + /** + * Create a record from the specified ID. + * + * If the ID is known, the record should be populated with metadata from + * the store. If the ID is not known, the record should be created with the + * delete field set to true. + * + * @param id + * string record ID + * @param collection + * Collection to add record to. This is typically passed into the + * constructor for the newly-created record. + * @return record type for this engine + */ createRecord: function Store_createRecord(id, collection) { throw "override createRecord in a subclass"; }, + /** + * Change the ID of a record. + * + * @param oldID + * string old/current record ID + * @param newID + * string new record ID + */ changeItemID: function Store_changeItemID(oldID, newID) { throw "override changeItemID in a subclass"; }, + /** + * Obtain the set of all known record IDs. + * + * @return Object with ID strings as keys and values of true. The values + * are ignored. + */ getAllIDs: function Store_getAllIDs() { throw "override getAllIDs in a subclass"; }, + /** + * Wipe all data in the store. + * + * This function is called during remote wipes or when replacing local data + * with remote data. + * + * This function should delete all local data that the store is managing. It + * can be thought of as clearing out all state and restoring the "new + * browser" state. + */ wipe: function Store_wipe() { throw "override wipe in a subclass"; } }; // Singleton service, holds registered engines