src/js/libs/tracemanager.js
branchpopcorn-port
changeset 841 8da49ff273e0
parent 835 a8af9da7c622
child 882 61c384dda19e
child 899 445631dffdf8
--- 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=$('<img/>').attr('src', this.url + 'trace/?data=' + data);
+                     var request=$('<img />').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;
  };