From 352b0e8d2047ec59703a81bfa7c242567474f741 Mon Sep 17 00:00:00 2001 From: Stefan Sayer Date: Fri, 19 Dec 2008 19:19:59 +0000 Subject: [PATCH] support for server timeout git-svn-id: http://svn.berlios.de/svnroot/repos/sems/trunk@1214 8eb893ce-cfd4-0310-b710-fb5ebe64c474 --- apps/xmlrpc2di/Makefile | 2 +- apps/xmlrpc2di/TOXmlRpcClient.cpp | 42 +++++++++++++++++++++++++++++++ apps/xmlrpc2di/TOXmlRpcClient.h | 24 ++++++++++++++++++ apps/xmlrpc2di/XMLRPC2DI.cpp | 41 ++++++++++++++++++++++-------- apps/xmlrpc2di/XMLRPC2DI.h | 2 ++ apps/xmlrpc2di/etc/xmlrpc2di.conf | 4 +++ 6 files changed, 103 insertions(+), 12 deletions(-) create mode 100644 apps/xmlrpc2di/TOXmlRpcClient.cpp create mode 100644 apps/xmlrpc2di/TOXmlRpcClient.h diff --git a/apps/xmlrpc2di/Makefile b/apps/xmlrpc2di/Makefile index c357a9be..2dd4ec2b 100644 --- a/apps/xmlrpc2di/Makefile +++ b/apps/xmlrpc2di/Makefile @@ -13,7 +13,7 @@ plug_in_name = xmlrpc2di # -D XMLRPCPP_SUPPORT_STRUCT_ACCESS # use these for local installation: - module_cflags = -I$(XMLRPCPP_DIR)/src -DHAVE_XMLRPCPP_SSL + module_cflags = -I$(XMLRPCPP_DIR)/src -DHAVE_XMLRPCPP_SSL -D XMLRPCPP_SUPPORT_STRUCT_ACCESS module_extra_objs = $(XMLRPCPP_DIR)/libXmlRpc.a extra_clean = clean_libxmlrpc # and comment module_ldflags line above diff --git a/apps/xmlrpc2di/TOXmlRpcClient.cpp b/apps/xmlrpc2di/TOXmlRpcClient.cpp new file mode 100644 index 00000000..a7b74edf --- /dev/null +++ b/apps/xmlrpc2di/TOXmlRpcClient.cpp @@ -0,0 +1,42 @@ +#include "XmlRpc.h" +#include "TOXmlRpcClient.h" +// Clear the referenced flag even if exceptions or errors occur. +struct ClearFlagOnExit { + ClearFlagOnExit(bool& flag) : _flag(flag) {} + ~ClearFlagOnExit() { _flag = false; } + bool& _flag; +}; + +bool TOXmlRpcClient::execute(const char* method, XmlRpcValue const& params, XmlRpcValue& result, double timeout) { + + XmlRpcUtil::log(1, "XmlRpcClient::execute: method %s (_connectionState %d).", method, _connectionState); + + // This is not a thread-safe operation, if you want to do multithreading, use separate + // clients for each thread. If you want to protect yourself from multiple threads + // accessing the same client, replace this code with a real mutex. + if (_executing) + return false; + + _executing = true; + ClearFlagOnExit cf(_executing); + + _sendAttempts = 0; + _isFault = false; + + if ( ! setupConnection()) + return false; + + if ( ! generateRequest(method, params)) + return false; + + result.clear(); + // double msTime = -1.0; // Process until exit is called + _disp.work(timeout); + + if (_connectionState != IDLE || ! parseResponse(result)) + return false; + + XmlRpcUtil::log(1, "XmlRpcClient::execute: method %s completed.", method); + _response = ""; + return true; +} diff --git a/apps/xmlrpc2di/TOXmlRpcClient.h b/apps/xmlrpc2di/TOXmlRpcClient.h new file mode 100644 index 00000000..aeb399e3 --- /dev/null +++ b/apps/xmlrpc2di/TOXmlRpcClient.h @@ -0,0 +1,24 @@ +#ifndef _TO_XMLRPCCLIENT_H +#define _TO_XMLRPCCLIENT_H +#include "XmlRpcClient.h" +using namespace XmlRpc; + +/* xmlrpc client with timeout */ +class TOXmlRpcClient : public XmlRpc::XmlRpcClient { + public: + TOXmlRpcClient(const char* host, int port, const char* uri=0 +#ifdef HAVE_XMLRPCPP_SSL + , bool ssl=false +#endif + ) + : XmlRpcClient(host, port, uri +#ifdef HAVE_XMLRPCPP_SSL + , ssl +#endif + ) { } + + bool execute(const char* method, XmlRpcValue const& params, + XmlRpcValue& result, double timeout); +}; + +#endif diff --git a/apps/xmlrpc2di/XMLRPC2DI.cpp b/apps/xmlrpc2di/XMLRPC2DI.cpp index 07a3e23f..ad4980f5 100644 --- a/apps/xmlrpc2di/XMLRPC2DI.cpp +++ b/apps/xmlrpc2di/XMLRPC2DI.cpp @@ -32,6 +32,7 @@ #include "AmUtils.h" #include "AmArg.h" #include "AmSession.h" +#include "TOXmlRpcClient.h" #define MOD_NAME "xmlrpc2di" @@ -43,6 +44,8 @@ XMLRPC2DI* XMLRPC2DI::_instance=0; // retry a failed server after 10 seconds unsigned int XMLRPC2DI::ServerRetryAfter = 10; +double XMLRPC2DI::ServerTimeout = -1; + XMLRPC2DI* XMLRPC2DI::instance() { if(_instance == NULL){ @@ -94,6 +97,21 @@ int XMLRPC2DI::load() { ServerRetryAfter = cfg.getParameterInt("server_retry_after", 10); DBG("retrying failed server after %u seconds\n", ServerRetryAfter); + + string server_timeout = cfg.getParameter("server_timeout"); + if (!server_timeout.empty()) { + unsigned int server_timeout_i = 0; + if (str2i(server_timeout, server_timeout_i)) { + ERROR("could not understand server_timeout=%s\n", + server_timeout.c_str()); + return -1; + } + + if (server_timeout_i) { + ServerTimeout = (double)server_timeout_i/1000.0; // in millisec + } + } + string run_server = cfg.getParameter("run_server","yes"); if (run_server != "yes") { DBG("XMLRPC server will not be started.\n"); @@ -203,7 +221,7 @@ void XMLRPC2DI::sendRequest(const AmArg& args, AmArg& ret) { ret.push("no active connections"); return; } - XmlRpcClient c((const char*)srv->server.c_str(), (int)srv->port, + TOXmlRpcClient c((const char*)srv->server.c_str(), (int)srv->port, (const char*)srv->uri.empty()?NULL:srv->uri.c_str() #ifdef HAVE_XMLRPCPP_SSL , false @@ -212,7 +230,8 @@ void XMLRPC2DI::sendRequest(const AmArg& args, AmArg& ret) { XmlRpcValue x_args, x_result; XMLRPC2DIServer::amarg2xmlrpcval(params, x_args); - if (c.execute(method.c_str(), x_args, x_result) && !c.isFault()) { + + if (c.execute(method.c_str(), x_args, x_result, XMLRPC2DI::ServerTimeout) && !c.isFault()) { DBG("successfully executed method %s on server %s:%d\n", method.c_str(), srv->server.c_str(), srv->port); ret.push(0); @@ -239,7 +258,7 @@ void XMLRPC2DI::sendRequestList(const AmArg& args, AmArg& ret) { ret.push("no active connections"); return; } - XmlRpcClient c((const char*)srv->server.c_str(), (int)srv->port, + TOXmlRpcClient c((const char*)srv->server.c_str(), (int)srv->port, (const char*)srv->uri.empty()?NULL:srv->uri.c_str() #ifdef HAVE_XMLRPCPP_SSL , false @@ -253,7 +272,7 @@ void XMLRPC2DI::sendRequestList(const AmArg& args, AmArg& ret) { XMLRPC2DIServer::amarg2xmlrpcval(args.get(i), x_args[i-2]); } - if (c.execute(method.c_str(), x_args, x_result) && !c.isFault()) { + if (c.execute(method.c_str(), x_args, x_result, XMLRPC2DI::ServerTimeout) && !c.isFault()) { DBG("successfully executed method %s on server %s:%d\n", method.c_str(), srv->server.c_str(), srv->port); ret.push(0); @@ -476,13 +495,13 @@ void XMLRPC2DIServer::xmlrpcval2amarg(XmlRpcValue& v, AmArg& a, xmlrpcval2amarg(v[i], a[a.size()-1], 0); } break; #ifdef XMLRPCPP_SUPPORT_STRUCT_ACCESS - case XmlRpcValue::TypeStruct: { - for (XmlRpc::XmlRpcValue::ValueStruct::iterator it= - ((XmlRpcValue::ValueStruct)v).begin(); - it != ((XmlRpcValue::ValueStruct)v).end(); it++) { - a[it->first] = AmArg(); - xmlrpcval2amarg(it->second, a[it->first], 0); - } + case XmlRpcValue::TypeStruct: { + for (XmlRpc::XmlRpcValue::ValueStruct::iterator it= + ((XmlRpcValue::ValueStruct)v).begin(); + it != ((XmlRpcValue::ValueStruct)v).end(); it++) { + a[it->first] = AmArg(); + xmlrpcval2amarg(it->second, a[it->first], 0); + } } break; #endif diff --git a/apps/xmlrpc2di/XMLRPC2DI.h b/apps/xmlrpc2di/XMLRPC2DI.h index 360afc57..bb497abc 100644 --- a/apps/xmlrpc2di/XMLRPC2DI.h +++ b/apps/xmlrpc2di/XMLRPC2DI.h @@ -157,6 +157,8 @@ class XMLRPC2DI const AmArg& args, AmArg& ret); static unsigned int ServerRetryAfter; + static double ServerTimeout; + }; #endif diff --git a/apps/xmlrpc2di/etc/xmlrpc2di.conf b/apps/xmlrpc2di/etc/xmlrpc2di.conf index 68750d55..2758d25e 100644 --- a/apps/xmlrpc2di/etc/xmlrpc2di.conf +++ b/apps/xmlrpc2di/etc/xmlrpc2di.conf @@ -25,3 +25,7 @@ xmlrpc_port=8090 # run the XMLRPC server at all (default: yes) # # run_server=yes + +# timeout for client requests, in milliseconds (0 to disable) +# +# server_timeout=500