~ubuntu-branches/ubuntu/oneiric/squid3/oneiric-security

« back to all changes in this revision

Viewing changes to src/store.cc

  • Committer: Bazaar Package Importer
  • Author(s): Luigi Gangitano
  • Date: 2007-05-13 16:03:16 UTC
  • mfrom: (1.1.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20070513160316-2h6kn6h1z0q1fvyo
Tags: 3.0.PRE6-1
* New upstream release
  - Removed patches integrated upsteam:
    + 04-m68k-ftbfs

* debian/rules
  - Enable delay pools (Closes: #410785)
  - Enable cache digests (Closes: #416631)
  - Enable ICAP client
  - Raised Max Filedescriptor limit to 65536

* debian/control
  - Added real package dependency for httpd in squid3-cgi

* debian/patches/02-makefile-defaults
  - Fix default configuration file for cachemgr.cgi (Closes: #416630)

* debian/squid3.postinst
  - Fixed bashish in postinst (Closes: #411797)

* debian/patches/05-helpers-typo
  - Added upstream patch fixing compilation error in src/helpers.cc

* debian/patches/06-mem-obj-reference
  - Added upstream patch fixing a mem_obj reference in src/store.cc

* debian/patches/07-close-icap-connections
  - Added upstream patch fixing icap connection starvation

* debian/squid3.rc
  - Added LSB-compliant description to rc script

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
 
2
2
/*
3
 
 * $Id: store.cc,v 1.602 2006/09/20 14:25:05 adrian Exp $
 
3
 * $Id: store.cc,v 1.612 2007/05/07 21:51:21 wessels Exp $
4
4
 *
5
5
 * DEBUG: section 20    Storage Manager
6
6
 * AUTHOR: Harvest Derived
105
105
 * local function prototypes
106
106
 */
107
107
static void storeGetMemSpace(int);
108
 
static void storeHashDelete(StoreEntry *);
109
 
static void destroy_MemObject(StoreEntry *);
110
 
static void storePurgeMem(StoreEntry *);
111
108
static int getKeyCounter(void);
112
 
static int storeKeepInMemory(const StoreEntry *);
113
109
static OBJH storeCheckCachableStats;
114
110
static EVH storeLateRelease;
115
111
 
183
179
    /* This object can be cached for a long time */
184
180
 
185
181
    if (EBIT_TEST(flags, ENTRY_CACHABLE))
186
 
        storeSetPublicKey(this);
 
182
        setPublicKey();
187
183
}
188
184
 
189
185
void
190
186
StoreEntry::makePrivate()
191
187
{
192
188
    /* This object should never be cached at all */
193
 
    storeExpireNow(this);
194
 
    storeReleaseRequest(this); /* delete object when not used */
195
 
    /* storeReleaseRequest clears ENTRY_CACHABLE flag */
 
189
    expireNow();
 
190
    releaseRequest(); /* delete object when not used */
 
191
    /* releaseRequest clears ENTRY_CACHABLE flag */
196
192
}
197
193
 
198
194
void
199
195
StoreEntry::cacheNegatively()
200
196
{
201
197
    /* This object may be negatively cached */
202
 
    storeNegativeCache(this);
 
198
    negativeCache();
203
199
 
204
200
    if (EBIT_TEST(flags, ENTRY_CACHABLE))
205
 
        storeSetPublicKey(this);
 
201
        setPublicKey();
206
202
}
207
203
 
208
204
size_t
317
313
 
318
314
    if (EBIT_TEST(flags, ENTRY_ABORTED)) {
319
315
        /* I don't think we should be adding clients to aborted entries */
320
 
        debug(20, 1) ("storeClientType: adding to ENTRY_ABORTED entry\n");
 
316
        debugs(20, 1, "storeClientType: adding to ENTRY_ABORTED entry");
321
317
        return STORE_MEM_CLIENT;
322
318
    }
323
319
 
376
372
    swap_dirn = -1;
377
373
}
378
374
 
379
 
static void
380
 
destroy_MemObject(StoreEntry * e)
 
375
void
 
376
StoreEntry::destroyMemObject()
381
377
{
382
 
    debugs(20, 3, HERE << "destroy mem_obj" << e->mem_obj);
383
 
    storeSetMemStatus(e, NOT_IN_MEMORY);
384
 
    MemObject *mem = e->mem_obj;
385
 
    e->mem_obj = NULL;
 
378
    debugs(20, 3, HERE << "destroyMemObject " << mem_obj);
 
379
    setMemStatus(NOT_IN_MEMORY);
 
380
    MemObject *mem = mem_obj;
 
381
    mem_obj = NULL;
386
382
    delete mem;
387
383
}
388
384
 
396
392
    if (e == NullStoreEntry::getInstance())
397
393
        return;
398
394
 
399
 
    destroy_MemObject(e);
 
395
    e->destroyMemObject();
400
396
 
401
 
    storeHashDelete(e);
 
397
    e->hashDelete();
402
398
 
403
399
    assert(e->key == NULL);
404
400
 
408
404
/* ----- INTERFACE BETWEEN STORAGE MANAGER AND HASH TABLE FUNCTIONS --------- */
409
405
 
410
406
void
411
 
storeHashInsert(StoreEntry * e, const cache_key * key)
 
407
StoreEntry::hashInsert(const cache_key * someKey)
412
408
{
413
 
    debug(20, 3) ("storeHashInsert: Inserting Entry %p key '%s'\n",
414
 
                  e, storeKeyText(key));
415
 
    e->key = storeKeyDup(key);
416
 
    hash_join(store_table, e);
 
409
    debugs(20, 3, "StoreEntry::hashInsert: Inserting Entry " << this << " key '" << storeKeyText(someKey) << "'");
 
410
    key = storeKeyDup(someKey);
 
411
    hash_join(store_table, this);
417
412
}
418
413
 
419
 
static void
420
 
storeHashDelete(StoreEntry * e)
 
414
void
 
415
StoreEntry::hashDelete()
421
416
{
422
 
    hash_remove_link(store_table, e);
423
 
    storeKeyFree((const cache_key *)e->key);
424
 
    e->key = NULL;
 
417
    hash_remove_link(store_table, this);
 
418
    storeKeyFree((const cache_key *)key);
 
419
    key = NULL;
425
420
}
426
421
 
427
422
/* -------------------------------------------------------------------------- */
428
423
 
429
424
 
430
425
/* get rid of memory copy of the object */
431
 
static void
432
 
storePurgeMem(StoreEntry * e)
 
426
void
 
427
StoreEntry::purgeMem()
433
428
{
434
 
    if (e->mem_obj == NULL)
 
429
    if (mem_obj == NULL)
435
430
        return;
436
431
 
437
 
    debug(20, 3) ("storePurgeMem: Freeing memory-copy of %s\n",
438
 
                  e->getMD5Text());
439
 
 
440
 
    destroy_MemObject(e);
441
 
 
442
 
    if (e->swap_status != SWAPOUT_DONE)
443
 
        e->release();
 
432
    debugs(20, 3, "StoreEntry::purgeMem: Freeing memory-copy of " << getMD5Text());
 
433
 
 
434
    destroyMemObject();
 
435
 
 
436
    if (swap_status != SWAPOUT_DONE)
 
437
        release();
444
438
}
445
439
 
446
440
/* RBC 20050104 this is wrong- memory ref counting
456
450
{
457
451
    lock_count++;
458
452
    debugs(20, 3, "StoreEntry::lock: key '" << getMD5Text() <<"' count=" <<
459
 
           lock_count << "\n");
 
453
           lock_count  );
460
454
    lastref = squid_curtime;
461
455
    Store::Root().reference(*this);
462
456
}
467
461
    if (EBIT_TEST(flags, RELEASE_REQUEST))
468
462
        return;
469
463
 
470
 
    debug(20, 3) ("StoreEntry::setReleaseFlag: '%s'\n", getMD5Text());
 
464
    debugs(20, 3, "StoreEntry::setReleaseFlag: '" << getMD5Text() << "'");
471
465
 
472
466
    EBIT_SET(flags, RELEASE_REQUEST);
473
467
}
474
468
 
475
469
void
476
 
storeReleaseRequest(StoreEntry * e)
 
470
StoreEntry::releaseRequest()
477
471
{
478
 
    if (EBIT_TEST(e->flags, RELEASE_REQUEST))
 
472
    if (EBIT_TEST(flags, RELEASE_REQUEST))
479
473
        return;
480
474
 
481
 
    e->setReleaseFlag();
 
475
    setReleaseFlag();
482
476
 
483
477
    /*
484
478
     * Clear cachable flag here because we might get called before
485
479
     * anyone else even looks at the cachability flag.  Also, this
486
480
     * prevents httpMakePublic from really setting a public key.
487
481
     */
488
 
    EBIT_CLR(e->flags, ENTRY_CACHABLE);
 
482
    EBIT_CLR(flags, ENTRY_CACHABLE);
489
483
 
490
 
    storeSetPrivateKey(e);
 
484
    setPrivateKey();
491
485
}
492
486
 
493
487
/* unlock object, return -1 if object get released after unlock
496
490
StoreEntry::unlock()
497
491
{
498
492
    lock_count--;
499
 
    debug(20, 3) ("StoreEntry::unlock: key '%s' count=%d\n",
500
 
                  getMD5Text(), lock_count);
 
493
    debugs(20, 3, "StoreEntry::unlock: key '" << getMD5Text() << "' count=" << lock_count);
501
494
 
502
495
    if (lock_count)
503
496
        return (int) lock_count;
509
502
 
510
503
    if (EBIT_TEST(flags, RELEASE_REQUEST))
511
504
        this->release();
512
 
    else if (storeKeepInMemory(this)) {
 
505
    else if (keepInMemory()) {
513
506
        Store::Root().dereference(*this);
514
 
        storeSetMemStatus(this, IN_MEMORY);
 
507
        setMemStatus(IN_MEMORY);
515
508
        mem_obj->unlinkRequest();
516
509
    } else {
517
510
        Store::Root().dereference(*this);
518
511
 
519
512
        if (EBIT_TEST(flags, KEY_PRIVATE))
520
 
            debug(20, 1) ("WARNING: %s:%d: found KEY_PRIVATE\n", __FILE__, __LINE__);
 
513
            debugs(20, 1, "WARNING: " << __FILE__ << ":" << __LINE__ << ": found KEY_PRIVATE");
521
514
 
522
 
        /* storePurgeMem may free e */
523
 
        storePurgeMem(this);
 
515
        /* StoreEntry::purgeMem may free e */
 
516
        purgeMem();
524
517
    }
525
518
 
526
519
    return 0;
607
600
 * concept'.
608
601
 */
609
602
void
610
 
storeSetPrivateKey(StoreEntry * e)
 
603
StoreEntry::setPrivateKey()
611
604
{
612
605
    const cache_key *newkey;
613
 
    MemObject *mem = e->mem_obj;
614
606
 
615
 
    if (e->key && EBIT_TEST(e->flags, KEY_PRIVATE))
 
607
    if (key && EBIT_TEST(flags, KEY_PRIVATE))
616
608
        return;                 /* is already private */
617
609
 
618
 
    if (e->key) {
619
 
        if (e->swap_filen > -1)
620
 
            storeDirSwapLog(e, SWAP_LOG_DEL);
 
610
    if (key) {
 
611
        if (swap_filen > -1)
 
612
            storeDirSwapLog(this, SWAP_LOG_DEL);
621
613
 
622
 
        storeHashDelete(e);
 
614
        hashDelete();
623
615
    }
624
616
 
625
 
    if (mem != NULL) {
626
 
        mem->id = getKeyCounter();
627
 
        newkey = storeKeyPrivate(mem->url, mem->method, mem->id);
 
617
    if (mem_obj != NULL) {
 
618
        mem_obj->id = getKeyCounter();
 
619
        newkey = storeKeyPrivate(mem_obj->url, mem_obj->method, mem_obj->id);
628
620
    } else {
629
621
        newkey = storeKeyPrivate("JUNK", METHOD_NONE, getKeyCounter());
630
622
    }
631
623
 
632
624
    assert(hash_lookup(store_table, newkey) == NULL);
633
 
    EBIT_SET(e->flags, KEY_PRIVATE);
634
 
    storeHashInsert(e, newkey);
 
625
    EBIT_SET(flags, KEY_PRIVATE);
 
626
    hashInsert(newkey);
635
627
}
636
628
 
637
629
void
638
 
storeSetPublicKey(StoreEntry * e)
 
630
StoreEntry::setPublicKey()
639
631
{
640
632
    StoreEntry *e2 = NULL;
641
633
    const cache_key *newkey;
642
 
    MemObject *mem = e->mem_obj;
643
634
 
644
 
    if (e->key && !EBIT_TEST(e->flags, KEY_PRIVATE))
 
635
    if (key && !EBIT_TEST(flags, KEY_PRIVATE))
645
636
        return;                 /* is already public */
646
637
 
647
 
    assert(mem);
 
638
    assert(mem_obj);
648
639
 
649
640
    /*
650
641
     * We can't make RELEASE_REQUEST objects public.  Depending on
654
645
     * been freed from memory.
655
646
     *
656
647
     * If RELEASE_REQUEST is set, then ENTRY_CACHABLE should not
657
 
     * be set, and storeSetPublicKey() should not be called.
 
648
     * be set, and StoreEntry::setPublicKey() should not be called.
658
649
     */
659
650
#if MORE_DEBUG_OUTPUT
660
651
 
661
 
    if (EBIT_TEST(e->flags, RELEASE_REQUEST))
662
 
        debug(20, 1) ("assertion failed: RELEASE key %s, url %s\n",
663
 
                      e->key, mem->url);
 
652
    if (EBIT_TEST(flags, RELEASE_REQUEST))
 
653
        debugs(20, 1, "assertion failed: RELEASE key " << key << ", url " << mem->url);
664
654
 
665
655
#endif
666
656
 
667
 
    assert(!EBIT_TEST(e->flags, RELEASE_REQUEST));
668
 
 
669
 
    if (mem->request) {
670
 
        HttpRequest *request = mem->request;
671
 
 
672
 
        if (!mem->vary_headers) {
 
657
    assert(!EBIT_TEST(flags, RELEASE_REQUEST));
 
658
 
 
659
    if (mem_obj->request) {
 
660
        HttpRequest *request = mem_obj->request;
 
661
 
 
662
        if (!mem_obj->vary_headers) {
673
663
            /* First handle the case where the object no longer varies */
674
664
            safe_free(request->vary_headers);
675
665
        } else {
676
 
            if (request->vary_headers && strcmp(request->vary_headers, mem->vary_headers) != 0) {
 
666
            if (request->vary_headers && strcmp(request->vary_headers, mem_obj->vary_headers) != 0) {
677
667
                /* Oops.. the variance has changed. Kill the base object
678
668
                 * to record the new variance key
679
669
                 */
680
670
                safe_free(request->vary_headers);       /* free old "bad" variance key */
681
 
                StoreEntry *pe = storeGetPublic(mem->url, mem->method);
 
671
                StoreEntry *pe = storeGetPublic(mem_obj->url, mem_obj->method);
682
672
 
683
673
                if (pe)
684
674
                    pe->release();
686
676
 
687
677
            /* Make sure the request knows the variance status */
688
678
            if (!request->vary_headers) {
689
 
                const char *vary = httpMakeVaryMark(request, mem->getReply());
 
679
                const char *vary = httpMakeVaryMark(request, mem_obj->getReply());
690
680
 
691
681
                if (vary)
692
682
                    request->vary_headers = xstrdup(vary);
693
683
            }
694
684
        }
695
685
 
696
 
        if (mem->vary_headers && !storeGetPublic(mem->url, mem->method)) {
 
686
        if (mem_obj->vary_headers && !storeGetPublic(mem_obj->url, mem_obj->method)) {
697
687
            /* Create "vary" base object */
698
688
            String vary;
699
 
            StoreEntry *pe = storeCreateEntry(mem->url, mem->log_url, request->flags, request->method);
 
689
            StoreEntry *pe = storeCreateEntry(mem_obj->url, mem_obj->log_url, request->flags, request->method);
700
690
            HttpVersion version(1, 0);
701
691
            /* We are allowed to do this typecast */
702
692
            HttpReply *rep = new HttpReply;
703
693
            rep->setHeaders(version, HTTP_OK, "Internal marker object", "x-squid-internal/vary", -1, -1, squid_curtime + 100000);
704
 
            vary = mem->getReply()->header.getList(HDR_VARY);
 
694
            vary = mem_obj->getReply()->header.getList(HDR_VARY);
705
695
 
706
696
            if (vary.size()) {
707
697
                /* Again, we own this structure layout */
710
700
            }
711
701
 
712
702
#if X_ACCELERATOR_VARY
713
 
            vary = mem->getReply()->header.getList(HDR_X_ACCELERATOR_VARY);
 
703
            vary = mem_obj->getReply()->header.getList(HDR_X_ACCELERATOR_VARY);
714
704
 
715
705
            if (vary.buf()) {
716
706
                /* Again, we own this structure layout */
721
711
#endif
722
712
            pe->replaceHttpReply(rep);
723
713
 
724
 
            storeTimestampsSet(pe);
 
714
            pe->timestampsSet();
725
715
 
726
716
            pe->makePublic();
727
717
 
730
720
            pe->unlock();
731
721
        }
732
722
 
733
 
        newkey = storeKeyPublicByRequest(mem->request);
 
723
        newkey = storeKeyPublicByRequest(mem_obj->request);
734
724
    } else
735
 
        newkey = storeKeyPublic(mem->url, mem->method);
 
725
        newkey = storeKeyPublic(mem_obj->url, mem_obj->method);
736
726
 
737
727
    if ((e2 = (StoreEntry *) hash_lookup(store_table, newkey))) {
738
 
        debug(20, 3) ("storeSetPublicKey: Making old '%s' private.\n", mem->url);
739
 
        storeSetPrivateKey(e2);
 
728
        debugs(20, 3, "StoreEntry::setPublicKey: Making old '" << mem_obj->url << "' private.");
 
729
        e2->setPrivateKey();
740
730
        e2->release();
741
731
 
742
 
        if (mem->request)
743
 
            newkey = storeKeyPublicByRequest(mem->request);
 
732
        if (mem_obj->request)
 
733
            newkey = storeKeyPublicByRequest(mem_obj->request);
744
734
        else
745
 
            newkey = storeKeyPublic(mem->url, mem->method);
 
735
            newkey = storeKeyPublic(mem_obj->url, mem_obj->method);
746
736
    }
747
737
 
748
 
    if (e->key)
749
 
        storeHashDelete(e);
750
 
 
751
 
    EBIT_CLR(e->flags, KEY_PRIVATE);
752
 
 
753
 
    storeHashInsert(e, newkey);
754
 
 
755
 
    if (e->swap_filen > -1)
756
 
        storeDirSwapLog(e, SWAP_LOG_ADD);
 
738
    if (key)
 
739
        hashDelete();
 
740
 
 
741
    EBIT_CLR(flags, KEY_PRIVATE);
 
742
 
 
743
    hashInsert(newkey);
 
744
 
 
745
    if (swap_filen > -1)
 
746
        storeDirSwapLog(this, SWAP_LOG_ADD);
757
747
}
758
748
 
759
749
StoreEntry *
761
751
{
762
752
    StoreEntry *e = NULL;
763
753
    MemObject *mem = NULL;
764
 
    debug(20, 3) ("storeCreateEntry: '%s'\n", url);
 
754
    debugs(20, 3, "storeCreateEntry: '" << url << "'");
765
755
 
766
756
    e = new StoreEntry(url, log_url);
767
757
    e->lock_count = 1;          /* Note lock here w/o calling storeLock() */
769
759
    mem->method = method;
770
760
 
771
761
    if (neighbors_do_private_keys || !flags.hierarchical)
772
 
        storeSetPrivateKey(e);
 
762
        e->setPrivateKey();
773
763
    else
774
 
        storeSetPublicKey(e);
 
764
        e->setPublicKey();
775
765
 
776
766
    if (flags.cachable) {
777
767
        EBIT_SET(e->flags, ENTRY_CACHABLE);
778
768
        EBIT_CLR(e->flags, RELEASE_REQUEST);
779
769
    } else {
780
 
        /* storeReleaseRequest() clears ENTRY_CACHABLE */
781
 
        storeReleaseRequest(e);
 
770
        /* StoreEntry::releaseRequest() clears ENTRY_CACHABLE */
 
771
        e->releaseRequest();
782
772
    }
783
773
 
784
774
    e->store_status = STORE_PENDING;
785
 
    storeSetMemStatus(e, NOT_IN_MEMORY);
 
775
    e->setMemStatus(NOT_IN_MEMORY);
786
776
    e->swap_status = SWAPOUT_NONE;
787
777
    e->swap_filen = -1;
788
778
    e->swap_dirn = -1;
789
779
    e->refcount = 0;
790
780
    e->lastref = squid_curtime;
791
 
    e->timestamp = -1;          /* set in storeTimestampsSet() */
 
781
    e->timestamp = -1;          /* set in StoreEntry::timestampsSet() */
792
782
    e->ping_status = PING_NONE;
793
783
    EBIT_SET(e->flags, ENTRY_VALIDATED);
794
784
    return e;
796
786
 
797
787
/* Mark object as expired */
798
788
void
799
 
storeExpireNow(StoreEntry * e)
 
789
StoreEntry::expireNow()
800
790
{
801
 
    debug(20, 3) ("storeExpireNow: '%s'\n", e->getMD5Text());
802
 
    e->expires = squid_curtime;
 
791
    debugs(20, 3, "StoreEntry::expireNow: '" << getMD5Text() << "'");
 
792
    expires = squid_curtime;
803
793
}
804
794
 
805
795
void
813
803
        return;
814
804
    }
815
805
 
816
 
    InvokeHandlers(e);
 
806
    e->invokeHandlers();
817
807
    PROF_stop(storeWriteComplete);
818
808
}
819
809
 
837
827
         * -RBC 20060903
838
828
         */
839
829
        PROF_stop(StoreEntry_write);
840
 
        InvokeHandlers(this);
 
830
        invokeHandlers();
841
831
        return;
842
832
      }
843
833
 
847
837
    mem_obj->write (writeBuffer, storeWriteComplete, this);
848
838
}
849
839
 
850
 
/* Legacy call for appending data to a store entry */
851
 
void
852
 
storeAppend(StoreEntry * e, const char *buf, int len)
853
 
{
854
 
    e->append(buf, len);
855
 
}
856
 
 
857
840
/* Append incoming data from a primary server to an entry. */
858
841
void
859
842
StoreEntry::append(char const *buf, int len)
906
889
    LOCAL_ARRAY(char, buf, 4096);
907
890
    buf[0] = '\0';
908
891
    vsnprintf(buf, 4096, fmt, vargs);
909
 
    storeAppend(e, buf, strlen(buf));
 
892
    e->append(buf, strlen(buf));
910
893
}
911
894
 
912
895
struct _store_check_cachable_hist
949
932
    return 0;
950
933
}
951
934
 
952
 
static int
953
 
storeCheckTooSmall(StoreEntry * e)
 
935
int
 
936
StoreEntry::checkTooSmall()
954
937
{
955
 
    MemObject * const mem = e->mem_obj;
956
 
 
957
 
    if (EBIT_TEST(e->flags, ENTRY_SPECIAL))
 
938
    if (EBIT_TEST(flags, ENTRY_SPECIAL))
958
939
        return 0;
959
940
 
960
 
    if (STORE_OK == e->store_status)
961
 
        if (mem->object_sz < 0 ||
962
 
                static_cast<size_t>(mem->object_sz)
 
941
    if (STORE_OK == store_status)
 
942
        if (mem_obj->object_sz < 0 ||
 
943
                static_cast<size_t>(mem_obj->object_sz)
963
944
                < Config.Store.minObjectSize)
964
945
            return 1;
965
 
    if (e->getReply()
966
 
            ->content_length > -1)
967
 
        if (e->getReply()
968
 
                ->content_length < (int) Config.Store.minObjectSize)
 
946
    if (getReply()->content_length > -1)
 
947
        if (getReply()->content_length < (int) Config.Store.minObjectSize)
969
948
            return 1;
970
949
    return 0;
971
950
}
972
951
 
973
952
int
974
 
storeCheckCachable(StoreEntry * e)
 
953
StoreEntry::checkCachable()
975
954
{
976
955
#if CACHE_ALL_METHODS
977
956
 
978
 
    if (e->mem_obj->method != METHOD_GET) {
979
 
        debug(20, 2) ("storeCheckCachable: NO: non-GET method\n");
 
957
    if (mem_obj->method != METHOD_GET) {
 
958
        debugs(20, 2, "StoreEntry::checkCachable: NO: non-GET method");
980
959
        store_check_cachable_hist.no.non_get++;
981
960
    } else
982
961
#endif
983
 
        if (e->store_status == STORE_OK && EBIT_TEST(e->flags, ENTRY_BAD_LENGTH)) {
984
 
            debug(20, 2) ("storeCheckCachable: NO: wrong content-length\n");
 
962
        if (store_status == STORE_OK && EBIT_TEST(flags, ENTRY_BAD_LENGTH)) {
 
963
            debugs(20, 2, "StoreEntry::checkCachable: NO: wrong content-length");
985
964
            store_check_cachable_hist.no.wrong_content_length++;
986
 
        } else if (!EBIT_TEST(e->flags, ENTRY_CACHABLE)) {
987
 
            debug(20, 2) ("storeCheckCachable: NO: not cachable\n");
 
965
        } else if (!EBIT_TEST(flags, ENTRY_CACHABLE)) {
 
966
            debugs(20, 2, "StoreEntry::checkCachable: NO: not cachable");
988
967
            store_check_cachable_hist.no.not_entry_cachable++;
989
 
        } else if (EBIT_TEST(e->flags, ENTRY_NEGCACHED)) {
990
 
            debug(20, 3) ("storeCheckCachable: NO: negative cached\n");
 
968
        } else if (EBIT_TEST(flags, ENTRY_NEGCACHED)) {
 
969
            debugs(20, 3, "StoreEntry::checkCachable: NO: negative cached");
991
970
            store_check_cachable_hist.no.negative_cached++;
992
971
            return 0;           /* avoid release call below */
993
 
        } else if ((e->getReply()->content_length > 0 &&
994
 
                    static_cast<size_t>(e->getReply()->content_length)
 
972
        } else if ((getReply()->content_length > 0 &&
 
973
                    static_cast<size_t>(getReply()->content_length)
995
974
                    > Config.Store.maxObjectSize) ||
996
 
                   static_cast<size_t>(e->mem_obj->endOffset()) > Config.Store.maxObjectSize) {
997
 
            debug(20, 2) ("storeCheckCachable: NO: too big\n");
998
 
            store_check_cachable_hist.no.too_big++;
999
 
        } else if (e->getReply()->content_length > (int) Config.Store.maxObjectSize) {
1000
 
            debug(20, 2)
1001
 
            ("storeCheckCachable: NO: too big\n");
1002
 
            store_check_cachable_hist.no.too_big++;
1003
 
        } else if (storeCheckTooSmall(e)) {
1004
 
            debug(20, 2)
1005
 
            ("storeCheckCachable: NO: too small\n");
 
975
                   static_cast<size_t>(mem_obj->endOffset()) > Config.Store.maxObjectSize) {
 
976
            debugs(20, 2, "StoreEntry::checkCachable: NO: too big");
 
977
            store_check_cachable_hist.no.too_big++;
 
978
        } else if (getReply()->content_length > (int) Config.Store.maxObjectSize) {
 
979
            debugs(20, 2, "StoreEntry::checkCachable: NO: too big");
 
980
            store_check_cachable_hist.no.too_big++;
 
981
        } else if (checkTooSmall()) {
 
982
            debugs(20, 2, "StoreEntry::checkCachable: NO: too small");
1006
983
            store_check_cachable_hist.no.too_small++;
1007
 
        } else if (EBIT_TEST(e->flags, KEY_PRIVATE)) {
1008
 
            debug(20, 3)
1009
 
            ("storeCheckCachable: NO: private key\n");
 
984
        } else if (EBIT_TEST(flags, KEY_PRIVATE)) {
 
985
            debugs(20, 3, "StoreEntry::checkCachable: NO: private key");
1010
986
            store_check_cachable_hist.no.private_key++;
1011
 
        } else if (e->swap_status != SWAPOUT_NONE) {
 
987
        } else if (swap_status != SWAPOUT_NONE) {
1012
988
            /*
1013
989
             * here we checked the swap_status because the remaining
1014
990
             * cases are only relevant only if we haven't started swapping
1016
992
             */
1017
993
            return 1;
1018
994
        } else if (storeTooManyDiskFilesOpen()) {
1019
 
            debug(20, 2)
1020
 
            ("storeCheckCachable: NO: too many disk files open\n");
 
995
            debugs(20, 2, "StoreEntry::checkCachable: NO: too many disk files open");
1021
996
            store_check_cachable_hist.no.too_many_open_files++;
1022
997
        } else if (fdNFree() < RESERVED_FD) {
1023
 
            debug(20, 2)
1024
 
            ("storeCheckCachable: NO: too many FD's open\n");
 
998
            debugs(20, 2, "StoreEntry::checkCachable: NO: too many FD's open");
1025
999
            store_check_cachable_hist.no.too_many_open_fds++;
1026
1000
        } else {
1027
1001
            store_check_cachable_hist.yes.Default++;
1028
1002
            return 1;
1029
1003
        }
1030
1004
 
1031
 
    storeReleaseRequest(e);
1032
 
    /* storeReleaseRequest() cleared ENTRY_CACHABLE */
 
1005
    releaseRequest();
 
1006
    /* StoreEntry::releaseRequest() cleared ENTRY_CACHABLE */
1033
1007
    return 0;
1034
1008
}
1035
1009
 
1036
 
static void
1037
 
storeCheckCachableStats(StoreEntry * sentry)
 
1010
void
 
1011
storeCheckCachableStats(StoreEntry *sentry)
1038
1012
{
1039
1013
    storeAppendPrintf(sentry, "Category\t Count\n");
1040
1014
 
1067
1041
void
1068
1042
StoreEntry::complete()
1069
1043
{
1070
 
    debug(20, 3) ("storeComplete: '%s'\n", getMD5Text());
 
1044
    debugs(20, 3, "storeComplete: '" << getMD5Text() << "'");
1071
1045
 
1072
1046
    if (store_status != STORE_PENDING) {
1073
1047
        /*
1090
1064
 
1091
1065
    if (!validLength()) {
1092
1066
        EBIT_SET(flags, ENTRY_BAD_LENGTH);
1093
 
        storeReleaseRequest(this);
 
1067
        releaseRequest();
1094
1068
    }
1095
1069
 
1096
1070
#if USE_CACHE_DIGESTS
1099
1073
 
1100
1074
#endif
1101
1075
    /*
1102
 
     * We used to call InvokeHandlers, then storeSwapOut.  However,
 
1076
     * We used to call invokeHandlers, then storeSwapOut.  However,
1103
1077
     * Madhukar Reddy <myreddy@persistence.com> reported that
1104
1078
     * responses without content length would sometimes get released
1105
1079
     * in client_side, thinking that the response is incomplete.
1106
1080
     */
1107
 
    InvokeHandlers(this);
 
1081
    invokeHandlers();
1108
1082
}
1109
1083
 
1110
1084
/*
1113
1087
 * entry for releasing
1114
1088
 */
1115
1089
void
1116
 
storeAbort(StoreEntry * e)
 
1090
StoreEntry::abort()
1117
1091
{
1118
1092
    statCounter.aborted_requests++;
1119
 
    MemObject *mem = e->mem_obj;
1120
 
    assert(e->store_status == STORE_PENDING);
1121
 
    assert(mem != NULL);
1122
 
    debug(20, 6) ("storeAbort: %s\n", e->getMD5Text());
 
1093
    assert(store_status == STORE_PENDING);
 
1094
    assert(mem_obj != NULL);
 
1095
    debugs(20, 6, "storeAbort: " << getMD5Text());
1123
1096
 
1124
 
    e->lock()
 
1097
    lock()
1125
1098
 
1126
1099
    ;         /* lock while aborting */
1127
 
    storeNegativeCache(e);
1128
 
 
1129
 
    storeReleaseRequest(e);
1130
 
 
1131
 
    EBIT_SET(e->flags, ENTRY_ABORTED);
1132
 
 
1133
 
    storeSetMemStatus(e, NOT_IN_MEMORY);
1134
 
 
1135
 
    e->store_status = STORE_OK;
 
1100
    negativeCache();
 
1101
 
 
1102
    releaseRequest();
 
1103
 
 
1104
    EBIT_SET(flags, ENTRY_ABORTED);
 
1105
 
 
1106
    setMemStatus(NOT_IN_MEMORY);
 
1107
 
 
1108
    store_status = STORE_OK;
1136
1109
 
1137
1110
    /*
1138
1111
     * We assign an object length here.  The only other place we assign
1142
1115
     * request, the request is private and negatively cached. Surely
1143
1116
     * the object length is inappropriate to set.
1144
1117
     */
1145
 
    mem->object_sz = mem->endOffset();
 
1118
    mem_obj->object_sz = mem_obj->endOffset();
1146
1119
 
1147
1120
    /* Notify the server side */
1148
1121
 
1149
 
    if (mem->abort.callback) {
1150
 
        eventAdd("mem->abort.callback",
1151
 
                 mem->abort.callback,
1152
 
                 mem->abort.data,
 
1122
    /*
 
1123
     * DPW 2007-05-07
 
1124
     * Should we check abort.data for validity?
 
1125
     */
 
1126
    if (mem_obj->abort.callback) {
 
1127
        if (!cbdataReferenceValid(mem_obj->abort.data))
 
1128
            debugs(20,1,HERE << "queueing event when abort.data is not valid");
 
1129
        eventAdd("mem_obj->abort.callback",
 
1130
                 mem_obj->abort.callback,
 
1131
                 mem_obj->abort.data,
1153
1132
                 0.0,
1154
 
                 0);
1155
 
        mem->abort.callback = NULL;
1156
 
        mem->abort.data = NULL;
 
1133
                 true);
 
1134
        unregisterAbort();
1157
1135
    }
1158
1136
 
1159
1137
    /* XXX Should we reverse these two, so that there is no
1160
1138
     * unneeded disk swapping triggered? 
1161
1139
     */
1162
1140
    /* Notify the client side */
1163
 
    InvokeHandlers(e);
 
1141
    invokeHandlers();
1164
1142
 
1165
1143
    /* Close any swapout file */
1166
 
    storeSwapOutFileClose(e);
 
1144
    swapOutFileClose();
1167
1145
 
1168
 
    e->unlock();       /* unlock */
 
1146
    unlock();       /* unlock */
1169
1147
}
1170
1148
 
1171
1149
/* Clear Memory storage to accommodate the given object len */
1200
1178
    walker = mem_policy->PurgeInit(mem_policy, 100000);
1201
1179
 
1202
1180
    while ((e = walker->Next(walker))) {
1203
 
        storePurgeMem(e);
 
1181
        e->purgeMem();
1204
1182
        released++;
1205
1183
 
1206
1184
        if (mem_node::InUseCount() + pages_needed < store_pages_max)
1208
1186
    }
1209
1187
 
1210
1188
    walker->Done(walker);
1211
 
    debug(20, 3) ("storeGetMemSpace stats:\n");
1212
 
    debug(20, 3) ("  %6d HOT objects\n", hot_obj_count);
1213
 
    debug(20, 3) ("  %6d were released\n", released);
 
1189
    debugs(20, 3, "storeGetMemSpace stats:");
 
1190
    debugs(20, 3, "  " << std::setw(6) << hot_obj_count  << " HOT objects");
 
1191
    debugs(20, 3, "  " << std::setw(6) << released  << " were released");
1214
1192
    PROF_stop(storeGetMemSpace);
1215
1193
}
1216
1194
 
1266
1244
StoreEntry::release()
1267
1245
{
1268
1246
    PROF_start(storeRelease);
1269
 
    debug(20, 3) ("storeRelease: Releasing: '%s'\n", getMD5Text());
 
1247
    debugs(20, 3, "storeRelease: Releasing: '" << getMD5Text() << "'");
1270
1248
    /* If, for any reason we can't discard this object because of an
1271
1249
     * outstanding request, mark it for pending release */
1272
1250
 
1273
 
    if (storeEntryLocked(this)) {
1274
 
        storeExpireNow(this);
1275
 
        debug(20, 3) ("storeRelease: Only setting RELEASE_REQUEST bit\n");
1276
 
        storeReleaseRequest(this);
 
1251
    if (locked()) {
 
1252
        expireNow();
 
1253
        debugs(20, 3, "storeRelease: Only setting RELEASE_REQUEST bit");
 
1254
        releaseRequest();
1277
1255
        PROF_stop(storeRelease);
1278
1256
        return;
1279
1257
    }
1280
1258
 
1281
1259
    if (StoreController::store_dirs_rebuilding && swap_filen > -1) {
1282
 
        storeSetPrivateKey(this);
 
1260
        setPrivateKey();
1283
1261
 
1284
1262
        if (mem_obj)
1285
 
            destroy_MemObject(this);
 
1263
            destroyMemObject();
1286
1264
 
1287
1265
        if (swap_filen > -1) {
1288
1266
            /*
1319
1297
 
1320
1298
    }
1321
1299
 
1322
 
    storeSetMemStatus(this, NOT_IN_MEMORY);
 
1300
    setMemStatus(NOT_IN_MEMORY);
1323
1301
    destroyStoreEntry(static_cast<hash_link *>(this));
1324
1302
    PROF_stop(storeRelease);
1325
1303
}
1341
1319
 
1342
1320
        if (e == NULL) {
1343
1321
            /* done! */
1344
 
            debug(20, 1) ("storeLateRelease: released %d objects\n", n);
 
1322
            debugs(20, 1, "storeLateRelease: released " << n << " objects");
1345
1323
            return;
1346
1324
        }
1347
1325
 
1354
1332
 
1355
1333
/* return 1 if a store entry is locked */
1356
1334
int
1357
 
storeEntryLocked(const StoreEntry * e)
 
1335
StoreEntry::locked() const
1358
1336
{
1359
 
    if (e->lock_count)
1360
 
        return 1;
1361
 
 
1362
 
    if (e->swap_status == SWAPOUT_WRITING)
1363
 
        return 1;
1364
 
 
1365
 
    if (e->store_status == STORE_PENDING)
 
1337
    if (lock_count)
 
1338
        return 1;
 
1339
 
 
1340
    if (swap_status == SWAPOUT_WRITING)
 
1341
        return 1;
 
1342
 
 
1343
    if (store_status == STORE_PENDING)
1366
1344
        return 1;
1367
1345
 
1368
1346
    /*
1369
1347
     * SPECIAL, PUBLIC entries should be "locked"
1370
1348
     */
1371
 
    if (EBIT_TEST(e->flags, ENTRY_SPECIAL))
1372
 
        if (!EBIT_TEST(e->flags, KEY_PRIVATE))
 
1349
    if (EBIT_TEST(flags, ENTRY_SPECIAL))
 
1350
        if (!EBIT_TEST(flags, KEY_PRIVATE))
1373
1351
            return 1;
1374
1352
 
1375
1353
    return 0;
1382
1360
    const HttpReply *reply;
1383
1361
    assert(mem_obj != NULL);
1384
1362
    reply = getReply();
1385
 
    debug(20, 3) ("storeEntryValidLength: Checking '%s'\n", getMD5Text());
 
1363
    debugs(20, 3, "storeEntryValidLength: Checking '" << getMD5Text() << "'");
1386
1364
    debugs(20, 5, "storeEntryValidLength:     object_len = " <<
1387
 
           objectLen(this));
1388
 
    debug(20, 5) ("storeEntryValidLength:         hdr_sz = %d\n",
1389
 
                  reply->hdr_sz);
1390
 
    debug(20, 5) ("storeEntryValidLength: content_length = %d\n",
1391
 
                  reply->content_length);
 
1365
           objectLen());
 
1366
    debugs(20, 5, "storeEntryValidLength:         hdr_sz = " << reply->hdr_sz);
 
1367
    debugs(20, 5, "storeEntryValidLength: content_length = " << reply->content_length);
1392
1368
 
1393
1369
    if (reply->content_length < 0) {
1394
 
        debug(20, 5) ("storeEntryValidLength: Unspecified content length: %s\n",
1395
 
                      getMD5Text());
 
1370
        debugs(20, 5, "storeEntryValidLength: Unspecified content length: " << getMD5Text());
1396
1371
        return 1;
1397
1372
    }
1398
1373
 
1399
1374
    if (reply->hdr_sz == 0) {
1400
 
        debug(20, 5) ("storeEntryValidLength: Zero header size: %s\n",
1401
 
                      getMD5Text());
 
1375
        debugs(20, 5, "storeEntryValidLength: Zero header size: " << getMD5Text());
1402
1376
        return 1;
1403
1377
    }
1404
1378
 
1405
1379
    if (mem_obj->method == METHOD_HEAD) {
1406
 
        debug(20, 5) ("storeEntryValidLength: HEAD request: %s\n",
1407
 
                      getMD5Text());
 
1380
        debugs(20, 5, "storeEntryValidLength: HEAD request: " << getMD5Text());
1408
1381
        return 1;
1409
1382
    }
1410
1383
 
1414
1387
    if (reply->sline.status == HTTP_NO_CONTENT)
1415
1388
        return 1;
1416
1389
 
1417
 
    diff = reply->hdr_sz + reply->content_length - objectLen(this);
 
1390
    diff = reply->hdr_sz + reply->content_length - objectLen();
1418
1391
 
1419
1392
    if (diff == 0)
1420
1393
        return 1;
1421
1394
 
1422
 
    debug(20, 3) ("storeEntryValidLength: %d bytes too %s; '%s'\n",
1423
 
                  diff < 0 ? -diff : diff,
1424
 
                  diff < 0 ? "big" : "small",
1425
 
                  getMD5Text());
 
1395
    debugs(20, 3, "storeEntryValidLength: " << (diff < 0 ? -diff : diff)  << " bytes too " << (diff < 0 ? "big" : "small") <<"; '" << getMD5Text() << "'" );
1426
1396
 
1427
1397
    return 0;
1428
1398
}
1463
1433
    store_pages_max = Config.memMaxSize / SM_PAGE_SIZE;
1464
1434
}
1465
1435
 
1466
 
static int
1467
 
storeKeepInMemory(const StoreEntry * e)
 
1436
int
 
1437
StoreEntry::keepInMemory() const
1468
1438
{
1469
 
    MemObject *mem = e->mem_obj;
1470
 
 
1471
 
    if (mem == NULL)
1472
 
        return 0;
1473
 
 
1474
 
    if (mem->data_hdr.size() == 0)
1475
 
        return 0;
1476
 
 
1477
 
    return mem->inmem_lo == 0;
 
1439
    if (mem_obj == NULL)
 
1440
        return 0;
 
1441
 
 
1442
    if (mem_obj->data_hdr.size() == 0)
 
1443
        return 0;
 
1444
 
 
1445
    return mem_obj->inmem_lo == 0;
1478
1446
}
1479
1447
 
1480
1448
int
1481
 
storeCheckNegativeHit(StoreEntry * e)
 
1449
StoreEntry::checkNegativeHit() const
1482
1450
{
1483
 
    if (!EBIT_TEST(e->flags, ENTRY_NEGCACHED))
1484
 
        return 0;
1485
 
 
1486
 
    if (e->expires <= squid_curtime)
1487
 
        return 0;
1488
 
 
1489
 
    if (e->store_status != STORE_OK)
 
1451
    if (!EBIT_TEST(flags, ENTRY_NEGCACHED))
 
1452
        return 0;
 
1453
 
 
1454
    if (expires <= squid_curtime)
 
1455
        return 0;
 
1456
 
 
1457
    if (store_status != STORE_OK)
1490
1458
        return 0;
1491
1459
 
1492
1460
    return 1;
1493
1461
}
1494
1462
 
1495
1463
void
1496
 
storeNegativeCache(StoreEntry * e)
 
1464
StoreEntry::negativeCache()
1497
1465
{
1498
 
    e->expires = squid_curtime + Config.negativeTtl;
1499
 
    EBIT_SET(e->flags, ENTRY_NEGCACHED);
 
1466
    expires = squid_curtime + Config.negativeTtl;
 
1467
    EBIT_SET(flags, ENTRY_NEGCACHED);
1500
1468
}
1501
1469
 
1502
1470
void
1523
1491
}
1524
1492
 
1525
1493
int
1526
 
storeEntryValidToSend(StoreEntry * e)
 
1494
StoreEntry::validToSend() const
1527
1495
{
1528
 
    if (EBIT_TEST(e->flags, RELEASE_REQUEST))
 
1496
    if (EBIT_TEST(flags, RELEASE_REQUEST))
1529
1497
        return 0;
1530
1498
 
1531
 
    if (EBIT_TEST(e->flags, ENTRY_NEGCACHED))
1532
 
        if (e->expires <= squid_curtime)
 
1499
    if (EBIT_TEST(flags, ENTRY_NEGCACHED))
 
1500
        if (expires <= squid_curtime)
1533
1501
            return 0;
1534
1502
 
1535
 
    if (EBIT_TEST(e->flags, ENTRY_ABORTED))
 
1503
    if (EBIT_TEST(flags, ENTRY_ABORTED))
1536
1504
        return 0;
1537
1505
 
1538
1506
    return 1;
1539
1507
}
1540
1508
 
1541
1509
void
1542
 
storeTimestampsSet(StoreEntry * entry)
 
1510
StoreEntry::timestampsSet()
1543
1511
{
1544
 
    const HttpReply *reply = entry->getReply();
 
1512
    const HttpReply *reply = getReply();
1545
1513
    time_t served_date = reply->date;
1546
1514
    int age = reply->header.getInt(HDR_AGE);
1547
1515
    /*
1567
1535
        if (squid_curtime > age)
1568
1536
            served_date = squid_curtime - age;
1569
1537
 
1570
 
    entry->expires = reply->expires;
1571
 
 
1572
 
    entry->lastmod = reply->last_modified;
1573
 
 
1574
 
    entry->timestamp = served_date;
1575
 
}
1576
 
 
1577
 
void
1578
 
storeRegisterAbort(StoreEntry * e, STABH * cb, void *data)
1579
 
{
1580
 
    MemObject *mem = e->mem_obj;
1581
 
    assert(mem);
1582
 
    assert(mem->abort.callback == NULL);
1583
 
    mem->abort.callback = cb;
1584
 
    mem->abort.data = data;
1585
 
}
1586
 
 
1587
 
void
1588
 
storeUnregisterAbort(StoreEntry * e)
1589
 
{
1590
 
    MemObject *mem = e->mem_obj;
1591
 
    assert(mem);
1592
 
    mem->abort.callback = NULL;
1593
 
}
1594
 
 
1595
 
void
1596
 
storeEntryDump(const StoreEntry * e, int l)
1597
 
{
1598
 
    debug(20, l) ("StoreEntry->key: %s\n", e->getMD5Text());
1599
 
    debug(20, l) ("StoreEntry->next: %p\n", e->next);
1600
 
    debug(20, l) ("StoreEntry->mem_obj: %p\n", e->mem_obj);
1601
 
    debug(20, l) ("StoreEntry->timestamp: %d\n", (int) e->timestamp);
1602
 
    debug(20, l) ("StoreEntry->lastref: %d\n", (int) e->lastref);
1603
 
    debug(20, l) ("StoreEntry->expires: %d\n", (int) e->expires);
1604
 
    debug(20, l) ("StoreEntry->lastmod: %d\n", (int) e->lastmod);
1605
 
    debug(20, l) ("StoreEntry->swap_file_sz: %d\n", (int) e->swap_file_sz);
1606
 
    debug(20, l) ("StoreEntry->refcount: %d\n", e->refcount);
1607
 
    debug(20, l) ("StoreEntry->flags: %s\n", storeEntryFlags(e));
1608
 
    debug(20, l) ("StoreEntry->swap_dirn: %d\n", (int) e->swap_dirn);
1609
 
    debug(20, l) ("StoreEntry->swap_filen: %d\n", (int) e->swap_filen);
1610
 
    debug(20, l) ("StoreEntry->lock_count: %d\n", (int) e->lock_count);
1611
 
    debug(20, l) ("StoreEntry->mem_status: %d\n", (int) e->mem_status);
1612
 
    debug(20, l) ("StoreEntry->ping_status: %d\n", (int) e->ping_status);
1613
 
    debug(20, l) ("StoreEntry->store_status: %d\n", (int) e->store_status);
1614
 
    debug(20, l) ("StoreEntry->swap_status: %d\n", (int) e->swap_status);
 
1538
    if (reply->expires > 0 && reply->date > -1)
 
1539
        expires = served_date + (reply->expires - reply->date);
 
1540
    else
 
1541
        expires = reply->expires;
 
1542
 
 
1543
    lastmod = reply->last_modified;
 
1544
 
 
1545
    timestamp = served_date;
 
1546
}
 
1547
 
 
1548
void
 
1549
StoreEntry::registerAbort(STABH * cb, void *data)
 
1550
{
 
1551
    assert(mem_obj);
 
1552
    assert(mem_obj->abort.callback == NULL);
 
1553
    mem_obj->abort.callback = cb;
 
1554
    mem_obj->abort.data = cbdataReference(data);
 
1555
}
 
1556
 
 
1557
void
 
1558
StoreEntry::unregisterAbort()
 
1559
{
 
1560
    assert(mem_obj);
 
1561
    if (mem_obj->abort.callback) {
 
1562
        mem_obj->abort.callback = NULL;
 
1563
        cbdataReferenceDone(mem_obj->abort.data);
 
1564
    }
 
1565
}
 
1566
 
 
1567
void
 
1568
StoreEntry::dump(int l) const
 
1569
{
 
1570
    debugs(20, l, "StoreEntry->key: " << getMD5Text());
 
1571
    debugs(20, l, "StoreEntry->next: " << next);
 
1572
    debugs(20, l, "StoreEntry->mem_obj: " << mem_obj);
 
1573
    debugs(20, l, "StoreEntry->timestamp: " << timestamp);
 
1574
    debugs(20, l, "StoreEntry->lastref: " << lastref);
 
1575
    debugs(20, l, "StoreEntry->expires: " << expires);
 
1576
    debugs(20, l, "StoreEntry->lastmod: " << lastmod);
 
1577
    debugs(20, l, "StoreEntry->swap_file_sz: " << swap_file_sz);
 
1578
    debugs(20, l, "StoreEntry->refcount: " << refcount);
 
1579
    debugs(20, l, "StoreEntry->flags: " << storeEntryFlags(this));
 
1580
    debugs(20, l, "StoreEntry->swap_dirn: " << swap_dirn);
 
1581
    debugs(20, l, "StoreEntry->swap_filen: " << swap_filen);
 
1582
    debugs(20, l, "StoreEntry->lock_count: " << lock_count);
 
1583
    debugs(20, l, "StoreEntry->mem_status: " << mem_status);
 
1584
    debugs(20, l, "StoreEntry->ping_status: " << ping_status);
 
1585
    debugs(20, l, "StoreEntry->store_status: " << store_status);
 
1586
    debugs(20, l, "StoreEntry->swap_status: " << swap_status);
1615
1587
}
1616
1588
 
1617
1589
/*
1618
1590
 * NOTE, this function assumes only two mem states
1619
1591
 */
1620
1592
void
1621
 
storeSetMemStatus(StoreEntry * e, mem_status_t new_status)
 
1593
StoreEntry::setMemStatus(mem_status_t new_status)
1622
1594
{
1623
 
    MemObject *mem = e->mem_obj;
1624
 
 
1625
 
    if (new_status == e->mem_status)
 
1595
    if (new_status == mem_status)
1626
1596
        return;
1627
1597
 
1628
 
    assert(mem != NULL);
 
1598
    assert(mem_obj != NULL);
1629
1599
 
1630
1600
    if (new_status == IN_MEMORY) {
1631
 
        assert(mem->inmem_lo == 0);
 
1601
        assert(mem_obj->inmem_lo == 0);
1632
1602
 
1633
 
        if (EBIT_TEST(e->flags, ENTRY_SPECIAL)) {
1634
 
            debug(20, 4) ("storeSetMemStatus: not inserting special %s into policy\n",
1635
 
                          mem->url);
 
1603
        if (EBIT_TEST(flags, ENTRY_SPECIAL)) {
 
1604
            debugs(20, 4, "StoreEntry::setMemStatus: not inserting special " << mem_obj->url << " into policy");
1636
1605
        } else {
1637
 
            mem_policy->Add(mem_policy, e, &mem->repl);
1638
 
            debug(20, 4) ("storeSetMemStatus: inserted mem node %s\n",
1639
 
                          mem->url);
 
1606
            mem_policy->Add(mem_policy, this, &mem_obj->repl);
 
1607
            debugs(20, 4, "StoreEntry::setMemStatus: inserted mem node " << mem_obj->url);
1640
1608
        }
1641
1609
 
1642
1610
        hot_obj_count++;
1643
1611
    } else {
1644
 
        if (EBIT_TEST(e->flags, ENTRY_SPECIAL)) {
1645
 
            debug(20, 4) ("storeSetMemStatus: special entry %s\n",
1646
 
                          mem->url);
 
1612
        if (EBIT_TEST(flags, ENTRY_SPECIAL)) {
 
1613
            debugs(20, 4, "StoreEntry::setMemStatus: special entry " << mem_obj->url);
1647
1614
        } else {
1648
 
            mem_policy->Remove(mem_policy, e, &mem->repl);
1649
 
            debug(20, 4) ("storeSetMemStatus: removed mem node %s\n",
1650
 
                          mem->url);
 
1615
            mem_policy->Remove(mem_policy, this, &mem_obj->repl);
 
1616
            debugs(20, 4, "StoreEntry::setMemStatus: removed mem node " << mem_obj->url);
1651
1617
        }
1652
1618
 
1653
1619
        hot_obj_count--;
1654
1620
    }
1655
1621
 
1656
 
    e->mem_status = new_status;
 
1622
    mem_status = new_status;
1657
1623
}
1658
1624
 
1659
1625
const char *
1660
 
storeUrl(const StoreEntry * e)
 
1626
StoreEntry::url() const
1661
1627
{
1662
 
    if (e == NULL)
 
1628
    if (this == NULL)
1663
1629
        return "[null_entry]";
1664
 
    else if (e->mem_obj == NULL)
 
1630
    else if (mem_obj == NULL)
1665
1631
        return "[null_mem_obj]";
1666
1632
    else
1667
 
        return e->mem_obj->url;
 
1633
        return mem_obj->url;
1668
1634
}
1669
1635
 
1670
1636
void
1671
 
storeCreateMemObject(StoreEntry * e, const char *url, const char *log_url)
 
1637
StoreEntry::createMemObject(const char *url, const char *log_url)
1672
1638
{
1673
 
    if (e->mem_obj)
 
1639
    if (mem_obj)
1674
1640
        return;
1675
1641
 
1676
 
    e->mem_obj = new MemObject(url, log_url);
1677
 
}
1678
 
 
1679
 
/* DEPRECATED: please use entry->buffer() */
1680
 
void
1681
 
storeBuffer(StoreEntry * e)
1682
 
{
1683
 
    e->buffer();
 
1642
    mem_obj = new MemObject(url, log_url);
1684
1643
}
1685
1644
 
1686
1645
/* this just sets DELAY_SENDING */
1690
1649
    EBIT_SET(flags, DELAY_SENDING);
1691
1650
}
1692
1651
 
1693
 
/* DEPRECATED - please use e->flush(); */
1694
 
void storeBufferFlush(StoreEntry * e)
1695
 
{
1696
 
    e->flush();
1697
 
}
1698
 
 
1699
1652
/* this just clears DELAY_SENDING and Invokes the handlers */
1700
1653
void
1701
1654
StoreEntry::flush()
1702
1655
{
1703
1656
    if (EBIT_TEST(flags, DELAY_SENDING)) {
1704
1657
        EBIT_CLR(flags, DELAY_SENDING);
1705
 
        InvokeHandlers(this);
 
1658
        invokeHandlers();
1706
1659
    }
1707
1660
}
1708
1661
 
1709
1662
ssize_t
1710
 
objectLen(const StoreEntry * e)
 
1663
StoreEntry::objectLen() const
1711
1664
{
1712
 
    assert(e->mem_obj != NULL);
1713
 
    return e->mem_obj->object_sz;
 
1665
    assert(mem_obj != NULL);
 
1666
    return mem_obj->object_sz;
1714
1667
}
1715
1668
 
1716
1669
int
1717
 
contentLen(const StoreEntry * e)
 
1670
StoreEntry::contentLen() const
1718
1671
{
1719
 
    assert(e->mem_obj != NULL);
1720
 
    assert(e->getReply() != NULL);
1721
 
    return objectLen(e) - e->getReply()->hdr_sz;
1722
 
 
 
1672
    assert(mem_obj != NULL);
 
1673
    assert(getReply() != NULL);
 
1674
    return objectLen() - getReply()->hdr_sz;
1723
1675
}
1724
1676
 
1725
1677
HttpReply const *
1732
1684
}
1733
1685
 
1734
1686
void
1735
 
storeEntryReset(StoreEntry * e)
 
1687
StoreEntry::reset()
1736
1688
{
1737
 
    MemObject *mem = e->mem_obj;
1738
 
    assert (mem);
1739
 
    debug(20, 3) ("storeEntryReset: %s\n", storeUrl(e));
1740
 
    mem->reset();
1741
 
    HttpReply *rep = (HttpReply *) e->getReply();       // bypass const
 
1689
    assert (mem_obj);
 
1690
    debugs(20, 3, "StoreEntry::reset: " << url());
 
1691
    mem_obj->reset();
 
1692
    HttpReply *rep = (HttpReply *) getReply();       // bypass const
1742
1693
    rep->reset();
1743
 
    e->expires = e->lastmod = e->timestamp = -1;
 
1694
    expires = lastmod = timestamp = -1;
1744
1695
}
1745
1696
 
1746
1697
/*
1792
1743
            return r->create(settings->args);
1793
1744
    }
1794
1745
 
1795
 
    debug(20, 1) ("ERROR: Unknown policy %s\n", settings->type);
1796
 
    debug(20, 1) ("ERROR: Be sure to have set cache_replacement_policy\n");
1797
 
    debug(20, 1) ("ERROR:   and memory_replacement_policy in squid.conf!\n");
 
1746
    debugs(20, 1, "ERROR: Unknown policy " << settings->type);
 
1747
    debugs(20, 1, "ERROR: Be sure to have set cache_replacement_policy");
 
1748
    debugs(20, 1, "ERROR:   and memory_replacement_policy in squid.conf!");
1798
1749
    fatalf("ERROR: Unknown policy %s\n", settings->type);
1799
1750
    return NULL;                /* NOTREACHED */
1800
1751
}
1828
1779
void
1829
1780
StoreEntry::replaceHttpReply(HttpReply *rep)
1830
1781
{
1831
 
    debug(20, 3) ("StoreEntry::replaceHttpReply: %s\n", storeUrl(this));
 
1782
    debugs(20, 3, "StoreEntry::replaceHttpReply: " << url());
1832
1783
    Packer p;
1833
1784
 
1834
1785
    if (!mem_obj) {
1835
 
        debug (20,0)("Attempt to replace object with no in-memory representation\n");
 
1786
        debugs(20, 0, "Attempt to replace object with no in-memory representation");
1836
1787
        return;
1837
1788
    }
1838
1789
 
1871
1822
StoreEntry::swapoutPossible()
1872
1823
{
1873
1824
    /* should we swap something out to disk? */
1874
 
    debug(20, 7) ("storeSwapOut: %s\n", storeUrl(this));
1875
 
    debug(20, 7) ("storeSwapOut: store_status = %s\n",
1876
 
                  storeStatusStr[store_status]);
 
1825
    debugs(20, 7, "storeSwapOut: " << url());
 
1826
    debugs(20, 7, "storeSwapOut: store_status = " << storeStatusStr[store_status]);
1877
1827
 
1878
1828
    if (EBIT_TEST(flags, ENTRY_ABORTED)) {
1879
1829
        assert(EBIT_TEST(flags, RELEASE_REQUEST));
1880
 
        storeSwapOutFileClose(this);
 
1830
        swapOutFileClose();
1881
1831
        return false;
1882
1832
    }
1883
1833
 
1884
1834
    if (EBIT_TEST(flags, ENTRY_SPECIAL)) {
1885
 
        debug(20, 3) ("storeSwapOut: %s SPECIAL\n", storeUrl(this));
 
1835
        debugs(20, 3, "storeSwapOut: " << url() << " SPECIAL");
1886
1836
        return false;
1887
1837
    }
1888
1838
 
1898
1848
 
1899
1849
    assert (mem_obj->policyLowestOffsetToKeep() > 0);
1900
1850
 
1901
 
    if (!storeSwapOutAble(this)) {
 
1851
    if (!swapOutAble()) {
1902
1852
        /*
1903
1853
         * Its not swap-able, and we're about to delete a chunk,
1904
1854
         * so we must make it PRIVATE.  This is tricky/ugly because
1905
1855
         * for the most part, we treat swapable == cachable here.
1906
1856
         */
1907
 
        storeReleaseRequest(this);
 
1857
        releaseRequest();
1908
1858
        mem_obj->trimUnSwappable ();
1909
1859
    } else {
1910
1860
        mem_obj->trimSwappable ();
1920
1870
    if (mod_time < 0)
1921
1871
        mod_time = timestamp;
1922
1872
 
1923
 
    debug(88, 3) ("modifiedSince: '%s'\n", storeUrl(this));
 
1873
    debugs(88, 3, "modifiedSince: '" << url() << "'");
1924
1874
 
1925
 
    debug(88, 3) ("modifiedSince: mod_time = %ld\n", (long int) mod_time);
 
1875
    debugs(88, 3, "modifiedSince: mod_time = " << mod_time);
1926
1876
 
1927
1877
    if (mod_time < 0)
1928
1878
        return true;
1931
1881
    object_length = getReply()->content_length;
1932
1882
 
1933
1883
    if (object_length < 0)
1934
 
        object_length = contentLen(this);
 
1884
        object_length = contentLen();
1935
1885
 
1936
1886
    if (mod_time > request->ims) {
1937
 
        debug(88, 3) ("--> YES: entry newer than client\n");
 
1887
        debugs(88, 3, "--> YES: entry newer than client");
1938
1888
        return true;
1939
1889
    } else if (mod_time < request->ims) {
1940
 
        debug(88, 3) ("-->  NO: entry older than client\n");
 
1890
        debugs(88, 3, "-->  NO: entry older than client");
1941
1891
        return false;
1942
1892
    } else if (request->imslen < 0) {
1943
 
        debug(88, 3) ("-->  NO: same LMT, no client length\n");
 
1893
        debugs(88, 3, "-->  NO: same LMT, no client length");
1944
1894
        return false;
1945
1895
    } else if (request->imslen == object_length) {
1946
 
        debug(88, 3) ("-->  NO: same LMT, same length\n");
 
1896
        debugs(88, 3, "-->  NO: same LMT, same length");
1947
1897
        return false;
1948
1898
    } else {
1949
 
        debug(88, 3) ("--> YES: same LMT, different length\n");
 
1899
        debugs(88, 3, "--> YES: same LMT, different length");
1950
1900
        return true;
1951
1901
    }
1952
1902
}