ServiceGroups.cc
Go to the documentation of this file.
1/*
2 * Copyright (C) 1996-2022 The Squid Software Foundation and contributors
3 *
4 * Squid software is distributed under GPLv2+ license and includes
5 * contributions from numerous individuals and organizations.
6 * Please see the COPYING and CONTRIBUTORS files for details.
7 */
8
9#include "squid.h"
11#include "adaptation/Config.h"
13#include "adaptation/Service.h"
16#include "ConfigParser.h"
17#include "debug/Stream.h"
18#include "StrList.h"
19#include "wordlist.h"
20
22 kind(aKind), method(methodNone), point(pointNone),
23 allServicesSame(allSame)
24{
25}
26
28{
29}
30
31void
33{
35
36 wordlist *names = nullptr;
38 for (wordlist *i = names; i; i = i->next)
39 services.push_back(i->key);
40 wordlistDestroy(&names);
41}
42
43// Note: configuration code aside, this method is called by DynamicServiceChain
44void
46{
47 // 1) warn if services have different methods or vectoring point
48 // 2) warn if all-same services have different bypass status
49 // 3) warn if there are seemingly identical services in the group
50 // TODO: optimize by remembering ServicePointers rather than IDs
51 if (!removedServices.empty()) {
52 String s;
53 for (Store::iterator it = removedServices.begin(); it != removedServices.end(); ++it) {
54 s.append(*it);
55 s.append(',');
56 }
57 s.cut(s.size() - 1);
58 debugs(93, DBG_IMPORTANT, "Adaptation group '" << id << "' contains disabled member(s) after reconfiguration: " << s);
59 removedServices.clear();
60 }
61
62 String baselineKey;
63 bool baselineBypass = false;
64 for (Pos pos = 0; has(pos); ++pos) {
65 // TODO: quit on all errors
66 const String &serviceId = services[pos];
67 ServicePointer service = at(pos);
68 if (service != nullptr) {
69 if (method == methodNone) {
70 // optimization: cache values that should be the same
71 method = service->cfg().method;
72 point = service->cfg().point;
73 } else {
74 if (method != service->cfg().method)
75 finalizeMsg("Inconsistent service method for", serviceId, true);
76 if (point != service->cfg().point)
77 finalizeMsg("Inconsistent vectoring point for", serviceId, true);
78 }
79
80 checkUniqueness(pos);
81
82 if (allServicesSame) {
83 if (!baselineKey.size()) {
84 baselineKey = service->cfg().key;
85 baselineBypass = service->cfg().bypass;
86 } else if (baselineBypass != service->cfg().bypass) {
87 debugs(93, DBG_CRITICAL, "WARNING: Inconsistent bypass in " << kind <<
88 ' ' << id << " may produce surprising results: " <<
89 baselineKey << " vs. " << serviceId);
90 }
91 }
92 } else {
93 finalizeMsg("ERROR: Unknown adaptation name", serviceId, true);
94 }
95 }
96 debugs(93,7, "finalized " << kind << ": " << id);
97}
98
100void
102{
103 ServicePointer checkedService = at(checkedPos);
104 if (!checkedService) // should not happen but be robust
105 return;
106
107 for (Pos p = checkedPos + 1; has(p); ++p) {
108 ServicePointer s = at(p);
109 if (s != nullptr && s->cfg().key == checkedService->cfg().key)
110 finalizeMsg("duplicate service name", s->cfg().key, false);
111 else if (s != nullptr && s->cfg().uri == checkedService->cfg().uri)
112 finalizeMsg("duplicate service URI", s->cfg().uri, false);
113 }
114}
115
117void
118Adaptation::ServiceGroup::finalizeMsg(const char *msg, const String &culprit,
119 bool error) const
120{
121 const int level = error ? DBG_CRITICAL :DBG_IMPORTANT;
122 const char *pfx = error ? "ERROR: " : "WARNING: ";
123 debugs(93,level, pfx << msg << ' ' << culprit << " in " << kind << " '" <<
124 id << "'");
125}
126
128{
129 return FindService(services[pos]);
130}
131
132// TODO: optimize to cut search short instead of looking for the best svc
133bool
135{
136 Pos pos = 0;
137 return findService(filter, pos);
138}
139
140bool
142{
143 if (method != filter.method || point != filter.point) {
144 debugs(93,5, id << " serves another location");
145 return false; // assume other services have the same wrong location
146 }
147
148 // find the next interested service, skipping problematic ones if possible
149 bool foundEssential = false;
150 Pos essPos = 0;
151 for (; has(pos); ++pos) {
152 debugs(93,9, id << " checks service at " << pos);
153 ServicePointer service = at(pos);
154
155 if (!service)
156 continue; // the service was lost due to reconfiguration
157
158 if (!service->wants(filter))
159 continue; // the service is not interested
160
161 if (service->up() || !service->probed()) {
162 debugs(93,9, id << " has matching service at " << pos);
163 return true;
164 }
165
166 if (service->cfg().bypass) { // we can safely ignore bypassable downers
167 debugs(93,9, id << " has bypassable service at " << pos);
168 continue;
169 }
170
171 if (!allServicesSame) { // cannot skip (i.e., find best) service
172 debugs(93,9, id << " has essential service at " << pos);
173 return true;
174 }
175
176 if (!foundEssential) {
177 debugs(93,9, id << " searches for best essential service from " << pos);
178 foundEssential = true;
179 essPos = pos;
180 }
181 }
182
183 if (foundEssential) {
184 debugs(93,9, id << " has best essential service at " << essPos);
185 pos = essPos;
186 return true;
187 }
188
189 debugs(93,5, id << " has no matching services");
190 return false;
191}
192
193bool
195{
196 return allServicesSame && findService(filter, pos);
197}
198
199bool
201{
202 return !allServicesSame && findService(filter, pos);
203}
204
205/* ServiceSet */
206
208{
209}
210
211/* SingleService */
212
214 ServiceGroup("single-service group", false)
215{
216 id = aServiceId;
217 services.push_back(aServiceId);
218}
219
220/* ServiceChain */
221
223{
224}
225
226/* DynamicServiceChain */
227
229 const DynamicGroupCfg &cfg, const ServiceFilter &filter)
230{
231 kind = "dynamic adaptation chain"; // TODO: optimize by using String const
232 id = cfg.id; // use services ids as the dynamic group ID
233 services = cfg.services;
234
235 // initialize cache to improve consistency checks in finalize()
236 method = filter.method;
237 point = filter.point;
238
239 finalize(); // will report [dynamic] config errors
240}
241
242void
244 const String &ids, DynamicGroupCfg &current,
245 DynamicGroupCfg &future)
246{
247 // walk the list of services and split it into two parts:
248 // services that are applicable now and future services
249 bool doingCurrent = true;
250 const char *item = nullptr;
251 int ilen = 0;
252 const char *pos = nullptr;
253 while (strListGetItem(&ids, ',', &item, &ilen, &pos)) {
254 String id;
255 id.assign(item, ilen);
256 ServicePointer service = FindService(id);
257 if (doingCurrent) {
258 if (!service || // cannot tell or matches current location
259 (service->cfg().method == filter.method &&
260 service->cfg().point == filter.point)) {
261 current.add(id);
262 continue;
263 } else {
264 doingCurrent = false;
265 }
266 }
267
268 if (!doingCurrent)
269 future.add(id);
270 }
271}
272
273/* ServicePlan */
274
276{
277}
278
280 const ServiceFilter &filter):
281 group(g), pos(0), atEof(!g || !g->has(pos))
282{
283 // this will find the first service because starting pos is zero
284 if (!atEof && !group->findService(filter, pos))
285 atEof = true;
286}
287
290{
291 // may return NULL even if not atEof
292 return atEof ? Adaptation::ServicePointer() : group->at(pos);
293}
294
297{
298 if (!atEof && !group->findReplacement(filter, ++pos))
299 atEof = true;
300 return current();
301}
302
305{
306 if (!atEof && !group->findLink(filter, ++pos))
307 atEof = true;
308 return current();
309}
310
311std::ostream &
312Adaptation::ServicePlan::print(std::ostream &os) const
313{
314 if (!group)
315 return os << "[nil]";
316
317 return os << group->id << '[' << pos << ".." << group->services.size() <<
318 (atEof ? ".]" : "]");
319}
320
321/* globals */
322
325{
326 static Groups *TheGroups = new Groups;
327 return *TheGroups;
328}
329
332{
333 typedef Groups::iterator GI;
334 for (GI i = AllGroups().begin(); i != AllGroups().end(); ++i) {
335 if ((*i)->id == id)
336 return *i;
337 }
338
339 return nullptr;
340}
341
#define true
Definition: GnuRegex.c:241
#define false
Definition: GnuRegex.c:240
int strListGetItem(const String *str, char del, const char **item, int *ilen, const char **pos)
Definition: StrList.cc:86
void error(char *format,...)
DynamicServiceGroup configuration to remember future dynamic chains.
Store services
services in the group
void add(const String &item)
updates group id and services
static void Split(const ServiceFilter &filter, const String &ids, DynamicGroupCfg &current, DynamicGroupCfg &future)
separates dynamic services matching current location from future ones
DynamicServiceChain(const DynamicGroupCfg &cfg, const ServiceFilter &f)
information used to search for adaptation services
Definition: ServiceFilter.h:23
Method method
adaptation direction
Definition: ServiceFilter.h:32
VectPoint point
adaptation location
Definition: ServiceFilter.h:33
bool wants(const ServiceFilter &filter) const
bool findLink(const ServiceFilter &filter, Pos &pos) const
find next to link after success, starting with pos
ServiceGroup(const String &aKind, bool areAllServicesSame)
void checkUniqueness(const Pos checkedPos) const
checks that the service name or URI is not repeated later in the group
ServicePointer at(const Pos pos) const
void finalizeMsg(const char *msg, const String &culprit, bool error) const
emits a formatted warning or error message at the appropriate dbg level
bool findReplacement(const ServiceFilter &filter, Pos &pos) const
these methods control group iteration; used by ServicePlan
bool findService(const ServiceFilter &filter, Pos &pos) const
ServicePointer replacement(const ServiceFilter &filter)
next to try after failure
bool atEof
cached information for better performance
Pos pos
current service position within the group
std::ostream & print(std::ostream &os) const
ServicePointer next(const ServiceFilter &filter)
next in chain after success
ServiceGroupPointer group
the group we are iterating
ServicePointer current() const
returns nil if the plan is complete
bool wants(const ServiceFilter &filter) const
Definition: Service.cc:36
const ServiceConfig & cfg() const
Definition: Service.h:51
virtual bool up() const =0
virtual bool probed() const =0
SingleService(const String &aServiceKey)
static char * NextToken()
static void ParseWordList(wordlist **list)
Definition: cache_cf.cc:3155
void assign(const char *str, int len)
Definition: String.cc:89
void cut(size_type newLength)
Definition: String.cc:222
void append(char const *buf, int len)
Definition: String.cc:149
size_type size() const
Definition: SquidString.h:73
wordlist * next
Definition: wordlist.h:33
#define DBG_IMPORTANT
Definition: Stream.h:41
#define debugs(SECTION, LEVEL, CONTENT)
Definition: Stream.h:196
#define DBG_CRITICAL
Definition: Stream.h:40
@ methodNone
Definition: Elements.h:17
std::vector< ServiceGroupPointer > Groups
@ pointNone
Definition: Elements.h:18
Groups & AllGroups()
ServiceGroupPointer FindGroup(const ServiceGroup::Id &id)
ServicePointer FindService(const Service::Id &key)
Definition: Service.cc:68
RefCount< Service > ServicePointer
Definition: forward.h:34
void wordlistDestroy(wordlist **list)
destroy a wordlist
Definition: wordlist.cc:16

 

Introduction

Documentation

Support

Miscellaneous

Web Site Translations

Mirrors