store_client.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 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 Assure(entry);
220 entry->lock("store_client");
221
222 flags.disk_io_pending = false;
223 flags.store_copying = false;
224 ++ entry->refcount;
225
226 if (getType() == STORE_DISK_CLIENT) {
227 /* assert we'll be able to get the data we want */
228 /* maybe we should open swapin_sio here */
230 }
231}
232
234{
235 assert(entry);
236 entry->unlock("store_client");
237}
238
239/* copy bytes requested by the client */
240void
242 StoreEntry * e,
243 StoreIOBuffer copyInto,
244 STCB * callback,
245 void *data)
246{
247 assert (sc != nullptr);
248 sc->copy(e, copyInto,callback,data);
249}
250
251void
253 StoreIOBuffer copyRequest,
254 STCB * callback_fn,
255 void *data)
256{
257 assert (anEntry == entry);
258 assert (callback_fn);
259 assert (data);
261 debugs(90, 3, "store_client::copy: " << entry->getMD5Text() << ", from " <<
262 copyRequest.offset << ", for length " <<
263 (int) copyRequest.length << ", cb " << callback_fn << ", cbdata " <<
264 data);
265
266#if STORE_CLIENT_LIST_DEBUG
267
268 assert(this == storeClientListSearch(entry->mem_obj, data));
269#endif
270
272#if ONLYCONTIGUOUSREQUESTS
273
274 assert(cmp_offset == copyRequest.offset);
275#endif
276 /* range requests will skip into the body */
277 cmp_offset = copyRequest.offset;
278 _callback = Callback (callback_fn, cbdataReference(data));
279 copyInto.data = copyRequest.data;
280 copyInto.length = copyRequest.length;
281 copyInto.offset = copyRequest.offset;
282
283 static bool copying (false);
284 assert (!copying);
285 copying = true;
286 /* we might be blocking comm reads due to readahead limits
287 * now we have a new offset, trigger those reads...
288 */
290 copying = false;
291
292 anEntry->lock("store_client::copy"); // see deletion note below
293
294 storeClientCopy2(entry, this);
295
296 // Bug 3480: This store_client object may be deleted now if, for example,
297 // the client rejects the hit response copied above. Use on-stack pointers!
298
299#if USE_ADAPTATION
300 anEntry->kickProducer();
301#endif
302 anEntry->unlock("store_client::copy");
303
304 // Add no code here. This object may no longer exist.
305}
306
308bool
310{
312 return true; // there may be more coming
313
314 /* STORE_OK, including aborted entries: no more data is coming */
315
316 const int64_t len = entry->objectLen();
317
318 // If we do not know the entry length, then we have to open the swap file.
319 const bool canSwapIn = entry->hasDisk();
320 if (len < 0)
321 return canSwapIn;
322
323 if (copyInto.offset >= len)
324 return false; // sent everything there is
325
326 if (canSwapIn)
327 return true; // if we lack prefix, we can swap it in
328
329 // If we cannot swap in, make sure we have what we want in RAM. Otherwise,
330 // scheduleRead calls scheduleDiskRead which asserts without a swap file.
331 const MemObject *mem = entry->mem_obj;
332 return mem &&
333 mem->inmem_lo <= copyInto.offset && copyInto.offset < mem->endOffset();
334}
335
336static void
338{
339 /* reentrancy not allowed - note this could lead to
340 * dropped notifications about response data availability
341 */
342
343 if (sc->flags.store_copying) {
344 debugs(90, 3, "prevented recursive copying for " << *e);
345 return;
346 }
347
348 debugs(90, 3, "storeClientCopy2: " << e->getMD5Text());
349 assert(sc->_callback.pending());
350 /*
351 * We used to check for ENTRY_ABORTED here. But there were some
352 * problems. For example, we might have a slow client (or two) and
353 * the peer server is reading far ahead and swapping to disk. Even
354 * if the peer aborts, we want to give the client(s)
355 * everything we got before the abort condition occurred.
356 */
357 sc->doCopy(e);
358}
359
360void
362{
364 Assure(!flags.disk_io_pending);
365 Assure(!flags.store_copying);
366
367 assert (anEntry == entry);
368 flags.store_copying = true;
369 MemObject *mem = entry->mem_obj;
370
371 debugs(33, 5, "store_client::doCopy: co: " <<
372 copyInto.offset << ", hi: " <<
373 mem->endOffset());
374
375 if (!moreToSend()) {
376 /* There is no more to send! */
377 debugs(33, 3, "There is no more to send!");
378 noteEof();
379 flags.store_copying = false;
380 return;
381 }
382
383 /* Check that we actually have data */
384 if (anEntry->store_status == STORE_PENDING && copyInto.offset >= mem->endOffset()) {
385 debugs(90, 3, "store_client::doCopy: Waiting for more");
386 flags.store_copying = false;
387 return;
388 }
389
390 /*
391 * Slight weirdness here. We open a swapin file for any
392 * STORE_DISK_CLIENT, even if we can copy the requested chunk
393 * from memory in the next block. We must try to open the
394 * swapin file before sending any data to the client side. If
395 * we postpone the open, and then can not open the file later
396 * on, the client loses big time. Its transfer just gets cut
397 * off. Better to open it early (while the client side handler
398 * is clientCacheHit) so that we can fall back to a cache miss
399 * if needed.
400 */
401
402 if (STORE_DISK_CLIENT == getType() && swapin_sio == nullptr) {
403 if (!startSwapin())
404 return; // failure
405 }
406 scheduleRead();
407}
408
410bool
412{
413 debugs(90, 3, "store_client::doCopy: Need to open swap in file");
414 /* gotta open the swapin file */
415
417 /* yuck -- this causes a TCP_SWAPFAIL_MISS on the client side */
418 fail();
419 flags.store_copying = false;
420 return false;
421 } else if (!flags.disk_io_pending) {
422 /* Don't set store_io_pending here */
423 storeSwapInStart(this);
424
425 if (swapin_sio == nullptr) {
426 fail();
427 flags.store_copying = false;
428 return false;
429 }
430
431 return true;
432 } else {
433 debugs(90, DBG_IMPORTANT, "WARNING: Averted multiple fd operation (1)");
434 flags.store_copying = false;
435 return false;
436 }
437}
438
439void
441{
443 if (error)
444 fail();
445 else
446 noteEof();
447}
448
449void
451{
452 MemObject *mem = entry->mem_obj;
453
454 if (copyInto.offset >= mem->inmem_lo && copyInto.offset < mem->endOffset())
456 else
458}
459
460void
462{
463 /* What the client wants is not in memory. Schedule a disk read */
464 if (getType() == STORE_DISK_CLIENT) {
465 // we should have called startSwapin() already
466 assert(swapin_sio != nullptr);
467 } else if (!swapin_sio && !startSwapin()) {
468 debugs(90, 3, "bailing after swapin start failure for " << *entry);
469 assert(!flags.store_copying);
470 return;
471 }
472
473 assert(!flags.disk_io_pending);
474
475 debugs(90, 3, "reading " << *entry << " from disk");
476
477 fileRead();
478
479 flags.store_copying = false;
480}
481
482void
484{
485 /* What the client wants is in memory */
486 /* Old style */
487 debugs(90, 3, "store_client::doCopy: Copying normal from memory");
488 const auto sz = entry->mem_obj->data_hdr.copy(copyInto); // may be <= 0 per copy() API
489 callback(sz);
490 flags.store_copying = false;
491}
492
493void
495{
496 MemObject *mem = entry->mem_obj;
497
499 assert(!flags.disk_io_pending);
500 flags.disk_io_pending = true;
501
502 if (mem->swap_hdr_sz != 0)
503 if (entry->swappingOut())
504 assert(mem->swapout.sio->offset() > copyInto.offset + (int64_t)mem->swap_hdr_sz);
505
512 this);
513}
514
515void
516store_client::readBody(const char *, ssize_t len)
517{
518 // Don't assert disk_io_pending here.. may be called by read_header
519 flags.disk_io_pending = false;
521 debugs(90, 3, "storeClientReadBody: len " << len << "");
522
523 if (len < 0)
524 return fail();
525
526 const auto rep = entry->mem_obj ? &entry->mem().baseReply() : nullptr;
527 if (copyInto.offset == 0 && len > 0 && rep && rep->sline.status() == Http::scNone) {
528 /* Our structure ! */
530 debugs(90, DBG_CRITICAL, "ERROR: Could not parse headers from on disk object");
531 }
532 }
533
534 if (len > 0 && rep && entry->mem_obj->inmem_lo == 0 && entry->objectLen() <= (int64_t)Config.Store.maxInMemObjSize && Config.onoff.memory_cache_disk) {
535 storeGetMemSpace(len);
536 // recheck for the above call may purge entry's data from the memory cache
537 if (entry->mem_obj->inmem_lo == 0) {
538 /* Copy read data back into memory.
539 * copyInto.offset includes headers, which is what mem cache needs
540 */
543 }
544 }
545 }
546
547 callback(len);
548}
549
550void
552{
553 debugs(90, 3, (object_ok ? "once" : "again"));
554 if (!object_ok)
555 return; // we failed earlier; nothing to do now
556
557 object_ok = false;
558
559 noteNews();
560}
561
563void
565{
566 /* synchronous open failures callback from the store,
567 * before startSwapin detects the failure.
568 * TODO: fix this inconsistent behaviour - probably by
569 * having storeSwapInStart become a callback functions,
570 * not synchronous
571 */
572
574 debugs(90, 5, "client lost interest");
575 return;
576 }
577
578 if (_callback.notifier) {
579 debugs(90, 5, "earlier news is being delivered by " << _callback.notifier);
580 return;
581 }
582
583 _callback.notifier = asyncCall(90, 4, "store_client::FinishCallback", cbdataDialer(store_client::FinishCallback, this));
585
587}
588
589static void
590storeClientReadHeader(void *data, const char *buf, ssize_t len, StoreIOState::Pointer)
591{
592 store_client *sc = (store_client *)data;
593 sc->readHeader(buf, len);
594}
595
596static void
597storeClientReadBody(void *data, const char *buf, ssize_t len, StoreIOState::Pointer)
598{
599 store_client *sc = (store_client *)data;
600 sc->readBody(buf, len);
601}
602
603void
604store_client::readHeader(char const *buf, ssize_t len)
605{
606 MemObject *const mem = entry->mem_obj;
607
608 assert(flags.disk_io_pending);
609 flags.disk_io_pending = false;
611
612 // abort if we fail()'d earlier
613 if (!object_ok)
614 return;
615
616 if (len < 0)
617 return fail();
618
619 try {
621 } catch (...) {
622 debugs(90, DBG_IMPORTANT, "ERROR: Failed to unpack Store entry metadata: " << CurrentException);
623 fail();
624 return;
625 }
626
627 /*
628 * If our last read got some data the client wants, then give
629 * it to them, otherwise schedule another read.
630 */
631 size_t body_sz = len - mem->swap_hdr_sz;
632
633 if (copyInto.offset < static_cast<int64_t>(body_sz)) {
634 /*
635 * we have (part of) what they want
636 */
637 size_t copy_sz = min(copyInto.length, body_sz);
638 debugs(90, 3, "storeClientReadHeader: copying " << copy_sz << " bytes of body");
639 memmove(copyInto.data, copyInto.data + mem->swap_hdr_sz, copy_sz);
640
641 readBody(copyInto.data, copy_sz);
642
643 return;
644 }
645
646 /*
647 * we don't have what the client wants, but at least we now
648 * know the swap header size.
649 */
650 fileRead();
651}
652
653/*
654 * This routine hasn't been optimised to take advantage of the
655 * passed sc. Yet.
656 */
657int
659{
660 MemObject *mem = e->mem_obj;
661#if STORE_CLIENT_LIST_DEBUG
662 assert(sc == storeClientListSearch(e->mem_obj, data));
663#else
664 (void)data;
665#endif
666
667 if (mem == nullptr)
668 return 0;
669
670 debugs(90, 3, "storeUnregister: called for '" << e->getMD5Text() << "'");
671
672 if (sc == nullptr) {
673 debugs(90, 3, "storeUnregister: No matching client for '" << e->getMD5Text() << "'");
674 return 0;
675 }
676
677 if (mem->clientCount() == 0) {
678 debugs(90, 3, "storeUnregister: Consistency failure - store client being unregistered is not in the mem object's list for '" << e->getMD5Text() << "'");
679 return 0;
680 }
681
682 dlinkDelete(&sc->node, &mem->clients);
683 -- mem->nclients;
684
685 const auto swapoutFinished = e->swappedOut() || e->swapoutFailed();
686 if (e->store_status == STORE_OK && !swapoutFinished)
687 e->swapOut();
688
689 if (sc->swapin_sio != nullptr) {
691 sc->swapin_sio = nullptr;
693 }
694
695 if (sc->_callback.callback_handler || sc->_callback.notifier) {
696 debugs(90, 3, "forgetting store_client callback for " << *e);
697 // Do not notify: Callers want to stop copying and forget about this
698 // pending copy request. Some would mishandle a notification from here.
699 if (sc->_callback.notifier)
700 sc->_callback.notifier->cancel("storeUnregister");
701 }
702
703#if STORE_CLIENT_LIST_DEBUG
704 cbdataReferenceDone(sc->owner);
705
706#endif
707
708 // We must lock to safely dereference e below, after deleting sc and after
709 // calling CheckQuickAbortIsReasonable().
710 e->lock("storeUnregister");
711
712 // XXX: We might be inside sc store_client method somewhere up the call
713 // stack. TODO: Convert store_client to AsyncJob to make destruction async.
714 delete sc;
715
717 e->abort();
718 else
719 mem->kickReads();
720
721#if USE_ADAPTATION
722 e->kickProducer();
723#endif
724
725 e->unlock("storeUnregister");
726 return 1;
727}
728
729/* Call handlers waiting for data to be appended to E. */
730void
732{
734 debugs(90, 3, "DELAY_SENDING is on, exiting " << *this);
735 return;
736 }
738 debugs(90, 3, "ENTRY_FWD_HDR_WAIT is on, exiting " << *this);
739 return;
740 }
741
742 /* Commit what we can to disk, if appropriate */
743 swapOut();
744 int i = 0;
746 dlink_node *nx = nullptr;
748
749 debugs(90, 3, mem_obj->nclients << " clients; " << *this << ' ' << getMD5Text());
750 /* walk the entire list looking for valid callbacks */
751
752 const auto savedContext = CodeContext::Current();
753 for (node = mem_obj->clients.head; node; node = nx) {
754 sc = (store_client *)node->data;
755 nx = node->next;
756 ++i;
757
758 if (!sc->_callback.pending())
759 continue;
760
761 if (sc->flags.disk_io_pending)
762 continue;
763
764 if (sc->flags.store_copying)
765 continue;
766
767 // XXX: If invokeHandlers() is (indirectly) called from a store_client
768 // method, then the above three conditions may not be sufficient to
769 // prevent us from reentering the same store_client object! This
770 // probably does not happen in the current code, but no observed
771 // invariant prevents this from (accidentally) happening in the future.
772
773 // TODO: Convert store_client into AsyncJob; make this call asynchronous
774 CodeContext::Reset(sc->_callback.codeContext);
775 debugs(90, 3, "checking client #" << i);
776 storeClientCopy2(this, sc);
777 }
778 CodeContext::Reset(savedContext);
779}
780
781// Does not account for remote readers/clients.
782int
784{
785 MemObject *mem = e->mem_obj;
786 int npend = nullptr == mem ? 0 : mem->nclients;
787 debugs(90, 3, "storePendingNClients: returning " << npend);
788 return npend;
789}
790
791/* return true if the request should be aborted */
792static bool
794{
795 assert(entry);
796 debugs(90, 3, "entry=" << *entry);
797
798 if (storePendingNClients(entry) > 0) {
799 debugs(90, 3, "quick-abort? NO storePendingNClients() > 0");
800 return false;
801 }
802
803 if (Store::Root().transientReaders(*entry)) {
804 debugs(90, 3, "quick-abort? NO still have one or more transient readers");
805 return false;
806 }
807
808 if (entry->store_status != STORE_PENDING) {
809 debugs(90, 3, "quick-abort? NO store_status != STORE_PENDING");
810 return false;
811 }
812
813 if (EBIT_TEST(entry->flags, ENTRY_SPECIAL)) {
814 debugs(90, 3, "quick-abort? NO ENTRY_SPECIAL");
815 return false;
816 }
817
818 if (shutting_down) {
819 debugs(90, 3, "quick-abort? YES avoid heavy optional work during shutdown");
820 return true;
821 }
822
823 MemObject * const mem = entry->mem_obj;
824 assert(mem);
825 debugs(90, 3, "mem=" << mem);
826
827 if (mem->request && !mem->request->flags.cachable) {
828 debugs(90, 3, "quick-abort? YES !mem->request->flags.cachable");
829 return true;
830 }
831
832 if (EBIT_TEST(entry->flags, KEY_PRIVATE)) {
833 debugs(90, 3, "quick-abort? YES KEY_PRIVATE");
834 return true;
835 }
836
837 const auto &reply = mem->baseReply();
838
839 if (reply.hdr_sz <= 0) {
840 // TODO: Check whether this condition works for HTTP/0 responses.
841 debugs(90, 3, "quick-abort? YES no object data received yet");
842 return true;
843 }
844
845 if (Config.quickAbort.min < 0) {
846 debugs(90, 3, "quick-abort? NO disabled");
847 return false;
848 }
849
850 if (mem->request && mem->request->range && mem->request->getRangeOffsetLimit() < 0) {
851 // the admin has configured "range_offset_limit none"
852 debugs(90, 3, "quick-abort? NO admin configured range replies to full-download");
853 return false;
854 }
855
856 if (reply.content_length < 0) {
857 // XXX: cf.data.pre does not document what should happen in this case
858 // We know that quick_abort is enabled, but no limit can be applied.
859 debugs(90, 3, "quick-abort? YES unknown content length");
860 return true;
861 }
862 const auto expectlen = reply.hdr_sz + reply.content_length;
863
864 int64_t curlen = mem->endOffset();
865
866 if (curlen > expectlen) {
867 debugs(90, 3, "quick-abort? YES bad content length (" << curlen << " of " << expectlen << " bytes received)");
868 return true;
869 }
870
871 if ((expectlen - curlen) < (Config.quickAbort.min << 10)) {
872 debugs(90, 3, "quick-abort? NO only a little more object left to receive");
873 return false;
874 }
875
876 if ((expectlen - curlen) > (Config.quickAbort.max << 10)) {
877 debugs(90, 3, "quick-abort? YES too much left to go");
878 return true;
879 }
880
881 // XXX: This is absurd! TODO: For positives, "a/(b/c) > d" is "a*c > b*d".
882 if (expectlen < 100) {
883 debugs(90, 3, "quick-abort? NO avoid FPE");
884 return false;
885 }
886
887 if ((curlen / (expectlen / 100)) > (Config.quickAbort.pct)) {
888 debugs(90, 3, "quick-abort? NO past point of no return");
889 return false;
890 }
891
892 debugs(90, 3, "quick-abort? YES default");
893 return true;
894}
895
896void
897store_client::dumpStats(MemBuf * output, int clientNumber) const
898{
899 if (_callback.pending())
900 return;
901
902 output->appendf("\tClient #%d, %p\n", clientNumber, _callback.callback_data);
903 output->appendf("\t\tcopy_offset: %" PRId64 "\n", copyInto.offset);
904 output->appendf("\t\tcopy_size: %" PRIuSIZE "\n", copyInto.length);
905 output->append("\t\tflags:", 8);
906
907 if (flags.disk_io_pending)
908 output->append(" disk_io_pending", 16);
909
910 if (flags.store_copying)
911 output->append(" store_copying", 14);
912
914 output->append(" notifying", 10);
915
916 output->append("\n",1);
917}
918
919bool
921{
922 return callback_handler && !notifier;
923}
924
926 callback_handler(function),
927 callback_data(data),
928 codeContext(CodeContext::Current())
929{
930}
931
932#if USE_DELAY_POOLS
933int
935{
936 // TODO: To avoid using stale copyInto, return zero if !_callback.pending()?
938}
939
940void
942{
943 delayId = delay_id;
944}
945#endif
946
#define Assure(condition)
Definition: Assure.h:35
#define ScheduleCallHere(call)
Definition: AsyncCall.h:165
RefCount< AsyncCallT< Dialer > > asyncCall(int aDebugSection, int aDebugLevel, const char *aName, const Dialer &aDialer)
Definition: AsyncCall.h:155
UnaryCbdataDialer< Argument1 > cbdataDialer(typename UnaryCbdataDialer< Argument1 >::Handler *handler, Argument1 *arg1)
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:17
int cbdataReferenceValid(const void *p)
Definition: cbdata.cc:265
#define cbdataReferenceDone(var)
Definition: cbdata.h:352
#define cbdataReference(var)
Definition: cbdata.h:343
#define CBDATA_CLASS_INIT(type)
Definition: cbdata.h:320
Acl::Answer const & fastCheck()
Definition: Checklist.cc:332
bool allowed() const
Definition: Acl.h:156
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:77
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
void append(const char *c, int sz) override
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
SupportOrVeto cachable
whether the response may be stored in the cache
Definition: RequestFlags.h:35
struct SquidConfig::@107 accessList
struct SquidConfig::@106 onoff
struct SquidConfig::@92 quickAbort
acl_access * collapsedForwardingAccess
Definition: SquidConfig.h:404
int memory_cache_disk
Definition: SquidConfig.h:334
size_t maxInMemObjSize
Definition: SquidConfig.h:266
struct SquidConfig::@104 Store
int collapsed_forwarding
Definition: SquidConfig.h:321
int64_t min
Definition: SquidConfig.h:92
int64_t max
Definition: SquidConfig.h:94
struct StatCounters::@132 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 unlock(const char *context)
Definition: store.cc:443
bool hasDisk(const sdirno dirn=-1, const sfileno filen=-1) const
Definition: store.cc:1897
void lock(const char *context)
Definition: store.cc:419
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:205
void kickProducer()
calls back producer registered with deferProducer
Definition: store.cc:350
MemObject * mem_obj
Definition: Store.h:221
void abort()
Definition: store.cc:1051
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
int64_t offset
Definition: StoreIOBuffer.h:55
struct StoreIOBuffer::@142 flags
@ readerDone
success or failure: either way, stop swapping in
Definition: StoreIOState.h:60
off_t offset() const
Definition: StoreIOState.h:48
void STRCB(void *their_data, const char *buf, ssize_t len, StoreIOState::Pointer self)
Definition: StoreIOState.h:29
Definition: cbdata.cc:38
ssize_t copy(StoreIOBuffer const &) const
Definition: stmem.cc:189
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.
void scheduleMemRead()
struct store_client::@141 flags
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:38
#define debugs(SECTION, LEVEL, CONTENT)
Definition: Stream.h:193
#define DBG_CRITICAL
Definition: Stream.h:37
#define EBIT_TEST(flag, bit)
Definition: defines.h:69
@ STORE_DISK_CLIENT
Definition: enums.h:74
@ 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_PENDING
Definition: enums.h:51
@ STORE_OK
Definition: enums.h:50
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:931
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:1095
int storeTooManyDiskFilesOpen(void)
Definition: store.cc:863
int storeUnregister(store_client *sc, StoreEntry *e, void *data)
void storeClientCopy(store_client *sc, StoreEntry *e, StoreIOBuffer copyInto, STCB *callback, 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:21
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
#define NULL
Definition: types.h:160
#define PRId64
Definition: types.h:104

 

Introduction

Documentation

Support

Miscellaneous

Web Site Translations

Mirrors