/*
- * DEBUG: section 20 Memory Cache
+ * Copyright (C) 1996-2015 The Squid Software Foundation and contributors
*
+ * Squid software is distributed under GPLv2+ license and includes
+ * contributions from numerous individuals and organizations.
+ * Please see the COPYING and CONTRIBUTORS files for details.
*/
+/* DEBUG: section 20 Memory Cache */
+
#include "squid.h"
#include "base/RunnersRegistry.h"
#include "CollapsedForwarding.h"
#include "tools.h"
/// shared memory segment path to use for MemStore maps
-static const char *MapLabel = "cache_mem_map";
+static const SBuf MapLabel("cache_mem_map");
/// shared memory segment path to use for the free slices index
static const char *SpaceLabel = "cache_mem_space";
+/// shared memory segment path to use for IDs of shared pages with slice data
+static const char *ExtrasLabel = "cache_mem_ex";
// TODO: sync with Rock::SwapDir::*Path()
// We store free slot IDs (i.e., "space") as Page objects so that we can use
}
freeSlots = shm_old(Ipc::Mem::PageStack)(SpaceLabel);
+ extras = shm_old(Extras)(ExtrasLabel);
Must(!map);
map = new MemStoreMap(MapLabel);
Math::doublePercent(currentSize(), maxSize()));
if (map) {
- const int limit = map->entryLimit();
- storeAppendPrintf(&e, "Maximum entries: %9d\n", limit);
- if (limit > 0) {
+ const int entryLimit = map->entryLimit();
+ const int slotLimit = map->sliceLimit();
+ storeAppendPrintf(&e, "Maximum entries: %9d\n", entryLimit);
+ if (entryLimit > 0) {
storeAppendPrintf(&e, "Current entries: %" PRId64 " %.2f%%\n",
- currentCount(), (100.0 * currentCount() / limit));
+ currentCount(), (100.0 * currentCount() / entryLimit));
+ }
+ storeAppendPrintf(&e, "Maximum slots: %9d\n", slotLimit);
+ if (slotLimit > 0) {
const unsigned int slotsFree =
Ipc::Mem::PagesAvailable(Ipc::Mem::PageId::cachePage);
- if (slotsFree <= static_cast<const unsigned int>(limit)) {
- const int usedSlots = limit - static_cast<const int>(slotsFree);
+ if (slotsFree <= static_cast<const unsigned int>(slotLimit)) {
+ const int usedSlots = slotLimit - static_cast<const int>(slotsFree);
storeAppendPrintf(&e, "Used slots: %9d %.2f%%\n",
- usedSlots, (100.0 * usedSlots / limit));
+ usedSlots, (100.0 * usedSlots / slotLimit));
}
- if (limit < 100) { // XXX: otherwise too expensive to count
+ if (slotLimit < 100) { // XXX: otherwise too expensive to count
Ipc::ReadWriteLockStats stats;
map->updateStats(stats);
stats.dump(e);
}
void
-MemStore::get(String const key, STOREGETCLIENT aCallback, void *aCallbackData)
+MemStore::get(String const, STOREGETCLIENT, void *)
{
// XXX: not needed but Store parent forces us to implement this
fatal("MemStore::get(key,callback,data) should not be called");
sfileno index;
const Ipc::StoreMapAnchor *const slot = map->openForReading(
- reinterpret_cast<cache_key*>(collapsed.key), index);
+ reinterpret_cast<cache_key*>(collapsed.key), index);
if (!slot)
return false;
const size_t prefixSize = e.mem_obj->endOffset() - sliceOffset;
assert(prefixSize <= wasSize);
- const MemStoreMap::Extras &extras = map->extras(sid);
- char *page = static_cast<char*>(PagePointer(extras.page));
+ const MemStoreMapExtras::Item &extra = extras->items[sid];
+
+ char *page = static_cast<char*>(PagePointer(extra.page));
const StoreIOBuffer sliceBuf(wasSize - prefixSize,
e.mem_obj->endOffset(),
page + prefixSize);
if (!copyFromShmSlice(e, sliceBuf, wasEof))
return false;
debugs(20, 9, "entry " << index << " copied slice " << sid <<
- " from " << extras.page << " +" << prefixSize);
+ " from " << extra.page << '+' << prefixSize);
}
// else skip a [possibly incomplete] slice that we copied earlier
/// whether we should cache the entry
bool
-MemStore::shouldCache(const StoreEntry &e) const
+MemStore::shouldCache(StoreEntry &e) const
{
if (e.mem_status == IN_MEMORY) {
debugs(20, 5, "already loaded from mem-cache: " << e);
return false; // will not cache due to cachable entry size limits
}
+ if (!e.mem_obj->isContiguous()) {
+ debugs(20, 5, "not contiguous");
+ return false;
+ }
+
if (!map) {
debugs(20, 5, HERE << "No map to mem-cache " << e);
return false;
e.mem_obj->memCache.io = MemObject::ioWriting;
slot->set(e);
map->startAppending(index);
+ e.memOutDecision(true);
return true;
}
if (anchor.start < 0) { // must allocate the very first slot for e
Ipc::Mem::PageId page;
anchor.start = reserveSapForWriting(page); // throws
- map->extras(anchor.start).page = page;
+ extras->items[anchor.start].page = page;
}
lastWritingSlice = anchor.start;
Ipc::Mem::PageId page;
slice.next = lastWritingSlice = reserveSapForWriting(page);
- map->extras(lastWritingSlice).page = page;
+ extras->items[lastWritingSlice].page = page;
debugs(20, 7, "entry " << index << " new slice: " << lastWritingSlice);
}
Ipc::StoreMap::Slice &slice =
map->writeableSlice(e.mem_obj->memCache.index, lastWritingSlice);
- Ipc::Mem::PageId page = map->extras(lastWritingSlice).page;
+ Ipc::Mem::PageId page = extras->items[lastWritingSlice].page;
assert(lastWritingSlice >= 0 && page);
debugs(20, 7, "entry " << e << " slice " << lastWritingSlice << " has " <<
page);
}
void
-MemStore::noteFreeMapSlice(const sfileno sliceId)
+MemStore::noteFreeMapSlice(const Ipc::StoreMapSliceId sliceId)
{
- Ipc::Mem::PageId &pageId = map->extras(sliceId).page;
+ Ipc::Mem::PageId &pageId = extras->items[sliceId].page;
debugs(20, 9, "slice " << sliceId << " freed " << pageId);
assert(pageId);
Ipc::Mem::PageId slotId;
case MemObject::ioUndecided:
if (!shouldCache(e) || !startCaching(e)) {
e.mem_obj->memCache.io = MemObject::ioDone;
- Store::Root().transientsAbandon(e);
+ e.memOutDecision(false);
return;
}
break;
return entryLimit;
}
-/// reports our needs for shared memory pages to Ipc::Mem::Pages
-class MemStoreClaimMemoryNeedsRr: public RegisteredRunner
+/// reports our needs for shared memory pages to Ipc::Mem::Pages;
+/// decides whether to use a shared memory cache or checks its configuration;
+/// and initializes shared memory segments used by MemStore
+class MemStoreRr: public Ipc::Mem::RegisteredRunner
{
public:
/* RegisteredRunner API */
- virtual void run(const RunnerRegistry &r);
+ MemStoreRr(): spaceOwner(NULL), mapOwner(NULL), extrasOwner(NULL) {}
+ virtual void finalizeConfig();
+ virtual void claimMemoryNeeds();
+ virtual void useConfig();
+ virtual ~MemStoreRr();
+
+protected:
+ /* Ipc::Mem::RegisteredRunner API */
+ virtual void create();
+
+private:
+ Ipc::Mem::Owner<Ipc::Mem::PageStack> *spaceOwner; ///< free slices Owner
+ MemStoreMap::Owner *mapOwner; ///< primary map Owner
+ Ipc::Mem::Owner<MemStoreMapExtras> *extrasOwner; ///< PageIds Owner
};
-RunnerRegistrationEntry(rrClaimMemoryNeeds, MemStoreClaimMemoryNeedsRr);
+RunnerRegistrationEntry(MemStoreRr);
void
-MemStoreClaimMemoryNeedsRr::run(const RunnerRegistry &)
+MemStoreRr::claimMemoryNeeds()
{
Ipc::Mem::NotePageNeed(Ipc::Mem::PageId::cachePage, MemStore::EntryLimit());
}
-/// decides whether to use a shared memory cache or checks its configuration
-class MemStoreCfgRr: public ::RegisteredRunner
-{
-public:
- /* RegisteredRunner API */
- virtual void run(const RunnerRegistry &);
-};
-
-RunnerRegistrationEntry(rrFinalizeConfig, MemStoreCfgRr);
-
-void MemStoreCfgRr::run(const RunnerRegistry &r)
+void
+MemStoreRr::finalizeConfig()
{
// decide whether to use a shared memory cache if the user did not specify
if (!Config.memShared.configured()) {
}
}
-/// initializes shared memory segments used by MemStore
-class MemStoreRr: public Ipc::Mem::RegisteredRunner
-{
-public:
- /* RegisteredRunner API */
- MemStoreRr(): spaceOwner(NULL), mapOwner(NULL) {}
- virtual void run(const RunnerRegistry &);
- virtual ~MemStoreRr();
-
-protected:
- virtual void create(const RunnerRegistry &);
-
-private:
- Ipc::Mem::Owner<Ipc::Mem::PageStack> *spaceOwner; ///< free slices Owner
- MemStoreMap::Owner *mapOwner; ///< primary map Owner
-};
-
-RunnerRegistrationEntry(rrAfterConfig, MemStoreRr);
-
-void MemStoreRr::run(const RunnerRegistry &r)
+void
+MemStoreRr::useConfig()
{
assert(Config.memShared.configured());
- Ipc::Mem::RegisteredRunner::run(r);
+ Ipc::Mem::RegisteredRunner::useConfig();
}
-void MemStoreRr::create(const RunnerRegistry &)
+void
+MemStoreRr::create()
{
if (!Config.memShared)
return;
Must(!spaceOwner);
spaceOwner = shm_new(Ipc::Mem::PageStack)(SpaceLabel, SpacePoolId,
- entryLimit,
- sizeof(Ipc::Mem::PageId));
+ entryLimit, 0);
Must(!mapOwner);
mapOwner = MemStoreMap::Init(MapLabel, entryLimit);
+ Must(!extrasOwner);
+ extrasOwner = shm_new(MemStoreMapExtras)(ExtrasLabel, entryLimit);
}
MemStoreRr::~MemStoreRr()
{
+ delete extrasOwner;
delete mapOwner;
delete spaceOwner;
}
+