167 lines, 73 LOC, 67 covered (91%)
10 | 1 | /* ***** BEGIN LICENSE BLOCK ***** |
2 | * Version: MPL 1.1/GPL 2.0/LGPL 2.1 |
|
3 | * |
|
4 | * The contents of this file are subject to the Mozilla Public License Version |
|
5 | * 1.1 (the "License"); you may not use this file except in compliance with |
|
6 | * the License. You may obtain a copy of the License at |
|
7 | * http://www.mozilla.org/MPL/ |
|
8 | * |
|
9 | * Software distributed under the License is distributed on an "AS IS" basis, |
|
10 | * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License |
|
11 | * for the specific language governing rights and limitations under the |
|
12 | * License. |
|
13 | * |
|
14 | * The Original Code is Bookmarks Sync. |
|
15 | * |
|
16 | * The Initial Developer of the Original Code is Mozilla. |
|
17 | * Portions created by the Initial Developer are Copyright (C) 2008 |
|
18 | * the Initial Developer. All Rights Reserved. |
|
19 | * |
|
20 | * Contributor(s): |
|
21 | * Anant Narayanan <anant@kix.in> |
|
22 | * |
|
23 | * Alternatively, the contents of this file may be used under the terms of |
|
24 | * either the GNU General Public License Version 2 or later (the "GPL"), or |
|
25 | * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), |
|
26 | * in which case the provisions of the GPL or the LGPL are applicable instead |
|
27 | * of those above. If you wish to allow use of your version of this file only |
|
28 | * under the terms of either the GPL or the LGPL, and not to allow others to |
|
29 | * use your version of this file under the terms of the MPL, indicate your |
|
30 | * decision by deleting the provisions above and replace them with the notice |
|
31 | * and other provisions required by the GPL or the LGPL. If you do not delete |
|
32 | * the provisions above, a recipient may use your version of this file under |
|
33 | * the terms of any one of the MPL, the GPL or the LGPL. |
|
34 | * |
|
35 | * ***** END LICENSE BLOCK ***** */ |
|
36 | ||
70 | 37 | const EXPORTED_SYMBOLS = ['Tracker']; |
38 | ||
40 | 39 | const Cc = Components.classes; |
40 | 40 | const Ci = Components.interfaces; |
40 | 41 | const Cr = Components.results; |
40 | 42 | const Cu = Components.utils; |
43 | ||
50 | 44 | Cu.import("resource://weave/log4moz.js"); |
50 | 45 | Cu.import("resource://weave/constants.js"); |
50 | 46 | Cu.import("resource://weave/util.js"); |
50 | 47 | Cu.import("resource://weave/ext/Observers.js"); |
48 | ||
49 | /* |
|
50 | * Trackers are associated with a single engine and deal with |
|
51 | * listening for changes to their particular data type. |
|
52 | * |
|
53 | * There are two things they keep track of: |
|
54 | * 1) A score, indicating how urgently the engine wants to sync |
|
55 | * 2) A list of IDs for all the changed items that need to be synced |
|
56 | * and updating their 'score', indicating how urgently they |
|
57 | * want to sync. |
|
58 | * |
|
59 | */ |
|
63 | 60 | function Tracker(name) { |
130 | 61 | name = name || "Unnamed"; |
301 | 62 | this.name = this.file = name.toLowerCase(); |
63 | ||
387 | 64 | this._log = Log4Moz.repository.getLogger("Tracker." + name); |
387 | 65 | let level = Svc.Prefs.get("log.logger.engine." + this.name, "Debug"); |
258 | 66 | this._log.level = Log4Moz.Level[level]; |
67 | ||
129 | 68 | this._score = 0; |
129 | 69 | this._ignored = []; |
129 | 70 | this.ignoreAll = false; |
172 | 71 | this.changedIDs = {}; |
215 | 72 | this.loadChangedIDs(); |
73 | } |
|
20 | 74 | Tracker.prototype = { |
75 | /* |
|
76 | * Score can be called as often as desired to decide which engines to sync |
|
77 | * |
|
78 | * Valid values for score: |
|
79 | * -1: Do not sync unless the user specifically requests it (almost disabled) |
|
80 | * 0: Nothing has changed |
|
81 | * 100: Please sync me ASAP! |
|
82 | * |
|
83 | * Setting it to other values should (but doesn't currently) throw an exception |
|
84 | */ |
|
239 | 85 | get score() { |
438 | 86 | return this._score; |
87 | }, |
|
88 | ||
224 | 89 | set score(value) { |
612 | 90 | this._score = value; |
1428 | 91 | Observers.notify("weave:engine:score:updated", this.name); |
92 | }, |
|
93 | ||
94 | // Should be called by service everytime a sync has been done for an engine |
|
29 | 95 | resetScore: function T_resetScore() { |
36 | 96 | this._score = 0; |
97 | }, |
|
98 | ||
2452 | 99 | saveChangedIDs: function T_saveChangedIDs() { |
7301 | 100 | Utils.delay(function() { |
50 | 101 | Utils.jsonSave("changes/" + this.file, this, this.changedIDs); |
14592 | 102 | }, 1000, this, "_lazySave"); |
103 | }, |
|
104 | ||
63 | 105 | loadChangedIDs: function T_loadChangedIDs() { |
394 | 106 | Utils.jsonLoad("changes/" + this.file, this, function(json) { |
28 | 107 | this.changedIDs = json; |
43 | 108 | }); |
109 | }, |
|
110 | ||
111 | // ignore/unignore specific IDs. Useful for ignoring items that are |
|
112 | // being processed, or that shouldn't be synced. |
|
113 | // But note: not persisted to disk |
|
114 | ||
50 | 115 | ignoreID: function T_ignoreID(id) { |
150 | 116 | this.unignoreID(id); |
210 | 117 | this._ignored.push(id); |
118 | }, |
|
119 | ||
50 | 120 | unignoreID: function T_unignoreID(id) { |
180 | 121 | let index = this._ignored.indexOf(id); |
90 | 122 | if (index != -1) |
30 | 123 | this._ignored.splice(index, 1); |
124 | }, |
|
125 | ||
2577 | 126 | addChangedID: function addChangedID(id, when) { |
7671 | 127 | if (!id) { |
128 | this._log.warn("Attempted to add undefined ID to tracker"); |
|
129 | return false; |
|
130 | } |
|
12785 | 131 | if (this.ignoreAll || (id in this._ignored)) |
132 | return false; |
|
133 | ||
134 | // Default to the current time in seconds if no time is provided |
|
7671 | 135 | if (when == null) |
1836 | 136 | when = Math.floor(Date.now() / 1000); |
137 | ||
138 | // Add/update the entry if we have a newer time |
|
20072 | 139 | if ((this.changedIDs[id] || -Infinity) < when) { |
24280 | 140 | this._log.trace("Adding changed ID: " + [id, when]); |
9712 | 141 | this.changedIDs[id] = when; |
9712 | 142 | this.saveChangedIDs(); |
143 | } |
|
5114 | 144 | return true; |
145 | }, |
|
146 | ||
23 | 147 | removeChangedID: function T_removeChangedID(id) { |
9 | 148 | if (!id) { |
149 | this._log.warn("Attempted to remove undefined ID to tracker"); |
|
150 | return false; |
|
151 | } |
|
15 | 152 | if (this.ignoreAll || (id in this._ignored)) |
153 | return false; |
|
15 | 154 | if (this.changedIDs[id] != null) { |
8 | 155 | this._log.trace("Removing changed ID " + id); |
4 | 156 | delete this.changedIDs[id]; |
4 | 157 | this.saveChangedIDs(); |
158 | } |
|
6 | 159 | return true; |
160 | }, |
|
161 | ||
53 | 162 | clearChangedIDs: function T_clearChangedIDs() { |
18 | 163 | this._log.trace("Clearing changed ID list"); |
12 | 164 | this.changedIDs = {}; |
15 | 165 | this.saveChangedIDs(); |
166 | } |
|
10 | 167 | }; |