]> git.ipfire.org Git - thirdparty/squid.git/commitdiff
apply the initial Phase3 of the SMP Cache Manager patch
authorChristos Tsantilas <chtsanti@users.sourceforge.net>
Mon, 24 Jan 2011 17:24:59 +0000 (19:24 +0200)
committerChristos Tsantilas <chtsanti@users.sourceforge.net>
Mon, 24 Jan 2011 17:24:59 +0000 (19:24 +0200)
14 files changed:
src/cache_manager.cc
src/mgr/ActionParams.cc
src/mgr/ActionParams.h
src/mgr/Inquirer.cc
src/mgr/Inquirer.h
src/mgr/IntParam.cc [new file with mode: 0644]
src/mgr/IntParam.h [new file with mode: 0644]
src/mgr/Makefile.am
src/mgr/QueryParam.h [new file with mode: 0644]
src/mgr/QueryParams.cc [new file with mode: 0644]
src/mgr/QueryParams.h [new file with mode: 0644]
src/mgr/StringParam.cc [new file with mode: 0644]
src/mgr/StringParam.h [new file with mode: 0644]
src/mgr/forward.h

index 95c4ac8f67440ca3aad036d9140ed8a79a084912..4bf081843e934ff38ba41a86bd0625ffe43be646 100644 (file)
@@ -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;
 }
index c05be965285fc8cc4d6b39a97bac178ee786871a..79355ea3496d1092b3e094b4fbde47b8d22dc02a 100644 (file)
@@ -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);
 }
index 4287a534556401495e5b09b121d6b68555409619..cb6e3d4befaec9c21026b0b54e43355671e7ce66 100644 (file)
@@ -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
index d249c3a9136948cf1987ab7ad4dd416fc39667c2..1c8b5bbc1fc10bbe94dc0f2cb1e9797ffe329198 100644 (file)
@@ -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<Inquirer, CommCloseCbParams>(this, &Inquirer::noteCommClosed));
     comm_add_close_handler(fd, closer);
@@ -86,7 +84,7 @@ Mgr::Inquirer::start()
     Must(aggrAction != NULL);
 
     std::auto_ptr<HttpReply> 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<MemBuf> 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<IntParam*>(processesParam.getRaw());
+            if (param != NULL && param->type == QueryParam::ptInt) {
+                const std::vector<int>& 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<IntParam*>(workersParam.getRaw());
+            if (param != NULL && param->type == QueryParam::ptInt) {
+                const std::vector<int>& 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;
+}
index 7059daa2b3945a2c72e12e2b13dc9fc63f40a9c2..92cc0a1c3e88073c1bd59342d329d512d0e49440 100644 (file)
@@ -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 (file)
index 0000000..d67382d
--- /dev/null
@@ -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<int>& anArray):
+    QueryParam(QueryParam::ptInt), array(anArray)
+{
+}
+
+void
+Mgr::IntParam::pack(Ipc::TypedMsgHdr& msg) const
+{
+    msg.putPod(type);
+    msg.putInt(array.size());
+    typedef std::vector<int>::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<int>&
+Mgr::IntParam::value() const
+{
+    return array;
+}
diff --git a/src/mgr/IntParam.h b/src/mgr/IntParam.h
new file mode 100644 (file)
index 0000000..fcf2ac0
--- /dev/null
@@ -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 <vector>
+
+
+namespace Mgr
+{
+
+class IntParam: public QueryParam
+{
+public:
+    IntParam();
+    IntParam(const std::vector<int>& anArray);
+    virtual void pack(Ipc::TypedMsgHdr& msg) const;
+    virtual void unpackValue(const Ipc::TypedMsgHdr& msg);
+    const std::vector<int>& value() const;
+
+private:
+    std::vector<int> array;
+};
+
+} // namespace Mgr
+
+#endif /* SQUID_MGR_INT_PARAM_H */
index 2d7d543002069873d1db24186d68c6a748bebe82..690ba6089ebcd2fed87a1e20e3c7a5b192e996f8 100644 (file)
@@ -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 (file)
index 0000000..5fc3a84
--- /dev/null
@@ -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<QueryParam> 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 (file)
index 0000000..3a0426b
--- /dev/null
@@ -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 <regex.h>
+
+
+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<int> 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 (file)
index 0000000..4a9fef0
--- /dev/null
@@ -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 <vector>
+#include <utility>
+
+
+namespace Mgr
+{
+
+class QueryParams
+{
+public:
+    typedef std::pair<String, QueryParam::Pointer> Param;
+    typedef std::vector<Param> 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 (file)
index 0000000..2f82d9d
--- /dev/null
@@ -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 (file)
index 0000000..e690b8d
--- /dev/null
@@ -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 */
index ecf303a948d622afd0d36dfb6361e5c3a70dccc2..f6592a0f1d22282f87e802546326d1102be41d50 100644 (file)
@@ -20,6 +20,8 @@ class ActionWriter;
 class Command;
 class Request;
 class Response;
+class QueryParam;
+class QueryParams;
 
 typedef RefCount<Action> ActionPointer;
 typedef RefCount<ActionProfile> ActionProfilePointer;