|
From: creedon <icr...@us...> - 2005-06-19 18:11:22
|
Update of /cvsroot/frontierkernel/odbs/frontierRoot/system/verbs/builtins/betty/rpc In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv10976 Modified Files: client clientMulticall Log Message: changed localhost to 127.0.0.1 Index: client =================================================================== RCS file: /cvsroot/frontierkernel/odbs/frontierRoot/system/verbs/builtins/betty/rpc/client,v retrieving revision 1.1.1.1 retrieving revision 1.2 diff -C2 -d -r1.1.1.1 -r1.2 *** client 26 Mar 2005 19:42:36 -0000 1.1.1.1 --- client 19 Jun 2005 18:11:12 -0000 1.2 *************** *** 1,3 **** FrontierVcsFile:1:scpt:system.verbs.builtins.betty.rpc.client ! on client (rpcServer="localhost", rpcPort=user.inetd.config.http.port, procedureName="", adrparamlist=nil, fldebug=false, ticksToTimeOut=nil, flShowMessages=true, rpcPath=nil, flAsynch=false, adrCallback=nil, extraInfo=nil, adrErrorCallback=nil, username="", password="") { ÇChange Ç8/20/02; 4:43:35 AM by JES ÇRespect user.betty.prefs.flSaveDatabaseAfterAsynchRpcCall. Ç1/4/02; 7:15:55 PM by DW ÇIf user.betty.prefs.flKeepClientCallTicks is true, keep track of call stats in system.temp.betty.clientCallTicks. ÇAdded a test code bundle at the end of the routine. Ç8/20/00 by AR ÇAdded optional username and password parameters for HTTP Basic Authentication. Ç10/8/99 by DW ÇAdded optional adrErrorCallback parameter, if specified, this script is called when there's an error sending an asynchronous XML-RPC call. Ç3/6/99 by DW ÇAdded three optional parameters to allow asynchronous RPC-ing that try until they connect. ÇflAsynch, defaults to false, if true it's an asynchronous call. ÇadrCallback, defaults to nil, if non-nil, it's the routine we call when we connect. ÇIt takes a single parameter, the value returned by the RPC server. ÇThe routine pointed to by this address must not be local to the script calling betty.rpc.client because it won't be around when the actual RPC call is made. ÇIt must be in Frontier.root or in a guest database. ÇextraInfo, defaults to nil, it's any kind of object, it's available to the callback to help it interpret the response. ÇIt will create a table at user.betty.queueOutgoing, which is watched by the agent. Ç1/17/99 by DW ÇChange default value of ticksToTimeOut to nil. If it's nil, set it to user.betty.prefs.rpcClientDefaultTimeout. ÇChange default value of rpcPath to nil. If it's nil, set it to user.betty.prefs.rpcClientDefaultPath. Ç1/15/99 by DW Çadded optional parameter, rpcPath, to facilitate communication with non-Frontier XML-RPC servers. Ç11/14/98 by DW ÇIn the 11/5 change, RPC error reporting lost a lot of its value due to a too-local declaration of adrtable. Ç11/5/98 by DW ÇAt the end of betty.rpc.client, there was some real ancient code for producing examples ÇIt was copying the XML request and the compiled XML that was returned into the params list ÇHowever, it's legal to call this routine without specifying the param list, it would fail if you did so. ÇThis code was only useful to people writing docs and testing this. ÇNow it's deployed, things will run faster if we don't do this. ÇAnd now you can leave out params if the procedure you're calling takes no parameters. Ç11/1/98 by DW ÇAdded ticksToTimeOut optional parameter, it's passed on to tcp.httpClient ÇSome operations take more than 30 seconds to complete, that's the default on tcp.httpClient ÇI imagine that some take much less than 30 seconds too... ÇAdded flShowMessages optional parameter, it's also passed on to tcp.httpClient ÇIf true, it will display messages in Frontier's About window, if false it won't. ÇPreviously, there was no way for an RPC caller to turn on tcp.httpClient messages. ÇThis is important if you want to see what's going on at the HTTP level. Ç7/17/98 by PBS ÇXML header is now lowercase to conform to spec. ÇChanged xml table from temp.rpcReturn to a local table for thread-safety. Ç4/4/98 by DW ÇA full-featured client for the RPC2 responder local (startticks = clock.ticks ()); betty.init (); //1/17/99 DW, make sure user.betty.prefs is set up bundle { //3/6/99 DW, handle asynchronous calls if flAsynch { local (adragent = @system.agents.asynchRPC); if not defined (adragent^) { new (scripttype, adragent); local (oldtarget = target.set (adragent)); op.setlinetext ("betty.rpc.agent ()"); target.set (oldtarget); script.compile (adragent)}; local (adrqueue = @user.betty.queueOutgoing); if not defined (adrqueue^) { new (tabletype, adrqueue)}; if not defined (adrqueue^.serialNum) { adrqueue^.serialNum = 1}; local (adrtable = @adrqueue^.table); if not defined (adrtable^) { new (tabletype, adrtable)}; local (adritem = @adrtable^.[string.padwithzeros (adrqueue^.serialNum++, 7)]); bundle { //populate it in a local table, don't want the agent catching it until we're ready local (localtable); new (tabletype, @localtable); localtable.rpcServer = rpcServer; localtable.rpcPort = rpcPort; localtable.procedureName = procedureName; localtable.paramlist = adrparamlist^; //have to copy the param list localtable.fldebug = fldebug; localtable.flShowMessages = flShowMessages; localtable.rpcPath = rpcPath; localtable.adrCallback = adrCallback; localtable.adrErrorCallback = adrErrorCallback; localtable.extraInfo = extraInfo; localtable.readyToRunAt = clock.now (); localtable.username = username; localtable.password = password; adritem^ = localtable}; if user.betty.prefs.flSaveDatabaseAfterAsynchRpcCall { fileMenu.save ()}; return (true)}}; bundle { //1/17/99 DW, check ticksToTimeOut, rpcPath if ticksToTimeOut == nil { ticksToTimeOut = user.betty.prefs.rpcClientDefaultTimeout}; if rpcPath == nil { rpcPath = user.betty.prefs.rpcClientDefaultPath}}; local (xmltext = ""); bundle { //build the XML request local (indentlevel = 0); on add (s) { xmltext = xmltext + string.filledString ("\t", indentlevel) + s + "\r\n"}; add ("<?xml version=\"1.0\"?>"); add ("<methodCall>"); indentlevel++; add ("<methodName>" + procedureName + "</methodName>"); add ("<params>"); indentlevel++; if adrparamlist != nil { local (item); for item in adrparamlist^ { add ("<param>"); indentlevel++; Çadd ("<name>" + nameOf (adritem^) + "</name>") add ("<value>" + xml.coercions.frontierValueToTaggedText (@item, indentlevel) + "</value>"); add ("</param>"); indentlevel--; if typeOf (item) == tableType { delete (@item)}}}; add ("</params>"); indentlevel--; add ("</methodCall>"); indentlevel--}; local (xtable); bundle { //send the HTTP request, store result in xtable local (s); s = tcp.httpClient (method:"POST", server:rpcServer, port:rpcPort, path:rpcPath, data:xmltext, datatype:"text/xml", username:username, password:password, debug:fldebug, timeOutTicks:ticksToTimeOut, flMessages:flShowMessages); if fldebug { edit (@scratchpad.httpResult); //the result of setting debug to true in the call above edit (@scratchpad.httpCommand)}; xml.compile (string.delete (s, 1, string.patternMatch ("\r\n\r\n", s) + 3), @xtable)}; local (returnedValue, adrtable); try { //walk the response structure, get returnedValue adrtable = @xtable; local (adrresponse = xml.getaddress (adrtable, "methodResponse")); local (adrparams = xml.getaddress (adrresponse, "params")); local (adrparam = xml.getaddress (adrparams, "param")); returnedValue = xml.getvalue (adrparam, "value"); if typeOf (returnedValue) == tableType { //4/16/98; 1:51:28 PM by DW local (newValue); xml.coercions.structToFrontierValue (@returnedValue [1], @newValue); table.assign (@returnedValue, newValue)}} else { //scriptError local (adrresponse = xml.getaddress (adrtable, "methodResponse")); local (adrfault = xml.getaddress (adrresponse, "fault")); local (adrvalue = xml.getaddress (adrfault, "value")); local (adrstruct = xml.getaddress (adrvalue, "struct")); local (memberlist = xml.getaddresslist (adrstruct, "member")); local (member, name, value, faultCode, faultString); for member in memberlist { name = xml.getvalue (member, "name"); value = xml.getvalue (member, "value"); case name { "faultCode" { faultCode = value}; "faultString" { faultString = value}}}; scriptError ("The server, " + rpcServer + ", returned error code " + faultCode + ": " + faultString)}; bundle { //track ticks, by procedure call in system.temp.betty.clientCallTicks if user.betty.prefs.flKeepClientCallTicks { local (adrtable = @system.temp.betty); if not defined (adrtable^) { new (tabletype, adrtable)}; adrtable = @adrtable^.clientCallTicks; if not defined (adrtable^) { new (tabletype, adrtable)}; local (adrcount = @adrtable^.[rpcServer + ":" + rpcPort + rpcPath + "/" + procedureName]); if not defined (adrcount^) { adrcount^ = 0}; adrcount^ = adrcount^ + (clock.ticks () - startticks)}}; return (returnedValue)}; Çbundle //test code Çlocal (params = {"Dave's Handsome Radio Blog", "http://radio.weblogs.com/0001015/"}) Çscratchpad.response = betty.rpc.client ("rpc.weblogs.com", 80, "weblogUpdates.ping", @params) \ No newline at end of file --- 1,3 ---- FrontierVcsFile:1:scpt:system.verbs.builtins.betty.rpc.client ! on client (rpcServer="127.0.0.1", rpcPort=user.inetd.config.http.port, procedureName="", adrparamlist=nil, fldebug=false, ticksToTimeOut=nil, flShowMessages=true, rpcPath=nil, flAsynch=false, adrCallback=nil, extraInfo=nil, adrErrorCallback=nil, username="", password="") { ÇChanges Ç6/19/05; 10:04:51 AM by TAC Çchanged localhost to 127.0.0.1 Ç8/20/02; 4:43:35 AM by JES ÇRespect user.betty.prefs.flSaveDatabaseAfterAsynchRpcCall. Ç1/4/02; 7:15:55 PM by DW ÇIf user.betty.prefs.flKeepClientCallTicks is true, keep track of call stats in system.temp.betty.clientCallTicks. ÇAdded a test code bundle at the end of the routine. Ç8/20/00 by AR ÇAdded optional username and password parameters for HTTP Basic Authentication. Ç10/8/99 by DW ÇAdded optional adrErrorCallback parameter, if specified, this script is called when there's an error sending an asynchronous XML-RPC call. Ç3/6/99 by DW ÇAdded three optional parameters to allow asynchronous RPC-ing that try until they connect. ÇflAsynch, defaults to false, if true it's an asynchronous call. ÇadrCallback, defaults to nil, if non-nil, it's the routine we call when we connect. ÇIt takes a single parameter, the value returned by the RPC server. ÇThe routine pointed to by this address must not be local to the script calling betty.rpc.client because it won't be around when the actual RPC call is made. ÇIt must be in Frontier.root or in a guest database. ÇextraInfo, defaults to nil, it's any kind of object, it's available to the callback to help it interpret the response. ÇIt will create a table at user.betty.queueOutgoing, which is watched by the agent. Ç1/17/99 by DW ÇChange default value of ticksToTimeOut to nil. If it's nil, set it to user.betty.prefs.rpcClientDefaultTimeout. ÇChange default value of rpcPath to nil. If it's nil, set it to user.betty.prefs.rpcClientDefaultPath. Ç1/15/99 by DW Çadded optional parameter, rpcPath, to facilitate communication with non-Frontier XML-RPC servers. Ç11/14/98 by DW ÇIn the 11/5 change, RPC error reporting lost a lot of its value due to a too-local declaration of adrtable. Ç11/5/98 by DW ÇAt the end of betty.rpc.client, there was some real ancient code for producing examples ÇIt was copying the XML request and the compiled XML that was returned into the params list ÇHowever, it's legal to call this routine without specifying the param list, it would fail if you did so. ÇThis code was only useful to people writing docs and testing this. ÇNow it's deployed, things will run faster if we don't do this. ÇAnd now you can leave out params if the procedure you're calling takes no parameters. Ç11/1/98 by DW ÇAdded ticksToTimeOut optional parameter, it's passed on to tcp.httpClient ÇSome operations take more than 30 seconds to complete, that's the default on tcp.httpClient ÇI imagine that some take much less than 30 seconds too... ÇAdded flShowMessages optional parameter, it's also passed on to tcp.httpClient ÇIf true, it will display messages in Frontier's About window, if false it won't. ÇPreviously, there was no way for an RPC caller to turn on tcp.httpClient messages. ÇThis is important if you want to see what's going on at the HTTP level. Ç7/17/98 by PBS ÇXML header is now lowercase to conform to spec. ÇChanged xml table from temp.rpcReturn to a local table for thread-safety. Ç4/4/98 by DW ÇA full-featured client for the RPC2 responder local (startticks = clock.ticks ()); betty.init (); //1/17/99 DW, make sure user.betty.prefs is set up bundle { //3/6/99 DW, handle asynchronous calls if flAsynch { local (adragent = @system.agents.asynchRPC); if not defined (adragent^) { new (scripttype, adragent); local (oldtarget = target.set (adragent)); op.setlinetext ("betty.rpc.agent ()"); target.set (oldtarget); script.compile (adragent)}; local (adrqueue = @user.betty.queueOutgoing); if not defined (adrqueue^) { new (tabletype, adrqueue)}; if not defined (adrqueue^.serialNum) { adrqueue^.serialNum = 1}; local (adrtable = @adrqueue^.table); if not defined (adrtable^) { new (tabletype, adrtable)}; local (adritem = @adrtable^.[string.padwithzeros (adrqueue^.serialNum++, 7)]); bundle { //populate it in a local table, don't want the agent catching it until we're ready local (localtable); new (tabletype, @localtable); localtable.rpcServer = rpcServer; localtable.rpcPort = rpcPort; localtable.procedureName = procedureName; localtable.paramlist = adrparamlist^; //have to copy the param list localtable.fldebug = fldebug; localtable.flShowMessages = flShowMessages; localtable.rpcPath = rpcPath; localtable.adrCallback = adrCallback; localtable.adrErrorCallback = adrErrorCallback; localtable.extraInfo = extraInfo; localtable.readyToRunAt = clock.now (); localtable.username = username; localtable.password = password; adritem^ = localtable}; if user.betty.prefs.flSaveDatabaseAfterAsynchRpcCall { fileMenu.save ()}; return (true)}}; bundle { //1/17/99 DW, check ticksToTimeOut, rpcPath if ticksToTimeOut == nil { ticksToTimeOut = user.betty.prefs.rpcClientDefaultTimeout}; if rpcPath == nil { rpcPath = user.betty.prefs.rpcClientDefaultPath}}; local (xmltext = ""); bundle { //build the XML request local (indentlevel = 0); on add (s) { xmltext = xmltext + string.filledString ("\t", indentlevel) + s + "\r\n"}; add ("<?xml version=\"1.0\"?>"); add ("<methodCall>"); indentlevel++; add ("<methodName>" + procedureName + "</methodName>"); add ("<params>"); indentlevel++; if adrparamlist != nil { local (item); for item in adrparamlist^ { add ("<param>"); indentlevel++; Çadd ("<name>" + nameOf (adritem^) + "</name>") add ("<value>" + xml.coercions.frontierValueToTaggedText (@item, indentlevel) + "</value>"); add ("</param>"); indentlevel--; if typeOf (item) == tableType { delete (@item)}}}; add ("</params>"); indentlevel--; add ("</methodCall>"); indentlevel--}; local (xtable); bundle { //send the HTTP request, store result in xtable local (s); s = tcp.httpClient (method:"POST", server:rpcServer, port:rpcPort, path:rpcPath, data:xmltext, datatype:"text/xml", username:username, password:password, debug:fldebug, timeOutTicks:ticksToTimeOut, flMessages:flShowMessages); if fldebug { edit (@scratchpad.httpResult); //the result of setting debug to true in the call above edit (@scratchpad.httpCommand)}; xml.compile (string.delete (s, 1, string.patternMatch ("\r\n\r\n", s) + 3), @xtable)}; local (returnedValue, adrtable); try { //walk the response structure, get returnedValue adrtable = @xtable; local (adrresponse = xml.getaddress (adrtable, "methodResponse")); local (adrparams = xml.getaddress (adrresponse, "params")); local (adrparam = xml.getaddress (adrparams, "param")); returnedValue = xml.getvalue (adrparam, "value"); if typeOf (returnedValue) == tableType { //4/16/98; 1:51:28 PM by DW local (newValue); xml.coercions.structToFrontierValue (@returnedValue [1], @newValue); table.assign (@returnedValue, newValue)}} else { //scriptError local (adrresponse = xml.getaddress (adrtable, "methodResponse")); local (adrfault = xml.getaddress (adrresponse, "fault")); local (adrvalue = xml.getaddress (adrfault, "value")); local (adrstruct = xml.getaddress (adrvalue, "struct")); local (memberlist = xml.getaddresslist (adrstruct, "member")); local (member, name, value, faultCode, faultString); for member in memberlist { name = xml.getvalue (member, "name"); value = xml.getvalue (member, "value"); case name { "faultCode" { faultCode = value}; "faultString" { faultString = value}}}; scriptError ("The server, " + rpcServer + ", returned error code " + faultCode + ": " + faultString)}; bundle { //track ticks, by procedure call in system.temp.betty.clientCallTicks if user.betty.prefs.flKeepClientCallTicks { local (adrtable = @system.temp.betty); if not defined (adrtable^) { new (tabletype, adrtable)}; adrtable = @adrtable^.clientCallTicks; if not defined (adrtable^) { new (tabletype, adrtable)}; local (adrcount = @adrtable^.[rpcServer + ":" + rpcPort + rpcPath + "/" + procedureName]); if not defined (adrcount^) { adrcount^ = 0}; adrcount^ = adrcount^ + (clock.ticks () - startticks)}}; return (returnedValue)}; Çbundle //test code Çlocal (params = {"Dave's Handsome Radio Blog", "http://radio.weblogs.com/0001015/"}) Çscratchpad.response = betty.rpc.client ("rpc.weblogs.com", 80, "weblogUpdates.ping", @params) \ No newline at end of file Index: clientMulticall =================================================================== RCS file: /cvsroot/frontierkernel/odbs/frontierRoot/system/verbs/builtins/betty/rpc/clientMulticall,v retrieving revision 1.1.1.1 retrieving revision 1.2 diff -C2 -d -r1.1.1.1 -r1.2 *** clientMulticall 26 Mar 2005 19:42:36 -0000 1.1.1.1 --- clientMulticall 19 Jun 2005 18:11:12 -0000 1.2 *************** *** 1,3 **** FrontierVcsFile:1:scpt:system.verbs.builtins.betty.rpc.clientMulticall ! on clientMultiCall (rpcServer="localhost", rpcPort=user.inetd.config.http.port, adrCallTable=nil, fldebug=false, ticksToTimeOut=nil, flShowMessages=true, rpcPath=nil, flAsynch=false, adrCallback=nil, extraInfo=nil, adrErrorCallback=nil, username="", password="") { ÇChanges Ç4/9/01; 8:09:48 PM by DW ÇCreated. Interfaces to the multicall capability. Çhttp://frontier.userland.com/stories/storyReader$7394 local (multicallparamlist = {}, adrsub, call); for adrsub in adrCallTable { new (tabletype, @call); call.methodName = adrsub^.methodName; call.params = adrsub^.params; multicallparamlist = multicallparamlist + {call}}; local (params = {multicallparamlist}); local (returnedlist = betty.rpc.client (rpcServer, rpcPort, "system.multicall", @params, fldebug, ticksToTimeOut, flShowMessages, rpcPath, username:username, password:password)); local (returnedtable, ixlist = 1); new (tabletype, @returnedtable); for adrsub in adrCallTable { adrreturnsub = @returnedtable.[nameof (adrsub^)]; new (tabletype, adrreturnsub); case typeof (returnedlist [ixlist]) { listtype { adrreturnsub^.flError = false; adrreturnsub^.value = returnedlist [ixlist] [1]}; tabletype { local (t = returnedlist [ixlist]); adrreturnsub^.flError = true; adrreturnsub^.faultCode = t.faultCode; adrreturnsub^.faultString = t.faultString}}; ixlist++}; return (returnedtable)}; bundle { //test code ÇNote ÇFor this test we use a special version of examples.getStateName that errors if the statenum is out of range. ÇThe handler follows, copy this into a new script at user.betty.rpcHandlers.examples.getStateNameWithError. Çon getStateNameWithError (statenum) Çif (statenum < 1) or (statenum > 50) Çscripterror ("Can't get the state name because the state num is less than 1 or greater than 50.") Çreturn (states.nthState (statenum)) local (calltable, i); new (tabletype, @calltable); for i = 1 to 10 { new (tabletype, @onecall); onecall.methodName = "examples.getStateNameWithError"; onecall.params = {random (35, 65)}; calltable.[string.padwithzeros (i, 3)] = onecall}; scratchpad.multicallresult = clientMultiCall (adrCallTable:@calltable); edit (@scratchpad.multicallresult)} \ No newline at end of file --- 1,3 ---- FrontierVcsFile:1:scpt:system.verbs.builtins.betty.rpc.clientMulticall ! on clientMultiCall (rpcServer="127.0.0.1", rpcPort=user.inetd.config.http.port, adrCallTable=nil, fldebug=false, ticksToTimeOut=nil, flShowMessages=true, rpcPath=nil, flAsynch=false, adrCallback=nil, extraInfo=nil, adrErrorCallback=nil, username="", password="") { ÇChanges Ç6/19/05; 10:06:03 AM by TAC Çchanged localhost to 127.0.0.1 Ç4/9/01; 8:09:48 PM by DW ÇCreated. Interfaces to the multicall capability. Çhttp://frontier.userland.com/stories/storyReader$7394 local (multicallparamlist = {}, adrsub, call); for adrsub in adrCallTable { new (tabletype, @call); call.methodName = adrsub^.methodName; call.params = adrsub^.params; multicallparamlist = multicallparamlist + {call}}; local (params = {multicallparamlist}); local (returnedlist = betty.rpc.client (rpcServer, rpcPort, "system.multicall", @params, fldebug, ticksToTimeOut, flShowMessages, rpcPath, username:username, password:password)); local (returnedtable, ixlist = 1); new (tabletype, @returnedtable); for adrsub in adrCallTable { adrreturnsub = @returnedtable.[nameof (adrsub^)]; new (tabletype, adrreturnsub); case typeof (returnedlist [ixlist]) { listtype { adrreturnsub^.flError = false; adrreturnsub^.value = returnedlist [ixlist] [1]}; tabletype { local (t = returnedlist [ixlist]); adrreturnsub^.flError = true; adrreturnsub^.faultCode = t.faultCode; adrreturnsub^.faultString = t.faultString}}; ixlist++}; return (returnedtable)}; bundle { //test code ÇNote ÇFor this test we use a special version of examples.getStateName that errors if the statenum is out of range. ÇThe handler follows, copy this into a new script at user.betty.rpcHandlers.examples.getStateNameWithError. Çon getStateNameWithError (statenum) Çif (statenum < 1) or (statenum > 50) Çscripterror ("Can't get the state name because the state num is less than 1 or greater than 50.") Çreturn (states.nthState (statenum)) local (calltable, i); new (tabletype, @calltable); for i = 1 to 10 { new (tabletype, @onecall); onecall.methodName = "examples.getStateNameWithError"; onecall.params = {random (35, 65)}; calltable.[string.padwithzeros (i, 3)] = onecall}; scratchpad.multicallresult = clientMultiCall (adrCallTable:@calltable); edit (@scratchpad.multicallresult)} \ No newline at end of file |