From: Christos Tsantilas Date: Mon, 24 Jan 2011 17:24:59 +0000 (+0200) Subject: apply the initial Phase3 of the SMP Cache Manager patch X-Git-Tag: take06~27^2~127^2~6 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=b8151fa1c3e4e2f7b729bca1f5a8984b0fc5e4e2;p=thirdparty%2Fsquid.git apply the initial Phase3 of the SMP Cache Manager patch --- diff --git a/src/cache_manager.cc b/src/cache_manager.cc index 95c4ac8f67..4bf081843e 100644 --- a/src/cache_manager.cc +++ b/src/cache_manager.cc @@ -48,6 +48,7 @@ #include "mgr/Command.h" #include "mgr/Forwarder.h" #include "mgr/FunAction.h" +#include "mgr/QueryParams.h" #include "protos.h" /* rotate_logs() */ #include "SquidTime.h" #include "Store.h" @@ -176,7 +177,22 @@ CacheManager::ParseUrl(const char *url) LOCAL_ARRAY(char, host, MAX_URL); LOCAL_ARRAY(char, request, MAX_URL); LOCAL_ARRAY(char, password, MAX_URL); - t = sscanf(url, "cache_object://%[^/]/%[^@]@%s", host, request, password); + LOCAL_ARRAY(char, params, MAX_URL); + host[0] = 0; + request[0] = 0; + password[0] = 0; + params[0] = 0; + int pos = -1; + int len = strlen(url); + Must(len > 0); + t = sscanf(url, "cache_object://%[^/]/%[^@?]%n@%[^?]?%s", host, request, &pos, password, params); + + Must(pos > 0); + if (url[pos] == '?') { + ++pos; + if (pos < len) + xstrncpy(params, url + pos, sizeof(params)); + } if (t < 2) xstrncpy(request, "menu", MAX_URL); @@ -204,10 +220,12 @@ CacheManager::ParseUrl(const char *url) } Mgr::Command::Pointer cmd = new Mgr::Command; + if (!Mgr::QueryParams::Parse(params, cmd->params.queryParams)) + return NULL; cmd->profile = profile; cmd->params.httpUri = url; cmd->params.userName = String(); - cmd->params.password = t == 3 ? String(password) : String(); + cmd->params.password = password; cmd->params.actionName = request; return cmd; } diff --git a/src/mgr/ActionParams.cc b/src/mgr/ActionParams.cc index c05be96528..79355ea349 100644 --- a/src/mgr/ActionParams.cc +++ b/src/mgr/ActionParams.cc @@ -27,6 +27,7 @@ Mgr::ActionParams::ActionParams(const Ipc::TypedMsgHdr &msg) msg.getString(actionName); msg.getString(userName); msg.getString(password); + queryParams.unpack(msg); } void @@ -39,4 +40,5 @@ Mgr::ActionParams::pack(Ipc::TypedMsgHdr &msg) const msg.putString(actionName); msg.putString(userName); msg.putString(password); + queryParams.pack(msg); } diff --git a/src/mgr/ActionParams.h b/src/mgr/ActionParams.h index 4287a53455..cb6e3d4bef 100644 --- a/src/mgr/ActionParams.h +++ b/src/mgr/ActionParams.h @@ -10,6 +10,7 @@ #include "HttpRequestMethod.h" #include "ipc/forward.h" +#include "mgr/QueryParams.h" namespace Mgr { @@ -33,7 +34,7 @@ public: String actionName; ///< action name (and credentials realm) String userName; ///< user login name; currently only used for logging String password; ///< user password; used for acceptance check and cleared - + QueryParams queryParams; }; } // namespace Mgr diff --git a/src/mgr/Inquirer.cc b/src/mgr/Inquirer.cc index d249c3a913..1c8b5bbc1f 100644 --- a/src/mgr/Inquirer.cc +++ b/src/mgr/Inquirer.cc @@ -13,6 +13,7 @@ #include "ipc/Coordinator.h" #include "mgr/ActionWriter.h" #include "mgr/Command.h" +#include "mgr/IntParam.h" #include "mgr/Inquirer.h" #include "mgr/Request.h" #include "mgr/Response.h" @@ -39,14 +40,11 @@ Mgr::Inquirer::Inquirer(Action::Pointer anAction, int aFd, aggrAction(anAction), cause(aCause), fd(aFd), - strands(coords), pos(strands.begin()), + strands(applyQueryParams(coords, aCause.params.queryParams)), pos(strands.begin()), requestId(0), closer(NULL), timeout(aggrAction->atomic() ? 10 : 100) { debugs(16, 5, HERE << "FD " << aFd << " action: " << aggrAction); - // order by ascending kid IDs; useful for non-aggregatable stats - std::sort(strands.begin(), strands.end(), LesserStrandByKidId); - closer = asyncCall(16, 5, "Mgr::Inquirer::noteCommClosed", CommCbMemFunT(this, &Inquirer::noteCommClosed)); comm_add_close_handler(fd, closer); @@ -86,7 +84,7 @@ Mgr::Inquirer::start() Must(aggrAction != NULL); std::auto_ptr reply(new HttpReply); - reply->setHeaders(HTTP_OK, NULL, "text/plain", -1, squid_curtime, squid_curtime); + reply->setHeaders(strands.empty() ? HTTP_BAD_REQUEST : HTTP_OK, NULL, "text/plain", -1, squid_curtime, squid_curtime); reply->header.putStr(HDR_CONNECTION, "close"); // until we chunk response std::auto_ptr replyBuf(reply->pack()); writer = asyncCall(16, 5, "Mgr::Inquirer::noteWroteHeader", @@ -166,7 +164,7 @@ Mgr::Inquirer::swanSong() DequeueRequest(requestId); requestId = 0; } - if (aggrAction->aggregatable()) { + if (!strands.empty() && aggrAction->aggregatable()) { removeCloseHandler(); AsyncJob::Start(new ActionWriter(aggrAction, fd)); fd = -1; // should not close fd because we passed it to ActionWriter @@ -251,3 +249,49 @@ Mgr::Inquirer::status() const buf.terminate(); return buf.content(); } + +Ipc::StrandCoords +Mgr::Inquirer::applyQueryParams(const Ipc::StrandCoords& aStrands, const QueryParams& aParams) +{ + Ipc::StrandCoords strands; + + QueryParam::Pointer processesParam = cause.params.queryParams.get("processes"); + QueryParam::Pointer workersParam = cause.params.queryParams.get("workers"); + + if (processesParam == NULL || workersParam == NULL) { + if (processesParam != NULL) { + IntParam* param = dynamic_cast(processesParam.getRaw()); + if (param != NULL && param->type == QueryParam::ptInt) { + const std::vector& processes = param->value(); + for (Ipc::StrandCoords::const_iterator iter = aStrands.begin(); + iter != aStrands.end(); ++iter) + { + if (std::find(processes.begin(), processes.end(), iter->kidId) != processes.end()) + strands.push_back(*iter); + } + } + } else if (workersParam != NULL) { + IntParam* param = dynamic_cast(workersParam.getRaw()); + if (param != NULL && param->type == QueryParam::ptInt) { + const std::vector& workers = param->value(); + for (size_t i = 0; i < aStrands.size(); ++i) + { + if (std::find(workers.begin(), workers.end(), i + 1) != workers.end()) + strands.push_back(aStrands[i]); + } + } + } else { + strands = aStrands; + } + + // order by ascending kid IDs; useful for non-aggregatable stats + std::sort(strands.begin(), strands.end(), LesserStrandByKidId); + } + + debugs(0, 0, HERE << "strands kid IDs = "); + for (Ipc::StrandCoords::const_iterator iter = strands.begin(); iter != strands.end(); ++iter) { + debugs(0, 0, HERE << iter->kidId); + } + + return strands; +} diff --git a/src/mgr/Inquirer.h b/src/mgr/Inquirer.h index 7059daa2b3..92cc0a1c3e 100644 --- a/src/mgr/Inquirer.h +++ b/src/mgr/Inquirer.h @@ -58,6 +58,8 @@ private: void close(); void removeCloseHandler(); + Ipc::StrandCoords applyQueryParams(const Ipc::StrandCoords& aStrands, + const QueryParams& aParams); private: Action::Pointer aggrAction; //< action to aggregate diff --git a/src/mgr/IntParam.cc b/src/mgr/IntParam.cc new file mode 100644 index 0000000000..d67382d926 --- /dev/null +++ b/src/mgr/IntParam.cc @@ -0,0 +1,48 @@ +/* + * $Id$ + * + * DEBUG: section 16 Cache Manager API + * + */ + +#include "config.h" +#include "base/TextException.h" +#include "ipc/TypedMsgHdr.h" +#include "mgr/IntParam.h" + + +Mgr::IntParam::IntParam(): + QueryParam(QueryParam::ptInt), array() +{ +} + +Mgr::IntParam::IntParam(const std::vector& anArray): + QueryParam(QueryParam::ptInt), array(anArray) +{ +} + +void +Mgr::IntParam::pack(Ipc::TypedMsgHdr& msg) const +{ + msg.putPod(type); + msg.putInt(array.size()); + typedef std::vector::const_iterator Iterator; + for (Iterator iter = array.begin(); iter != array.end(); ++iter) + msg.putInt(*iter); +} + +void +Mgr::IntParam::unpackValue(const Ipc::TypedMsgHdr& msg) +{ + array.clear(); + int count = msg.getInt(); + Must(count >= 0); + for ( ; count > 0; --count) + array.push_back(msg.getInt()); +} + +const std::vector& +Mgr::IntParam::value() const +{ + return array; +} diff --git a/src/mgr/IntParam.h b/src/mgr/IntParam.h new file mode 100644 index 0000000000..fcf2ac0592 --- /dev/null +++ b/src/mgr/IntParam.h @@ -0,0 +1,35 @@ +/* + * $Id$ + * + * DEBUG: section 16 Cache Manager API + * + */ + +#ifndef SQUID_MGR_INT_PARAM_H +#define SQUID_MGR_INT_PARAM_H + +#include "ipc/forward.h" +#include "mgr/forward.h" +#include "mgr/QueryParam.h" +#include + + +namespace Mgr +{ + +class IntParam: public QueryParam +{ +public: + IntParam(); + IntParam(const std::vector& anArray); + virtual void pack(Ipc::TypedMsgHdr& msg) const; + virtual void unpackValue(const Ipc::TypedMsgHdr& msg); + const std::vector& value() const; + +private: + std::vector array; +}; + +} // namespace Mgr + +#endif /* SQUID_MGR_INT_PARAM_H */ diff --git a/src/mgr/Makefile.am b/src/mgr/Makefile.am index 2d7d543002..690ba6089e 100644 --- a/src/mgr/Makefile.am +++ b/src/mgr/Makefile.am @@ -44,4 +44,11 @@ libmgr_la_SOURCES = \ StoreIoAction.cc \ StoreIoAction.h \ StoreToCommWriter.cc \ - StoreToCommWriter.h + StoreToCommWriter.h \ + QueryParam.h \ + QueryParams.cc \ + QueryParams.h \ + IntParam.cc \ + IntParam.h \ + StringParam.cc \ + StringParam.h diff --git a/src/mgr/QueryParam.h b/src/mgr/QueryParam.h new file mode 100644 index 0000000000..5fc3a84d4c --- /dev/null +++ b/src/mgr/QueryParam.h @@ -0,0 +1,40 @@ +/* + * $Id$ + * + * DEBUG: section 16 Cache Manager API + * + */ + +#ifndef SQUID_MGR_QUERY_PARAM_H +#define SQUID_MGR_QUERY_PARAM_H + +#include "ipc/forward.h" +#include "RefCount.h" + + +namespace Mgr +{ + +class QueryParam: public RefCountable +{ +public: + typedef enum {ptInt = 1, ptString} Type; + typedef RefCount Pointer; + +public: + QueryParam(Type aType): type(aType) {} + virtual ~QueryParam() {} + virtual void pack(Ipc::TypedMsgHdr& msg) const = 0; ///< store parameter into msg + virtual void unpackValue(const Ipc::TypedMsgHdr& msg) = 0; ///< load parameter value from msg + +private: + QueryParam(const QueryParam&); // not implemented + QueryParam& operator= (const QueryParam&); // not implemented + +public: + Type type; +}; + +} // namespace Mgr + +#endif /* SQUID_MGR_QUERY_PARAM_H */ diff --git a/src/mgr/QueryParams.cc b/src/mgr/QueryParams.cc new file mode 100644 index 0000000000..3a0426b647 --- /dev/null +++ b/src/mgr/QueryParams.cc @@ -0,0 +1,139 @@ +/* + * $Id$ + * + * DEBUG: section 16 Cache Manager API + * + */ + +#include "config.h" +#include "base/TextException.h" +#include "ipc/TypedMsgHdr.h" +#include "mgr/IntParam.h" +#include "mgr/StringParam.h" +#include "mgr/QueryParams.h" +#include + + +Mgr::QueryParam::Pointer +Mgr::QueryParams::get(const String& name) +{ + Must(name.size() != 0); + Params::iterator pos = find(name); + return (pos == params.end() ? NULL : pos->second); +} + +void +Mgr::QueryParams::pack(Ipc::TypedMsgHdr& msg) const +{ + msg.putInt(params.size()); + for (Params::const_iterator iter = params.begin(); iter != params.end(); ++iter) { + Must(iter->first.size() != 0); + msg.putString(iter->first); + Must(iter->second != NULL); + iter->second->pack(msg); + } +} + +void +Mgr::QueryParams::unpack(const Ipc::TypedMsgHdr& msg) +{ + int count = msg.getInt(); + Must(count >= 0); + params.clear(); + for ( ; count > 0; --count) { + String name; + msg.getString(name); + Must(name.size() != 0); + QueryParam::Type type; + msg.getPod(type); + QueryParam::Pointer value = CreateParam(type); + value->unpackValue(msg); + params.push_back(Param(name, value)); + } +} + +Mgr::QueryParams::Params::iterator +Mgr::QueryParams::find(const String& name) +{ + Must(name.size() != 0); + Params::iterator iter = params.begin(); + for ( ; iter != params.end(); ++iter) { + if (name.caseCmp(iter->first) == 0) + break; + } + return iter; +} + +bool +Mgr::QueryParams::ParseParam(const String& paramStr, Param& param) +{ + bool parsed = false; + regmatch_t pmatch[3]; + regex_t intExpr; + regcomp(&intExpr, "^([a-z][a-z0-9_]*)=([0-9]+((,[0-9]+))*)$", REG_EXTENDED | REG_ICASE); + regex_t stringExpr; + regcomp(&stringExpr, "^([a-z][a-z0-9_]*)=([^&= ]+)$", REG_EXTENDED | REG_ICASE); + if (regexec(&intExpr, paramStr.termedBuf(), 3, pmatch, 0) == 0) { + param.first = paramStr.substr(pmatch[1].rm_so, pmatch[1].rm_eo); + std::vector array; + int n = pmatch[2].rm_so; + for (int i = n; i < pmatch[2].rm_eo; ++i) { + if (paramStr[i] == ',') { + array.push_back(atoi(paramStr.substr(n, i).termedBuf())); + n = i + 1; + } + } + if (n < pmatch[2].rm_eo) + array.push_back(atoi(paramStr.substr(n, pmatch[2].rm_eo).termedBuf())); + param.second = new IntParam(array); + parsed = true; + } else if (regexec(&stringExpr, paramStr.termedBuf(), 3, pmatch, 0) == 0) { + param.first = paramStr.substr(pmatch[1].rm_so, pmatch[1].rm_eo); + param.second = new StringParam(paramStr.substr(pmatch[2].rm_so, pmatch[2].rm_eo)); + parsed = true; + } + regfree(&stringExpr); + regfree(&intExpr); + return parsed; +} + +bool +Mgr::QueryParams::Parse(const String& aParamsStr, QueryParams& aParams) +{ + if (aParamsStr.size() != 0) { + Param param; + size_t n = 0; + size_t len = aParamsStr.size(); + for (size_t i = n; i < len; ++i) { + if (aParamsStr[i] == '&') { + if (!ParseParam(aParamsStr.substr(n, i), param)) + return false; + aParams.params.push_back(param); + n = i + 1; + } + } + if (n < len) { + if (!ParseParam(aParamsStr.substr(n, len), param)) + return false; + aParams.params.push_back(param); + } + } + return true; +} + +Mgr::QueryParam::Pointer +Mgr::QueryParams::CreateParam(QueryParam::Type aType) +{ + switch(aType) { + case QueryParam::ptInt: + return new IntParam(); + + case QueryParam::ptString: + return new StringParam(); + + default: + throw TexcHere("unknown parameter type"); + break; + } + return NULL; +} diff --git a/src/mgr/QueryParams.h b/src/mgr/QueryParams.h new file mode 100644 index 0000000000..4a9fef093d --- /dev/null +++ b/src/mgr/QueryParams.h @@ -0,0 +1,49 @@ +/* + * $Id$ + * + * DEBUG: section 16 Cache Manager API + * + */ + +#ifndef SQUID_MGR_QUERY_PARAMS_H +#define SQUID_MGR_QUERY_PARAMS_H + +#include "ipc/forward.h" +#include "mgr/QueryParam.h" +#include "SquidString.h" +#include +#include + + +namespace Mgr +{ + +class QueryParams +{ +public: + typedef std::pair Param; + typedef std::vector Params; + +public: + /// returns query parameter by name + QueryParam::Pointer get(const String& name); + void pack(Ipc::TypedMsgHdr& msg) const; ///< store params into msg + void unpack(const Ipc::TypedMsgHdr& msg); ///< load params from msg + /// parses the query string parameters + static bool Parse(const String& aParamsStr, QueryParams& aParams); + +private: + /// find query parameter by name + Params::iterator find(const String& name); + /// creates a parameter of the specified type + static QueryParam::Pointer CreateParam(QueryParam::Type aType); + /// parses string like "param=value"; returns true if success + static bool ParseParam(const String& paramStr, Param& param); + +private: + Params params; +}; + +} // namespace Mgr + +#endif /* SQUID_MGR_QUERY_PARAMS_H */ diff --git a/src/mgr/StringParam.cc b/src/mgr/StringParam.cc new file mode 100644 index 0000000000..2f82d9d2b8 --- /dev/null +++ b/src/mgr/StringParam.cc @@ -0,0 +1,40 @@ +/* + * $Id$ + * + * DEBUG: section 16 Cache Manager API + * + */ + +#include "config.h" +#include "ipc/TypedMsgHdr.h" +#include "mgr/StringParam.h" + + +Mgr::StringParam::StringParam(): + QueryParam(QueryParam::ptString), str() +{ +} + +Mgr::StringParam::StringParam(const String& aString): + QueryParam(QueryParam::ptString), str(aString) +{ +} + +void +Mgr::StringParam::pack(Ipc::TypedMsgHdr& msg) const +{ + msg.putPod(type); + msg.putString(str); +} + +void +Mgr::StringParam::unpackValue(const Ipc::TypedMsgHdr& msg) +{ + msg.getString(str); +} + +const String& +Mgr::StringParam::value() const +{ + return str; +} diff --git a/src/mgr/StringParam.h b/src/mgr/StringParam.h new file mode 100644 index 0000000000..e690b8d6c7 --- /dev/null +++ b/src/mgr/StringParam.h @@ -0,0 +1,35 @@ +/* + * $Id$ + * + * DEBUG: section 16 Cache Manager API + * + */ + +#ifndef SQUID_MGR_STRING_PARAM_H +#define SQUID_MGR_STRING_PARAM_H + +#include "ipc/forward.h" +#include "mgr/forward.h" +#include "mgr/QueryParam.h" +#include "SquidString.h" + + +namespace Mgr +{ + +class StringParam: public QueryParam +{ +public: + StringParam(); + StringParam(const String& aString); + virtual void pack(Ipc::TypedMsgHdr& msg) const; + virtual void unpackValue(const Ipc::TypedMsgHdr& msg); + const String& value() const; + +private: + String str; +}; + +} // namespace Mgr + +#endif /* SQUID_MGR_STRING_PARAM_H */ diff --git a/src/mgr/forward.h b/src/mgr/forward.h index ecf303a948..f6592a0f1d 100644 --- a/src/mgr/forward.h +++ b/src/mgr/forward.h @@ -20,6 +20,8 @@ class ActionWriter; class Command; class Request; class Response; +class QueryParam; +class QueryParams; typedef RefCount ActionPointer; typedef RefCount ActionProfilePointer;