From: Alex Rousskov Date: Thu, 27 Jan 2011 21:19:45 +0000 (-0700) Subject: Support multiple services and vectoring-point crossing in ICAP X-Next-Services. X-Git-Tag: take01~27 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=16b07f2d0b5f4bfcffeb2b1b049ed8f31842b933;p=thirdparty%2Fsquid.git Support multiple services and vectoring-point crossing in ICAP X-Next-Services. Merged from the 3p1-rock branch (r9630). --- diff --git a/src/adaptation/AccessCheck.cc b/src/adaptation/AccessCheck.cc index 1f880ba52a..d63199e01f 100644 --- a/src/adaptation/AccessCheck.cc +++ b/src/adaptation/AccessCheck.cc @@ -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 diff --git a/src/adaptation/AccessCheck.h b/src/adaptation/AccessCheck.h index 11f89af5df..e0e4793daf 100644 --- a/src/adaptation/AccessCheck.h +++ b/src/adaptation/AccessCheck.h @@ -55,6 +55,7 @@ protected: virtual void start(); virtual bool doneAll() const { return false; } /// not done until mustStop + bool usedDynamicRules(); void check(); private: diff --git a/src/adaptation/History.cc b/src/adaptation/History.cc index 3eda70b91a..158da387df 100644 --- a/src/adaptation/History.cc +++ b/src/adaptation/History.cc @@ -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; +} diff --git a/src/adaptation/History.h b/src/adaptation/History.h index 93614d7572..19d67fbbc1 100644 --- a/src/adaptation/History.h +++ b/src/adaptation/History.h @@ -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 diff --git a/src/adaptation/Iterator.cc b/src/adaptation/Iterator.cc index 6f46121c38..8331f5e13c 100644 --- a/src/adaptation/Iterator.cc +++ b/src/adaptation/Iterator.cc @@ -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; } diff --git a/src/adaptation/Makefile.am b/src/adaptation/Makefile.am index 5ecd433aec..ca50cac9ff 100644 --- a/src/adaptation/Makefile.am +++ b/src/adaptation/Makefile.am @@ -22,6 +22,8 @@ libadaptation_la_SOURCES = \ AccessRule.h \ Config.cc \ Config.h \ + DynamicGroupCfg.cc \ + DynamicGroupCfg.h \ Elements.cc \ Elements.h \ forward.h \ diff --git a/src/adaptation/ServiceGroups.cc b/src/adaptation/ServiceGroups.cc index a680b17e9c..4716b4c393 100644 --- a/src/adaptation/ServiceGroups.cc +++ b/src/adaptation/ServiceGroups.cc @@ -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 ¤t, + 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 */ diff --git a/src/adaptation/ServiceGroups.h b/src/adaptation/ServiceGroups.h index 30b03234f6..3cf5c99e25 100644 --- a/src/adaptation/ServiceGroups.h +++ b/src/adaptation/ServiceGroups.h @@ -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 ¤t, DynamicGroupCfg &future); }; diff --git a/src/adaptation/forward.h b/src/adaptation/forward.h index 9e693a3e4b..b339c9fb4b 100644 --- a/src/adaptation/forward.h +++ b/src/adaptation/forward.h @@ -16,6 +16,7 @@ namespace Adaptation class Service; class ServiceConfig; +class DynamicGroupCfg; class Class; class Initiate; class Initiator;