diff -r ac66e2240e1e -r 8da49ff273e0 src/js/libs/tracemanager.js --- a/src/js/libs/tracemanager.js Fri Mar 30 18:00:26 2012 +0200 +++ b/src/js/libs/tracemanager.js Tue Apr 03 20:30:12 2012 +0200 @@ -2,9 +2,13 @@ * Modelled Trace API */ IriSP.TraceManager = function($) { - /* - * FIXME: Write proper representation functions (str, json, ...) - */ + // If there are more than MAX_FAILURE_COUNT synchronisation + // failures, then disable synchronisation + MAX_FAILURE_COUNT = 20; + + // If there are more than MAX_BUFFER_SIZE obsels in the buffer, + // then "compress" them as a single "ktbsFullBuffer" + MAX_BUFFER_SIZE = 500; var BufferedService_prototype = { /* @@ -14,15 +18,18 @@ // buffer: [], // isReady: false, // timer: null, + // failureCount: 0, /* Flush buffer */ flush: function() { - // FIXME: should add a counter to avoid starving the sync - // process in case of too many generated obsels. // FIXME: add mutex on this.buffer if (! this.isReady) { - console.log("Sync service not ready"); + if (window.console) window.console.log("Sync service not ready"); + } else if (this.failureCount > MAX_FAILURE_COUNT) + { + // Disable synchronisation + this.set_sync_mode('none'); } else if (this.buffer.length) { var temp = this.buffer; this.buffer = []; @@ -34,11 +41,13 @@ // prefixing it with c var data = 'c' + JSON.stringify(temp.map(function (o) { return o.toCompactJSON(); })); // Swap " (very frequent, which will be - // serialized into %22) and / (rather rare), this + // serialized into %22) and ; (rather rare), this // saves some bytes - data = data.replace(/[\/"]/g, function(s){ return s == '/' ? '"' : '/'; }).replace('#','%23'); + data = data.replace(/[;"]/g, function(s){ return s == ';' ? '"' : ';'; }).replace(/#/g, '%23'); // FIXME: check data length (< 2K is safe) - var request=$('').attr('src', this.url + 'trace/?data=' + data); + var request=$('').error( function() { this.failureCount += 1; }) + .load( function() { this.failureCount = 0; }) + .attr('src', this.url + 'trace/?data=' + data); } else { @@ -50,28 +59,52 @@ // Type of the returned data. dataType: "html", error: function(jqXHR, textStatus, errorThrown) { - // FIXME: not called for JSONP/crossdomain - console.log("Error when sending buffer:", textStatus); + if (window.console) window.console.log("Error when sending buffer:", textStatus); + this.failureCount += 1; }, success: function(data, textStatus, jqXHR) { - // FIXME: parse the returned JSON, and get - // the updated properties (id, uri...) to apply them to temp items + // Reset failureCount to 0 as soon as there is 1 valid answer + this.failureCount = 0; } }); } } }, + /* Sync mode: delayed, sync (immediate sync), none (no + * synchronisation with server, the trace has to be explicitly saved + * if needed */ + set_sync_mode: function(mode) { + this.sync_mode = mode; + if (! this.isReady && mode !== "none") + this.init(); + if (mode == 'delayed') { + this.start_timer(); + } else { + this.stop_timer(); + } + }, + /* Enqueue an obsel */ enqueue: function(obsel) { + if (this.buffer.length > MAX_BUFFER_SIZE) + { + obsel = new Obsel('ktbsFullBuffer', this.buffer[0].begin, + this.buffer[this.buffer.length - 1].end, this.buffer[0].subject); + obsel.trace = this.buffer[0].trace; + this.buffer = []; + } this.buffer.push(obsel); + if (this.sync_mode === 'sync') { + // Immediate sync of the obsel. + this.flush(); + } }, start_timer: function() { var self = this; if (this.timer === null) { this.timer = window.setInterval(function() { - console.log("Flushing timeout"); self.flush(); }, this.timeOut); } @@ -120,6 +153,9 @@ this.buffer = []; this.isReady = false; this.timer = null; + this.failureCount = 0; + // sync_mode is either "none", "sync" or "buffered" + this.sync_mode = "none"; /* mode can be either POST or GET */ if (mode == 'POST' || mode == 'GET') this.mode = mode; @@ -137,7 +173,6 @@ obsels: [], /* Trace URI */ uri: "", - sync_mode: "none", default_subject: "", /* baseuri is used as the base URI to resolve relative * attribute-type names in obsels. Strictly speaking, this @@ -159,16 +194,8 @@ * synchronisation with server, the trace has to be explicitly saved * if needed */ set_sync_mode: function(mode) { - this.sync_mode = mode; - if (this.syncservice != null) { - if (mode !== 'none') { - this.syncservice.init(); - } - if (mode == 'delayed') { - this.syncservice.start_timer(); - } else { - this.syncservice.stop_timer(); - } + if (this.syncservice !== null) { + this.syncservice.set_sync_mode(mode); } }, @@ -237,38 +264,10 @@ } o.trace = this; this.obsels.push(o); - if (this.syncservice !== null && this.sync_mode != 'none') { + if (this.syncservice !== null) this.syncservice.enqueue(o); - if (this.sync_mode === 'sync') { - // Immediate sync of the obsel. - this.syncservice.flush(); - } - } }, - obselProbe : function(element, bindingEvent, ObselFunction) { - console.log("!!!!!!!!- ICI -!!!!!!!!!"); - console.log(element); - console.log(bindingEvent); - console.log(ObselFunction); - - //var myOPI = self.setInterval("ObselProbeInterval("+element+","+bindingEvent+","+ObselFunction+")",1000); - var myOPI = self.setInterval("ObselProbeInterval("+element+")",1000); - //var ObselProbeInterval = function(element, bindingEvent, ObselFunction){ - var ObselProbeInterval = function(element) { - console.log("!!!!!!!!- ObselProbeInterval -!!!!!!!!!"); - console.log($(element).length); - /* - if($(element).length!=0){ - $(element).bind(bindingEvent, ObselFunction ); - this.clearInterval(); - }else{ console.log("!!!!!!!!- EXISTE PAS -!!!!!!!!!") - } - */ - // - }; - - }, /* Helper methods */ /* Create a new obsel with the given attributes */ @@ -320,7 +319,6 @@ * purposes. They MUST be defined in the constructor * function. */ trace: undefined, - obselProbe: undefined, type: undefined, begin: undefined, end: undefined, @@ -334,7 +332,6 @@ }, get_obsel_type: function() { - /* FIXME: maybe we should return a ObselType object. In the meantime, return the URI */ return this.type; }, get_begin: function() { @@ -350,7 +347,8 @@ list_attribute_types: function() { var result = []; for (var prop in this.attributes) { - result.push(prop); + if (this.hasOwnProperty(prop)) + result.push(prop); } /* FIXME: we return URIs here instead of AttributeType elements */ return result; @@ -422,7 +420,8 @@ "subject": this.subject }; for (var prop in this.attributes) { - r[prop] = this.attributes[prop]; + if (this.hasOwnProperty(prop)) + r[prop] = this.attributes[prop]; } return r; }, @@ -434,15 +433,20 @@ toCompactJSON: function() { var r = { "@i": this.id, - "@t": (this.trace.shorthands.hasOwnProperty(this.type) - ? this.trace.shorthands[this.type] : this.type), + "@t": (this.trace.shorthands.hasOwnProperty(this.type) ? this.trace.shorthands[this.type] : this.type), "@b": this.begin, - "@e": this.end, "@s": this.subject }; + // Store duration (to save some bytes) and only if it is non-null + if (this.begin !== this.end) + r["@d"] = this.end - this.begin; + for (var prop in this.attributes) { - var v = this.attributes[prop]; - r[prop] = this.trace.shorthands.hasOwnProperty(v) ? this.trace.shorthands[v] : v; + if (this.hasOwnProperty(prop)) + { + var v = this.attributes[prop]; + r[prop] = this.trace.shorthands.hasOwnProperty(v) ? this.trace.shorthands[v] : v; + } } return r; }, @@ -485,12 +489,14 @@ */ init_trace: function(name, params) { - console.log("init_trace", params); + if (window.console) window.console.log("init_trace", params); url = params.url ? params.url : ""; requestmode = params.requestmode ? params.requestmode : "POST"; syncmode = params.syncmode ? params.syncmode : "none"; + default_subject = params.default_subject ? params.default_subject : "default"; var t = new Trace(url, requestmode); t.set_sync_mode(syncmode); + t.set_default_subject(default_subject); this.traces[name] = t; return t; } @@ -501,5 +507,6 @@ }; TraceManager.prototype = TraceManager_prototype; - return new TraceManager(); + var tracemanager = new TraceManager(); + return tracemanager; };