ServiceRep.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 /* DEBUG: section 93 ICAP (RFC 3507) Client */
10 
11 #include "squid.h"
12 #include "adaptation/Answer.h"
13 #include "adaptation/icap/Config.h"
18 #include "base/TextException.h"
19 #include "comm/Connection.h"
20 #include "ConfigParser.h"
21 #include "debug/Stream.h"
22 #include "fde.h"
23 #include "globals.h"
24 #include "HttpReply.h"
25 #include "ip/tools.h"
26 #include "SquidConfig.h"
27 
28 #define DEFAULT_ICAP_PORT 1344
29 #define DEFAULT_ICAPS_PORT 11344
30 
32 
34  AsyncJob("Adaptation::Icap::ServiceRep"), Adaptation::Service(svcCfg),
35  theOptions(NULL), theOptionsFetcher(0), theLastUpdate(0),
36  theBusyConns(0),
37  theAllWaiters(0),
38  connOverloadReported(false),
39  theIdleConns(NULL),
40  isSuspended(0), notifying(false),
41  updateScheduled(false),
42  wasAnnouncedUp(true), // do not announce an "up" service at startup
43  isDetached(false)
44 {
46  theIdleConns = new IdleConnList("ICAP Service", NULL);
47 }
48 
50 {
52  delete theIdleConns;
53  Must(!theOptionsFetcher);
54  delete theOptions;
55  });
56 }
57 
58 void
60 {
62 
63  // use /etc/services or default port if needed
64  const bool have_port = cfg().port >= 0;
65  if (!have_port) {
66  struct servent *serv;
67  if (cfg().protocol.caseCmp("icaps") == 0)
68  serv = getservbyname("icaps", "tcp");
69  else
70  serv = getservbyname("icap", "tcp");
71 
72  if (serv) {
73  writeableCfg().port = htons(serv->s_port);
74  } else {
75  writeableCfg().port = cfg().protocol.caseCmp("icaps") == 0 ? DEFAULT_ICAPS_PORT : DEFAULT_ICAP_PORT;
76  }
77  }
78 
79  if (cfg().protocol.caseCmp("icaps") == 0)
80  writeableCfg().secure.encryptTransport = true;
81 
82  if (cfg().secure.encryptTransport) {
83  debugs(3, DBG_IMPORTANT, "Initializing service " << cfg().resource << " SSL context");
84  sslContext = writeableCfg().secure.createClientContext(true);
85  }
86 
87  if (!cfg().connectionEncryption.configured())
88  writeableCfg().connectionEncryption.defaultTo(cfg().secure.encryptTransport);
89 
90  theSessionFailures.configure(TheConfig.oldest_service_failure > 0 ?
92 }
93 
95 {
96  const int failures = theSessionFailures.count(1);
97  debugs(93,4, " failure " << failures << " out of " <<
98  TheConfig.service_failure_limit << " allowed in " <<
99  TheConfig.oldest_service_failure << "sec " << status());
100 
101  if (isSuspended)
102  return;
103 
104  if (TheConfig.service_failure_limit >= 0 &&
105  failures > TheConfig.service_failure_limit)
106  suspend("too many failures");
107 
108  // TODO: Should bypass setting affect how much Squid tries to talk to
109  // the ICAP service that is currently unusable and is likely to remain
110  // so for some time? The current code says "no". Perhaps the answer
111  // should be configurable.
112 }
113 
114 // TODO: getIdleConnection() and putConnection()/noteConnectionFailed() manage a
115 // "used connection slot" resource. Automate that resource tracking (RAII/etc.).
118 {
119  Comm::ConnectionPointer connection;
120 
121  /* 2011-06-17: rousskov:
122  * There are two things that happen at the same time in pop(). Both are important.
123  * 1) Ensure that we can use a pconn for this transaction.
124  * 2) Ensure that the number of idle pconns does not grow without bounds.
125  *
126  * Both happen in the beginning of the transaction. Both are dictated by real-world problems.
127  * retriable means you can repeat the request if you suspect the first try failed due to a pconn race.
128  * HTTP and ICAP rules prohibit the use of pconns for non-retriable requests.
129  *
130  * If there are zero idle connections, (2) is irrelevant. (2) is only relevant when there are many
131  * idle connections and we should not open more connections without closing some idle ones,
132  * or instead of just opening a new connection and leaving idle connections as is.
133  * In other words, (2) tells us to close one FD for each new one we open due to retriable.
134  */
135  if (retriableXact)
136  connection = theIdleConns->pop();
137  else
138  theIdleConns->closeN(1);
139 
140  ++theBusyConns;
141  debugs(93,3, "got connection: " << connection);
142  return connection;
143 }
144 
145 // pools connection if it is reusable or closes it
146 void Adaptation::Icap::ServiceRep::putConnection(const Comm::ConnectionPointer &conn, bool isReusable, bool sendReset, const char *comment)
147 {
149  // do not pool an idle connection if we owe connections
150  if (isReusable && excessConnections() == 0) {
151  debugs(93, 3, "pushing pconn" << comment);
152  theIdleConns->push(conn);
153  } else {
154  debugs(93, 3, (sendReset ? "RST" : "FIN") << "-closing " <<
155  comment);
156  // comm_close called from Connection::close will clear timeout
157  // TODO: add "bool sendReset = false" to Connection::close()?
158  if (sendReset)
160  else
161  conn->close();
162  }
163 
164  Must(theBusyConns > 0);
165  --theBusyConns;
166  // a connection slot released. Check if there are waiters....
167  busyCheckpoint();
168 }
169 
170 // a wrapper to avoid exposing theIdleConns
172 {
174  fd_table[conn->fd].noteUse(); // pconn re-use, albeit not via PconnPool API
175 }
176 
178 {
179  debugs(93, 3, "Connection failed: " << comment);
180  --theBusyConns;
181 }
182 
184 {
185  if (cfg().maxConn >= 0)
186  theMaxConnections = cfg().maxConn;
187  else if (theOptions && theOptions->max_connections >= 0)
188  theMaxConnections = theOptions->max_connections;
189  else {
190  theMaxConnections = -1;
191  return;
192  }
193 
194  if (::Config.workers > 1 )
195  theMaxConnections /= ::Config.workers;
196 }
197 
199 {
200  if (theMaxConnections < 0)
201  return -1;
202 
203  // we are available if we can open or reuse connections
204  // in other words, if we will not create debt
205  int available = max(0, theMaxConnections - theBusyConns);
206 
207  if (!available && !connOverloadReported) {
208  debugs(93, DBG_IMPORTANT, "WARNING: ICAP Max-Connections limit " <<
209  "exceeded for service " << cfg().uri << ". Open connections now: " <<
210  theBusyConns + theIdleConns->count() << ", including " <<
211  theIdleConns->count() << " idle persistent connections.");
212  connOverloadReported = true;
213  }
214 
215  if (cfg().onOverload == srvForce)
216  return -1;
217 
218  return available;
219 }
220 
221 // The number of connections which excess the Max-Connections limit
223 {
224  if (theMaxConnections < 0)
225  return 0;
226 
227  // Waiters affect the number of needed connections but a needed
228  // connection may still be excessive from Max-Connections p.o.v.
229  // so we should not account for waiting transaction needs here.
230  const int debt = theBusyConns + theIdleConns->count() - theMaxConnections;
231  if (debt > 0)
232  return debt;
233  else
234  return 0;
235 }
236 
238 {
239  --theAllWaiters;
240 
241  // in case the notified transaction did not take the connection slot
242  busyCheckpoint();
243 }
244 
245 // called when a connection slot may become available
247 {
248  if (theNotificationWaiters.empty()) // nobody is waiting for a slot
249  return;
250 
251  int freed = 0;
252  int available = availableConnections();
253 
254  if (available < 0) {
255  // It is possible to have waiters when no limit on connections exist in
256  // case of reconfigure or because new Options received.
257  // In this case, notify all waiting transactions.
258  freed = theNotificationWaiters.size();
259  } else {
260  // avoid notifying more waiters than there will be available slots
261  const int notifiedWaiters = theAllWaiters - theNotificationWaiters.size();
262  freed = available - notifiedWaiters;
263  }
264 
265  debugs(93,7, "Available connections: " << available <<
266  " freed slots: " << freed <<
267  " waiting in queue: " << theNotificationWaiters.size());
268 
269  while (freed > 0 && !theNotificationWaiters.empty()) {
270  Client i = theNotificationWaiters.front();
271  theNotificationWaiters.pop_front();
273  i.callback = NULL;
274  --freed;
275  }
276 }
277 
279 {
280  if (isSuspended) {
281  debugs(93,4, "keeping suspended, also for " << reason);
282  } else {
283  isSuspended = reason;
284  debugs(93, DBG_IMPORTANT, "suspending ICAP service for " << reason);
286  announceStatusChange("suspended", true);
287  }
288 }
289 
291 {
292  return theLastUpdate != 0;
293 }
294 
296 {
297  return theOptions && theOptions->valid() && theOptions->fresh();
298 }
299 
301 {
302  return !isSuspended && hasOptions();
303 }
304 
306 {
307  Must(up());
308  int available = availableConnections();
309  if (available < 0)
310  return true;
311  else
312  return (available - theAllWaiters > 0);
313 }
314 
316 {
317  Must(up());
318 
319  int available = availableConnections();
320  return (available != 0); // it is -1 (no limit) or has available slots
321 }
322 
324 {
325  Must(hasOptions());
326  return theOptions->transferKind(urlPath) != Adaptation::Icap::Options::xferIgnore;
327 }
328 
329 bool Adaptation::Icap::ServiceRep::wantsPreview(const SBuf &urlPath, size_t &wantedSize) const
330 {
331  Must(hasOptions());
332 
333  if (theOptions->preview < 0)
334  return false;
335 
336  if (theOptions->transferKind(urlPath) != Adaptation::Icap::Options::xferPreview)
337  return false;
338 
339  wantedSize = theOptions->preview;
340 
341  return true;
342 }
343 
345 {
346  Must(hasOptions());
347  return true; // in the future, we may have ACLs to prevent 204s
348 }
349 
351 {
352  Must(hasOptions());
353  if (theOptions->allow206)
354  return true; // in the future, we may have ACLs to prevent 206s
355  return false;
356 }
357 
358 static
360 {
361  Adaptation::Icap::ServiceRep *service = static_cast<Adaptation::Icap::ServiceRep*>(data);
362  Must(service);
363  service->noteTimeToUpdate();
364 }
365 
367 {
368  if (!detached())
369  updateScheduled = false;
370 
371  if (detached() || theOptionsFetcher.set()) {
372  debugs(93,5, "ignores options update " << status());
373  return;
374  }
375 
376  debugs(93,5, "performs a regular options update " << status());
377  startGettingOptions();
378 }
379 
381 {
382  Must(!notifying);
383  notifying = true;
384  debugs(93,7, "notifies " << theClients.size() << " clients " <<
385  status());
386 
387  // note: we must notify even if we are invalidated
388 
389  Pointer us = NULL;
390 
391  while (!theClients.empty()) {
392  Client i = theClients.back();
393  theClients.pop_back();
395  i.callback = 0;
396  }
397 
398  notifying = false;
399 }
400 
402 {
403  debugs(93,8, "ICAPServiceRep::callWhenAvailable");
404  Must(cb!=NULL);
405  Must(up());
406  Must(!theIdleConns->count()); // or we should not be waiting
407 
408  Client i;
409  i.service = Pointer(this);
410  i.callback = cb;
411  if (priority)
412  theNotificationWaiters.push_front(i);
413  else
414  theNotificationWaiters.push_back(i);
415 
416  busyCheckpoint();
417 }
418 
420 {
421  Must(cb!=NULL);
422 
423  debugs(93,5, "Adaptation::Icap::Service is asked to call " << *cb <<
424  " when ready " << status());
425 
426  Must(!broken()); // we do not wait for a broken service
427 
428  Client i;
429  i.service = Pointer(this); // TODO: is this really needed?
430  i.callback = cb;
431  theClients.push_back(i);
432 
433  if (theOptionsFetcher.set() || notifying)
434  return; // do nothing, we will be picked up in noteTimeToNotify()
435 
436  if (needNewOptions())
437  startGettingOptions();
438  else
439  scheduleNotification();
440 }
441 
443 {
444  debugs(93,7, "will notify " << theClients.size() << " clients");
445  CallJobHere(93, 5, this, Adaptation::Icap::ServiceRep, noteTimeToNotify);
446 }
447 
449 {
450  return !detached() && !up();
451 }
452 
454 {
455  debugs(93,8, "changes options from " << theOptions << " to " <<
456  newOptions << ' ' << status());
457 
458  delete theOptions;
459  theOptions = newOptions;
460  theSessionFailures.clear();
461  isSuspended = 0;
462  theLastUpdate = squid_curtime;
463 
464  checkOptions();
465  announceStatusChange("down after an options fetch failure", true);
466 }
467 
469 {
470  if (theOptions == NULL)
471  return;
472 
473  if (!theOptions->valid()) {
474  debugs(93, DBG_IMPORTANT, "WARNING: Squid got an invalid ICAP OPTIONS response " <<
475  "from service " << cfg().uri << "; error: " << theOptions->error);
476  return;
477  }
478 
479  /*
480  * Issue a warning if the ICAP server returned methods in the
481  * options response that don't match the method from squid.conf.
482  */
483 
484  if (!theOptions->methods.empty()) {
485  bool method_found = false;
486  String method_list;
487  std::vector <ICAP::Method>::iterator iter = theOptions->methods.begin();
488 
489  while (iter != theOptions->methods.end()) {
490 
491  if (*iter == cfg().method) {
492  method_found = true;
493  break;
494  }
495 
496  method_list.append(ICAP::methodStr(*iter));
497  method_list.append(" ", 1);
498  ++iter;
499  }
500 
501  if (!method_found) {
502  debugs(93, DBG_IMPORTANT, "WARNING: Squid is configured to use ICAP method " <<
503  cfg().methodStr() <<
504  " for service " << cfg().uri <<
505  " but OPTIONS response declares the methods are " << method_list);
506  }
507  }
508 
509  /*
510  * Check the ICAP server's date header for clock skew
511  */
512  const int skew = (int)(theOptions->timestamp() - squid_curtime);
513  if (abs(skew) > theOptions->ttl()) {
514  // TODO: If skew is negative, the option will be considered down
515  // because of stale options. We should probably change this.
516  debugs(93, DBG_IMPORTANT, "ICAP service's clock is skewed by " << skew <<
517  " seconds: " << cfg().uri);
518  }
519 }
520 
521 void Adaptation::Icap::ServiceRep::announceStatusChange(const char *downPhrase, bool important) const
522 {
523  if (wasAnnouncedUp == up()) // no significant changes to announce
524  return;
525 
526  const char *what = cfg().bypass ? "optional" : "essential";
527  const char *state = wasAnnouncedUp ? downPhrase : "up";
528  const int level = important ? 1 :2;
529  debugs(93,level, what << " ICAP service is " << state << ": " <<
530  cfg().uri << ' ' << status());
531 
532  wasAnnouncedUp = !wasAnnouncedUp;
533 }
534 
535 // we are receiving ICAP OPTIONS response headers here or NULL on failures
537 {
538  Must(initiated(theOptionsFetcher));
539  clearAdaptation(theOptionsFetcher);
540 
541  if (answer.kind == Answer::akError) {
542  debugs(93,3, "failed to fetch options " << status());
543  handleNewOptions(0);
544  return;
545  }
546 
547  Must(answer.kind == Answer::akForward); // no akBlock for OPTIONS requests
548  const Http::Message *msg = answer.message.getRaw();
549  Must(msg);
550 
551  debugs(93,5, "is interpreting new options " << status());
552 
553  Adaptation::Icap::Options *newOptions = NULL;
554  if (const HttpReply *r = dynamic_cast<const HttpReply*>(msg)) {
555  newOptions = new Adaptation::Icap::Options;
556  newOptions->configure(r);
557  } else {
558  debugs(93, DBG_IMPORTANT, "ICAP service got wrong options message " << status());
559  }
560 
561  handleNewOptions(newOptions);
562 }
563 
564 // we (a) must keep trying to get OPTIONS and (b) are RefCounted so we
565 // must keep our job alive (XXX: until nobody needs us)
566 void Adaptation::Icap::ServiceRep::callException(const std::exception &e)
567 {
568  clearAdaptation(theOptionsFetcher);
569  debugs(93,2, "ICAP probably failed to fetch options (" << e.what() <<
570  ")" << status());
571  handleNewOptions(0);
572 }
573 
575 {
576  // new options may be NULL
577  changeOptions(newOptions);
578 
579  debugs(93,3, "got new options and is now " << status());
580 
581  scheduleUpdate(optionsFetchTime());
582 
583  // XXX: this whole feature bases on the false assumption a service only has one IP
584  setMaxConnections();
585  const int excess = excessConnections();
586  // if we owe connections and have idle pconns, close the latter
587  if (excess && theIdleConns->count() > 0) {
588  const int n = min(excess, theIdleConns->count());
589  debugs(93,5, "closing " << n << " pconns to relief debt");
590  theIdleConns->closeN(n);
591  }
592 
593  scheduleNotification();
594 }
595 
597 {
598  Must(!theOptionsFetcher);
599  debugs(93,6, "will get new options " << status());
600 
601  // XXX: "this" here is "self"; works until refcounting API changes
602  theOptionsFetcher = initiateAdaptation(
604  // TODO: timeout in case Adaptation::Icap::OptXact never calls us back?
605  // Such a timeout should probably be a generic AsyncStart feature.
606 }
607 
609 {
610  if (updateScheduled) {
611  debugs(93,7, "reschedules update");
612  // XXX: check whether the event is there because AR saw
613  // an unreproducible eventDelete assertion on 2007/06/18
616  else
617  debugs(93, DBG_IMPORTANT, "ERROR: Squid BUG: ICAP service lost an update event.");
618  updateScheduled = false;
619  }
620 
621  debugs(93,7, "raw OPTIONS fetch at " << when << " or in " <<
622  (when - squid_curtime) << " sec");
623  debugs(93,9, "last fetched at " << theLastUpdate << " or " <<
624  (squid_curtime - theLastUpdate) << " sec ago");
625 
626  /* adjust update time to prevent too-frequent updates */
627 
628  if (when < squid_curtime)
629  when = squid_curtime;
630 
631  // XXX: move hard-coded constants from here to Adaptation::Icap::TheConfig
632  const int minUpdateGap = 30; // seconds
633  if (when < theLastUpdate + minUpdateGap)
634  when = theLastUpdate + minUpdateGap;
635 
636  const int delay = when - squid_curtime;
637  debugs(93,5, "will fetch OPTIONS in " << delay << " sec");
638 
639  eventAdd("Adaptation::Icap::ServiceRep::noteTimeToUpdate",
640  &ServiceRep_noteTimeToUpdate, this, delay, 0, true);
641  updateScheduled = true;
642 }
643 
644 // returns absolute time when OPTIONS should be fetched
645 time_t
647 {
648  if (theOptions && theOptions->valid()) {
649  const time_t expire = theOptions->expire();
650  debugs(93,7, "options expire on " << expire << " >= " << squid_curtime);
651 
652  // conservative estimate of how long the OPTIONS transaction will take
653  // XXX: move hard-coded constants from here to Adaptation::Icap::TheConfig
654  const int expectedWait = 20; // seconds
655 
656  // Unknown or invalid (too small) expiration times should not happen.
657  // Adaptation::Icap::Options should use the default TTL, and ICAP servers should not
658  // send invalid TTLs, but bugs and attacks happen.
659  if (expire < expectedWait)
660  return squid_curtime;
661  else
662  return expire - expectedWait; // before the current options expire
663  }
664 
665  // use revival delay as "expiration" time for a service w/o valid options
667 }
668 
672 {
673  return new Adaptation::Icap::ModXactLauncher(virgin, cause, alp, this);
674 }
675 
676 // returns a temporary string depicting service status, for debugging
678 {
679  static MemBuf buf;
680 
681  buf.reset();
682  buf.append("[", 1);
683 
684  if (up())
685  buf.append("up", 2);
686  else {
687  buf.append("down", 4);
688  if (isSuspended)
689  buf.append(",susp", 5);
690 
691  if (!theOptions)
692  buf.append(",!opt", 5);
693  else if (!theOptions->valid())
694  buf.append(",!valid", 7);
695  else if (!theOptions->fresh())
696  buf.append(",stale", 6);
697  }
698 
699  if (detached())
700  buf.append(",detached", 9);
701 
702  if (theOptionsFetcher.set())
703  buf.append(",fetch", 6);
704 
705  if (notifying)
706  buf.append(",notif", 6);
707 
708  if (const int failures = theSessionFailures.remembered())
709  buf.appendf(",fail%d", failures);
710 
711  buf.append("]", 1);
712  buf.terminate();
713 
714  return buf.content();
715 }
716 
718 {
719  debugs(93,3, "detaching ICAP service: " << cfg().uri <<
720  ' ' << status());
721  isDetached = true;
722 }
723 
725 {
726  return isDetached;
727 }
728 
731  Parent(xact, aHandler)
732 {
733  theService = &xact->service();
734  theService->noteNewWaiter();
735 }
736 
738 {
739  theService = aConnWaiter.theService;
740  theService->noteNewWaiter();
741 }
742 
744 {
745  theService->noteGoneWaiter();
746 }
747 
#define ScheduleCallHere(call)
Definition: AsyncCall.h:164
#define CallJobHere(debugSection, debugLevel, job, Class, method)
Definition: AsyncJobCalls.h:58
#define true
Definition: GnuRegex.c:234
#define false
Definition: GnuRegex.c:233
time_t squid_curtime
Definition: stub_libtime.cc:20
#define SWALLOW_EXCEPTIONS(code)
Definition: TextException.h:75
#define Must(condition)
Definition: TextException.h:71
int conn
the current server connection FD
Definition: Transport.cc:26
summarizes adaptation service answer for the noteAdaptationAnswer() API
Definition: Answer.h:23
Kind kind
the type of the answer
Definition: Answer.h:42
Http::MessagePointer message
HTTP request or response to forward.
Definition: Answer.h:39
@ akForward
forward the supplied adapted HTTP message
Definition: Answer.h:27
@ akError
no adapted message will come; see bypassable
Definition: Answer.h:29
time_t oldest_service_failure
Definition: Config.h:55
int service_failure_limit
Definition: Config.h:54
int service_revival_delay
Definition: Config.h:56
ServiceRep::Pointer theService
Definition: ServiceRep.h:199
ConnWaiterDialer(const CbcPointer< Adaptation::Icap::ModXact > &xact, Adaptation::Icap::ConnWaiterDialer::Parent::Method aHandler)
Definition: ServiceRep.cc:729
void configure(const HttpReply *reply)
Definition: Options.cc:84
void scheduleUpdate(time_t when)
Definition: ServiceRep.cc:608
virtual bool probed() const
Definition: ServiceRep.cc:290
bool wantsUrl(const SBuf &urlPath) const
Definition: ServiceRep.cc:323
bool availableForOld() const
a transaction notified about connection slot availability may start communicating with the service
Definition: ServiceRep.cc:315
void noteConnectionUse(const Comm::ConnectionPointer &conn)
Definition: ServiceRep.cc:171
virtual bool detached() const
whether detached() was called
Definition: ServiceRep.cc:724
void suspend(const char *reason)
Definition: ServiceRep.cc:278
time_t optionsFetchTime() const
Definition: ServiceRep.cc:646
void changeOptions(Options *newOptions)
Definition: ServiceRep.cc:453
IdleConnList * theIdleConns
idle persistent connection pool
Definition: ServiceRep.h:143
const char * status() const
internal cleanup; do not call directly
Definition: ServiceRep.cc:677
virtual Initiate * makeXactLauncher(Http::Message *virginHeader, HttpRequest *virginCause, AccessLogEntry::Pointer &alp)
Definition: ServiceRep.cc:670
virtual void callException(const std::exception &e)
called when the job throws during an async call
Definition: ServiceRep.cc:566
ServiceRep(const ServiceConfigPointer &aConfig)
Definition: ServiceRep.cc:33
void callWhenAvailable(AsyncCall::Pointer &cb, bool priority=false)
Definition: ServiceRep.cc:401
void setMaxConnections()
Set the maximum allowed connections for the service.
Definition: ServiceRep.cc:183
void callWhenReady(AsyncCall::Pointer &cb)
Definition: ServiceRep.cc:419
void announceStatusChange(const char *downPhrase, bool important) const
Definition: ServiceRep.cc:521
void noteGoneWaiter()
An xaction is not waiting any more for service to be available.
Definition: ServiceRep.cc:237
bool wantsPreview(const SBuf &urlPath, size_t &wantedSize) const
Definition: ServiceRep.cc:329
virtual bool up() const
Definition: ServiceRep.cc:300
Comm::ConnectionPointer getIdleConnection(bool isRetriable)
Definition: ServiceRep.cc:117
virtual void noteAdaptationAnswer(const Answer &answer)
Definition: ServiceRep.cc:536
bool availableForNew() const
a new transaction may start communicating with the service
Definition: ServiceRep.cc:305
void handleNewOptions(Options *newOptions)
Definition: ServiceRep.cc:574
void noteConnectionFailed(const char *comment)
Definition: ServiceRep.cc:177
void putConnection(const Comm::ConnectionPointer &conn, bool isReusable, bool sendReset, const char *comment)
Definition: ServiceRep.cc:146
int excessConnections() const
The number of connections which excess the Max-Connections limit.
Definition: ServiceRep.cc:222
virtual void finalize()
Definition: Service.cc:26
common parts of HttpRequest and HttpReply
Definition: Message.h:26
Definition: MemBuf.h:24
virtual void append(const char *c, int sz)
Definition: MemBuf.cc:209
char * content()
start of the added data
Definition: MemBuf.h:41
void reset()
Definition: MemBuf.cc:129
void terminate()
Definition: MemBuf.cc:241
void appendf(const char *fmt,...) PRINTF_FORMAT_ARG2
Append operation with printf-style arguments.
Definition: Packable.h:61
C * getRaw() const
Definition: RefCount.h:80
Definition: SBuf.h:94
void append(char const *buf, int len)
Definition: String.cc:149
void comm_reset_close(const Comm::ConnectionPointer &conn)
Definition: comm.cc:753
A const & max(A const &lhs, A const &rhs)
A const & min(A const &lhs, A const &rhs)
#define DBG_IMPORTANT
Definition: Stream.h:41
#define debugs(SECTION, LEVEL, CONTENT)
Definition: Stream.h:196
int eventFind(EVH *func, void *arg)
Definition: event.cc:153
void eventDelete(EVH *func, void *arg)
Definition: event.cc:129
void eventAdd(const char *name, EVH *func, void *arg, double when, int weight, bool cbdata)
Definition: event.cc:107
#define fd_table
Definition: fde.h:189
#define DEFAULT_ICAP_PORT
Definition: ServiceRep.cc:28
CBDATA_NAMESPACED_CLASS_INIT(Adaptation::Icap, ServiceRep)
#define DEFAULT_ICAPS_PORT
Definition: ServiceRep.cc:29
static void ServiceRep_noteTimeToUpdate(void *data)
Definition: ServiceRep.cc:359
std::vector< const Option * > Options
Definition: Options.h:214
Config TheConfig
Definition: Config.cc:19
@ srvForce
Definition: Elements.h:19
const char * methodStr(Method)
Definition: Elements.cc:15
bool IsConnOpen(const Comm::ConnectionPointer &conn)
Definition: Connection.cc:27
struct servent * getservbyname()
int unsigned int
Definition: stub_fd.cc:19
#define NULL
Definition: types.h:166

 

Introduction

Documentation

Support

Miscellaneous

Web Site Translations

Mirrors