~measurement-factory/squid/bag5

« back to all changes in this revision

Viewing changes to src/store.cc

  • Committer: Alex Rousskov
  • Date: 2013-08-16 15:40:14 UTC
  • mfrom: (12501.2.58 collapsed-fwd)
  • Revision ID: rousskov@measurement-factory.com-20130816154014-od2kncs1egeerazs
Merged from collapsed-fwd (r12587) to get initial Collapsed Forwarding
support and Large Rock/Store fixes.

Show diffs side-by-side

added added

removed removed

Lines of Context:
74
74
#include <limits.h>
75
75
#endif
76
76
 
77
 
static STMCB storeWriteComplete;
78
 
 
79
77
#define REBUILD_TIMESTAMP_DELTA_MAX 2
80
78
 
81
79
#define STORE_IN_MEM_BUCKETS            (229)
193
191
{
194
192
    /* This object can be cached for a long time */
195
193
 
196
 
    if (EBIT_TEST(flags, ENTRY_CACHABLE))
 
194
    if (!EBIT_TEST(flags, RELEASE_REQUEST))
197
195
        setPublicKey();
198
196
}
199
197
 
203
201
    /* This object should never be cached at all */
204
202
    expireNow();
205
203
    releaseRequest(); /* delete object when not used */
206
 
    /* releaseRequest clears ENTRY_CACHABLE flag */
207
204
}
208
205
 
209
206
void
211
208
{
212
209
    /* This object may be negatively cached */
213
210
    negativeCache();
214
 
 
215
 
    if (EBIT_TEST(flags, ENTRY_CACHABLE))
216
 
        setPublicKey();
 
211
    makePublic();
217
212
}
218
213
 
219
214
size_t
314
309
        mem_obj->setNoDelay(newValue);
315
310
}
316
311
 
 
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.
317
317
store_client_t
318
318
StoreEntry::storeClientType() const
319
319
{
323
323
     * offset 0 in the memory object is the HTTP headers.
324
324
     */
325
325
 
326
 
    if (mem_status == IN_MEMORY && Config.memShared && IamWorkerProcess()) {
327
 
        // clients of an object cached in shared memory are memory clients
328
 
        return STORE_MEM_CLIENT;
329
 
    }
330
 
 
331
326
    assert(mem_obj);
332
327
 
333
328
    if (mem_obj->inmem_lo)
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;
351
346
                }
352
347
            } else {
382
377
 
383
378
StoreEntry::StoreEntry() :
384
379
        mem_obj(NULL),
385
 
        hidden_mem_obj(NULL),
386
 
        timestamp(-1),
387
 
        lastref(-1),
388
 
        expires(-1),
389
 
        lastmod(-1),
390
 
        swap_file_sz(0),
391
 
        refcount(0),
392
 
        flags(0),
393
 
        swap_filen(-1),
394
 
        swap_dirn(-1),
395
 
        lock_count(0),
396
 
        mem_status(NOT_IN_MEMORY),
397
 
        ping_status(PING_NONE),
398
 
        store_status(STORE_PENDING),
399
 
        swap_status(SWAPOUT_NONE)
400
 
{
401
 
    debugs(20, 3, HERE << "new StoreEntry " << this);
402
 
}
403
 
 
404
 
StoreEntry::StoreEntry(const char *aUrl, const char *aLogUrl) :
405
 
        mem_obj(NULL),
406
 
        hidden_mem_obj(NULL),
407
 
        timestamp(-1),
408
 
        lastref(-1),
409
 
        expires(-1),
410
 
        lastmod(-1),
411
 
        swap_file_sz(0),
412
 
        refcount(0),
413
 
        flags(0),
414
 
        swap_filen(-1),
415
 
        swap_dirn(-1),
416
 
        lock_count(0),
417
 
        mem_status(NOT_IN_MEMORY),
418
 
        ping_status(PING_NONE),
419
 
        store_status(STORE_PENDING),
420
 
        swap_status(SWAPOUT_NONE)
421
 
{
422
 
    debugs(20, 3, HERE << "new StoreEntry " << this);
423
 
    mem_obj = new MemObject(aUrl, aLogUrl);
 
380
        timestamp(-1),
 
381
        lastref(-1),
 
382
        expires(-1),
 
383
        lastmod(-1),
 
384
        swap_file_sz(0),
 
385
        refcount(0),
 
386
        flags(0),
 
387
        swap_filen(-1),
 
388
        swap_dirn(-1),
 
389
        mem_status(NOT_IN_MEMORY),
 
390
        ping_status(PING_NONE),
 
391
        store_status(STORE_PENDING),
 
392
        swap_status(SWAPOUT_NONE),
 
393
        lock_count(0)
 
394
{
 
395
    debugs(20, 3, HERE << "new StoreEntry " << this);
424
396
}
425
397
 
426
398
StoreEntry::~StoreEntry()
427
399
{
428
 
    if (swap_filen >= 0) {
429
 
        SwapDir &sd = dynamic_cast<SwapDir&>(*store());
430
 
        sd.disconnect(*this);
431
 
    }
432
 
    delete hidden_mem_obj;
433
400
}
434
401
 
435
402
#if USE_ADAPTATION
457
424
StoreEntry::destroyMemObject()
458
425
{
459
426
    debugs(20, 3, HERE << "destroyMemObject " << mem_obj);
460
 
    setMemStatus(NOT_IN_MEMORY);
461
 
    MemObject *mem = mem_obj;
462
 
    mem_obj = NULL;
463
 
    delete mem;
464
 
    delete hidden_mem_obj;
465
 
    hidden_mem_obj = NULL;
466
 
}
467
 
 
468
 
void
469
 
StoreEntry::hideMemObject()
470
 
{
471
 
    debugs(20, 3, HERE << "hiding " << mem_obj);
472
 
    assert(mem_obj);
473
 
    assert(!hidden_mem_obj);
474
 
    hidden_mem_obj = mem_obj;
475
 
    mem_obj = NULL;
 
427
 
 
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);
 
434
 
 
435
        setMemStatus(NOT_IN_MEMORY);
 
436
        mem_obj = NULL;
 
437
        delete mem;
 
438
    }
476
439
}
477
440
 
478
441
void
485
448
    if (e == NullStoreEntry::getInstance())
486
449
        return;
487
450
 
 
451
    // Store::Root() is FATALly missing during shutdown
 
452
    if (e->swap_filen >= 0 && !shutting_down) {
 
453
        SwapDir &sd = dynamic_cast<SwapDir&>(*e->store());
 
454
        sd.disconnect(*e);
 
455
    }
 
456
 
488
457
    e->destroyMemObject();
489
458
 
490
459
    e->hashDelete();
499
468
void
500
469
StoreEntry::hashInsert(const cache_key * someKey)
501
470
{
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);
505
474
}
523
492
 
524
493
    debugs(20, 3, "StoreEntry::purgeMem: Freeing memory-copy of " << getMD5Text());
525
494
 
526
 
    destroyMemObject();
 
495
    Store::Root().memoryUnlink(*this);
527
496
 
528
497
    if (swap_status != SWAPOUT_DONE)
529
498
        release();
551
520
    debugs(20, 3, "StoreEntry::setReleaseFlag: '" << getMD5Text() << "'");
552
521
 
553
522
    EBIT_SET(flags, RELEASE_REQUEST);
 
523
 
 
524
    Store::Root().markForUnlink(*this);
554
525
}
555
526
 
556
527
void
559
530
    if (EBIT_TEST(flags, RELEASE_REQUEST))
560
531
        return;
561
532
 
562
 
    setReleaseFlag();
563
 
 
564
 
    /*
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.
568
 
     */
569
 
    EBIT_CLR(flags, ENTRY_CACHABLE);
 
533
    setReleaseFlag(); // makes validToSend() false, preventing future hits
570
534
 
571
535
    setPrivateKey();
572
536
}
687
651
        return;                 /* is already private */
688
652
 
689
653
    if (key) {
 
654
        setReleaseFlag(); // will markForUnlink(); all caches/workers will know
 
655
 
 
656
        // TODO: move into SwapDir::markForUnlink() already called by Root()
690
657
        if (swap_filen > -1)
691
658
            storeDirSwapLog(this, SWAP_LOG_DEL);
692
659
 
693
660
        hashDelete();
694
661
    }
695
662
 
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);
699
666
    } else {
700
667
        newkey = storeKeyPrivate("JUNK", Http::METHOD_NONE, getKeyCounter());
701
668
    }
708
675
void
709
676
StoreEntry::setPublicKey()
710
677
{
711
 
    StoreEntry *e2 = NULL;
712
678
    const cache_key *newkey;
713
679
 
714
680
    if (key && !EBIT_TEST(flags, KEY_PRIVATE))
723
689
     * store clients won't be able to access object data which has
724
690
     * been freed from memory.
725
691
     *
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.
728
693
     */
729
694
#if MORE_DEBUG_OUTPUT
730
695
 
747
712
                 * to record the new variance key
748
713
                 */
749
714
                safe_free(request->vary_headers);       /* free old "bad" variance key */
750
 
                StoreEntry *pe = storeGetPublic(mem_obj->url, mem_obj->method);
751
 
 
752
 
                if (pe)
 
715
                if (StoreEntry *pe = storeGetPublic(mem_obj->storeId(), mem_obj->method))
753
716
                    pe->release();
754
717
            }
755
718
 
764
727
 
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 */
769
732
            String vary;
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);
797
760
 
798
761
            pe->complete();
799
762
 
800
 
            pe->unlock();
 
763
            pe->unlock("StoreEntry::setPublicKey+Vary");
801
764
        }
802
765
 
803
766
        newkey = storeKeyPublicByRequest(mem_obj->request);
804
767
    } else
805
 
        newkey = storeKeyPublic(mem_obj->url, mem_obj->method);
 
768
        newkey = storeKeyPublic(mem_obj->storeId(), mem_obj->method);
806
769
 
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();
810
773
        e2->release();
811
774
 
812
775
        if (mem_obj->request)
813
776
            newkey = storeKeyPublicByRequest(mem_obj->request);
814
777
        else
815
 
            newkey = storeKeyPublic(mem_obj->url, mem_obj->method);
 
778
            newkey = storeKeyPublic(mem_obj->storeId(), mem_obj->method);
816
779
    }
817
780
 
818
781
    if (key)
827
790
}
828
791
 
829
792
StoreEntry *
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)
831
794
{
832
795
    StoreEntry *e = NULL;
833
 
    MemObject *mem = NULL;
834
796
    debugs(20, 3, "storeCreateEntry: '" << url << "'");
835
797
 
836
 
    e = new StoreEntry(url, log_url);
837
 
    e->lock_count = 1;          /* Note lock here w/o calling storeLock() */
838
 
    mem = e->mem_obj;
839
 
    mem->method = method;
840
 
 
841
 
    if (neighbors_do_private_keys || !flags.hierarchical)
842
 
        e->setPrivateKey();
843
 
    else
844
 
        e->setPublicKey();
 
798
    e = new StoreEntry();
 
799
    e->makeMemObject();
 
800
    e->mem_obj->setUris(url, log_url, method);
845
801
 
846
802
    if (flags.cachable) {
847
 
        EBIT_SET(e->flags, ENTRY_CACHABLE);
848
803
        EBIT_CLR(e->flags, RELEASE_REQUEST);
849
804
    } else {
850
 
        /* StoreEntry::releaseRequest() clears ENTRY_CACHABLE */
851
805
        e->releaseRequest();
852
806
    }
853
807
 
854
808
    e->store_status = STORE_PENDING;
855
 
    e->setMemStatus(NOT_IN_MEMORY);
856
809
    e->refcount = 0;
857
810
    e->lastref = squid_curtime;
858
811
    e->timestamp = -1;          /* set in StoreEntry::timestampsSet() */
861
814
    return e;
862
815
}
863
816
 
 
817
StoreEntry *
 
818
storeCreateEntry(const char *url, const char *logUrl, const RequestFlags &flags, const HttpRequestMethod& method)
 
819
{
 
820
    StoreEntry *e = storeCreatePureEntry(url, logUrl, flags, method);
 
821
    e->lock("storeCreateEntry");
 
822
 
 
823
    if (neighbors_do_private_keys || !flags.hierarchical)
 
824
        e->setPrivateKey();
 
825
    else
 
826
        e->setPublicKey();
 
827
 
 
828
    return e;
 
829
}
 
830
 
864
831
/* Mark object as expired */
865
832
void
866
833
StoreEntry::expireNow()
870
837
}
871
838
 
872
839
void
873
 
storeWriteComplete (void *data, StoreIOBuffer wroteBuffer)
874
 
{
875
 
    PROF_start(storeWriteComplete);
876
 
    StoreEntry *e = (StoreEntry *)data;
877
 
 
878
 
    if (EBIT_TEST(e->flags, DELAY_SENDING)) {
879
 
        PROF_stop(storeWriteComplete);
880
 
        return;
881
 
    }
882
 
 
883
 
    e->invokeHandlers();
884
 
    PROF_stop(storeWriteComplete);
885
 
}
886
 
 
887
 
void
888
840
StoreEntry::write (StoreIOBuffer writeBuffer)
889
841
{
890
842
    assert(mem_obj != NULL);
892
844
    PROF_start(StoreEntry_write);
893
845
    assert(store_status == STORE_PENDING);
894
846
 
 
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;
 
850
 
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);
 
855
 
 
856
    if (!EBIT_TEST(flags, DELAY_SENDING))
 
857
        invokeHandlers();
899
858
}
900
859
 
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;
1036
995
        }
1037
996
 
1038
997
    releaseRequest();
1039
 
    /* StoreEntry::releaseRequest() cleared ENTRY_CACHABLE */
1040
998
    return 0;
1041
999
}
1042
1000
 
1127
1085
    assert(mem_obj != NULL);
1128
1086
    debugs(20, 6, "storeAbort: " << getMD5Text());
1129
1087
 
1130
 
    lock();         /* lock while aborting */
 
1088
    lock("StoreEntry::abort");         /* lock while aborting */
1131
1089
    negativeCache();
1132
1090
 
1133
1091
    releaseRequest();
1164
1122
    // abort swap out, invalidating what was created so far (release follows)
1165
1123
    swapOutFileClose(StoreIOState::writerGone);
1166
1124
 
1167
 
    unlock();       /* unlock */
 
1125
    unlock("StoreEntry::abort");       /* unlock */
1168
1126
}
1169
1127
 
1170
1128
/**
1267
1225
StoreEntry::release()
1268
1226
{
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 */
1273
1231
 
1279
1237
        return;
1280
1238
    }
1281
1239
 
 
1240
    Store::Root().memoryUnlink(*this);
 
1241
 
1282
1242
    if (StoreController::store_dirs_rebuilding && swap_filen > -1) {
1283
1243
        setPrivateKey();
1284
1244
 
1285
 
        if (mem_obj)
1286
 
            destroyMemObject();
1287
 
 
1288
1245
        if (swap_filen > -1) {
1289
1246
            /*
1290
1247
             * Fake a call to StoreEntry->lock()  When rebuilding is done,
1291
1248
             * we'll just call StoreEntry->unlock() on these.
1292
1249
             */
1293
 
            ++lock_count;
 
1250
            lock("StoreEntry::release+rebuilding");
1294
1251
            setReleaseFlag();
1295
1252
            LateReleaseStack.push_back(this);
1296
1253
        } else {
1312
1269
        unlink();
1313
1270
    }
1314
1271
 
1315
 
    setMemStatus(NOT_IN_MEMORY);
1316
1272
    destroyStoreEntry(static_cast<hash_link *>(this));
1317
1273
    PROF_stop(storeRelease);
1318
1274
}
1338
1294
            return;
1339
1295
        }
1340
1296
 
1341
 
        e->unlock();
 
1297
        e->unlock("storeLateRelease");
1342
1298
        ++n;
1343
1299
    }
1344
1300
 
1352
1308
    if (lock_count)
1353
1309
        return 1;
1354
1310
 
1355
 
    if (swap_status == SWAPOUT_WRITING)
1356
 
        return 1;
1357
 
 
1358
 
    if (store_status == STORE_PENDING)
1359
 
        return 1;
1360
 
 
1361
1311
    /*
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.
1363
1314
     */
1364
1315
    if (EBIT_TEST(flags, ENTRY_SPECIAL))
1365
1316
        if (!EBIT_TEST(flags, KEY_PRIVATE))
1534
1485
    if (EBIT_TEST(flags, ENTRY_ABORTED))
1535
1486
        return 0;
1536
1487
 
 
1488
    // now check that the entry has a cache backing or is collapsed
 
1489
    if (swap_filen > -1) // backed by a disk cache
 
1490
        return 1;
 
1491
 
 
1492
    if (swappingOut()) // will be backed by a disk cache
 
1493
        return 1;
 
1494
 
 
1495
    if (!mem_obj) // not backed by a memory cache and not collapsed
 
1496
        return 0;
 
1497
 
 
1498
    if (mem_obj->memCache.index >= 0) // backed by a shared memory cache
 
1499
        return 0;
 
1500
 
 
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
 
1505
        return 0;
 
1506
 
1537
1507
    return 1;
1538
1508
}
1539
1509
 
1637
1607
 
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);
1653
1621
 
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");
1656
1624
        } else {
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());
1659
1627
        }
1660
1628
 
1661
1629
        ++hot_obj_count; // TODO: maintain for the shared hot cache as well
1662
1630
    } else {
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");
1665
1633
        } else {
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);
1668
1636
        }
1669
1637
 
1670
1638
        --hot_obj_count;
1681
1649
    else if (mem_obj == NULL)
1682
1650
        return "[null_mem_obj]";
1683
1651
    else
1684
 
        return mem_obj->url;
 
1652
        return mem_obj->storeId();
 
1653
}
 
1654
 
 
1655
MemObject *
 
1656
StoreEntry::makeMemObject()
 
1657
{
 
1658
    if (!mem_obj)
 
1659
        mem_obj = new MemObject();
 
1660
    return mem_obj;
1685
1661
}
1686
1662
 
1687
1663
void
1688
 
StoreEntry::createMemObject(const char *aUrl, const char *aLogUrl)
 
1664
StoreEntry::createMemObject(const char *aUrl, const char *aLogUrl, const HttpRequestMethod &aMethod)
1689
1665
{
1690
 
    debugs(20, 3, "A mem_obj create attempted using : " << aUrl);
1691
 
 
1692
 
    if (mem_obj)
1693
 
        return;
1694
 
 
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);
1700
 
        return;
1701
 
    }
1702
 
 
1703
 
    mem_obj = new MemObject(aUrl, aLogUrl);
 
1666
    makeMemObject();
 
1667
    mem_obj->setUris(aUrl, aLogUrl, aMethod);
1704
1668
}
1705
1669
 
1706
1670
/* this just sets DELAY_SENDING */
1873
1837
 
1874
1838
    rep->packHeadersInto(&p);
1875
1839
    mem_obj->markEndOfReplyHeaders();
 
1840
    EBIT_CLR(flags, ENTRY_FWD_HDR_WAIT);
1876
1841
 
1877
1842
    rep->body.packInto(&p);
1878
1843
 
1905
1870
    if (EBIT_TEST(flags, ENTRY_SPECIAL))
1906
1871
        return; // cannot trim because we do not load them again
1907
1872
 
1908
 
    if (!preserveSwappable) {
1909
 
        if (mem_obj->policyLowestOffsetToKeep(0) == 0) {
1910
 
            /* Nothing to do */
1911
 
            return;
1912
 
        }
1913
 
        /*
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.
1917
 
         */
1918
 
        releaseRequest();
1919
 
        mem_obj->trimUnSwappable ();
1920
 
    } else {
1921
 
        mem_obj->trimSwappable ();
1922
 
    }
 
1873
    if (preserveSwappable)
 
1874
        mem_obj->trimSwappable();
 
1875
    else
 
1876
        mem_obj->trimUnSwappable();
 
1877
 
 
1878
    debugs(88, 7, *this << " inmem_lo=" << mem_obj->inmem_lo);
1923
1879
}
1924
1880
 
1925
1881
bool
2052
2008
 
2053
2009
std::ostream &operator <<(std::ostream &os, const StoreEntry &e)
2054
2010
{
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;
 
2011
    os << "e:";
 
2012
 
 
2013
    if (e.mem_obj) {
 
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;
 
2018
    }
 
2019
    if (e.swap_filen > -1 || e.swap_dirn > -1)
 
2020
        os << 'd' << e.swap_filen << '@' << e.swap_dirn;
 
2021
 
 
2022
    os << '=';
 
2023
 
 
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;
 
2033
    }
 
2034
 
 
2035
    // print only set flags, using unique letters
 
2036
    if (e.flags) {
 
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';
 
2049
    }
 
2050
 
 
2051
    if (e.mem_obj && e.mem_obj->smpCollapsed)
 
2052
        os << 'O';
 
2053
 
 
2054
    return os << '/' << &e << '*' << e.locks();
2058
2055
}
2059
2056
 
2060
2057
/* NullStoreEntry */