src/js/libs/tracemanager.js
branchpopcorn-port
changeset 841 8da49ff273e0
parent 835 a8af9da7c622
child 882 61c384dda19e
child 899 445631dffdf8
equal deleted inserted replaced
840:ac66e2240e1e 841:8da49ff273e0
     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();
   318      var Obsel_prototype = {
   317      var Obsel_prototype = {
   319          /* The following attributes are here for documentation
   318          /* The following attributes are here for documentation
   320           * purposes. They MUST be defined in the constructor
   319           * purposes. They MUST be defined in the constructor
   321           * function. */
   320           * function. */
   322          trace: undefined,
   321          trace: undefined,
   323 		 obselProbe: undefined,
       
   324          type: undefined,
   322          type: undefined,
   325          begin: undefined,
   323          begin: undefined,
   326          end: undefined,
   324          end: undefined,
   327          subject: undefined,
   325          subject: undefined,
   328          /* Dictionary indexed by ObselType URIs */
   326          /* Dictionary indexed by ObselType URIs */
   332          get_trace: function() {
   330          get_trace: function() {
   333              return this.trace;
   331              return this.trace;
   334          },
   332          },
   335 
   333 
   336          get_obsel_type: function() {
   334          get_obsel_type: function() {
   337              /* FIXME: maybe we should return a ObselType object. In the meantime, return the URI */
       
   338              return this.type;
   335              return this.type;
   339          },
   336          },
   340          get_begin: function() {
   337          get_begin: function() {
   341              return this.begin;
   338              return this.begin;
   342          },
   339          },
   348          },
   345          },
   349 
   346 
   350          list_attribute_types: function() {
   347          list_attribute_types: function() {
   351              var result = [];
   348              var result = [];
   352              for (var prop in this.attributes) {
   349              for (var prop in this.attributes) {
   353                  result.push(prop);
   350                  if (this.hasOwnProperty(prop))
       
   351                      result.push(prop);
   354              }
   352              }
   355              /* FIXME: we return URIs here instead of AttributeType elements */
   353              /* FIXME: we return URIs here instead of AttributeType elements */
   356              return result;
   354              return result;
   357          },
   355          },
   358 
   356 
   420                  "begin": this.begin,
   418                  "begin": this.begin,
   421                  "end": this.end,
   419                  "end": this.end,
   422                  "subject": this.subject
   420                  "subject": this.subject
   423              };
   421              };
   424              for (var prop in this.attributes) {
   422              for (var prop in this.attributes) {
   425                  r[prop] = this.attributes[prop];
   423                  if (this.hasOwnProperty(prop))
       
   424                      r[prop] = this.attributes[prop];
   426              }
   425              }
   427              return r;
   426              return r;
   428          },
   427          },
   429 
   428 
   430          /*
   429          /*
   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  };