ServiceGroups.cc
Go to the documentation of this file.
1 /*
2  * Copyright (C) 1996-2018 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"
10 #include "adaptation/AccessRule.h"
11 #include "adaptation/Config.h"
13 #include "adaptation/Service.h"
16 #include "ConfigParser.h"
17 #include "Debug.h"
18 #include "StrList.h"
19 #include "wordlist.h"
20 
21 Adaptation::ServiceGroup::ServiceGroup(const String &aKind, bool allSame):
22  kind(aKind), method(methodNone), point(pointNone),
23  allServicesSame(allSame)
24 {
25 }
26 
28 {
29 }
30 
31 void
33 {
35 
36  wordlist *names = NULL;
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
44 void
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 != NULL) {
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, HERE << "finalized " << kind << ": " << id);
97 }
98 
100 void
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 != NULL && s->cfg().key == checkedService->cfg().key)
110  finalizeMsg("duplicate service name", s->cfg().key, false);
111  else if (s != NULL && s->cfg().uri == checkedService->cfg().uri)
112  finalizeMsg("duplicate service URI", s->cfg().uri, false);
113  }
114 }
115 
117 void
118 Adaptation::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 
133 bool
135 {
136  Pos pos = 0;
137  return findService(filter, pos);
138 }
139 
140 bool
142 {
143  if (method != filter.method || point != filter.point) {
144  debugs(93,5,HERE << 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,HERE << 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,HERE << 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,HERE << id << " has bypassable service at " << pos);
168  continue;
169  }
170 
171  if (!allServicesSame) { // cannot skip (i.e., find best) service
172  debugs(93,9,HERE << id << " has essential service at " << pos);
173  return true;
174  }
175 
176  if (!foundEssential) {
177  debugs(93,9,HERE << id << " searches for best essential service from " << pos);
178  foundEssential = true;
179  essPos = pos;
180  }
181  }
182 
183  if (foundEssential) {
184  debugs(93,9,HERE << id << " has best essential service at " << essPos);
185  pos = essPos;
186  return true;
187  }
188 
189  debugs(93,5,HERE << id << " has no matching services");
190  return false;
191 }
192 
193 bool
195 {
196  return allServicesSame && findService(filter, pos);
197 }
198 
199 bool
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 
242 void
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 = NULL;
251  int ilen = 0;
252  const char *pos = NULL;
253  while (strListGetItem(&ids, ',', &item, &ilen, &pos)) {
254  String id;
255  id.limitInit(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 
311 std::ostream &
312 Adaptation::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 NULL;
340 }
341 
ServicePointer replacement(const ServiceFilter &filter)
next to try after failure
bool wants(const ServiceFilter &filter) const
Definition: Service.cc:36
int strListGetItem(const String *str, char del, const char **item, int *ilen, const char **pos)
Definition: StrList.cc:77
void limitInit(const char *str, int len)
Definition: String.cc:94
std::ostream & print(std::ostream &os) const
bool findReplacement(const ServiceFilter &filter, Pos &pos) const
these methods control group iteration; used by ServicePlan
bool findLink(const ServiceFilter &filter, Pos &pos) const
find next to link after success, starting with pos
static void Split(const ServiceFilter &filter, const String &ids, DynamicGroupCfg &current, DynamicGroupCfg &future)
separates dynamic services matching current location from future ones
void error(char *format,...)
int i
Definition: membanger.c:49
void wordlistDestroy(wordlist **list)
destroy a wordlist
Definition: wordlist.cc:16
Method method
adaptation direction
Definition: ServiceFilter.h:32
const ServiceConfig & cfg() const
Definition: Service.h:51
SingleService(const String &aServiceKey)
VectPoint point
adaptation location
Definition: ServiceFilter.h:33
DynamicServiceChain(const DynamicGroupCfg &cfg, const ServiceFilter &f)
#define DBG_CRITICAL
Definition: Debug.h:45
char * p
Definition: membanger.c:43
bool wants(const ServiceFilter &filter) const
size_type size() const
Definition: SquidString.h:72
DynamicServiceGroup configuration to remember future dynamic chains.
ServiceGroupPointer FindGroup(const ServiceGroup::Id &id)
void append(char const *buf, int len)
Definition: String.cc:161
ServicePointer FindService(const Service::Id &key)
Definition: Service.cc:68
static void ParseWordList(wordlist **list)
Definition: cache_cf.cc:3170
#define debugs(SECTION, LEVEL, CONTENT)
Definition: Debug.h:121
#define true
Definition: GnuRegex.c:234
#define DBG_IMPORTANT
Definition: Debug.h:46
void add(const String &item)
updates group id and services
void checkUniqueness(const Pos checkedPos) const
checks that the service name or URI is not repeated later in the group
static char * NextToken()
std::vector< ServiceGroupPointer > Groups
ServiceGroup(const String &aKind, bool areAllServicesSame)
void cut(size_type newLength)
Definition: String.cc:236
ServiceGroupPointer group
the group we are iterating
std::ostream & HERE(std::ostream &s)
Definition: Debug.h:145
information used to search for adaptation services
Definition: ServiceFilter.h:22
Pos pos
current service position within the group
ServicePointer current() const
returns nil if the plan is complete
ServicePointer at(const Pos pos) const
ServicePointer next(const ServiceFilter &filter)
next in chain after success
size_t HttpReply *STUB StoreEntry const KeyScope scope const HttpRequestMethod & method
Definition: stub_store.cc:126
Store services
services in the group
void finalizeMsg(const char *msg, const String &culprit, bool error) const
emits a formatted warning or error message at the appropriate dbg level
bool atEof
cached information for better performance
bool findService(const ServiceFilter &filter, Pos &pos) const
#define NULL
Definition: types.h:166
virtual bool probed() const =0
Groups & AllGroups()
RefCount< Service > ServicePointer
Definition: forward.h:32
#define false
Definition: GnuRegex.c:233
virtual bool up() const =0

 

Introduction

Documentation

Support

Miscellaneous

Web Site Translations

Mirrors