store_client.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 90 Storage Manager Client-Side Interface */
10
11#include "squid.h"
12#include "acl/FilledChecklist.h"
14#include "base/CodeContext.h"
15#include "event.h"
16#include "globals.h"
17#include "HttpReply.h"
18#include "HttpRequest.h"
19#include "MemBuf.h"
20#include "MemObject.h"
21#include "mime_header.h"
22#include "SquidConfig.h"
23#include "StatCounters.h"
24#include "Store.h"
25#include "store/SwapMetaIn.h"
26#include "store_swapin.h"
27#include "StoreClient.h"
28#if USE_DELAY_POOLS
29#include "DelayPools.h"
30#endif
31
32/*
33 * NOTE: 'Header' refers to the swapfile metadata header.
34 * 'OBJHeader' refers to the object header, with canonical
35 * processed object headers (which may derive from FTP/HTTP etc
36 * upstream protocols
37 * 'Body' refers to the swapfile body, which is the full
38 * HTTP reply (including HTTP headers and body).
39 */
42static void storeClientCopy2(StoreEntry * e, store_client * sc);
43static bool CheckQuickAbortIsReasonable(StoreEntry * entry);
44
46
47/* StoreClient */
48
49bool
51{
53 return false;
54
56 return true;
57
59 fillChecklist(checklist);
60 return checklist.fastCheck().allowed();
61}
62
63bool
64StoreClient::startCollapsingOn(const StoreEntry &e, const bool doingRevalidation) const
65{
67 return false; // collapsing is impossible due to the entry state
68
69 if (!onCollapsingPath())
70 return false; // collapsing is impossible due to Squid configuration
71
72 /* collapsing is possible; the caller must collapse */
73
74 if (const auto tags = loggingTags()) {
75 if (doingRevalidation)
76 tags->collapsingHistory.revalidationCollapses++;
77 else
78 tags->collapsingHistory.otherCollapses++;
79 }
80
81 debugs(85, 5, e << " doingRevalidation=" << doingRevalidation);
82 return true;
83}
84
85/* store_client */
86
87int
89{
90 return type;
91}
92
93#if STORE_CLIENT_LIST_DEBUG
94static store_client *
95storeClientListSearch(const MemObject * mem, void *data)
96{
99
100 for (node = mem->clients.head; node; node = node->next) {
101 sc = node->data;
102
103 if (sc->owner == data)
104 return sc;
105 }
106
107 return NULL;
108}
109
110int
111storeClientIsThisAClient(store_client * sc, void *someClient)
112{
113 return sc->owner == someClient;
114}
115
116#endif
117#include "HttpRequest.h"
118
119/* add client with fd to client list */
122{
123 MemObject *mem = e->mem_obj;
125 assert(mem);
126#if STORE_CLIENT_LIST_DEBUG
127
128 if (storeClientListSearch(mem, data) != NULL)
129 /* XXX die! */
130 assert(1 == 0);
131#else
132 (void)data;
133#endif
134
135 sc = new store_client (e);
136
137 mem->addClient(sc);
138
139 return sc;
140}
141
144void
145store_client::callback(const ssize_t outcome)
146{
147 if (outcome > 0)
148 return noteCopiedBytes(outcome);
149
150 if (outcome < 0)
151 return fail();
152
153 noteEof();
154}
155
157void
159{
160 sc->finishCallback();
161}
162
164void
166{
169
170 // callers are not ready to handle a content+error combination
172
174 result.flags.error = object_ok ? 0 : 1;
175 copiedSize = 0;
176
177 cmp_offset = result.offset + result.length;
178 STCB *temphandler = _callback.callback_handler;
180 _callback = Callback(nullptr, nullptr);
181 copyInto.data = nullptr;
182
184 temphandler(cbdata, result);
185
187}
188
191void
192store_client::noteCopiedBytes(const size_t bytesCopied)
193{
194 debugs(90, 5, bytesCopied);
195 Assure(bytesCopied > 0);
197 copiedSize = bytesCopied;
198 noteNews();
199}
200
201void
203{
204 debugs(90, 5, copiedSize);
206 noteNews();
207}
208
210 cmp_offset(0),
211#if STORE_CLIENT_LIST_DEBUG
212 owner(cbdataReference(data)),
213#endif
214 entry(e),
215 type(e->storeClientType()),
216 object_ok(true),
217 copiedSize(0)
218{
219 flags.disk_io_pending = false;
220 flags.store_copying = false;
221 ++ entry->refcount;
222
223 if (getType() == STORE_DISK_CLIENT) {
224 /* assert we'll be able to get the data we want */
225 /* maybe we should open swapin_sio here */
227 }
228}
229
231{}
232
233/* copy bytes requested by the client */
234void
236 StoreEntry * e,
237 StoreIOBuffer copyInto,
238 STCB * callback,
239 void *data)
240{
241 assert (sc != nullptr);
242 sc->copy(e, copyInto,callback,data);
243}
244
245void
247 StoreIOBuffer copyRequest,
248 STCB * callback_fn,
249 void *data)
250{
251 assert (anEntry == entry);
252 assert (callback_fn);
253 assert (data);
255 debugs(90, 3, "store_client::copy: " << entry->getMD5Text() << ", from " <<
256 copyRequest.offset << ", for length " <<
257 (int) copyRequest.length << ", cb " << callback_fn << ", cbdata " <<
258 data);
259
260#if STORE_CLIENT_LIST_DEBUG
261
262 assert(this == storeClientListSearch(entry->mem_obj, data));
263#endif
264
266#if ONLYCONTIGUOUSREQUESTS
267
268 assert(cmp_offset == copyRequest.offset);
269#endif
270 /* range requests will skip into the body */
271 cmp_offset = copyRequest.offset;
272 _callback = Callback (callback_fn, cbdataReference(data));
273 copyInto.data = copyRequest.data;
274 copyInto.length = copyRequest.length;
275 copyInto.offset = copyRequest.offset;
276
277 static bool copying (false);
278 assert (!copying);
279 copying = true;
280 /* we might be blocking comm reads due to readahead limits
281 * now we have a new offset, trigger those reads...
282 */
284 copying = false;
285
286 anEntry->lock("store_client::copy"); // see deletion note below
287
288 storeClientCopy2(entry, this);
289
290 // Bug 3480: This store_client object may be deleted now if, for example,
291 // the client rejects the hit response copied above. Use on-stack pointers!
292
293#if USE_ADAPTATION
294 anEntry->kickProducer();
295#endif
296 anEntry->unlock("store_client::copy");
297
298 // Add no code here. This object may no longer exist.
299}
300
302bool
304{
306 return true; // there may be more coming
307
308 /* STORE_OK, including aborted entries: no more data is coming */
309
310 const int64_t len = entry->objectLen();
311
312 // If we do not know the entry length, then we have to open the swap file.
313 const bool canSwapIn = entry->hasDisk();
314 if (len < 0)
315 return canSwapIn;
316
317 if (copyInto.offset >= len)
318 return false; // sent everything there is
319
320 if (canSwapIn)
321 return true; // if we lack prefix, we can swap it in
322
323 // If we cannot swap in, make sure we have what we want in RAM. Otherwise,
324 // scheduleRead calls scheduleDiskRead which asserts without a swap file.
325 const MemObject *mem = entry->mem_obj;
326 return mem &&
327 mem->inmem_lo <= copyInto.offset && copyInto.offset < mem->endOffset();
328}
329
330static void
332{
333 /* reentrancy not allowed - note this could lead to
334 * dropped notifications about response data availability
335 */
336
337 if (sc->flags.store_copying) {
338 debugs(90, 3, "prevented recursive copying for " << *e);
339 return;
340 }
341
342 debugs(90, 3, "storeClientCopy2: " << e->getMD5Text());
343 assert(sc->_callback.pending());
344 /*
345 * We used to check for ENTRY_ABORTED here. But there were some
346 * problems. For example, we might have a slow client (or two) and
347 * the peer server is reading far ahead and swapping to disk. Even
348 * if the peer aborts, we want to give the client(s)
349 * everything we got before the abort condition occurred.
350 */
351 sc->doCopy(e);
352}
353
354void
356{
358 Assure(!flags.disk_io_pending);
359 Assure(!flags.store_copying);
360
361 assert (anEntry == entry);
362 flags.store_copying = true;
363 MemObject *mem = entry->mem_obj;
364
365 debugs(33, 5, "store_client::doCopy: co: " <<
366 copyInto.offset << ", hi: " <<
367 mem->endOffset());
368
369 if (!moreToSend()) {
370 /* There is no more to send! */
371 debugs(33, 3, "There is no more to send!");
372 noteEof();
373 flags.store_copying = false;
374 return;
375 }
376
377 /* Check that we actually have data */
378 if (anEntry->store_status == STORE_PENDING && copyInto.offset >= mem->endOffset()) {
379 debugs(90, 3, "store_client::doCopy: Waiting for more");
380 flags.store_copying = false;
381 return;
382 }
383
384 /*
385 * Slight weirdness here. We open a swapin file for any
386 * STORE_DISK_CLIENT, even if we can copy the requested chunk
387 * from memory in the next block. We must try to open the
388 * swapin file before sending any data to the client side. If
389 * we postpone the open, and then can not open the file later
390 * on, the client loses big time. Its transfer just gets cut
391 * off. Better to open it early (while the client side handler
392 * is clientCacheHit) so that we can fall back to a cache miss
393 * if needed.
394 */
395
396 if (STORE_DISK_CLIENT == getType() && swapin_sio == nullptr) {
397 if (!startSwapin())
398 return; // failure
399 }
400 scheduleRead();
401}
402
404bool
406{
407 debugs(90, 3, "store_client::doCopy: Need to open swap in file");
408 /* gotta open the swapin file */
409
411 /* yuck -- this causes a TCP_SWAPFAIL_MISS on the client side */
412 fail();
413 flags.store_copying = false;
414 return false;
415 } else if (!flags.disk_io_pending) {
416 /* Don't set store_io_pending here */
417 storeSwapInStart(this);
418
419 if (swapin_sio == nullptr) {
420 fail();
421 flags.store_copying = false;
422 return false;
423 }
424
425 return true;
426 } else {
427 debugs(90, DBG_IMPORTANT, "WARNING: Averted multiple fd operation (1)");
428 flags.store_copying = false;
429 return false;
430 }
431}
432
433void
435{
437 if (error)
438 fail();
439 else
440 noteEof();
441}
442
443void
445{
446 MemObject *mem = entry->mem_obj;
447
448 if (copyInto.offset >= mem->inmem_lo && copyInto.offset < mem->endOffset())
450 else
452}
453
454void
456{
457 /* What the client wants is not in memory. Schedule a disk read */
458 if (getType() == STORE_DISK_CLIENT) {
459 // we should have called startSwapin() already
460 assert(swapin_sio != nullptr);
461 } else if (!swapin_sio && !startSwapin()) {
462 debugs(90, 3, "bailing after swapin start failure for " << *entry);
463 assert(!flags.store_copying);
464 return;
465 }
466
467 assert(!flags.disk_io_pending);
468
469 debugs(90, 3, "reading " << *entry << " from disk");
470
471 fileRead();
472
473 flags.store_copying = false;
474}
475
476void
478{
479 /* What the client wants is in memory */
480 /* Old style */
481 debugs(90, 3, "store_client::doCopy: Copying normal from memory");
482 const auto sz = entry->mem_obj->data_hdr.copy(copyInto); // may be <= 0 per copy() API
483 callback(sz);
484 flags.store_copying = false;
485}
486
487void
489{
490 MemObject *mem = entry->mem_obj;
491
493 assert(!flags.disk_io_pending);
494 flags.disk_io_pending = true;
495
496 if (mem->swap_hdr_sz != 0)
497 if (entry->swappingOut())
498 assert(mem->swapout.sio->offset() > copyInto.offset + (int64_t)mem->swap_hdr_sz);
499
506 this);
507}
508
509void
510store_client::readBody(const char *, ssize_t len)
511{
512 // Don't assert disk_io_pending here.. may be called by read_header
513 flags.disk_io_pending = false;
515 debugs(90, 3, "storeClientReadBody: len " << len << "");
516
517 if (len < 0)
518 return fail();
519
520 const auto rep = entry->mem_obj ? &entry->mem().baseReply() : nullptr;
521 if (copyInto.offset == 0 && len > 0 && rep && rep->sline.status() == Http::scNone) {
522 /* Our structure ! */
524 debugs(90, DBG_CRITICAL, "ERROR: Could not parse headers from on disk object");
525 }
526 }
527
528 if (len > 0 && rep && entry->mem_obj->inmem_lo == 0 && entry->objectLen() <= (int64_t)Config.Store.maxInMemObjSize && Config.onoff.memory_cache_disk) {
529 storeGetMemSpace(len);
530 // The above may start to free our object so we need to check again
531 if (entry->mem_obj->inmem_lo == 0) {
532 /* Copy read data back into memory.
533 * copyInto.offset includes headers, which is what mem cache needs
534 */
537 }
538 }
539 }
540
541 callback(len);
542}
543
544void
546{
547 debugs(90, 3, (object_ok ? "once" : "again"));
548 if (!object_ok)
549 return; // we failed earlier; nothing to do now
550
551 object_ok = false;
552
553 noteNews();
554}
555
557void
559{
560 /* synchronous open failures callback from the store,
561 * before startSwapin detects the failure.
562 * TODO: fix this inconsistent behaviour - probably by
563 * having storeSwapInStart become a callback functions,
564 * not synchronous
565 */
566
568 debugs(90, 5, "client lost interest");
569 return;
570 }
571
572 if (_callback.notifier) {
573 debugs(90, 5, "earlier news is being delivered by " << _callback.notifier);
574 return;
575 }
576
577 _callback.notifier = asyncCall(90, 4, "store_client::FinishCallback", cbdataDialer(store_client::FinishCallback, this));
579
581}
582
583static void
584storeClientReadHeader(void *data, const char *buf, ssize_t len, StoreIOState::Pointer)
585{
586 store_client *sc = (store_client *)data;
587 sc->readHeader(buf, len);
588}
589
590static void
591storeClientReadBody(void *data, const char *buf, ssize_t len, StoreIOState::Pointer)
592{
593 store_client *sc = (store_client *)data;
594 sc->readBody(buf, len);
595}
596
597void
598store_client::readHeader(char const *buf, ssize_t len)
599{
600 MemObject *const mem = entry->mem_obj;
601
602 assert(flags.disk_io_pending);
603 flags.disk_io_pending = false;
605
606 // abort if we fail()'d earlier
607 if (!object_ok)
608 return;
609
610 if (len < 0)
611 return fail();
612
613 try {
615 } catch (...) {
616 debugs(90, DBG_IMPORTANT, "ERROR: Failed to unpack Store entry metadata: " << CurrentException);
617 fail();
618 return;
619 }
620
621 /*
622 * If our last read got some data the client wants, then give
623 * it to them, otherwise schedule another read.
624 */
625 size_t body_sz = len - mem->swap_hdr_sz;
626
627 if (copyInto.offset < static_cast<int64_t>(body_sz)) {
628 /*
629 * we have (part of) what they want
630 */
631 size_t copy_sz = min(copyInto.length, body_sz);
632 debugs(90, 3, "storeClientReadHeader: copying " << copy_sz << " bytes of body");
633 memmove(copyInto.data, copyInto.data + mem->swap_hdr_sz, copy_sz);
634
635 readBody(copyInto.data, copy_sz);
636
637 return;
638 }
639
640 /*
641 * we don't have what the client wants, but at least we now
642 * know the swap header size.
643 */
644 fileRead();
645}
646
647int
649{
650#if STORE_CLIENT_LIST_DEBUG
651 assert(sc == storeClientListSearch(e->mem_obj, data));
652#else
653 (void)data;
654#endif
655
656 assert(sc);
657 assert(sc->entry == e);
658
659 if (!sc->_callback.pending())
660 return 0;
661
662 return 1;
663}
664
665/*
666 * This routine hasn't been optimised to take advantage of the
667 * passed sc. Yet.
668 */
669int
671{
672 MemObject *mem = e->mem_obj;
673#if STORE_CLIENT_LIST_DEBUG
674 assert(sc == storeClientListSearch(e->mem_obj, data));
675#else
676 (void)data;
677#endif
678
679 if (mem == nullptr)
680 return 0;
681
682 debugs(90, 3, "storeUnregister: called for '" << e->getMD5Text() << "'");
683
684 if (sc == nullptr) {
685 debugs(90, 3, "storeUnregister: No matching client for '" << e->getMD5Text() << "'");
686 return 0;
687 }
688
689 if (mem->clientCount() == 0) {
690 debugs(90, 3, "storeUnregister: Consistency failure - store client being unregistered is not in the mem object's list for '" << e->getMD5Text() << "'");
691 return 0;
692 }
693
694 dlinkDelete(&sc->node, &mem->clients);
695 -- mem->nclients;
696
697 const auto swapoutFinished = e->swappedOut() || e->swapoutFailed();
698 if (e->store_status == STORE_OK && !swapoutFinished)
699 e->swapOut();
700
701 if (sc->swapin_sio != nullptr) {
703 sc->swapin_sio = nullptr;
705 }
706
707 if (sc->_callback.callback_handler || sc->_callback.notifier) {
708 debugs(90, 3, "forgetting store_client callback for " << *e);
709 // Do not notify: Callers want to stop copying and forget about this
710 // pending copy request. Some would mishandle a notification from here.
711 if (sc->_callback.notifier)
712 sc->_callback.notifier->cancel("storeUnregister");
713 }
714
715#if STORE_CLIENT_LIST_DEBUG
716 cbdataReferenceDone(sc->owner);
717
718#endif
719
720 // XXX: We might be inside sc store_client method somewhere up the call
721 // stack. TODO: Convert store_client to AsyncJob to make destruction async.
722 delete sc;
723
724 assert(e->locked());
725 // An entry locked by others may be unlocked (and destructed) by others, so
726 // we must lock again to safely dereference e after CheckQuickAbortIsReasonable().
727 e->lock("storeUnregister");
728
730 e->abort();
731 else
732 mem->kickReads();
733
734#if USE_ADAPTATION
735 e->kickProducer();
736#endif
737
738 e->unlock("storeUnregister");
739 return 1;
740}
741
742/* Call handlers waiting for data to be appended to E. */
743void
745{
747 debugs(90, 3, "DELAY_SENDING is on, exiting " << *this);
748 return;
749 }
751 debugs(90, 3, "ENTRY_FWD_HDR_WAIT is on, exiting " << *this);
752 return;
753 }
754
755 /* Commit what we can to disk, if appropriate */
756 swapOut();
757 int i = 0;
759 dlink_node *nx = nullptr;
761
762 debugs(90, 3, mem_obj->nclients << " clients; " << *this << ' ' << getMD5Text());
763 /* walk the entire list looking for valid callbacks */
764
765 const auto savedContext = CodeContext::Current();
766 for (node = mem_obj->clients.head; node; node = nx) {
767 sc = (store_client *)node->data;
768 nx = node->next;
769 ++i;
770
771 if (!sc->_callback.pending())
772 continue;
773
774 if (sc->flags.disk_io_pending)
775 continue;
776
777 if (sc->flags.store_copying)
778 continue;
779
780 // XXX: If invokeHandlers() is (indirectly) called from a store_client
781 // method, then the above three conditions may not be sufficient to
782 // prevent us from reentering the same store_client object! This
783 // probably does not happen in the current code, but no observed
784 // invariant prevents this from (accidentally) happening in the future.
785
786 // TODO: Convert store_client into AsyncJob; make this call asynchronous
787 CodeContext::Reset(sc->_callback.codeContext);
788 debugs(90, 3, "checking client #" << i);
789 storeClientCopy2(this, sc);
790 }
791 CodeContext::Reset(savedContext);
792}
793
794// Does not account for remote readers/clients.
795int
797{
798 MemObject *mem = e->mem_obj;
799 int npend = nullptr == mem ? 0 : mem->nclients;
800 debugs(90, 3, "storePendingNClients: returning " << npend);
801 return npend;
802}
803
804/* return true if the request should be aborted */
805static bool
807{
808 assert(entry);
809 debugs(90, 3, "entry=" << *entry);
810
811 if (storePendingNClients(entry) > 0) {
812 debugs(90, 3, "quick-abort? NO storePendingNClients() > 0");
813 return false;
814 }
815
816 if (Store::Root().transientReaders(*entry)) {
817 debugs(90, 3, "quick-abort? NO still have one or more transient readers");
818 return false;
819 }
820
821 if (entry->store_status != STORE_PENDING) {
822 debugs(90, 3, "quick-abort? NO store_status != STORE_PENDING");
823 return false;
824 }
825
826 if (EBIT_TEST(entry->flags, ENTRY_SPECIAL)) {
827 debugs(90, 3, "quick-abort? NO ENTRY_SPECIAL");
828 return false;
829 }
830
831 if (shutting_down) {
832 debugs(90, 3, "quick-abort? YES avoid heavy optional work during shutdown");
833 return true;
834 }
835
836 MemObject * const mem = entry->mem_obj;
837 assert(mem);
838 debugs(90, 3, "mem=" << mem);
839
840 if (mem->request && !mem->request->flags.cachable) {
841 debugs(90, 3, "quick-abort? YES !mem->request->flags.cachable");
842 return true;
843 }
844
845 if (EBIT_TEST(entry->flags, KEY_PRIVATE)) {
846 debugs(90, 3, "quick-abort? YES KEY_PRIVATE");
847 return true;
848 }
849
850 const auto &reply = mem->baseReply();
851
852 if (reply.hdr_sz <= 0) {
853 // TODO: Check whether this condition works for HTTP/0 responses.
854 debugs(90, 3, "quick-abort? YES no object data received yet");
855 return true;
856 }
857
858 if (Config.quickAbort.min < 0) {
859 debugs(90, 3, "quick-abort? NO disabled");
860 return false;
861 }
862
863 if (mem->request && mem->request->range && mem->request->getRangeOffsetLimit() < 0) {
864 // the admin has configured "range_offset_limit none"
865 debugs(90, 3, "quick-abort? NO admin configured range replies to full-download");
866 return false;
867 }
868
869 if (reply.content_length < 0) {
870 // XXX: cf.data.pre does not document what should happen in this case
871 // We know that quick_abort is enabled, but no limit can be applied.
872 debugs(90, 3, "quick-abort? YES unknown content length");
873 return true;
874 }
875 const auto expectlen = reply.hdr_sz + reply.content_length;
876
877 int64_t curlen = mem->endOffset();
878
879 if (curlen > expectlen) {
880 debugs(90, 3, "quick-abort? YES bad content length (" << curlen << " of " << expectlen << " bytes received)");
881 return true;
882 }
883
884 if ((expectlen - curlen) < (Config.quickAbort.min << 10)) {
885 debugs(90, 3, "quick-abort? NO only a little more object left to receive");
886 return false;
887 }
888
889 if ((expectlen - curlen) > (Config.quickAbort.max << 10)) {
890 debugs(90, 3, "quick-abort? YES too much left to go");
891 return true;
892 }
893
894 // XXX: This is absurd! TODO: For positives, "a/(b/c) > d" is "a*c > b*d".
895 if (expectlen < 100) {
896 debugs(90, 3, "quick-abort? NO avoid FPE");
897 return false;
898 }
899
900 if ((curlen / (expectlen / 100)) > (Config.quickAbort.pct)) {
901 debugs(90, 3, "quick-abort? NO past point of no return");
902 return false;
903 }
904
905 debugs(90, 3, "quick-abort? YES default");
906 return true;
907}
908
909void
910store_client::dumpStats(MemBuf * output, int clientNumber) const
911{
912 if (_callback.pending())
913 return;
914
915 output->appendf("\tClient #%d, %p\n", clientNumber, _callback.callback_data);
916 output->appendf("\t\tcopy_offset: %" PRId64 "\n", copyInto.offset);
917 output->appendf("\t\tcopy_size: %" PRIuSIZE "\n", copyInto.length);
918 output->append("\t\tflags:", 8);
919
920 if (flags.disk_io_pending)
921 output->append(" disk_io_pending", 16);
922
923 if (flags.store_copying)
924 output->append(" store_copying", 14);
925
927 output->append(" notifying", 10);
928
929 output->append("\n",1);
930}
931
932bool
934{
935 return callback_handler && !notifier;
936}
937
939 callback_handler(function),
940 callback_data(data),
941 codeContext(CodeContext::Current())
942{
943}
944
945#if USE_DELAY_POOLS
946int
948{
949 // TODO: To avoid using stale copyInto, return zero if !_callback.pending()?
951}
952
953void
955{
956 delayId = delay_id;
957}
958#endif
959
#define Assure(condition)
Definition: Assure.h:35
#define ScheduleCallHere(call)
Definition: AsyncCall.h:164
AsyncCall * asyncCall(int aDebugSection, int aDebugLevel, const char *aName, const Dialer &aDialer)
Definition: AsyncCall.h:154
UnaryCbdataDialer< Argument1 > cbdataDialer(typename UnaryCbdataDialer< Argument1 >::Handler *handler, Argument1 *arg1)
#define true
Definition: GnuRegex.c:241
class SquidConfig Config
Definition: SquidConfig.cc:12
StatCounters statCounter
Definition: StatCounters.cc:12
int storeClientIsThisAClient(store_client *sc, void *someClient)
void STCB(void *, StoreIOBuffer)
Definition: StoreClient.h:19
std::ostream & CurrentException(std::ostream &os)
prints active (i.e., thrown but not yet handled) exception
void error(char *format,...)
#define assert(EX)
Definition: assert.h:19
int cbdataReferenceValid(const void *p)
Definition: cbdata.cc:398
#define cbdataReferenceDone(var)
Definition: cbdata.h:350
#define cbdataReference(var)
Definition: cbdata.h:341
#define CBDATA_CLASS_INIT(type)
Definition: cbdata.h:318
Acl::Answer const & fastCheck()
Definition: Checklist.cc:332
bool allowed() const
Definition: Acl.h:150
virtual void fillChecklist(ACLFilledChecklist &) const =0
configure the given checklist (to reflect the current transaction state)
static const Pointer & Current()
Definition: CodeContext.cc:33
static void Reset()
forgets the current context, setting it to nil/unknown
Definition: CodeContext.cc:75
int bytesWanted(int min, int max) const
Definition: DelayId.cc:130
HttpHdrRange * range
Definition: HttpRequest.h:143
int64_t getRangeOffsetLimit()
Definition: HttpRequest.cc:597
RequestFlags flags
Definition: HttpRequest.h:141
bool parseCharBuf(const char *buf, ssize_t end)
Definition: Message.cc:140
Definition: MemBuf.h:24
virtual void append(const char *c, int sz)
Definition: MemBuf.cc:209
StoreIOState::Pointer sio
Definition: MemObject.h:152
size_t clientCount() const
Definition: MemObject.h:142
int nclients
Definition: MemObject.h:146
SwapOut swapout
Definition: MemObject.h:159
HttpRequestPointer request
Definition: MemObject.h:188
void addClient(store_client *)
Definition: MemObject.cc:303
dlink_list clients
Definition: MemObject.h:140
mem_hdr data_hdr
Definition: MemObject.h:138
void write(const StoreIOBuffer &buf)
Definition: MemObject.cc:136
int64_t inmem_lo
Definition: MemObject.h:139
size_t swap_hdr_sz
Definition: MemObject.h:199
int64_t endOffset() const
Definition: MemObject.cc:214
const HttpReply & baseReply() const
Definition: MemObject.h:59
HttpReply & adjustableBaseReply()
Definition: MemObject.cc:121
void kickReads()
Definition: MemObject.cc:453
void appendf(const char *fmt,...) PRINTF_FORMAT_ARG2
Append operation with printf-style arguments.
Definition: Packable.h:61
struct SquidConfig::@111 onoff
struct SquidConfig::@112 accessList
acl_access * collapsedForwardingAccess
Definition: SquidConfig.h:404
int memory_cache_disk
Definition: SquidConfig.h:334
size_t maxInMemObjSize
Definition: SquidConfig.h:266
struct SquidConfig::@109 Store
struct SquidConfig::@97 quickAbort
int collapsed_forwarding
Definition: SquidConfig.h:321
int64_t min
Definition: SquidConfig.h:92
int64_t max
Definition: SquidConfig.h:94
struct StatCounters::@137 swap
bool onCollapsingPath() const
whether Squid configuration allows collapsing for this transaction
Definition: store_client.cc:50
virtual LogTags * loggingTags() const =0
bool startCollapsingOn(const StoreEntry &, const bool doingRevalidation) const
Definition: store_client.cc:64
bool swappedOut() const
whether the entire entry is now on disk (possibly marked for deletion)
Definition: Store.h:136
uint16_t flags
Definition: Store.h:232
void invokeHandlers()
MemObject & mem()
Definition: Store.h:51
int locked() const
Definition: Store.h:146
int unlock(const char *context)
Definition: store.cc:442
bool hasDisk(const sdirno dirn=-1, const sfileno filen=-1) const
Definition: store.cc:1896
void lock(const char *context)
Definition: store.cc:418
bool swappingOut() const
whether we are in the process of writing this entry to disk
Definition: Store.h:134
const char * getMD5Text() const
Definition: store.cc:204
void kickProducer()
calls back producer registered with deferProducer
Definition: store.cc:349
MemObject * mem_obj
Definition: Store.h:221
void abort()
Definition: store.cc:1050
int64_t objectLen() const
Definition: Store.h:257
store_status_t store_status
Definition: Store.h:244
bool swapoutFailed() const
whether we failed to write this entry to disk
Definition: Store.h:138
uint16_t refcount
Definition: Store.h:231
void swapOut()
bool hittingRequiresCollapsing() const
whether this entry can feed collapsed requests and only them
Definition: Store.h:216
unsigned error
Definition: StoreIOBuffer.h:52
struct StoreIOBuffer::@147 flags
int64_t offset
Definition: StoreIOBuffer.h:55
@ readerDone
success or failure: either way, stop swapping in
Definition: StoreIOState.h:72
off_t offset() const
Definition: StoreIOState.h:60
void STRCB(void *their_data, const char *buf, ssize_t len, StoreIOState::Pointer self)
Definition: StoreIOState.h:29
Definition: cbdata.cc:60
ssize_t copy(StoreIOBuffer const &) const
Definition: stmem.cc:225
int64_t cmp_offset
Definition: StoreClient.h:91
int getType() const
Definition: store_client.cc:88
void readHeader(const char *buf, ssize_t len)
void setDelayId(DelayId delay_id)
void scheduleDiskRead()
bool startSwapin()
opens the swapin "file" if possible; otherwise, fail()s and returns false
bool moreToSend() const
Whether there is (or will be) more entry data for us.
void noteNews()
if necessary and possible, informs the Store reader about copy() result
void noteSwapInDone(bool error)
void scheduleRead()
void readBody(const char *buf, ssize_t len)
DelayId delayId
Definition: StoreClient.h:112
StoreEntry * entry
Definition: StoreClient.h:97
void copy(StoreEntry *, StoreIOBuffer, STCB *, void *)
int bytesWanted() const
void doCopy(StoreEntry *e)
void noteCopiedBytes(size_t)
struct store_client::Callback _callback
StoreIOBuffer copyInto
Definition: StoreClient.h:147
void finishCallback()
finishes a copy()-STCB sequence by synchronously calling STCB
size_t copiedSize
Definition: StoreClient.h:151
store_client(StoreEntry *)
static void FinishCallback(store_client *)
finishCallback() wrapper; TODO: Add NullaryMemFunT for non-jobs.
struct store_client::@146 flags
void scheduleMemRead()
StoreIOState::Pointer swapin_sio
Definition: StoreClient.h:98
void dumpStats(MemBuf *output, int clientNumber) const
void callback(ssize_t)
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
#define DBG_CRITICAL
Definition: Stream.h:40
#define EBIT_TEST(flag, bit)
Definition: defines.h:69
@ ENTRY_SPECIAL
Definition: enums.h:84
@ KEY_PRIVATE
Definition: enums.h:102
@ ENTRY_FWD_HDR_WAIT
Definition: enums.h:111
@ DELAY_SENDING
Definition: enums.h:97
@ ENTRY_ABORTED
Definition: enums.h:115
@ STORE_DISK_CLIENT
Definition: enums.h:74
@ STORE_PENDING
Definition: enums.h:51
@ STORE_OK
Definition: enums.h:50
int type
Definition: errorpage.cc:152
int shutting_down
size_t headersEnd(const char *mime, size_t l, bool &containsObsFold)
Definition: mime_header.cc:17
@ scNone
Definition: StatusCode.h:21
Controller & Root()
safely access controller singleton
Definition: Controller.cc:926
void UnpackHitSwapMeta(char const *, ssize_t, StoreEntry &)
deserializes entry metadata from the given buffer into the cache hit entry
Definition: SwapMetaIn.cc:310
static int sc[16]
Definition: smbdes.c:121
void storeGetMemSpace(int size)
Definition: store.cc:1094
int storeTooManyDiskFilesOpen(void)
Definition: store.cc:862
int storeUnregister(store_client *sc, StoreEntry *e, void *data)
void storeClientCopy(store_client *sc, StoreEntry *e, StoreIOBuffer copyInto, STCB *callback, void *data)
int storeClientCopyPending(store_client *sc, StoreEntry *e, void *data)
int storePendingNClients(const StoreEntry *e)
static void storeClientCopy2(StoreEntry *e, store_client *sc)
store_client * storeClientListAdd(StoreEntry *e, void *data)
static bool CheckQuickAbortIsReasonable(StoreEntry *entry)
static StoreIOState::STRCB storeClientReadBody
Definition: store_client.cc:40
static StoreIOState::STRCB storeClientReadHeader
Definition: store_client.cc:41
void storeClose(StoreIOState::Pointer sio, int how)
Definition: store_io.cc:65
void storeRead(StoreIOState::Pointer sio, char *buf, size_t size, off_t offset, StoreIOState::STRCB *callback, void *callback_data)
Definition: store_io.cc:79
void storeSwapInStart(store_client *sc)
Definition: store_swapin.cc:22
Definition: parse.c:104
struct node * next
Definition: parse.c:105
AsyncCall::Pointer notifier
a scheduled asynchronous finishCallback() call (or nil)
Definition: StoreClient.h:172
void const char int sz
Definition: stub_cbdata.cc:16
#define NULL
Definition: types.h:166
#define PRId64
Definition: types.h:110

 

Introduction

Documentation

Support

Miscellaneous

Web Site Translations

Mirrors