1 /* |
1 /* |
2 * Modelled Trace API |
2 * Modelled Trace API |
3 */ |
3 */ |
4 IriSP.TraceManager = function($) { |
4 IriSP.TraceManager = function($) { |
5 /* |
5 // If there are more than MAX_FAILURE_COUNT synchronisation |
6 * FIXME: Write proper representation functions (str, json, ...) |
6 // failures, then disable synchronisation |
7 */ |
7 MAX_FAILURE_COUNT = 20; |
|
8 |
|
9 // If there are more than MAX_BUFFER_SIZE obsels in the buffer, |
|
10 // then "compress" them as a single "ktbsFullBuffer" |
|
11 MAX_BUFFER_SIZE = 500; |
8 |
12 |
9 var BufferedService_prototype = { |
13 var BufferedService_prototype = { |
10 /* |
14 /* |
11 * Buffered service for traces |
15 * Buffered service for traces |
12 */ |
16 */ |
13 // url: "", |
17 // url: "", |
14 // buffer: [], |
18 // buffer: [], |
15 // isReady: false, |
19 // isReady: false, |
16 // timer: null, |
20 // timer: null, |
|
21 // failureCount: 0, |
17 |
22 |
18 /* Flush buffer */ |
23 /* Flush buffer */ |
19 flush: function() { |
24 flush: function() { |
20 // FIXME: should add a counter to avoid starving the sync |
|
21 // process in case of too many generated obsels. |
|
22 // FIXME: add mutex on this.buffer |
25 // FIXME: add mutex on this.buffer |
23 if (! this.isReady) |
26 if (! this.isReady) |
24 { |
27 { |
25 console.log("Sync service not ready"); |
28 if (window.console) window.console.log("Sync service not ready"); |
|
29 } else if (this.failureCount > MAX_FAILURE_COUNT) |
|
30 { |
|
31 // Disable synchronisation |
|
32 this.set_sync_mode('none'); |
26 } else if (this.buffer.length) { |
33 } else if (this.buffer.length) { |
27 var temp = this.buffer; |
34 var temp = this.buffer; |
28 this.buffer = []; |
35 this.buffer = []; |
29 |
36 |
30 if (this.mode == 'GET') |
37 if (this.mode == 'GET') |
32 // GET mode: do some data mangline. We mark the |
39 // GET mode: do some data mangline. We mark the |
33 // "compressed" nature of the generated JSON by |
40 // "compressed" nature of the generated JSON by |
34 // prefixing it with c |
41 // prefixing it with c |
35 var data = 'c' + JSON.stringify(temp.map(function (o) { return o.toCompactJSON(); })); |
42 var data = 'c' + JSON.stringify(temp.map(function (o) { return o.toCompactJSON(); })); |
36 // Swap " (very frequent, which will be |
43 // Swap " (very frequent, which will be |
37 // serialized into %22) and / (rather rare), this |
44 // serialized into %22) and ; (rather rare), this |
38 // saves some bytes |
45 // saves some bytes |
39 data = data.replace(/[\/"]/g, function(s){ return s == '/' ? '"' : '/'; }).replace('#','%23'); |
46 data = data.replace(/[;"]/g, function(s){ return s == ';' ? '"' : ';'; }).replace(/#/g, '%23'); |
40 // FIXME: check data length (< 2K is safe) |
47 // FIXME: check data length (< 2K is safe) |
41 var request=$('<img/>').attr('src', this.url + 'trace/?data=' + data); |
48 var request=$('<img />').error( function() { this.failureCount += 1; }) |
|
49 .load( function() { this.failureCount = 0; }) |
|
50 .attr('src', this.url + 'trace/?data=' + data); |
42 } |
51 } |
43 else |
52 else |
44 { |
53 { |
45 $.ajax({ url: this.url + 'trace/', |
54 $.ajax({ url: this.url + 'trace/', |
46 type: 'POST', |
55 type: 'POST', |
48 data: JSON.stringify(temp.map(function (o) { return o.toJSON(); })), |
57 data: JSON.stringify(temp.map(function (o) { return o.toJSON(); })), |
49 processData: false, |
58 processData: false, |
50 // Type of the returned data. |
59 // Type of the returned data. |
51 dataType: "html", |
60 dataType: "html", |
52 error: function(jqXHR, textStatus, errorThrown) { |
61 error: function(jqXHR, textStatus, errorThrown) { |
53 // FIXME: not called for JSONP/crossdomain |
62 if (window.console) window.console.log("Error when sending buffer:", textStatus); |
54 console.log("Error when sending buffer:", textStatus); |
63 this.failureCount += 1; |
55 }, |
64 }, |
56 success: function(data, textStatus, jqXHR) { |
65 success: function(data, textStatus, jqXHR) { |
57 // FIXME: parse the returned JSON, and get |
66 // Reset failureCount to 0 as soon as there is 1 valid answer |
58 // the updated properties (id, uri...) to apply them to temp items |
67 this.failureCount = 0; |
59 } |
68 } |
60 }); |
69 }); |
61 } |
70 } |
62 } |
71 } |
63 }, |
72 }, |
64 |
73 |
|
74 /* Sync mode: delayed, sync (immediate sync), none (no |
|
75 * synchronisation with server, the trace has to be explicitly saved |
|
76 * if needed */ |
|
77 set_sync_mode: function(mode) { |
|
78 this.sync_mode = mode; |
|
79 if (! this.isReady && mode !== "none") |
|
80 this.init(); |
|
81 if (mode == 'delayed') { |
|
82 this.start_timer(); |
|
83 } else { |
|
84 this.stop_timer(); |
|
85 } |
|
86 }, |
|
87 |
65 /* Enqueue an obsel */ |
88 /* Enqueue an obsel */ |
66 enqueue: function(obsel) { |
89 enqueue: function(obsel) { |
|
90 if (this.buffer.length > MAX_BUFFER_SIZE) |
|
91 { |
|
92 obsel = new Obsel('ktbsFullBuffer', this.buffer[0].begin, |
|
93 this.buffer[this.buffer.length - 1].end, this.buffer[0].subject); |
|
94 obsel.trace = this.buffer[0].trace; |
|
95 this.buffer = []; |
|
96 } |
67 this.buffer.push(obsel); |
97 this.buffer.push(obsel); |
|
98 if (this.sync_mode === 'sync') { |
|
99 // Immediate sync of the obsel. |
|
100 this.flush(); |
|
101 } |
68 }, |
102 }, |
69 |
103 |
70 start_timer: function() { |
104 start_timer: function() { |
71 var self = this; |
105 var self = this; |
72 if (this.timer === null) { |
106 if (this.timer === null) { |
73 this.timer = window.setInterval(function() { |
107 this.timer = window.setInterval(function() { |
74 console.log("Flushing timeout"); |
|
75 self.flush(); |
108 self.flush(); |
76 }, this.timeOut); |
109 }, this.timeOut); |
77 } |
110 } |
78 }, |
111 }, |
79 |
112 |
118 var BufferedService = function(url, mode) { |
151 var BufferedService = function(url, mode) { |
119 this.url = url; |
152 this.url = url; |
120 this.buffer = []; |
153 this.buffer = []; |
121 this.isReady = false; |
154 this.isReady = false; |
122 this.timer = null; |
155 this.timer = null; |
|
156 this.failureCount = 0; |
|
157 // sync_mode is either "none", "sync" or "buffered" |
|
158 this.sync_mode = "none"; |
123 /* mode can be either POST or GET */ |
159 /* mode can be either POST or GET */ |
124 if (mode == 'POST' || mode == 'GET') |
160 if (mode == 'POST' || mode == 'GET') |
125 this.mode = mode; |
161 this.mode = mode; |
126 else |
162 else |
127 this.mode = 'POST'; |
163 this.mode = 'POST'; |
135 http://closure-library.googlecode.com/svn/docs/class_goog_structs_AvlTree.html |
171 http://closure-library.googlecode.com/svn/docs/class_goog_structs_AvlTree.html |
136 to speed up queries based on time */ |
172 to speed up queries based on time */ |
137 obsels: [], |
173 obsels: [], |
138 /* Trace URI */ |
174 /* Trace URI */ |
139 uri: "", |
175 uri: "", |
140 sync_mode: "none", |
|
141 default_subject: "", |
176 default_subject: "", |
142 /* baseuri is used as the base URI to resolve relative |
177 /* baseuri is used as the base URI to resolve relative |
143 * attribute-type names in obsels. Strictly speaking, this |
178 * attribute-type names in obsels. Strictly speaking, this |
144 * should rather be expressed as a reference to model, or |
179 * should rather be expressed as a reference to model, or |
145 * more generically, as a qname/URI dict */ |
180 * more generically, as a qname/URI dict */ |
157 |
192 |
158 /* Sync mode: delayed, sync (immediate sync), none (no |
193 /* Sync mode: delayed, sync (immediate sync), none (no |
159 * synchronisation with server, the trace has to be explicitly saved |
194 * synchronisation with server, the trace has to be explicitly saved |
160 * if needed */ |
195 * if needed */ |
161 set_sync_mode: function(mode) { |
196 set_sync_mode: function(mode) { |
162 this.sync_mode = mode; |
197 if (this.syncservice !== null) { |
163 if (this.syncservice != null) { |
198 this.syncservice.set_sync_mode(mode); |
164 if (mode !== 'none') { |
|
165 this.syncservice.init(); |
|
166 } |
|
167 if (mode == 'delayed') { |
|
168 this.syncservice.start_timer(); |
|
169 } else { |
|
170 this.syncservice.stop_timer(); |
|
171 } |
|
172 } |
199 } |
173 }, |
200 }, |
174 |
201 |
175 /* |
202 /* |
176 * Return a list of the obsels of this trace matching the parameters |
203 * Return a list of the obsels of this trace matching the parameters |
235 if (typeof _attributes !== 'undefined') { |
262 if (typeof _attributes !== 'undefined') { |
236 o.attributes = _attributes; |
263 o.attributes = _attributes; |
237 } |
264 } |
238 o.trace = this; |
265 o.trace = this; |
239 this.obsels.push(o); |
266 this.obsels.push(o); |
240 if (this.syncservice !== null && this.sync_mode != 'none') { |
267 if (this.syncservice !== null) |
241 this.syncservice.enqueue(o); |
268 this.syncservice.enqueue(o); |
242 if (this.sync_mode === 'sync') { |
269 }, |
243 // Immediate sync of the obsel. |
270 |
244 this.syncservice.flush(); |
|
245 } |
|
246 } |
|
247 }, |
|
248 |
|
249 obselProbe : function(element, bindingEvent, ObselFunction) { |
|
250 console.log("!!!!!!!!- ICI -!!!!!!!!!"); |
|
251 console.log(element); |
|
252 console.log(bindingEvent); |
|
253 console.log(ObselFunction); |
|
254 |
|
255 //var myOPI = self.setInterval("ObselProbeInterval("+element+","+bindingEvent+","+ObselFunction+")",1000); |
|
256 var myOPI = self.setInterval("ObselProbeInterval("+element+")",1000); |
|
257 //var ObselProbeInterval = function(element, bindingEvent, ObselFunction){ |
|
258 var ObselProbeInterval = function(element) { |
|
259 console.log("!!!!!!!!- ObselProbeInterval -!!!!!!!!!"); |
|
260 console.log($(element).length); |
|
261 /* |
|
262 if($(element).length!=0){ |
|
263 $(element).bind(bindingEvent, ObselFunction ); |
|
264 this.clearInterval(); |
|
265 }else{ console.log("!!!!!!!!- EXISTE PAS -!!!!!!!!!") |
|
266 } |
|
267 */ |
|
268 // |
|
269 }; |
|
270 |
|
271 }, |
|
272 /* Helper methods */ |
271 /* Helper methods */ |
273 |
272 |
274 /* Create a new obsel with the given attributes */ |
273 /* Create a new obsel with the given attributes */ |
275 trace: function(type, _attributes, _begin, _end, _subject) { |
274 trace: function(type, _attributes, _begin, _end, _subject) { |
276 var t = (new Date()).getTime(); |
275 var t = (new Date()).getTime(); |
432 * Use predefined + custom shorthands for types/properties |
431 * Use predefined + custom shorthands for types/properties |
433 */ |
432 */ |
434 toCompactJSON: function() { |
433 toCompactJSON: function() { |
435 var r = { |
434 var r = { |
436 "@i": this.id, |
435 "@i": this.id, |
437 "@t": (this.trace.shorthands.hasOwnProperty(this.type) |
436 "@t": (this.trace.shorthands.hasOwnProperty(this.type) ? this.trace.shorthands[this.type] : this.type), |
438 ? this.trace.shorthands[this.type] : this.type), |
|
439 "@b": this.begin, |
437 "@b": this.begin, |
440 "@e": this.end, |
|
441 "@s": this.subject |
438 "@s": this.subject |
442 }; |
439 }; |
|
440 // Store duration (to save some bytes) and only if it is non-null |
|
441 if (this.begin !== this.end) |
|
442 r["@d"] = this.end - this.begin; |
|
443 |
443 for (var prop in this.attributes) { |
444 for (var prop in this.attributes) { |
444 var v = this.attributes[prop]; |
445 if (this.hasOwnProperty(prop)) |
445 r[prop] = this.trace.shorthands.hasOwnProperty(v) ? this.trace.shorthands[v] : v; |
446 { |
|
447 var v = this.attributes[prop]; |
|
448 r[prop] = this.trace.shorthands.hasOwnProperty(v) ? this.trace.shorthands[v] : v; |
|
449 } |
446 } |
450 } |
447 return r; |
451 return r; |
448 }, |
452 }, |
449 |
453 |
450 toJSONstring: function() { |
454 toJSONstring: function() { |
483 * |
487 * |
484 * If another existed with the same name before, then it is replaced by a new one. |
488 * If another existed with the same name before, then it is replaced by a new one. |
485 */ |
489 */ |
486 init_trace: function(name, params) |
490 init_trace: function(name, params) |
487 { |
491 { |
488 console.log("init_trace", params); |
492 if (window.console) window.console.log("init_trace", params); |
489 url = params.url ? params.url : ""; |
493 url = params.url ? params.url : ""; |
490 requestmode = params.requestmode ? params.requestmode : "POST"; |
494 requestmode = params.requestmode ? params.requestmode : "POST"; |
491 syncmode = params.syncmode ? params.syncmode : "none"; |
495 syncmode = params.syncmode ? params.syncmode : "none"; |
|
496 default_subject = params.default_subject ? params.default_subject : "default"; |
492 var t = new Trace(url, requestmode); |
497 var t = new Trace(url, requestmode); |
493 t.set_sync_mode(syncmode); |
498 t.set_sync_mode(syncmode); |
|
499 t.set_default_subject(default_subject); |
494 this.traces[name] = t; |
500 this.traces[name] = t; |
495 return t; |
501 return t; |
496 } |
502 } |
497 }; |
503 }; |
498 |
504 |
499 var TraceManager = function() { |
505 var TraceManager = function() { |
500 this.traces = {}; |
506 this.traces = {}; |
501 }; |
507 }; |
502 TraceManager.prototype = TraceManager_prototype; |
508 TraceManager.prototype = TraceManager_prototype; |
503 |
509 |
504 return new TraceManager(); |
510 var tracemanager = new TraceManager(); |
|
511 return tracemanager; |
505 }; |
512 }; |