store_client.cc
Go to the documentation of this file.
1 /*
2  * Copyright (C) 1996-2018 The Squid Software Foundation and contributors
3  *
4  * Squid software is distributed under GPLv2+ license and includes
5  * contributions from numerous individuals and organizations.
6  * Please see the COPYING and CONTRIBUTORS files for details.
7  */
8 
9 /* DEBUG: section 90 Storage Manager Client-Side Interface */
10 
11 #include "squid.h"
12 #include "acl/FilledChecklist.h"
13 #include "event.h"
14 #include "globals.h"
15 #include "HttpReply.h"
16 #include "HttpRequest.h"
17 #include "MemBuf.h"
18 #include "MemObject.h"
19 #include "mime_header.h"
20 #include "profiler/Profiler.h"
21 #include "SquidConfig.h"
22 #include "StatCounters.h"
23 #include "Store.h"
24 #include "store_swapin.h"
25 #include "StoreClient.h"
26 #include "StoreMeta.h"
27 #include "StoreMetaUnpacker.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 cannonical
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  */
42 static void storeClientCopy2(StoreEntry * e, store_client * sc);
44 static bool CheckQuickAbortIsReasonable(StoreEntry * entry);
45 
47 
48 /* StoreClient */
49 
50 bool
52 {
54  return false;
55 
57  return true;
58 
60  fillChecklist(checklist);
61  return checklist.fastCheck().allowed();
62 }
63 
64 bool
65 StoreClient::startCollapsingOn(const StoreEntry &e, const bool doingRevalidation)
66 {
68  return false; // collapsing is impossible due to the entry state
69 
70  if (!onCollapsingPath())
71  return false; // collapsing is impossible due to Squid configuration
72 
73  /* collapsing is possible; the caller must collapse */
74 
75  if (const auto tags = loggingTags()) {
76  if (doingRevalidation)
77  tags->collapsingHistory.revalidationCollapses++;
78  else
79  tags->collapsingHistory.otherCollapses++;
80  }
81 
82  debugs(85, 5, e << " doingRevalidation=" << doingRevalidation);
83  return true;
84 }
85 
86 void
88 {
89  // TODO: Consider moving all CF-related methods into a new dedicated class.
90  Must(!"startCollapsingOn() caller must override fillChecklist()");
91 }
92 
93 /* store_client */
94 
95 bool
97 {
98  return getType() == STORE_MEM_CLIENT && copyInto.offset < anOffset;
99 }
100 
101 int
103 {
104  return type;
105 }
106 
107 #if STORE_CLIENT_LIST_DEBUG
108 static store_client *
109 storeClientListSearch(const MemObject * mem, void *data)
110 {
111  dlink_node *node;
112  store_client *sc = NULL;
113 
114  for (node = mem->clients.head; node; node = node->next) {
115  sc = node->data;
116 
117  if (sc->owner == data)
118  return sc;
119  }
120 
121  return NULL;
122 }
123 
124 int
125 storeClientIsThisAClient(store_client * sc, void *someClient)
126 {
127  return sc->owner == someClient;
128 }
129 
130 #endif
131 #include "HttpRequest.h"
132 
133 /* add client with fd to client list */
134 store_client *
136 {
137  MemObject *mem = e->mem_obj;
138  store_client *sc;
139  assert(mem);
140 #if STORE_CLIENT_LIST_DEBUG
141 
142  if (storeClientListSearch(mem, data) != NULL)
143  /* XXX die! */
144  assert(1 == 0);
145 
146 #endif
147 
148  sc = new store_client (e);
149 
150  mem->addClient(sc);
151 
152  return sc;
153 }
154 
155 void
156 store_client::callback(ssize_t sz, bool error)
157 {
158  size_t bSz = 0;
159 
160  if (sz >= 0 && !error)
161  bSz = sz;
162 
163  StoreIOBuffer result(bSz, 0,copyInto.data);
164 
165  if (sz < 0 || error)
166  result.flags.error = 1;
167 
168  result.offset = cmp_offset;
170  cmp_offset = copyInto.offset + bSz;
171  STCB *temphandler = _callback.callback_handler;
174  copyInto.data = NULL;
175 
176  if (cbdataReferenceValid(cbdata))
177  temphandler(cbdata, result);
178 
179  cbdataReferenceDone(cbdata);
180 }
181 
182 static void
184 {
185  store_client *sc = (store_client *)data;
186  debugs(90, 3, "storeClientCopyEvent: Running");
188  sc->flags.copy_event_pending = false;
189 
190  if (!sc->_callback.pending())
191  return;
192 
193  storeClientCopy2(sc->entry, sc);
194 }
195 
197  cmp_offset(0),
198 #if STORE_CLIENT_LIST_DEBUG
199  owner(cbdataReference(data)),
200 #endif
201  entry(e),
202  type(e->storeClientType()),
203  object_ok(true)
204 {
205  flags.disk_io_pending = false;
206  flags.store_copying = false;
207  flags.copy_event_pending = false;
208  ++ entry->refcount;
209 
210  if (getType() == STORE_DISK_CLIENT) {
211  /* assert we'll be able to get the data we want */
212  /* maybe we should open swapin_sio here */
214  }
215 }
216 
218 {}
219 
220 /* copy bytes requested by the client */
221 void
223  StoreEntry * e,
224  StoreIOBuffer copyInto,
225  STCB * callback,
226  void *data)
227 {
228  assert (sc != NULL);
229  sc->copy(e, copyInto,callback,data);
230 }
231 
232 void
234  StoreIOBuffer copyRequest,
235  STCB * callback_fn,
236  void *data)
237 {
238  assert (anEntry == entry);
239  assert (callback_fn);
240  assert (data);
242  debugs(90, 3, "store_client::copy: " << entry->getMD5Text() << ", from " <<
243  copyRequest.offset << ", for length " <<
244  (int) copyRequest.length << ", cb " << callback_fn << ", cbdata " <<
245  data);
246 
247 #if STORE_CLIENT_LIST_DEBUG
248 
249  assert(this == storeClientListSearch(entry->mem_obj, data));
250 #endif
251 
253 #if ONLYCONTIGUOUSREQUESTS
254 
255  assert(cmp_offset == copyRequest.offset);
256 #endif
257  /* range requests will skip into the body */
258  cmp_offset = copyRequest.offset;
259  _callback = Callback (callback_fn, cbdataReference(data));
260  copyInto.data = copyRequest.data;
261  copyInto.length = copyRequest.length;
262  copyInto.offset = copyRequest.offset;
263 
264  static bool copying (false);
265  assert (!copying);
266  copying = true;
267  PROF_start(storeClient_kickReads);
268  /* we might be blocking comm reads due to readahead limits
269  * now we have a new offset, trigger those reads...
270  */
271  entry->mem_obj->kickReads();
272  PROF_stop(storeClient_kickReads);
273  copying = false;
274 
275  anEntry->lock("store_client::copy"); // see deletion note below
276 
277  storeClientCopy2(entry, this);
278 
279  // Bug 3480: This store_client object may be deleted now if, for example,
280  // the client rejects the hit response copied above. Use on-stack pointers!
281 
282 #if USE_ADAPTATION
283  anEntry->kickProducer();
284 #endif
285  anEntry->unlock("store_client::copy");
286 
287  // Add no code here. This object may no longer exist.
288 }
289 
291 bool
293 {
295  return true; // there may be more coming
296 
297  /* STORE_OK, including aborted entries: no more data is coming */
298 
299  const int64_t len = entry->objectLen();
300 
301  // If we do not know the entry length, then we have to open the swap file.
302  const bool canSwapIn = entry->hasDisk();
303  if (len < 0)
304  return canSwapIn;
305 
306  if (copyInto.offset >= len)
307  return false; // sent everything there is
308 
309  if (canSwapIn)
310  return true; // if we lack prefix, we can swap it in
311 
312  // If we cannot swap in, make sure we have what we want in RAM. Otherwise,
313  // scheduleRead calls scheduleDiskRead which asserts without a swap file.
314  const MemObject *mem = entry->mem_obj;
315  return mem &&
316  mem->inmem_lo <= copyInto.offset && copyInto.offset < mem->endOffset();
317 }
318 
319 static void
321 {
322  /* reentrancy not allowed - note this could lead to
323  * dropped events
324  */
325 
326  if (sc->flags.copy_event_pending) {
327  return;
328  }
329 
330  if (sc->flags.store_copying) {
331  sc->flags.copy_event_pending = true;
332  debugs(90, 3, "storeClientCopy2: Queueing storeClientCopyEvent()");
333  eventAdd("storeClientCopyEvent", storeClientCopyEvent, sc, 0.0, 0);
334  return;
335  }
336 
337  debugs(90, 3, "storeClientCopy2: " << e->getMD5Text());
338  assert(sc->_callback.pending());
339  /*
340  * We used to check for ENTRY_ABORTED here. But there were some
341  * problems. For example, we might have a slow client (or two) and
342  * the peer server is reading far ahead and swapping to disk. Even
343  * if the peer aborts, we want to give the client(s)
344  * everything we got before the abort condition occurred.
345  */
346  /* Warning: doCopy may indirectly free itself in callbacks,
347  * hence the lock to keep it active for the duration of
348  * this function
349  * XXX: Locking does not prevent calling sc destructor (it only prevents
350  * freeing sc memory) so sc may become invalid from C++ p.o.v.
351  */
352  CbcPointer<store_client> tmpLock = sc;
353  assert (!sc->flags.store_copying);
354  sc->doCopy(e);
355  assert(!sc->flags.store_copying);
356 }
357 
358 void
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, HERE << "There is no more to send!");
372  callback(0);
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 == NULL) {
397  if (!startSwapin())
398  return; // failure
399  }
400  scheduleRead();
401 }
402 
404 bool
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 == NULL) {
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 
433 void
435 {
436  MemObject *mem = entry->mem_obj;
437 
438  if (copyInto.offset >= mem->inmem_lo && copyInto.offset < mem->endOffset())
439  scheduleMemRead();
440  else
442 }
443 
444 void
446 {
447  /* What the client wants is not in memory. Schedule a disk read */
448  if (getType() == STORE_DISK_CLIENT) {
449  // we should have called startSwapin() already
450  assert(swapin_sio != NULL);
451  } else if (!swapin_sio && !startSwapin()) {
452  debugs(90, 3, "bailing after swapin start failure for " << *entry);
453  assert(!flags.store_copying);
454  return;
455  }
456 
457  assert(!flags.disk_io_pending);
458 
459  debugs(90, 3, "reading " << *entry << " from disk");
460 
461  fileRead();
462 
463  flags.store_copying = false;
464 }
465 
466 void
468 {
469  /* What the client wants is in memory */
470  /* Old style */
471  debugs(90, 3, "store_client::doCopy: Copying normal from memory");
472  size_t sz = entry->mem_obj->data_hdr.copy(copyInto);
473  callback(sz);
474  flags.store_copying = false;
475 }
476 
477 void
479 {
480  MemObject *mem = entry->mem_obj;
481 
483  assert(!flags.disk_io_pending);
484  flags.disk_io_pending = true;
485 
486  if (mem->swap_hdr_sz != 0)
487  if (entry->swappingOut())
488  assert(mem->swapout.sio->offset() > copyInto.offset + (int64_t)mem->swap_hdr_sz);
489 
491  copyInto.data,
493  copyInto.offset + mem->swap_hdr_sz,
496  this);
497 }
498 
499 void
500 store_client::readBody(const char *, ssize_t len)
501 {
502  int parsed_header = 0;
503 
504  // Don't assert disk_io_pending here.. may be called by read_header
505  flags.disk_io_pending = false;
507  debugs(90, 3, "storeClientReadBody: len " << len << "");
508 
509  if (copyInto.offset == 0 && len > 0 && entry->getReply()->sline.status() == Http::scNone) {
510  /* Our structure ! */
511  HttpReply *rep = (HttpReply *) entry->getReply(); // bypass const
512 
513  if (!rep->parseCharBuf(copyInto.data, headersEnd(copyInto.data, len))) {
514  debugs(90, DBG_CRITICAL, "Could not parse headers from on disk object");
515  } else {
516  parsed_header = 1;
517  }
518  }
519 
520  const HttpReply *rep = entry->getReply();
521  if (len > 0 && rep && entry->mem_obj->inmem_lo == 0 && entry->objectLen() <= (int64_t)Config.Store.maxInMemObjSize && Config.onoff.memory_cache_disk) {
522  storeGetMemSpace(len);
523  // The above may start to free our object so we need to check again
524  if (entry->mem_obj->inmem_lo == 0) {
525  /* Copy read data back into memory.
526  * copyInto.offset includes headers, which is what mem cache needs
527  */
528  int64_t mem_offset = entry->mem_obj->endOffset();
529  if ((copyInto.offset == mem_offset) || (parsed_header && mem_offset == rep->hdr_sz)) {
531  }
532  }
533  }
534 
535  callback(len);
536 }
537 
538 void
540 {
541  object_ok = false;
542  /* synchronous open failures callback from the store,
543  * before startSwapin detects the failure.
544  * TODO: fix this inconsistent behaviour - probably by
545  * having storeSwapInStart become a callback functions,
546  * not synchronous
547  */
548 
549  if (_callback.pending())
550  callback(0, true);
551 }
552 
553 static void
554 storeClientReadHeader(void *data, const char *buf, ssize_t len, StoreIOState::Pointer)
555 {
556  store_client *sc = (store_client *)data;
557  sc->readHeader(buf, len);
558 }
559 
560 static void
561 storeClientReadBody(void *data, const char *buf, ssize_t len, StoreIOState::Pointer)
562 {
563  store_client *sc = (store_client *)data;
564  sc->readBody(buf, len);
565 }
566 
567 bool
568 store_client::unpackHeader(char const *buf, ssize_t len)
569 {
570  int xerrno = errno; // FIXME: where does errno come from?
571  debugs(90, 3, "store_client::unpackHeader: len " << len << "");
572 
573  if (len < 0) {
574  debugs(90, 3, "WARNING: unpack error: " << xstrerr(xerrno));
575  return false;
576  }
577 
578  int swap_hdr_sz = 0;
579  tlv *tlv_list = nullptr;
580  try {
581  StoreMetaUnpacker aBuilder(buf, len, &swap_hdr_sz);
582  tlv_list = aBuilder.createStoreMeta();
583  } catch (const std::exception &e) {
584  debugs(90, DBG_IMPORTANT, "WARNING: failed to unpack metadata because " << e.what());
585  return false;
586  }
587  assert(tlv_list);
588 
589  /*
590  * Check the meta data and make sure we got the right object.
591  */
592  for (tlv *t = tlv_list; t; t = t->next) {
593  if (!t->checkConsistency(entry)) {
594  storeSwapTLVFree(tlv_list);
595  return false;
596  }
597  }
598 
599  storeSwapTLVFree(tlv_list);
600 
601  assert(swap_hdr_sz >= 0);
602  entry->mem_obj->swap_hdr_sz = swap_hdr_sz;
603  if (entry->swap_file_sz > 0) { // collapsed hits may not know swap_file_sz
604  assert(entry->swap_file_sz >= static_cast<uint64_t>(swap_hdr_sz));
605  entry->mem_obj->object_sz = entry->swap_file_sz - swap_hdr_sz;
606  }
607  debugs(90, 5, "store_client::unpackHeader: swap_file_sz=" <<
608  entry->swap_file_sz << "( " << swap_hdr_sz << " + " <<
609  entry->mem_obj->object_sz << ")");
610  return true;
611 }
612 
613 void
614 store_client::readHeader(char const *buf, ssize_t len)
615 {
616  MemObject *const mem = entry->mem_obj;
617 
618  assert(flags.disk_io_pending);
619  flags.disk_io_pending = false;
621 
622  // abort if we fail()'d earlier
623  if (!object_ok)
624  return;
625 
626  if (!unpackHeader(buf, len)) {
627  fail();
628  return;
629  }
630 
631  /*
632  * If our last read got some data the client wants, then give
633  * it to them, otherwise schedule another read.
634  */
635  size_t body_sz = len - mem->swap_hdr_sz;
636 
637  if (copyInto.offset < static_cast<int64_t>(body_sz)) {
638  /*
639  * we have (part of) what they want
640  */
641  size_t copy_sz = min(copyInto.length, body_sz);
642  debugs(90, 3, "storeClientReadHeader: copying " << copy_sz << " bytes of body");
643  memmove(copyInto.data, copyInto.data + mem->swap_hdr_sz, copy_sz);
644 
645  readBody(copyInto.data, copy_sz);
646 
647  return;
648  }
649 
650  /*
651  * we don't have what the client wants, but at least we now
652  * know the swap header size.
653  */
654  fileRead();
655 }
656 
657 int
659 {
660 #if STORE_CLIENT_LIST_DEBUG
661  assert(sc == storeClientListSearch(e->mem_obj, data));
662 #endif
663 #ifndef SILLY_CODE
664 
665  assert(sc);
666 #endif
667 
668  assert(sc->entry == e);
669 #if SILLY_CODE
670 
671  if (sc == NULL)
672  return 0;
673 
674 #endif
675 
676  if (!sc->_callback.pending())
677  return 0;
678 
679  return 1;
680 }
681 
682 /*
683  * This routine hasn't been optimised to take advantage of the
684  * passed sc. Yet.
685  */
686 int
688 {
689  MemObject *mem = e->mem_obj;
690 #if STORE_CLIENT_LIST_DEBUG
691 
692  assert(sc == storeClientListSearch(e->mem_obj, data));
693 #endif
694 
695  if (mem == NULL)
696  return 0;
697 
698  debugs(90, 3, "storeUnregister: called for '" << e->getMD5Text() << "'");
699 
700  if (sc == NULL) {
701  debugs(90, 3, "storeUnregister: No matching client for '" << e->getMD5Text() << "'");
702  return 0;
703  }
704 
705  if (mem->clientCount() == 0) {
706  debugs(90, 3, "storeUnregister: Consistency failure - store client being unregistered is not in the mem object's list for '" << e->getMD5Text() << "'");
707  return 0;
708  }
709 
710  dlinkDelete(&sc->node, &mem->clients);
711  -- mem->nclients;
712 
713  if (e->store_status == STORE_OK && !e->swappedOut())
714  e->swapOut();
715 
716  if (sc->swapin_sio != NULL) {
718  sc->swapin_sio = NULL;
719  ++statCounter.swap.ins;
720  }
721 
722  if (sc->_callback.pending()) {
723  /* callback with ssize = -1 to indicate unexpected termination */
724  debugs(90, 3, "store_client for " << *e << " has a callback");
725  sc->fail();
726  }
727 
728 #if STORE_CLIENT_LIST_DEBUG
729  cbdataReferenceDone(sc->owner);
730 
731 #endif
732 
733  delete sc;
734 
735  assert(e->locked());
736  // An entry locked by others may be unlocked (and destructed) by others, so
737  // we must lock again to safely dereference e after CheckQuickAbortIsReasonable().
738  e->lock("storeUnregister");
739 
741  e->abort();
742  else
743  mem->kickReads();
744 
745 #if USE_ADAPTATION
746  e->kickProducer();
747 #endif
748 
749  e->unlock("storeUnregister");
750  return 1;
751 }
752 
753 /* Call handlers waiting for data to be appended to E. */
754 void
756 {
757  if (EBIT_TEST(flags, DELAY_SENDING)) {
758  debugs(90, 3, "DELAY_SENDING is on, exiting " << *this);
759  return;
760  }
762  debugs(90, 3, "ENTRY_FWD_HDR_WAIT is on, exiting " << *this);
763  return;
764  }
765 
766  /* Commit what we can to disk, if appropriate */
767  swapOut();
768  int i = 0;
769  store_client *sc;
770  dlink_node *nx = NULL;
771  dlink_node *node;
772 
773  PROF_start(InvokeHandlers);
774 
775  debugs(90, 3, "InvokeHandlers: " << getMD5Text() );
776  /* walk the entire list looking for valid callbacks */
777 
778  for (node = mem_obj->clients.head; node; node = nx) {
779  sc = (store_client *)node->data;
780  nx = node->next;
781  debugs(90, 3, "StoreEntry::InvokeHandlers: checking client #" << i );
782  ++i;
783 
784  if (!sc->_callback.pending())
785  continue;
786 
787  if (sc->flags.disk_io_pending)
788  continue;
789 
790  storeClientCopy2(this, sc);
791  }
792  PROF_stop(InvokeHandlers);
793 }
794 
795 // Does not account for remote readers/clients.
796 int
798 {
799  MemObject *mem = e->mem_obj;
800  int npend = NULL == mem ? 0 : mem->nclients;
801  debugs(90, 3, "storePendingNClients: returning " << npend);
802  return npend;
803 }
804 
805 /* return true if the request should be aborted */
806 static bool
808 {
809  assert(entry);
810  debugs(90, 3, "entry=" << *entry);
811 
812  if (storePendingNClients(entry) > 0) {
813  debugs(90, 3, "quick-abort? NO storePendingNClients() > 0");
814  return false;
815  }
816 
817  if (!shutting_down && Store::Root().transientReaders(*entry)) {
818  debugs(90, 3, "quick-abort? NO still have one or more transient readers");
819  return false;
820  }
821 
822  if (entry->store_status != STORE_PENDING) {
823  debugs(90, 3, "quick-abort? NO store_status != STORE_PENDING");
824  return false;
825  }
826 
827  if (EBIT_TEST(entry->flags, ENTRY_SPECIAL)) {
828  debugs(90, 3, "quick-abort? NO ENTRY_SPECIAL");
829  return false;
830  }
831 
832  MemObject * const mem = entry->mem_obj;
833  assert(mem);
834  debugs(90, 3, "mem=" << mem);
835 
836  if (mem->request && !mem->request->flags.cachable) {
837  debugs(90, 3, "quick-abort? YES !mem->request->flags.cachable");
838  return true;
839  }
840 
841  if (EBIT_TEST(entry->flags, KEY_PRIVATE)) {
842  debugs(90, 3, "quick-abort? YES KEY_PRIVATE");
843  return true;
844  }
845 
846  int64_t expectlen = entry->getReply()->content_length + entry->getReply()->hdr_sz;
847 
848  if (expectlen < 0) {
849  /* expectlen is < 0 if *no* information about the object has been received */
850  debugs(90, 3, "quick-abort? YES no object data received yet");
851  return true;
852  }
853 
854  int64_t curlen = mem->endOffset();
855 
856  if (Config.quickAbort.min < 0) {
857  debugs(90, 3, "quick-abort? NO disabled");
858  return false;
859  }
860 
861  if (mem->request && mem->request->range && mem->request->getRangeOffsetLimit() < 0) {
862  /* Don't abort if the admin has configured range_ofset -1 to download fully for caching. */
863  debugs(90, 3, "quick-abort? NO admin configured range replies to full-download");
864  return false;
865  }
866 
867  if (curlen > expectlen) {
868  debugs(90, 3, "quick-abort? YES bad content length (" << curlen << " of " << expectlen << " bytes received)");
869  return true;
870  }
871 
872  if ((expectlen - curlen) < (Config.quickAbort.min << 10)) {
873  debugs(90, 3, "quick-abort? NO only a little more object left to receive");
874  return false;
875  }
876 
877  if ((expectlen - curlen) > (Config.quickAbort.max << 10)) {
878  debugs(90, 3, "quick-abort? YES too much left to go");
879  return true;
880  }
881 
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 
896 void
897 store_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 
913  if (flags.copy_event_pending)
914  output->append(" copy_event_pending", 19);
915 
916  output->append("\n",1);
917 }
918 
919 bool
921 {
923 }
924 
925 store_client::Callback::Callback(STCB *function, void *data) : callback_handler(function), callback_data (data) {}
926 
927 #if USE_DELAY_POOLS
928 void
930 {
931  delayId = delay_id;
932 }
933 #endif
934 
bool startCollapsingOn(const StoreEntry &, const bool doingRevalidation)
Definition: store_client.cc:65
bool moreToSend() const
Whether there is (or will be) more entry data for us.
StoreMeta * createStoreMeta()
HttpHdrRange * range
Definition: HttpRequest.h:135
StatCounters statCounter
Definition: StatCounters.cc:12
#define assert(EX)
Definition: assert.h:17
void kickReads()
Definition: MemObject.cc:442
void const char HLPCB * callback
Definition: stub_helper.cc:16
size_t maxInMemObjSize
Definition: SquidConfig.h:268
void storeClientCopy(store_client *sc, StoreEntry *e, StoreIOBuffer copyInto, STCB *callback, void *data)
static int sc[16]
Definition: smbdes.c:121
#define cbdataReferenceDone(var)
Definition: cbdata.h:350
virtual void append(const char *c, int sz)
Definition: MemBuf.cc:216
int unlock(const char *context)
Definition: store.cc:457
size_t swap_hdr_sz
Definition: MemObject.h:169
int storeClientCopyPending(store_client *sc, StoreEntry *e, void *data)
Definition: cbdata.cc:60
int storePendingNClients(const StoreEntry *e)
int hdr_sz
Definition: Message.h:82
int type
Definition: errorpage.cc:78
void STRCB(void *their_data, const char *buf, ssize_t len, StoreIOState::Pointer self)
Definition: StoreIOState.h:29
int collapsed_forwarding
Definition: SquidConfig.h:326
void storeClose(StoreIOState::Pointer sio, int how)
Definition: store_io.cc:68
void error(char *format,...)
int i
Definition: membanger.c:49
int64_t endOffset() const
Definition: MemObject.cc:218
#define PRId64
Definition: types.h:110
int getType() const
bool hasDisk(const sdirno dirn=-1, const sfileno filen=-1) const
Definition: store.cc:1997
off_t offset() const
Definition: StoreIOState.h:60
bool swappingOut() const
whether we are in the process of writing this entry to disk
Definition: Store.h:119
#define Must(condition)
Like assert() but throws an exception instead of aborting the process.
Definition: TextException.h:69
bool startSwapin()
opens the swapin &quot;file&quot; if possible; otherwise, fail()s and returns false
struct SquidConfig::@110 Store
store_client * storeClientListAdd(StoreEntry *e, void *data)
#define DBG_CRITICAL
Definition: Debug.h:45
Controller & Root()
safely access controller singleton
Definition: Controller.cc:877
int storeTooManyDiskFilesOpen(void)
Definition: store.cc:911
bool memReaderHasLowerOffset(int64_t) const
Definition: store_client.cc:96
store_client(StoreEntry *)
struct store_client::@145 flags
void setDelayId(DelayId delay_id)
StoreIOState::Pointer sio
Definition: MemObject.h:117
struct StatCounters::@137 swap
dlink_node node
Definition: StoreClient.h:99
void invokeHandlers()
void readBody(const char *buf, ssize_t len)
int locked() const
Definition: store.cc:1249
uint64_t swap_file_sz
Definition: Store.h:206
int shutting_down
Definition: testAddress.cc:36
const char * xstrerr(int error)
Definition: xstrerror.cc:83
static StoreIOState::STRCB storeClientReadBody
Definition: store_client.cc:40
void const char HLPCB void * data
Definition: stub_helper.cc:16
int64_t offset
Definition: StoreIOBuffer.h:55
Definition: parse.c:104
int64_t content_length
Definition: Message.h:84
void EVH(void *)
Definition: event.h:19
int64_t object_sz
Definition: MemObject.h:168
#define debugs(SECTION, LEVEL, CONTENT)
Definition: Debug.h:124
int64_t objectLen() const
Definition: store.cc:1655
#define cbdataReference(var)
Definition: cbdata.h:341
#define true
Definition: GnuRegex.c:234
#define DBG_IMPORTANT
Definition: Debug.h:46
void abort()
Definition: store.cc:1107
success or failure: either way, stop swapping in
Definition: StoreIOState.h:72
int storeClientIsThisAClient(store_client *sc, void *someClient)
HttpReply const * getReply() const
Definition: store.cc:1670
static bool CheckQuickAbortIsReasonable(StoreEntry *entry)
int64_t min
Definition: SquidConfig.h:88
static StoreIOState::STRCB storeClientReadHeader
Definition: store_client.cc:41
bool unpackHeader(char const *buf, ssize_t len)
acl_access * collapsedForwardingAccess
Definition: SquidConfig.h:405
void scheduleDiskRead()
StoreIOBuffer copyInto
Definition: StoreClient.h:101
struct SquidConfig::@113 accessList
bool allowed() const
Definition: Acl.h:141
StoreIOState::Pointer swapin_sio
Definition: StoreClient.h:86
uint16_t flags
Definition: Store.h:208
bool copy_event_pending
Definition: StoreClient.h:91
void scheduleMemRead()
class StoreMeta tlv
Definition: StoreMeta.h:15
ssize_t copy(StoreIOBuffer const &) const
Definition: stmem.cc:226
StoreEntry * entry
Definition: StoreClient.h:85
Http::StatusLine sline
Definition: HttpReply.h:60
MemObject * mem_obj
Definition: Store.h:197
struct StoreIOBuffer::@146 flags
void storeSwapTLVFree(tlv *n)
void write(const StoreIOBuffer &buf)
Definition: MemObject.cc:136
int64_t cmp_offset
Definition: StoreClient.h:79
int unsigned int const char *desc STUB void int len
Definition: stub_fd.cc:20
void dumpStats(MemBuf *output, int clientNumber) const
uint16_t refcount
Definition: Store.h:207
void const char * buf
Definition: stub_helper.cc:16
std::ostream & HERE(std::ostream &s)
Definition: Debug.h:153
struct SquidConfig::@112 onoff
void storeGetMemSpace(int size)
Definition: store.cc:1161
unsigned error
Definition: StoreIOBuffer.h:52
SwapOut swapout
Definition: MemObject.h:124
void doCopy(StoreEntry *e)
virtual LogTags * loggingTags()=0
int storeUnregister(store_client *sc, StoreEntry *e, void *data)
Definition: enums.h:46
bool SIGHDLR int STUB void int
Definition: stub_tools.cc:68
static void storeClientCopy2(StoreEntry *e, store_client *sc)
int64_t max
Definition: SquidConfig.h:90
void eventAdd(const char *name, EVH *func, void *arg, double when, int weight, bool cbdata)
Definition: event.cc:109
const char * getMD5Text() const
Definition: store.cc:184
RequestFlags flags
Definition: HttpRequest.h:133
bool store_copying
Definition: StoreClient.h:90
virtual void fillChecklist(ACLFilledChecklist &) const =0
configure the ACL checklist with the current transaction state
Definition: store_client.cc:87
store_status_t store_status
Definition: Store.h:220
allow_t const & fastCheck()
Definition: Checklist.cc:336
static EVH storeClientCopyEvent
Definition: store_client.cc:43
int64_t getRangeOffsetLimit()
Definition: HttpRequest.cc:601
#define PROF_start(probename)
Definition: Profiler.h:62
void copy(StoreEntry *, StoreIOBuffer, STCB *, void *)
#define CBDATA_CLASS_INIT(type)
Definition: cbdata.h:318
int memory_cache_disk
Definition: SquidConfig.h:339
void STCB(void *, StoreIOBuffer)
Definition: StoreClient.h:16
void appendf(const char *fmt,...) PRINTF_FORMAT_ARG2
Append operation with printf-style arguments.
Definition: Packable.h:61
dlink_list clients
Definition: MemObject.h:105
bool disk_io_pending
Definition: StoreClient.h:89
bool hittingRequiresCollapsing() const
whether this entry can feed collapsed requests and only them
Definition: Store.h:192
Definition: MemBuf.h:23
struct SquidConfig::@97 quickAbort
void scheduleRead()
bool parseCharBuf(const char *buf, ssize_t end)
Definition: Message.cc:148
void readHeader(const char *buf, ssize_t len)
int nclients
Definition: MemObject.h:111
int cbdataReferenceValid(const void *p)
Definition: cbdata.cc:412
DelayId delayId
Definition: StoreClient.h:95
#define PROF_stop(probename)
Definition: Profiler.h:63
size_t clientCount() const
Definition: MemObject.h:107
mem_hdr data_hdr
Definition: MemObject.h:103
void swapOut()
size_t headersEnd(const char *mime, size_t l, bool &containsObsFold)
Definition: mime_header.cc:16
bool onCollapsingPath() const
whether Squid configuration allows collapsing for this transaction
Definition: store_client.cc:51
bool swappedOut() const
whether the entire entry is now on disk (possibly marked for deletion)
Definition: Store.h:121
HttpRequestPointer request
Definition: MemObject.h:155
#define EBIT_TEST(flag, bit)
Definition: defines.h:107
void storeSwapInStart(store_client *sc)
Definition: store_swapin.cc:22
class SquidConfig Config
Definition: SquidConfig.cc:12
#define NULL
Definition: types.h:166
struct store_client::Callback _callback
void addClient(store_client *)
Definition: MemObject.cc:295
void callback(ssize_t len, bool error=false)
A const & min(A const &lhs, A const &rhs)
int64_t inmem_lo
Definition: MemObject.h:104
void storeRead(StoreIOState::Pointer sio, char *buf, size_t size, off_t offset, StoreIOState::STRCB *callback, void *callback_data)
Definition: store_io.cc:82
void kickProducer()
calls back producer registered with deferProducer
Definition: store.cc:362
Http::StatusCode status() const
retrieve the status code for this status line
Definition: StatusLine.h:45
void lock(const char *context)
Definition: store.cc:433

 

Introduction

Documentation

Support

Miscellaneous

Web Site Translations

Mirrors