]> git.ipfire.org Git - thirdparty/squid.git/commitdiff
Support multiple services and vectoring-point crossing in ICAP X-Next-Services.
authorAlex Rousskov <rousskov@measurement-factory.com>
Thu, 27 Jan 2011 21:19:45 +0000 (14:19 -0700)
committerAlex Rousskov <rousskov@measurement-factory.com>
Thu, 27 Jan 2011 21:19:45 +0000 (14:19 -0700)
Merged from the 3p1-rock branch (r9630).

src/adaptation/AccessCheck.cc
src/adaptation/AccessCheck.h
src/adaptation/History.cc
src/adaptation/History.h
src/adaptation/Iterator.cc
src/adaptation/Makefile.am
src/adaptation/ServiceGroups.cc
src/adaptation/ServiceGroups.h
src/adaptation/forward.h

index 1f880ba52a6155190647e2bf1ac7e78f168fe343..d63199e01f1668d857080a80ba67b3a7e8aaeca9 100644 (file)
@@ -65,7 +65,31 @@ void
 Adaptation::AccessCheck::start()
 {
     AsyncJob::start();
-    check();
+
+    if (!usedDynamicRules())
+        check();
+}
+
+/// returns true if previous services configured dynamic chaining "rules"
+bool
+Adaptation::AccessCheck::usedDynamicRules()
+{
+    Adaptation::History::Pointer ah = filter.request->adaptHistory();
+    if (!ah)
+        return false; // dynamic rules not enabled or not triggered
+
+    DynamicGroupCfg services;
+    if (!ah->extractFutureServices(services)) { // clears history
+        debugs(85,9, HERE << "no service-proposed rules stored");
+        return false; // earlier service did not plan for the future
+    }
+
+    debugs(85,3, HERE << "using stored service-proposed rules: " << services);
+
+    ServiceGroupPointer g = new DynamicServiceChain(services, filter);
+    callBack(g);
+    Must(done());
+    return true;
 }
 
 /// Walk the access rules list to find rules with applicable service groups
index 11f89af5df2b033b3f4de0c8250272b338652914..e0e4793daf8c7deece85b6e57b1c1f3a718eb7e5 100644 (file)
@@ -55,6 +55,7 @@ protected:
     virtual void start();
     virtual bool doneAll() const { return false; } /// not done until mustStop
 
+    bool usedDynamicRules();
     void check();
 
 private:
index 3eda70b91a8f2fa4c05ab3a69132f93a16b0c410..158da387df9077975008a54ec34ac233362bf355 100644 (file)
@@ -136,3 +136,22 @@ bool Adaptation::History::extractNextServices(String &value)
     theNextServices = TheNullServices; // prevents resetting the plan twice
     return true;
 }
+
+void
+Adaptation::History::setFutureServices(const DynamicGroupCfg &services)
+{
+    if (!theFutureServices.empty())
+        debugs(93,3, HERE << "old future services: " << theFutureServices);
+    debugs(93,3, HERE << "new future services: " << services);
+    theFutureServices = services; // may be empty
+}
+
+bool Adaptation::History::extractFutureServices(DynamicGroupCfg &value)
+{
+    if (theFutureServices.empty())
+        return false;
+
+    value = theFutureServices;
+    theFutureServices.clear();
+    return true;
+}
index 93614d75725af9cd4a799289be46dbee5ad1e264..19d67fbbc138a8d076c985c879aac26a83291053 100644 (file)
@@ -4,6 +4,7 @@
 #include "RefCount.h"
 #include "Array.h"
 #include "SquidString.h"
+#include "adaptation/DynamicGroupCfg.h"
 
 namespace Adaptation
 {
@@ -41,6 +42,12 @@ public:
     /// returns true, fills the value, and resets iff next services were set
     bool extractNextServices(String &value);
 
+    /// sets future services for the Adaptation::AccessCheck to notice
+    void setFutureServices(const DynamicGroupCfg &services);
+
+    /// returns true, fills the value, and resets iff future services were set
+    bool extractFutureServices(DynamicGroupCfg &services);
+
 private:
     /// single Xaction stats (i.e., a historical record entry)
     class Entry
@@ -70,6 +77,7 @@ private:
     String theXxValue; ///< value part of the cross-xactional database record
 
     String theNextServices; ///< services Adaptation::Iterator must use next
+    DynamicGroupCfg theFutureServices; ///< services AccessCheck must use
 };
 
 } // namespace Adaptation
index 6f46121c3894ae96190e69223d9ad3bffd66a0b9..8331f5e13c1f61a001cb149d37586b7c9913ef8a 100644 (file)
@@ -178,8 +178,19 @@ bool Adaptation::Iterator::updatePlan(bool adopt)
     }
 
     debugs(85,3, HERE << "retiring old plan: " << thePlan);
-    theGroup = new DynamicServiceChain(services, theGroup); // refcounted
-    thePlan = ServicePlan(theGroup, filter());
+
+    Adaptation::ServiceFilter filter = this->filter();
+    DynamicGroupCfg current, future;
+    DynamicServiceChain::Split(filter, services, current, future);
+
+    if (!future.empty()) {
+        ah->setFutureServices(future);
+        debugs(85,3, HERE << "noted future service-proposed plan: " << future);
+    }
+
+    // use the current config even if it is empty; we must replace the old plan
+    theGroup = new DynamicServiceChain(current, filter); // refcounted
+    thePlan = ServicePlan(theGroup, filter);
     debugs(85,3, HERE << "adopted service-proposed plan: " << thePlan);
     return true;
 }
index 5ecd433aec03fc96ec6361aaee7ed44f379ecd9b..ca50cac9ff121064f7328fba582b3df416b63e21 100644 (file)
@@ -22,6 +22,8 @@ libadaptation_la_SOURCES = \
        AccessRule.h \
        Config.cc \
        Config.h \
+       DynamicGroupCfg.cc \
+       DynamicGroupCfg.h \
        Elements.cc \
        Elements.h \
        forward.h \
index a680b17e9c66ae323cfe4f5cc8d8a78569845990..4716b4c393e622dfb4ccbbf925308f5f3520434f 100644 (file)
@@ -1,14 +1,13 @@
 #include "squid.h"
 
 #include "ConfigParser.h"
-#include "Array.h"      // really Vector
 #include "adaptation/Config.h"
 #include "adaptation/AccessRule.h"
+#include "adaptation/DynamicGroupCfg.h"
 #include "adaptation/Service.h"
 #include "adaptation/ServiceFilter.h"
 #include "adaptation/ServiceGroups.h"
 
-#define ServiceGroup ServiceGroup
 
 Adaptation::ServiceGroup::ServiceGroup(const String &aKind, bool allSame):
         kind(aKind), method(methodNone), point(pointNone),
@@ -209,28 +208,51 @@ Adaptation::ServiceChain::ServiceChain(): ServiceGroup("adaptation chain", false
 }
 
 
-/* ServiceChain */
+/* DynamicServiceChain */
 
-Adaptation::DynamicServiceChain::DynamicServiceChain(const String &ids,
-        const ServiceGroupPointer prev)
+Adaptation::DynamicServiceChain::DynamicServiceChain(
+    const DynamicGroupCfg &cfg, const ServiceFilter &filter)
 {
     kind = "dynamic adaptation chain"; // TODO: optimize by using String const
-    id = ids; // use services ids as the dynamic group ID
+    id = cfg.id; // use services ids as the dynamic group ID
+    services = cfg.services;
 
     // initialize cache to improve consistency checks in finalize()
-    if (prev != NULL) {
-        method = prev->method;
-        point = prev->point;
-    }
+    method = filter.method;
+    point = filter.point;
+
+    finalize(); // will report [dynamic] config errors
+}
 
-    // populate services storage with supplied service ids
+void
+Adaptation::DynamicServiceChain::Split(const ServiceFilter &filter,
+                                       const String &ids, DynamicGroupCfg &current,
+                                       DynamicGroupCfg &future)
+{
+    // walk the list of services and split it into two parts:
+    // services that are applicable now and future services
+    bool doingCurrent = true;
     const char *item = NULL;
     int ilen = 0;
     const char *pos = NULL;
-    while (strListGetItem(&ids, ',', &item, &ilen, &pos))
-        services.push_back(item);
+    while (strListGetItem(&ids, ',', &item, &ilen, &pos)) {
+        String id;
+        id.limitInit(item, ilen);
+        ServicePointer service = FindService(id);
+        if (doingCurrent) {
+            if (!service || // cannot tell or matches current location
+                    (service->cfg().method == filter.method &&
+                     service->cfg().point == filter.point)) {
+                current.add(id);
+                continue;
+            } else {
+                doingCurrent = false;
+            }
+        }
 
-    finalize(); // will report [dynamic] config errors
+        if (!doingCurrent)
+            future.add(id);
+    }
 }
 
 /* ServicePlan */
index 30b03234f64c5b3c633a299640b71eecfea9ed5b..3cf5c99e25a3afb7540412ca2205b5ece2b21cef 100644 (file)
@@ -100,7 +100,11 @@ protected:
 class DynamicServiceChain: public ServiceChain
 {
 public:
-    DynamicServiceChain(const String &srvcs, const ServiceGroupPointer prev);
+    DynamicServiceChain(const DynamicGroupCfg &cfg, const ServiceFilter &f);
+
+    /// separates dynamic services matching current location from future ones
+    static void Split(const ServiceFilter &filter, const String &ids,
+                      DynamicGroupCfg &current, DynamicGroupCfg &future);
 };
 
 
index 9e693a3e4b5139c58218d4ab2d0cd2d2bdfee3b7..b339c9fb4b60ede559524721eb652c2531425ef9 100644 (file)
@@ -16,6 +16,7 @@ namespace Adaptation
 
 class Service;
 class ServiceConfig;
+class DynamicGroupCfg;
 class Class;
 class Initiate;
 class Initiator;