[z3-checkins] r25954 - z3/jsonserver/branch/merge/browser

reebalazs at codespeak.net reebalazs at codespeak.net
Tue Apr 18 17:11:19 CEST 2006


Author: reebalazs
Date: Tue Apr 18 17:11:16 2006
New Revision: 25954

Added:
   z3/jsonserver/branch/merge/browser/logging.js
   z3/jsonserver/branch/merge/browser/requestmanager.js
Modified:
   z3/jsonserver/branch/merge/browser/configure.zcml
   z3/jsonserver/branch/merge/browser/json.js
Log:
Add logging and simple support for simple request queue management

Modified: z3/jsonserver/branch/merge/browser/configure.zcml
==============================================================================
--- z3/jsonserver/branch/merge/browser/configure.zcml	(original)
+++ z3/jsonserver/branch/merge/browser/configure.zcml	Tue Apr 18 17:11:16 2006
@@ -4,9 +4,11 @@
 
     <browser:concatresource
                            name="jsonrpc.js"
-                           files="xmlhttp.js
+                           files="logging.js
+						   xmlhttp.js
                            json.js
-                           pythonkw.js"
+                           pythonkw.js
+						   requestmanager.js"
                            />
 
- </configure>
\ No newline at end of file
+ </configure>

Modified: z3/jsonserver/branch/merge/browser/json.js
==============================================================================
--- z3/jsonserver/branch/merge/browser/json.js	(original)
+++ z3/jsonserver/branch/merge/browser/json.js	Tue Apr 18 17:11:16 2006
@@ -51,6 +51,21 @@
 function JSONSupplement(data, id) {
 	return new json.SupplementWrapper(data, id);
 	}
+ 
+// Direct method creation, by creating an implicit proxy
+// if methodName == '' then the url is taken as full url
+function makeJSONRPCMethod(url, methodName, callback, error, timeout, supplementData, 
+					requestId, requestManager, user, pass) {
+    if (typeof(methodName) == 'undefined' || methodName == null || methodName == '') {
+		var pieces = url.split('/');
+		methodName = pieces.pop();
+		url = pieces.join('/');
+    }
+    var proxy = new JSONRPC(url);
+    proxy.addMethod(methodName, callback, error, timeout, supplementData, 
+		requestId, requestManager, user, pass);
+    return proxy[methodName];
+}
 
 function JSONRPC(url) {
     this._url = url;
@@ -63,7 +78,7 @@
     return new JSONRPC(url);
 }
 
-JSONRPC.prototype.addMethod = function(name, callback, errHandler, timeout, supplementData, requestId) {
+JSONRPC.prototype.addMethod = function(name, callback, errHandler, timeout, supplementData, requestId, requestManager) {
     if (typeof(errHandler) == 'undefined') {
         errHandler = null;
     }
@@ -76,9 +91,13 @@
     if (typeof(requestId) == 'undefined' || requestId == null) {
         requestId = "jsonRequest";
     }
+    if (typeof(requestManager) == 'undefined' || requestManager == null) {
+        requestManager = _dummyRequestManager;
+	}
     var self = this;
     if(!self[name]){
-        var method = new JSONRPCMethod(this._url, name, callback, errHandler, timeout, supplementData, requestId, this._user, this._password);
+        var method = new JSONRPCMethod(this._url, name, callback, errHandler, timeout, supplementData, requestId, 
+					requestManager, this._user, this._password);
         self[name] = method;
         this._methods.push(method);
     }
@@ -92,12 +111,26 @@
     }
 }
 
-function JSONRPCMethod(url, methodName, callback, errHandler, timeout, supplementData, requestId, user, pass) {
+function _DummyRequestManager() {
+	}
+
+_DummyRequestManager.prototype.notifyServer = function(method_with_parms, url) {
+	method_with_parms();
+	}
+	
+_DummyRequestManager.prototype.receivedResult = function() {
+	}
+
+var _dummyRequestManager = _DummyRequestManager();
+
+function JSONRPCMethod(url, methodName, callback, errHandler, timeout, supplementData, requestId, 
+			requestManager, user, pass) {
     this.methodName = methodName;
     this.callback = callback;
 	this.errHandler = errHandler;
     this.supplementData = supplementData;
     this.requestId = requestId;
+	this.requestManager = requestManager;
     this.url = url;
     this.user = user;
     this.password = pass;
@@ -132,26 +165,30 @@
 			}
         if(self.callback) {
             var data = self.jsonRequest(requestId, self.methodName, args);
-			self.postData(self.url, self.user, self.password, data, timeout, function(resp){
-				var res = null;
-				var exc = null;
-				try {
-					res = self.handleResponse(resp);
-				} catch(e) {
-					if (e.name == 'JSONRPCError' && self.errHandler) {
-						exc = e;
+			var do_postdata = function() {
+				self.postData(self.url, self.user, self.password, data, timeout, function(resp){
+					var res = null;
+					var exc = null;
+					try {
+						res = self.handleResponse(resp);
+					} catch(e) {
+						if (e.name == 'JSONRPCError' && self.errHandler) {
+							exc = e;
+						} else {
+							throw(e);
+						}
+					}
+					self.requestManager.receivedResult();
+					if (exc == null) {
+						self.callback(res, supplementData, requestId);
 					} else {
-						throw(e);
+						self.errHandler(exc, supplementData, requestId);
 					}
-				}
-				if (exc == null) {
-					self.callback(res, supplementData, requestId);
-				} else {
-					self.errHandler(exc, supplementData, requestId);
-				}
-				args = null;
-				resp = null;
-			});
+					args = null;
+					resp = null;
+				});
+			}
+			self.requestManager.notifyServer(do_postdata, self.url + '/' + self.methodName);
         } else {
             var data = self.jsonRequest(requestId, self.methodName, args);
             var resp = self.postData(self.url, self.user, self.password, data, timeout);
@@ -159,7 +196,6 @@
         }
     }
     return fn;
-
 }
 
 JSONRPCMethod.prototype.postData = function(url, user, pass, data, timeout, callback) {

Added: z3/jsonserver/branch/merge/browser/logging.js
==============================================================================
--- (empty file)
+++ z3/jsonserver/branch/merge/browser/logging.js	Tue Apr 18 17:11:16 2006
@@ -0,0 +1,23 @@
+/* Set up logging with Mochikit, if that is installed */
+
+/* Create jsonrpc namespace */
+
+if (typeof(jsonrpc) == 'undefined') {
+    var jsonrpc = {};
+}
+
+/* check whether the logging stuff of MochiKit is available */
+try {
+    MochiKit.Logging.log('Initializing jsonrpc');
+    jsonrpc.log = MochiKit.Logging.log;
+    jsonrpc.logError = MochiKit.Logging.logError;
+    jsonrpc.logDebug = MochiKit.Logging.logDebug;
+    jsonrpc.logFatal = MochiKit.Logging.logFatal;
+    jsonrpc.logWarning = MochiKit.Logging.logWarning;
+} catch(e) {
+    jsonrpc.log = function(str){};
+    jsonrpc.logError = jsonrpc.log;
+    jsonrpc.logDebug = jsonrpc.log;
+    jsonrpc.logFatal = jsonrpc.log;
+    jsonrpc.logWarning = jsonrpc.log;
+}

Added: z3/jsonserver/branch/merge/browser/requestmanager.js
==============================================================================
--- (empty file)
+++ z3/jsonserver/branch/merge/browser/requestmanager.js	Tue Apr 18 17:11:16 2006
@@ -0,0 +1,141 @@
+/* Request manager 
+
+This limits the number of outgoing requests. Extra
+requests are stored and sent out on demand.
+
+XXX Requests never, at the moment, time out from the queue
+TODO should take care of this.
+
+It is possible to have more instances and have different methods
+queue up in different queues.
+
+Usage:
+
+- instantiate a queue
+- use it as a parameter for addMethod
+- it will only queue async requests.
+
+Usage manually:
+
+- notifyServer(func, url) , where func is a partial containing
+	all parameters,
+- receivedResult() when result is received or an error is signalled.
+
+*/
+
+jsonrpc.RequestManager = function (name, maxNr) {
+    this.waitingQueue = new jsonrpc.FifoQueue();
+    this.sentNr = 0;
+	if (typeof(name) == undefined) {
+		name = null;
+	}
+	this.name = name;
+	var namestr = '';
+	if (name != null) {
+		namestr = '[' + name + '] '
+		}
+	this.namestr = namestr;
+	if (typeof(maxNr) != undefined && maxNr != null) {
+		this.maxNr = maxNr;
+	}
+}
+
+// max request nr
+jsonrpc.RequestManager.prototype.maxNr = 4;
+
+jsonrpc.RequestManager.prototype.getInfo = function() {
+    return '(RQ: ' + this.sentNr + ' OUT, ' + this.waitingQueue.size() + ' WAI)';
+}
+
+jsonrpc.RequestManager.prototype.log = function(txt) {
+    jsonrpc.logDebug('RequestManager ' + this.namestr + txt + ' ' + this.getInfo());
+}
+
+jsonrpc.RequestManager.prototype.pushWaitingRequest = function(func, url) {
+    this.waitingQueue.push([func, url]);
+}
+
+jsonrpc.RequestManager.prototype.popWaitingRequest = function() {
+    return this.waitingQueue.pop();
+}
+
+jsonrpc.RequestManager.prototype.isWaitingRequestQueueEmpty = function() {
+    return this.waitingQueue.empty();
+}
+
+jsonrpc.RequestManager.prototype.pushSentRequest = function(func, url) {
+    // we do not store the elems, since they are not needed now
+    this.sentNr = this.sentNr + 1;
+}
+
+jsonrpc.RequestManager.prototype.popSentRequest = function() {
+    this.sentNr = this.sentNr - 1;
+}
+
+jsonrpc.RequestManager.prototype.isSentRequestQueueFull = function() {
+    return (this.sentNr >= this.maxNr)
+}
+
+/* request manager notification API */
+
+jsonrpc.RequestManager.prototype.notifyServer = function(func, url) {
+  // func must be a partial (e.g. use Mochikit or wrap up)
+  // here url is only for the logging
+  if (! jsonrpc.requestManager.isSentRequestQueueFull()) {
+    // can be sent if we are not over the limit.
+    this.pushSentRequest(func, url);
+    this.log('Notify server at ' + url);
+    func();
+  } else {
+    this.pushWaitingRequest(func, url);
+    this.log('Queue server notification at ' + url);
+  }
+}
+
+jsonrpc.RequestManager.prototype.receivedResult = function() {
+  // must be called when one result arrived
+  // Mark that we have one less request out.
+  jsonrpc.requestManager.popSentRequest();
+  if (! jsonrpc.requestManager.isWaitingRequestQueueEmpty()) {
+    // see if we can send another request in place of the received one
+    // request is waiting, send it.
+    var waiting = jsonrpc.requestManager.popWaitingRequest();
+    var func = waiting[0];
+    var url = waiting[1];
+    jsonrpc.requestManager.pushSentRequest(func, url);
+    this.log("Send queued notification to server at " + url);
+    func();
+  } else {
+    this.log("Request queue empty.");
+  }
+}
+
+/* simple FIFO queue */
+
+jsonrpc.FifoQueue = function () {
+    this.reset();
+}
+
+jsonrpc.FifoQueue.prototype.reset = function() {
+    this.elements = new Array();
+}
+
+jsonrpc.FifoQueue.prototype.push = function(obj) {
+    this.elements.push(obj);
+}
+
+jsonrpc.FifoQueue.prototype.pop = function() {
+    return this.elements.shift();
+}
+
+jsonrpc.FifoQueue.prototype.empty = function() {
+    return ! this.elements.length;
+}
+
+jsonrpc.FifoQueue.prototype.size = function() {
+    return this.elements.length;
+}
+
+jsonrpc.FifoQueue.prototype.front = function() {
+    return this.elements[0];
+}


More information about the z3-checkins mailing list