ServiceRep.cc
Go to the documentation of this file.
1/*
2 * Copyright (C) 1996-2023 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"
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(nullptr), theOptionsFetcher(nullptr), theLastUpdate(0),
36 theBusyConns(0),
37 theAllWaiters(0),
38 connOverloadReported(false),
39 theIdleConns(nullptr),
40 isSuspended(nullptr), 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", nullptr);
47}
48
50{
52 delete theIdleConns;
53 Must(!theOptionsFetcher);
54 delete theOptions;
55 });
56}
57
58void
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, 2, "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
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
146void 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 = nullptr;
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
329bool 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
358static
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 = nullptr;
390
391 while (!theClients.empty()) {
392 Client i = theClients.back();
393 theClients.pop_back();
395 i.callback = nullptr;
396 }
397
398 notifying = false;
399}
400
402{
403 debugs(93,8, "ICAPServiceRep::callWhenAvailable");
404 Must(cb!=nullptr);
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!=nullptr);
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 = nullptr;
462 theLastUpdate = squid_curtime;
463
464 checkOptions();
465 announceStatusChange("down after an options fetch failure", true);
466}
467
469{
470 if (theOptions == nullptr)
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
521void 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(nullptr);
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 = nullptr;
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)
567{
568 clearAdaptation(theOptionsFetcher);
569 debugs(93,2, "ICAP probably failed to fetch options (" << e.what() <<
570 ")" << status());
571 handleNewOptions(nullptr);
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
645time_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:166
#define CallJobHere(debugSection, debugLevel, job, Class, method)
Definition: AsyncJobCalls.h:58
time_t squid_curtime
Definition: stub_libtime.cc:20
class SquidConfig Config
Definition: SquidConfig.cc:12
#define SWALLOW_EXCEPTIONS(code)
Definition: TextException.h:79
#define Must(condition)
Definition: TextException.h:75
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
void noteFailure() override
Definition: ServiceRep.cc:94
void noteAdaptationAnswer(const Answer &answer) override
Definition: ServiceRep.cc:536
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
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
void callException(const std::exception &e) override
called when the job throws during an async call
Definition: ServiceRep.cc:566
bool up() const override
Definition: ServiceRep.cc:300
ServiceRep(const ServiceConfigPointer &aConfig)
Definition: ServiceRep.cc:33
void callWhenAvailable(AsyncCall::Pointer &cb, bool priority=false)
Definition: ServiceRep.cc:401
bool detached() const override
whether detached() was called
Definition: ServiceRep.cc:724
bool wantsUrl(const SBuf &urlPath) const override
Definition: ServiceRep.cc:323
const char * status() const override
internal cleanup; do not call directly
Definition: ServiceRep.cc:677
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 probed() const override
Definition: ServiceRep.cc:290
Initiate * makeXactLauncher(Http::Message *virginHeader, HttpRequest *virginCause, AccessLogEntry::Pointer &alp) override
Definition: ServiceRep.cc:670
bool wantsPreview(const SBuf &urlPath, size_t &wantedSize) const
Definition: ServiceRep.cc:329
Comm::ConnectionPointer getIdleConnection(bool isRetriable)
Definition: ServiceRep.cc:117
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
void finalize() override
Definition: ServiceRep.cc:59
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
void append(const char *c, int sz) override
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:89
Definition: SBuf.h:94
void append(char const *buf, int len)
Definition: String.cc:130
void comm_reset_close(const Comm::ConnectionPointer &conn)
Definition: comm.cc:785
A const & max(A const &lhs, A const &rhs)
A const & min(A const &lhs, A const &rhs)
#define DBG_IMPORTANT
Definition: Stream.h:38
#define debugs(SECTION, LEVEL, CONTENT)
Definition: Stream.h:194
int eventFind(EVH *func, void *arg)
Definition: event.cc:145
void eventDelete(EVH *func, void *arg)
Definition: event.cc:127
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
int unsigned int
Definition: stub_fd.cc:19

 

Introduction

Documentation

Support

Miscellaneous

Web Site Translations

Mirrors