314
309
mem_obj->setNoDelay(newValue);
312
// XXX: Type names mislead. STORE_DISK_CLIENT actually means that we should
313
// open swapin file, aggressively trim memory, and ignore read-ahead gap.
314
// It does not mean we will read from disk exclusively (or at all!).
315
// XXX: May create STORE_DISK_CLIENT with no disk caching configured.
316
// XXX: Collapsed clients cannot predict their type.
318
318
StoreEntry::storeClientType() const
346
341
if (swap_status == SWAPOUT_DONE) {
347
342
debugs(20,7, HERE << mem_obj << " lo: " << mem_obj->inmem_lo << " hi: " << mem_obj->endOffset() << " size: " << mem_obj->object_sz);
348
343
if (mem_obj->endOffset() == mem_obj->object_sz) {
349
/* hot object fully swapped in */
344
/* hot object fully swapped in (XXX: or swapped out?) */
350
345
return STORE_MEM_CLIENT;
383
378
StoreEntry::StoreEntry() :
385
hidden_mem_obj(NULL),
396
mem_status(NOT_IN_MEMORY),
397
ping_status(PING_NONE),
398
store_status(STORE_PENDING),
399
swap_status(SWAPOUT_NONE)
401
debugs(20, 3, HERE << "new StoreEntry " << this);
404
StoreEntry::StoreEntry(const char *aUrl, const char *aLogUrl) :
406
hidden_mem_obj(NULL),
417
mem_status(NOT_IN_MEMORY),
418
ping_status(PING_NONE),
419
store_status(STORE_PENDING),
420
swap_status(SWAPOUT_NONE)
422
debugs(20, 3, HERE << "new StoreEntry " << this);
423
mem_obj = new MemObject(aUrl, aLogUrl);
389
mem_status(NOT_IN_MEMORY),
390
ping_status(PING_NONE),
391
store_status(STORE_PENDING),
392
swap_status(SWAPOUT_NONE),
395
debugs(20, 3, HERE << "new StoreEntry " << this);
426
398
StoreEntry::~StoreEntry()
428
if (swap_filen >= 0) {
429
SwapDir &sd = dynamic_cast<SwapDir&>(*store());
430
sd.disconnect(*this);
432
delete hidden_mem_obj;
435
402
#if USE_ADAPTATION
457
424
StoreEntry::destroyMemObject()
459
426
debugs(20, 3, HERE << "destroyMemObject " << mem_obj);
460
setMemStatus(NOT_IN_MEMORY);
461
MemObject *mem = mem_obj;
464
delete hidden_mem_obj;
465
hidden_mem_obj = NULL;
469
StoreEntry::hideMemObject()
471
debugs(20, 3, HERE << "hiding " << mem_obj);
473
assert(!hidden_mem_obj);
474
hidden_mem_obj = mem_obj;
428
if (MemObject *mem = mem_obj) {
429
// Store::Root() is FATALly missing during shutdown
430
if (mem->xitTable.index >= 0 && !shutting_down)
431
Store::Root().transientsDisconnect(*mem);
432
if (mem->memCache.index >= 0 && !shutting_down)
433
Store::Root().memoryDisconnect(*this);
435
setMemStatus(NOT_IN_MEMORY);
500
469
StoreEntry::hashInsert(const cache_key * someKey)
502
debugs(20, 3, "StoreEntry::hashInsert: Inserting Entry " << this << " key '" << storeKeyText(someKey) << "'");
471
debugs(20, 3, "StoreEntry::hashInsert: Inserting Entry " << *this << " key '" << storeKeyText(someKey) << "'");
503
472
key = storeKeyDup(someKey);
504
473
hash_join(store_table, this);
559
530
if (EBIT_TEST(flags, RELEASE_REQUEST))
565
* Clear cachable flag here because we might get called before
566
* anyone else even looks at the cachability flag. Also, this
567
* prevents httpMakePublic from really setting a public key.
569
EBIT_CLR(flags, ENTRY_CACHABLE);
533
setReleaseFlag(); // makes validToSend() false, preventing future hits
687
651
return; /* is already private */
654
setReleaseFlag(); // will markForUnlink(); all caches/workers will know
656
// TODO: move into SwapDir::markForUnlink() already called by Root()
690
657
if (swap_filen > -1)
691
658
storeDirSwapLog(this, SWAP_LOG_DEL);
696
if (mem_obj != NULL) {
663
if (mem_obj && mem_obj->hasUris()) {
697
664
mem_obj->id = getKeyCounter();
698
newkey = storeKeyPrivate(mem_obj->url, mem_obj->method, mem_obj->id);
665
newkey = storeKeyPrivate(mem_obj->storeId(), mem_obj->method, mem_obj->id);
700
667
newkey = storeKeyPrivate("JUNK", Http::METHOD_NONE, getKeyCounter());
723
689
* store clients won't be able to access object data which has
724
690
* been freed from memory.
726
* If RELEASE_REQUEST is set, then ENTRY_CACHABLE should not
727
* be set, and StoreEntry::setPublicKey() should not be called.
692
* If RELEASE_REQUEST is set, setPublicKey() should not be called.
729
694
#if MORE_DEBUG_OUTPUT
747
712
* to record the new variance key
749
714
safe_free(request->vary_headers); /* free old "bad" variance key */
750
StoreEntry *pe = storeGetPublic(mem_obj->url, mem_obj->method);
715
if (StoreEntry *pe = storeGetPublic(mem_obj->storeId(), mem_obj->method))
765
728
// TODO: storeGetPublic() calls below may create unlocked entries.
766
729
// We should add/use storeHas() API or lock/unlock those entries.
767
if (mem_obj->vary_headers && !storeGetPublic(mem_obj->url, mem_obj->method)) {
730
if (mem_obj->vary_headers && !storeGetPublic(mem_obj->storeId(), mem_obj->method)) {
768
731
/* Create "vary" base object */
770
StoreEntry *pe = storeCreateEntry(mem_obj->url, mem_obj->log_url, request->flags, request->method);
733
StoreEntry *pe = storeCreateEntry(mem_obj->storeId(), mem_obj->logUri(), request->flags, request->method);
771
734
/* We are allowed to do this typecast */
772
735
HttpReply *rep = new HttpReply;
773
736
rep->setHeaders(Http::scOkay, "Internal marker object", "x-squid-internal/vary", -1, -1, squid_curtime + 100000);
763
pe->unlock("StoreEntry::setPublicKey+Vary");
803
766
newkey = storeKeyPublicByRequest(mem_obj->request);
805
newkey = storeKeyPublic(mem_obj->url, mem_obj->method);
768
newkey = storeKeyPublic(mem_obj->storeId(), mem_obj->method);
807
if ((e2 = (StoreEntry *) hash_lookup(store_table, newkey))) {
808
debugs(20, 3, "StoreEntry::setPublicKey: Making old '" << mem_obj->url << "' private.");
770
if (StoreEntry *e2 = (StoreEntry *)hash_lookup(store_table, newkey)) {
771
debugs(20, 3, "Making old " << *e2 << " private.");
809
772
e2->setPrivateKey();
812
775
if (mem_obj->request)
813
776
newkey = storeKeyPublicByRequest(mem_obj->request);
815
newkey = storeKeyPublic(mem_obj->url, mem_obj->method);
778
newkey = storeKeyPublic(mem_obj->storeId(), mem_obj->method);
830
storeCreateEntry(const char *url, const char *log_url, const RequestFlags &flags, const HttpRequestMethod& method)
793
storeCreatePureEntry(const char *url, const char *log_url, const RequestFlags &flags, const HttpRequestMethod& method)
832
795
StoreEntry *e = NULL;
833
MemObject *mem = NULL;
834
796
debugs(20, 3, "storeCreateEntry: '" << url << "'");
836
e = new StoreEntry(url, log_url);
837
e->lock_count = 1; /* Note lock here w/o calling storeLock() */
839
mem->method = method;
841
if (neighbors_do_private_keys || !flags.hierarchical)
798
e = new StoreEntry();
800
e->mem_obj->setUris(url, log_url, method);
846
802
if (flags.cachable) {
847
EBIT_SET(e->flags, ENTRY_CACHABLE);
848
803
EBIT_CLR(e->flags, RELEASE_REQUEST);
850
/* StoreEntry::releaseRequest() clears ENTRY_CACHABLE */
851
805
e->releaseRequest();
854
808
e->store_status = STORE_PENDING;
855
e->setMemStatus(NOT_IN_MEMORY);
857
810
e->lastref = squid_curtime;
858
811
e->timestamp = -1; /* set in StoreEntry::timestampsSet() */
818
storeCreateEntry(const char *url, const char *logUrl, const RequestFlags &flags, const HttpRequestMethod& method)
820
StoreEntry *e = storeCreatePureEntry(url, logUrl, flags, method);
821
e->lock("storeCreateEntry");
823
if (neighbors_do_private_keys || !flags.hierarchical)
864
831
/* Mark object as expired */
866
833
StoreEntry::expireNow()
873
storeWriteComplete (void *data, StoreIOBuffer wroteBuffer)
875
PROF_start(storeWriteComplete);
876
StoreEntry *e = (StoreEntry *)data;
878
if (EBIT_TEST(e->flags, DELAY_SENDING)) {
879
PROF_stop(storeWriteComplete);
884
PROF_stop(storeWriteComplete);
888
840
StoreEntry::write (StoreIOBuffer writeBuffer)
890
842
assert(mem_obj != NULL);
892
844
PROF_start(StoreEntry_write);
893
845
assert(store_status == STORE_PENDING);
847
// XXX: caller uses content offset, but we also store headers
848
if (const HttpReply *reply = mem_obj->getReply())
849
writeBuffer.offset += reply->hdr_sz;
895
851
debugs(20, 5, "storeWrite: writing " << writeBuffer.length << " bytes for '" << getMD5Text() << "'");
896
852
PROF_stop(StoreEntry_write);
897
853
storeGetMemSpace(writeBuffer.length);
898
mem_obj->write (writeBuffer, storeWriteComplete, this);
854
mem_obj->write(writeBuffer);
856
if (!EBIT_TEST(flags, DELAY_SENDING))
901
860
/* Append incoming data from a primary server to an entry. */
999
958
if (store_status == STORE_OK && EBIT_TEST(flags, ENTRY_BAD_LENGTH)) {
1000
959
debugs(20, 2, "StoreEntry::checkCachable: NO: wrong content-length");
1001
960
++store_check_cachable_hist.no.wrong_content_length;
1002
} else if (!EBIT_TEST(flags, ENTRY_CACHABLE)) {
961
} else if (EBIT_TEST(flags, RELEASE_REQUEST)) {
1003
962
debugs(20, 2, "StoreEntry::checkCachable: NO: not cachable");
1004
++store_check_cachable_hist.no.not_entry_cachable;
963
++store_check_cachable_hist.no.not_entry_cachable; // TODO: rename?
1005
964
} else if (EBIT_TEST(flags, ENTRY_NEGCACHED)) {
1006
965
debugs(20, 3, "StoreEntry::checkCachable: NO: negative cached");
1007
966
++store_check_cachable_hist.no.negative_cached;
1267
1225
StoreEntry::release()
1269
1227
PROF_start(storeRelease);
1270
debugs(20, 3, "storeRelease: Releasing: '" << getMD5Text() << "'");
1228
debugs(20, 3, "releasing " << *this << ' ' << getMD5Text());
1271
1229
/* If, for any reason we can't discard this object because of an
1272
1230
* outstanding request, mark it for pending release */
1240
Store::Root().memoryUnlink(*this);
1282
1242
if (StoreController::store_dirs_rebuilding && swap_filen > -1) {
1283
1243
setPrivateKey();
1288
1245
if (swap_filen > -1) {
1290
1247
* Fake a call to StoreEntry->lock() When rebuilding is done,
1291
1248
* we'll just call StoreEntry->unlock() on these.
1250
lock("StoreEntry::release+rebuilding");
1294
1251
setReleaseFlag();
1295
1252
LateReleaseStack.push_back(this);
1352
1308
if (lock_count)
1355
if (swap_status == SWAPOUT_WRITING)
1358
if (store_status == STORE_PENDING)
1362
* SPECIAL, PUBLIC entries should be "locked"
1312
* SPECIAL, PUBLIC entries should be "locked";
1313
* XXX: Their owner should lock them then instead of relying on this hack.
1364
1315
if (EBIT_TEST(flags, ENTRY_SPECIAL))
1365
1316
if (!EBIT_TEST(flags, KEY_PRIVATE))
1534
1485
if (EBIT_TEST(flags, ENTRY_ABORTED))
1488
// now check that the entry has a cache backing or is collapsed
1489
if (swap_filen > -1) // backed by a disk cache
1492
if (swappingOut()) // will be backed by a disk cache
1495
if (!mem_obj) // not backed by a memory cache and not collapsed
1498
if (mem_obj->memCache.index >= 0) // backed by a shared memory cache
1501
// StoreEntry::storeClientType() assumes DISK_CLIENT here, but there is no
1502
// disk cache backing so we should not rely on the store cache at all. This
1503
// is wrong for range requests that could feed off nibbled memory (XXX).
1504
if (mem_obj->inmem_lo) // in local memory cache, but got nibbled at
1638
1608
// are we using a shared memory cache?
1639
1609
if (Config.memShared && IamWorkerProcess()) {
1640
// enumerate calling cases if shared memory is enabled
1641
assert(new_status != IN_MEMORY || EBIT_TEST(flags, ENTRY_SPECIAL));
1642
1610
// This method was designed to update replacement policy, not to
1643
1611
// actually purge something from the memory cache (TODO: rename?).
1644
1612
// Shared memory cache does not have a policy that needs updates.
1652
1620
assert(mem_obj->inmem_lo == 0);
1654
1622
if (EBIT_TEST(flags, ENTRY_SPECIAL)) {
1655
debugs(20, 4, "StoreEntry::setMemStatus: not inserting special " << mem_obj->url << " into policy");
1623
debugs(20, 4, "not inserting special " << *this << " into policy");
1657
1625
mem_policy->Add(mem_policy, this, &mem_obj->repl);
1658
debugs(20, 4, "StoreEntry::setMemStatus: inserted mem node " << mem_obj->url << " key: " << getMD5Text());
1626
debugs(20, 4, "inserted " << *this << " key: " << getMD5Text());
1661
1629
++hot_obj_count; // TODO: maintain for the shared hot cache as well
1663
1631
if (EBIT_TEST(flags, ENTRY_SPECIAL)) {
1664
debugs(20, 4, "StoreEntry::setMemStatus: special entry " << mem_obj->url);
1632
debugs(20, 4, "not removing special " << *this << " from policy");
1666
1634
mem_policy->Remove(mem_policy, this, &mem_obj->repl);
1667
debugs(20, 4, "StoreEntry::setMemStatus: removed mem node " << mem_obj->url);
1635
debugs(20, 4, "removed " << *this);
1670
1638
--hot_obj_count;
1681
1649
else if (mem_obj == NULL)
1682
1650
return "[null_mem_obj]";
1684
return mem_obj->url;
1652
return mem_obj->storeId();
1656
StoreEntry::makeMemObject()
1659
mem_obj = new MemObject();
1688
StoreEntry::createMemObject(const char *aUrl, const char *aLogUrl)
1664
StoreEntry::createMemObject(const char *aUrl, const char *aLogUrl, const HttpRequestMethod &aMethod)
1690
debugs(20, 3, "A mem_obj create attempted using : " << aUrl);
1695
if (hidden_mem_obj) {
1696
debugs(20, 3, HERE << "restoring " << hidden_mem_obj);
1697
mem_obj = hidden_mem_obj;
1698
hidden_mem_obj = NULL;
1699
mem_obj->resetUrls(aUrl, aLogUrl);
1703
mem_obj = new MemObject(aUrl, aLogUrl);
1667
mem_obj->setUris(aUrl, aLogUrl, aMethod);
1706
1670
/* this just sets DELAY_SENDING */
1905
1870
if (EBIT_TEST(flags, ENTRY_SPECIAL))
1906
1871
return; // cannot trim because we do not load them again
1908
if (!preserveSwappable) {
1909
if (mem_obj->policyLowestOffsetToKeep(0) == 0) {
1914
* Its not swap-able, and we're about to delete a chunk,
1915
* so we must make it PRIVATE. This is tricky/ugly because
1916
* for the most part, we treat swapable == cachable here.
1919
mem_obj->trimUnSwappable ();
1921
mem_obj->trimSwappable ();
1873
if (preserveSwappable)
1874
mem_obj->trimSwappable();
1876
mem_obj->trimUnSwappable();
1878
debugs(88, 7, *this << " inmem_lo=" << mem_obj->inmem_lo);
2053
2009
std::ostream &operator <<(std::ostream &os, const StoreEntry &e)
2055
return os << e.swap_filen << '@' << e.swap_dirn << '=' <<
2056
e.mem_status << '/' << e.ping_status << '/' << e.store_status << '/' <<
2057
e.swap_status << '*' << e.lock_count;
2014
if (e.mem_obj->xitTable.index > -1)
2015
os << 't' << e.mem_obj->xitTable.index;
2016
if (e.mem_obj->memCache.index > -1)
2017
os << 'm' << e.mem_obj->memCache.index;
2019
if (e.swap_filen > -1 || e.swap_dirn > -1)
2020
os << 'd' << e.swap_filen << '@' << e.swap_dirn;
2024
// print only non-default status values, using unique letters
2025
if (e.mem_status != NOT_IN_MEMORY ||
2026
e.store_status != STORE_PENDING ||
2027
e.swap_status != SWAPOUT_NONE ||
2028
e.ping_status != PING_NONE) {
2029
if (e.mem_status != NOT_IN_MEMORY) os << 'm';
2030
if (e.store_status != STORE_PENDING) os << 's';
2031
if (e.swap_status != SWAPOUT_NONE) os << 'w' << e.swap_status;
2032
if (e.ping_status != PING_NONE) os << 'p' << e.ping_status;
2035
// print only set flags, using unique letters
2037
if (EBIT_TEST(e.flags, ENTRY_SPECIAL)) os << 'S';
2038
if (EBIT_TEST(e.flags, ENTRY_REVALIDATE)) os << 'R';
2039
if (EBIT_TEST(e.flags, DELAY_SENDING)) os << 'P';
2040
if (EBIT_TEST(e.flags, RELEASE_REQUEST)) os << 'X';
2041
if (EBIT_TEST(e.flags, REFRESH_REQUEST)) os << 'F';
2042
if (EBIT_TEST(e.flags, ENTRY_DISPATCHED)) os << 'D';
2043
if (EBIT_TEST(e.flags, KEY_PRIVATE)) os << 'I';
2044
if (EBIT_TEST(e.flags, ENTRY_FWD_HDR_WAIT)) os << 'W';
2045
if (EBIT_TEST(e.flags, ENTRY_NEGCACHED)) os << 'N';
2046
if (EBIT_TEST(e.flags, ENTRY_VALIDATED)) os << 'V';
2047
if (EBIT_TEST(e.flags, ENTRY_BAD_LENGTH)) os << 'L';
2048
if (EBIT_TEST(e.flags, ENTRY_ABORTED)) os << 'A';
2051
if (e.mem_obj && e.mem_obj->smpCollapsed)
2054
return os << '/' << &e << '*' << e.locks();
2060
2057
/* NullStoreEntry */