]> git.ipfire.org Git - thirdparty/squid.git/blobdiff - src/adaptation/ServiceGroups.h
SourceFormat Enforcement
[thirdparty/squid.git] / src / adaptation / ServiceGroups.h
index e76f1474f18d349598daa8e9be94b81d8a0a9758..a0d2ea5069bc733ff96cf73bc9d68a67547d58ed 100644 (file)
@@ -1,42 +1,76 @@
+/*
+ * Copyright (C) 1996-2017 The Squid Software Foundation and contributors
+ *
+ * Squid software is distributed under GPLv2+ license and includes
+ * contributions from numerous individuals and organizations.
+ * Please see the COPYING and CONTRIBUTORS files for details.
+ */
+
 #ifndef SQUID_ADAPTATION__SERVICE_GROUPS_H
 #define SQUID_ADAPTATION__SERVICE_GROUPS_H
 
+#include "adaptation/Elements.h"
 #include "adaptation/forward.h"
+#include "base/RefCount.h"
+#include "SquidString.h"
+
+#include <vector>
 
-namespace Adaptation {
+namespace Adaptation
+{
 
 // Interface for grouping adaptation services together.
 // Specific groups differ in how the first and the next services are selected
-class ServiceGroup
+class ServiceGroup: public RefCountable
 {
 public:
-    typedef Vector<String> Store;
-    typedef Store::iterator iterator;
-    typedef String Id;
+    typedef RefCount<ServiceGroup> Pointer;
 
-    // Information sufficient to iterate services stored in the group,
-    // grouped together to simplify initial/sequentialServices interfaces.
-    // The iterators point back to 
-    struct Loop {
-        Loop(const iterator &b, const iterator &e): begin(b), end(e) {}
-               iterator begin;
-               iterator end;
-       };
+    typedef std::vector<String> Store;
+    typedef String Id;
+    typedef unsigned int Pos; // vector<>::position_type
+    friend class ServicePlan;
 
 public:
-    ServiceGroup(const String &aKind);
+    ServiceGroup(const String &aKind, bool areAllServicesSame);
     virtual ~ServiceGroup();
 
     virtual void parse();
     virtual void finalize(); // called after all are parsed
 
-    virtual Loop initialServices() = 0;
-    // TODO: virtual Loop sequentialServices() = 0;
+    bool wants(const ServiceFilter &filter) const;
+
+protected:
+    ///< whether this group has a service at the specified pos
+    bool has(const Pos pos) const {
+        // does not check that the service at pos still exists
+        return pos < services.size(); // unsigned pos is never negative
+    }
+
+    /// these methods control group iteration; used by ServicePlan
+
+    /// find next to try after failure, starting with pos
+    bool findReplacement(const ServiceFilter &filter, Pos &pos) const;
+    /// find next to link after success, starting with pos
+    bool findLink(const ServiceFilter &filter, Pos &pos) const;
+
+private:
+    ServicePointer at(const Pos pos) const;
+    bool findService(const ServiceFilter &filter, Pos &pos) const;
+
+    void checkUniqueness(const Pos checkedPos) const;
+    void finalizeMsg(const char *msg, const String &culprit, bool error) const;
 
 public:
     String kind;
     Id id;
     Store services;
+    Store removedServices;///< the disabled services in the case ecap or icap is disabled
+
+    Method method; /// based on the first added service
+    VectPoint point; /// based on the first added service
+
+    const bool allServicesSame; // whether we can freely substitute services
 };
 
 // a group of equivalent services; one service per set is usually used
@@ -44,7 +78,10 @@ class ServiceSet: public ServiceGroup
 {
 public:
     ServiceSet();
-    virtual Loop initialServices();
+
+protected:
+    virtual bool replace(Pos &pos) const { return has(++pos); }
+    virtual bool advance(Pos &) const { return false; }
 };
 
 // corner case: a group consisting of one service
@@ -52,17 +89,70 @@ class SingleService: public ServiceGroup
 {
 public:
     SingleService(const String &aServiceKey);
-    virtual Loop initialServices();
+
+protected:
+    virtual bool replace(Pos &) const { return false; }
+    virtual bool advance(Pos &) const { return false; }
 };
 
-// TODO: a group of services that must be used one after another
-// class ServiceChain: public ServiceGroup
+/// a group of services that must be used one after another
+class ServiceChain: public ServiceGroup
+{
+public:
+    ServiceChain();
 
+protected:
+    virtual bool replace(Pos &) const { return false; }
+    virtual bool advance(Pos &pos) const { return has(++pos); }
+};
 
-typedef Vector<Adaptation::ServiceGroup*> Groups;
-extern Groups &AllGroups();
-extern ServiceGroup *FindGroup(const ServiceGroup::Id &id);
+/// a temporary service chain built upon another service request
+class DynamicServiceChain: public ServiceChain
+{
+public:
+    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);
+};
+
+/** iterates services stored in a group; iteration is not linear because we
+    need to both replace failed services and advance to the next chain link */
+class ServicePlan
+{
+public:
+    typedef unsigned int Pos; // vector<>::position_type
+
+public:
+    ServicePlan();
+    explicit ServicePlan(const ServiceGroupPointer &g, const ServiceFilter &filter);
+
+    ///< true iff there are no more services planned
+    bool exhausted() const { return atEof; }
+
+    /// returns nil if the plan is complete
+    ServicePointer current() const; ///< current service
+    ServicePointer replacement(const ServiceFilter &filter); ///< next to try after failure
+    ServicePointer next(const ServiceFilter &filter); ///< next in chain after success
+
+    std::ostream &print(std::ostream &os) const;
+
+private:
+    ServiceGroupPointer group; ///< the group we are iterating
+    Pos pos; ///< current service position within the group
+    bool atEof; ///< cached information for better performance
+};
+
+inline
+std::ostream &operator <<(std::ostream &os, const ServicePlan &p)
+{
+    return p.print(os);
+}
 
+typedef std::vector<ServiceGroupPointer> Groups;
+Groups &AllGroups();
+ServiceGroupPointer FindGroup(const ServiceGroup::Id &id);
 
 } // namespace Adaptation