[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