Inside StoreEntry::swapOut() the StoreEntry::trimMemory() method called
to release unused MemObjects memory. The trimMemory method must called
for all store entries, but current code blocks that call for
not-swappable objects, at least.
This patch trying to fix this bug implementing the following simple logic:
{
bool weAreOrMayBeSwappingOut =
swappingOut() || mayStartSwapout();
trimMemory(weAreOrMayBeSwappingOut);
if (!weAreOrMayBeSwappingOut)
return; // nothing else to do
}
This is a Measurement Factory project
trimMemory for unswappable objects
Inside StoreEntry::swapOut() the StoreEntry::trimMemory() method called to
release unused MemObjects memory. The trimMemory method must called for all
store entries, but current code blocks that call for not-swappable objects,
at least.
This patch trying to fix this bug implementing the following simple logic:
{
bool weAreOrMayBeSwappingOut =
swappingOut() || mayStartSwapout();
trimMemory(weAreOrMayBeSwappingOut);
if (!weAreOrMayBeSwappingOut)
return; // nothing else to do
}
=== modified file 'src/MemObject.cc'
--- src/MemObject.cc 2011-09-06 22:32:30 +0000
+++ src/MemObject.cc 2011-11-23 12:42:07 +0000
@@ -475,20 +475,26 @@
continue;
#endif
if (sc->getType() != STORE_MEM_CLIENT)
/* reading off disk */
continue;
j = sc->delayId.bytesWanted(0, sc->copyInto.length);
if (j > jmax) {
jmax = j;
result = sc->delayId;
}
}
return result;
}
#endif
+
+int64_t
+MemObject::availableForSwapOut() const
+{
+ return endOffset() - swapout.queue_offset;
+}
=== modified file 'src/MemObject.h'
--- src/MemObject.h 2011-04-28 22:45:55 +0000
+++ src/MemObject.h 2012-01-07 09:57:12 +0000
@@ -64,40 +64,41 @@
void write(StoreIOBuffer, STMCB *, void *);
void unlinkRequest();
HttpReply const *getReply() const;
void replaceHttpReply(HttpReply *newrep);
void stat (MemBuf * mb) const;
int64_t endOffset () const;
void markEndOfReplyHeaders(); ///< sets _reply->hdr_sz to endOffset()
/// negative if unknown; otherwise, expected object_sz, expected endOffset
/// maximum, and stored reply headers+body size (all three are the same)
int64_t expectedReplySize() const;
int64_t size() const;
void reset();
int64_t lowestMemReaderOffset() const;
bool readAheadPolicyCanRead() const;
void addClient(store_client *);
/* XXX belongs in MemObject::swapout, once swaphdrsz is managed
* better
*/
int64_t objectBytesOnDisk() const;
int64_t policyLowestOffsetToKeep(bool swap) const;
+ int64_t availableForSwapOut() const; ///< buffered bytes we have not swapped out yet
void trimSwappable();
void trimUnSwappable();
bool isContiguous() const;
int mostBytesWanted(int max) const;
void setNoDelay(bool const newValue);
#if USE_DELAY_POOLS
DelayId mostBytesAllowed() const;
#endif
#if URL_CHECKSUM_DEBUG
void checkUrlChecksum() const;
#endif
HttpRequestMethod method;
char *url;
mem_hdr data_hdr;
int64_t inmem_lo;
dlink_list clients;
=== modified file 'src/Store.h'
--- src/Store.h 2011-11-18 16:53:45 +0000
+++ src/Store.h 2011-11-23 15:23:13 +0000
@@ -75,57 +75,59 @@
public:
static DeferredRead::DeferrableRead DeferReader;
bool checkDeferRead(int fd) const;
virtual const char *getMD5Text() const;
StoreEntry();
StoreEntry(const char *url, const char *log_url);
virtual ~StoreEntry();
virtual HttpReply const *getReply() const;
virtual void write (StoreIOBuffer);
virtual _SQUID_INLINE_ bool isEmpty() const;
virtual bool isAccepting() const;
virtual size_t bytesWanted(Range<size_t> const) const;
virtual void complete();
virtual store_client_t storeClientType() const;
virtual char const *getSerialisedMetaData();
void replaceHttpReply(HttpReply *, bool andStartWriting = true);
void startWriting(); ///< pack and write reply headers and, maybe, body
- virtual bool swapoutPossible();
- virtual void trimMemory();
+ /// whether we may start writing to disk (now or in the future)
+ virtual bool mayStartSwapOut();
+ virtual void trimMemory(const bool preserveSwappable);
void abort();
void unlink();
void makePublic();
void makePrivate();
void setPublicKey();
void setPrivateKey();
void expireNow();
void releaseRequest();
void negativeCache();
void cacheNegatively(); /** \todo argh, why both? */
void invokeHandlers();
void purgeMem();
void cacheInMemory(); ///< start or continue storing in memory cache
void swapOut();
- bool swapOutAble() const;
+ /// whether we are in the process of writing this entry to disk
+ bool swappingOut() const { return swap_status == SWAPOUT_WRITING; }
void swapOutFileClose(int how);
const char *url() const;
int checkCachable();
int checkNegativeHit() const;
int locked() const;
int validToSend() const;
bool memoryCachable() const; ///< may be cached in memory
void createMemObject(const char *, const char *);
void hideMemObject(); ///< no mem_obj for callers until createMemObject
void dump(int debug_lvl) const;
void hashDelete();
void hashInsert(const cache_key *);
void registerAbort(STABH * cb, void *);
void reset();
void setMemStatus(mem_status_t);
void timestampsSet();
void unregisterAbort();
void destroyMemObject();
int checkTooSmall();
@@ -230,41 +232,41 @@
static NullStoreEntry *getInstance();
bool isNull() {
return true;
}
const char *getMD5Text() const;
_SQUID_INLINE_ HttpReply const *getReply() const;
void write (StoreIOBuffer) {}
bool isEmpty () const {return true;}
virtual size_t bytesWanted(Range<size_t> const aRange) const { assert (aRange.size()); return aRange.end - 1;}
void operator delete(void *address);
void complete() {}
private:
store_client_t storeClientType() const {return STORE_MEM_CLIENT;}
char const *getSerialisedMetaData();
- bool swapoutPossible() {return false;}
+ bool mayStartSwapout() {return false;}
void trimMemory() {}
static NullStoreEntry _instance;
};
/// \ingroup StoreAPI
typedef void (*STOREGETCLIENT) (StoreEntry *, void *cbdata);
/**
\ingroup StoreAPI
* Abstract base class that will replace the whole store and swapdir interface.
*/
class Store : public RefCountable
{
public:
/** The root store */
=== modified file 'src/client_side.cc'
--- src/client_side.cc 2011-12-30 12:26:51 +0000
+++ src/client_side.cc 2012-01-09 11:11:15 +0000
@@ -2685,41 +2685,41 @@
context->mayUseConnection(true);
assert(conn->flags.readMore);
}
}
http->calloutContext = new ClientRequestContext(http);
http->doCallouts();
finish:
if (!notedUseOfBuffer)
connNoteUseOfBuffer(conn, http->req_sz);
/*
* DPW 2007-05-18
* Moved the TCP_RESET feature from clientReplyContext::sendMoreData
* to here because calling comm_reset_close() causes http to
* be freed and the above connNoteUseOfBuffer() would hit an
* assertion, not to mention that we were accessing freed memory.
*/
- if (http->request->flags.resetTCP() && Comm::IsConnOpen(conn->clientConnection)) {
+ if (request && request->flags.resetTCP() && Comm::IsConnOpen(conn->clientConnection)) {
debugs(33, 3, HERE << "Sending TCP RST on " << conn->clientConnection);
conn->flags.readMore = false;
comm_reset_close(conn->clientConnection);
}
}
static void
connStripBufferWhitespace (ConnStateData * conn)
{
while (conn->in.notYetUsed > 0 && xisspace(conn->in.buf[0])) {
memmove(conn->in.buf, conn->in.buf + 1, conn->in.notYetUsed - 1);
--conn->in.notYetUsed;
}
}
static int
connOkToAddRequest(ConnStateData * conn)
{
int result = conn->getConcurrentRequestCount() < (Config.onoff.pipeline_prefetch ? 2 : 1);
=== modified file 'src/store.cc'
--- src/store.cc 2011-12-10 16:29:31 +0000
+++ src/store.cc 2012-01-07 09:34:28 +0000
@@ -1874,139 +1874,52 @@
mem_obj->markEndOfReplyHeaders();
rep->body.packInto(&p);
packerClean(&p);
}
char const *
StoreEntry::getSerialisedMetaData()
{
StoreMeta *tlv_list = storeSwapMetaBuild(this);
int swap_hdr_sz;
char *result = storeSwapMetaPack(tlv_list, &swap_hdr_sz);
storeSwapTLVFree(tlv_list);
assert (swap_hdr_sz >= 0);
mem_obj->swap_hdr_sz = (size_t) swap_hdr_sz;
return result;
}
-bool
-StoreEntry::swapoutPossible()
-{
- if (!Config.cacheSwap.n_configured)
- return false;
-
- /* should we swap something out to disk? */
- debugs(20, 7, "storeSwapOut: " << url());
- debugs(20, 7, "storeSwapOut: store_status = " << storeStatusStr[store_status]);
-
- assert(mem_obj);
- MemObject::SwapOut::Decision &decision = mem_obj->swapout.decision;
-
- // if we decided that swapout is not possible, do not repeat same checks
- if (decision == MemObject::SwapOut::swImpossible) {
- debugs(20, 3, "storeSwapOut: already rejected");
- return false;
- }
-
- // this flag may change so we must check it even if we already said "yes"
- if (EBIT_TEST(flags, ENTRY_ABORTED)) {
- assert(EBIT_TEST(flags, RELEASE_REQUEST));
- // StoreEntry::abort() already closed the swap out file, if any
- decision = MemObject::SwapOut::swImpossible;
- return false;
- }
-
- // if we decided that swapout is possible, do not repeat same checks
- if (decision == MemObject::SwapOut::swPossible) {
- debugs(20, 3, "storeSwapOut: already allowed");
- return true;
- }
-
- // if we are swapping out already, do not repeat same checks
- if (swap_status != SWAPOUT_NONE) {
- debugs(20, 3, "storeSwapOut: already started");
- decision = MemObject::SwapOut::swPossible;
- return true;
- }
-
- if (!checkCachable()) {
- debugs(20, 3, "storeSwapOut: not cachable");
- decision = MemObject::SwapOut::swImpossible;
- return false;
- }
-
- if (EBIT_TEST(flags, ENTRY_SPECIAL)) {
- debugs(20, 3, "storeSwapOut: " << url() << " SPECIAL");
- decision = MemObject::SwapOut::swImpossible;
- return false;
- }
-
- // check cache_dir max-size limit if all cache_dirs have it
- if (store_maxobjsize >= 0) {
- // TODO: add estimated store metadata size to be conservative
-
- // use guaranteed maximum if it is known
- const int64_t expectedEnd = mem_obj->expectedReplySize();
- debugs(20, 7, "storeSwapOut: expectedEnd = " << expectedEnd);
- if (expectedEnd > store_maxobjsize) {
- debugs(20, 3, "storeSwapOut: will not fit: " << expectedEnd <<
- " > " << store_maxobjsize);
- decision = MemObject::SwapOut::swImpossible;
- return false; // known to outgrow the limit eventually
- }
-
- // use current minimum (always known)
- const int64_t currentEnd = mem_obj->endOffset();
- if (currentEnd > store_maxobjsize) {
- debugs(20, 3, "storeSwapOut: does not fit: " << currentEnd <<
- " > " << store_maxobjsize);
- decision = MemObject::SwapOut::swImpossible;
- return false; // already does not fit and may only get bigger
- }
-
- // prevent default swPossible answer for yet unknown length
- if (expectedEnd < 0) {
- debugs(20, 3, "storeSwapOut: wait for more info: " <<
- store_maxobjsize);
- return false; // may fit later, but will be rejected now
- }
- }
-
- decision = MemObject::SwapOut::swPossible;
- return true;
-}
-
void
-StoreEntry::trimMemory()
+StoreEntry::trimMemory(const bool preserveSwappable)
{
/*
* DPW 2007-05-09
* Bug #1943. We must not let go any data for IN_MEMORY
* objects. We have to wait until the mem_status changes.
*/
if (mem_status == IN_MEMORY)
return;
- if (!swapOutAble()) {
+ if (!preserveSwappable) {
if (mem_obj->policyLowestOffsetToKeep(0) == 0) {
/* Nothing to do */
return;
}
/*
* Its not swap-able, and we're about to delete a chunk,
* so we must make it PRIVATE. This is tricky/ugly because
* for the most part, we treat swapable == cachable here.
*/
releaseRequest();
mem_obj->trimUnSwappable ();
} else {
mem_obj->trimSwappable ();
}
}
bool
StoreEntry::modifiedSince(HttpRequest * request) const
{
int object_length;
=== modified file 'src/store_client.cc'
--- src/store_client.cc 2011-12-10 16:29:31 +0000
+++ src/store_client.cc 2012-01-07 09:34:28 +0000
@@ -178,41 +178,41 @@
if (!sc->_callback.pending())
return;
storeClientCopy2(sc->entry, sc);
}
store_client::store_client(StoreEntry *e) : entry (e)
#if USE_DELAY_POOLS
, delayId()
#endif
, type (e->storeClientType())
, object_ok(true)
{
cmp_offset = 0;
flags.disk_io_pending = 0;
entry->refcount++;
if (getType() == STORE_DISK_CLIENT)
/* assert we'll be able to get the data we want */
/* maybe we should open swapin_sio here */
- assert(entry->swap_filen > -1 || entry->swapOutAble());
+ assert(entry->swap_filen > -1 || entry->swappingOut());
#if STORE_CLIENT_LIST_DEBUG
owner = cbdataReference(data);
#endif
}
store_client::~store_client()
{}
/* copy bytes requested by the client */
void
storeClientCopy(store_client * sc,
StoreEntry * e,
StoreIOBuffer copyInto,
STCB * callback,
void *data)
{
assert (sc != NULL);
=== modified file 'src/store_swapout.cc'
--- src/store_swapout.cc 2011-12-10 16:29:31 +0000
+++ src/store_swapout.cc 2012-01-10 09:48:22 +0000
@@ -171,101 +171,84 @@
if (anEntry->store_status == STORE_PENDING)
if (swapout_size < SM_PAGE_SIZE)
break;
if (swapout_size <= 0)
return;
} while (true);
}
/* This routine is called every time data is sent to the client side.
* It's overhead is therefor, significant.
*/
void
StoreEntry::swapOut()
{
if (!mem_obj)
return;
- if (!swapoutPossible())
+ // this flag may change so we must check even if we are swappingOut
+ if (EBIT_TEST(flags, ENTRY_ABORTED)) {
+ assert(EBIT_TEST(flags, RELEASE_REQUEST));
+ // StoreEntry::abort() already closed the swap out file, if any
+ // no trimming: data producer must stop production if ENTRY_ABORTED
return;
+ }
+
+ const bool weAreOrMayBeSwappingOut = swappingOut() || mayStartSwapOut();
+
+ trimMemory(weAreOrMayBeSwappingOut);
+
+ if (!weAreOrMayBeSwappingOut)
+ return; // nothing else to do
// Aborted entries have STORE_OK, but swapoutPossible rejects them. Thus,
// store_status == STORE_OK below means we got everything we wanted.
debugs(20, 7, HERE << "storeSwapOut: mem->inmem_lo = " << mem_obj->inmem_lo);
debugs(20, 7, HERE << "storeSwapOut: mem->endOffset() = " << mem_obj->endOffset());
debugs(20, 7, HERE << "storeSwapOut: swapout.queue_offset = " << mem_obj->swapout.queue_offset);
if (mem_obj->swapout.sio != NULL)
debugs(20, 7, "storeSwapOut: storeOffset() = " << mem_obj->swapout.sio->offset() );
- // buffered bytes we have not swapped out yet
- int64_t swapout_maxsize = mem_obj->endOffset() - mem_obj->swapout.queue_offset;
-
- assert(swapout_maxsize >= 0);
-
int64_t const lowest_offset = mem_obj->lowestMemReaderOffset();
debugs(20, 7, HERE << "storeSwapOut: lowest_offset = " << lowest_offset);
- // Check to see whether we're going to defer the swapout based upon size
- if (store_status != STORE_OK) {
- const int64_t expectedSize = mem_obj->expectedReplySize();
- const int64_t maxKnownSize = expectedSize < 0 ?
- swapout_maxsize : expectedSize;
- debugs(20, 7, HERE << "storeSwapOut: maxKnownSize= " << maxKnownSize);
-
- if (maxKnownSize < store_maxobjsize) {
- /*
- * NOTE: the store_maxobjsize here is the max of optional
- * max-size values from 'cache_dir' lines. It is not the
- * same as 'maximum_object_size'. By default, store_maxobjsize
- * will be set to -1. However, I am worried that this
- * deferance may consume a lot of memory in some cases.
- * Should we add an option to limit this memory consumption?
- */
- debugs(20, 5, "storeSwapOut: Deferring swapout start for " <<
- (store_maxobjsize - maxKnownSize) << " bytes");
- return;
- }
- }
-
-// TODO: it is better to trim as soon as we swap something out, not before
- trimMemory();
#if SIZEOF_OFF_T <= 4
if (mem_obj->endOffset() > 0x7FFF0000) {
debugs(20, 0, "WARNING: preventing off_t overflow for " << url());
abort();
return;
}
#endif
if (swap_status == SWAPOUT_WRITING)
assert(mem_obj->inmem_lo <= mem_obj->objectBytesOnDisk() );
- if (!swapOutAble())
- return;
-
+ // buffered bytes we have not swapped out yet
+ const int64_t swapout_maxsize = mem_obj->availableForSwapOut();
+ assert(swapout_maxsize >= 0);
debugs(20, 7, "storeSwapOut: swapout_size = " << swapout_maxsize);
if (swapout_maxsize == 0) { // swapped everything we got
if (store_status == STORE_OK) { // got everything we wanted
assert(mem_obj->object_sz >= 0);
swapOutFileClose(StoreIOState::wroteAll);
}
// else need more data to swap out
return;
}
if (store_status == STORE_PENDING) {
/* wait for a full block to write */
if (swapout_maxsize < SM_PAGE_SIZE)
return;
/*
* Wait until we are below the disk FD limit, only if the
* next server-side read won't be deferred.
@@ -357,59 +340,154 @@
e->swap_status = SWAPOUT_DONE;
e->store()->swappedOut(*e);
// XXX: For some Stores, it is pointless to re-check cachability here
// and it leads to double counts in store_check_cachable_hist. We need
// another way to signal a completed but failed swapout. Or, better,
// each Store should handle its own logging and LOG state setting.
if (e->checkCachable()) {
storeLog(STORE_LOG_SWAPOUT, e);
storeDirSwapLog(e, SWAP_LOG_ADD);
}
++statCounter.swap.outs;
}
debugs(20, 3, "storeSwapOutFileClosed: " << __FILE__ << ":" << __LINE__);
mem->swapout.sio = NULL;
e->unlock();
}
-/*
- * Is this entry a candidate for writing to disk?
- */
bool
-StoreEntry::swapOutAble() const
+StoreEntry::mayStartSwapOut()
{
dlink_node *node;
- if (mem_obj->swapout.sio != NULL)
+ // must be checked in the caller
+ assert(!EBIT_TEST(flags, ENTRY_ABORTED));
+
+ if (!Config.cacheSwap.n_configured)
+ return false;
+
+ assert(mem_obj);
+ MemObject::SwapOut::Decision &decision = mem_obj->swapout.decision;
+
+ // if we decided that swapout is not possible, do not repeat same checks
+ if (decision == MemObject::SwapOut::swImpossible) {
+ debugs(20, 3, HERE << " already rejected");
+ return false;
+ }
+
+ // if we decided that swapout is possible, do not repeat same checks
+ if (decision == MemObject::SwapOut::swPossible) {
+ debugs(20, 3, HERE << "already allowed");
return true;
+ }
- if (mem_obj->inmem_lo > 0)
+ // if we are swapping out already, do not repeat same checks
+ if (swap_status != SWAPOUT_NONE) {
+ debugs(20, 3, HERE << " already started");
+ decision = MemObject::SwapOut::swPossible;
+ return true;
+ }
+
+ if (!checkCachable()) {
+ debugs(20, 3, HERE << "not cachable");
+ decision = MemObject::SwapOut::swImpossible;
return false;
+ }
+
+ if (EBIT_TEST(flags, ENTRY_SPECIAL)) {
+ debugs(20, 3, HERE << url() << " SPECIAL");
+ decision = MemObject::SwapOut::swImpossible;
+ return false;
+ }
+
+ // check cache_dir max-size limit if all cache_dirs have it
+ if (store_maxobjsize >= 0) {
+ // TODO: add estimated store metadata size to be conservative
+
+ // use guaranteed maximum if it is known
+ const int64_t expectedEnd = mem_obj->expectedReplySize();
+ debugs(20, 7, HERE << "expectedEnd = " << expectedEnd);
+ if (expectedEnd > store_maxobjsize) {
+ debugs(20, 3, HERE << "will not fit: " << expectedEnd <<
+ " > " << store_maxobjsize);
+ decision = MemObject::SwapOut::swImpossible;
+ return false; // known to outgrow the limit eventually
+ }
+
+ // use current minimum (always known)
+ const int64_t currentEnd = mem_obj->endOffset();
+ if (currentEnd > store_maxobjsize) {
+ debugs(20, 3, HERE << "does not fit: " << currentEnd <<
+ " > " << store_maxobjsize);
+ decision = MemObject::SwapOut::swImpossible;
+ return false; // already does not fit and may only get bigger
+ }
+
+ // prevent default swPossible answer for yet unknown length
+ if (expectedEnd < 0) {
+ debugs(20, 3, HERE << "wait for more info: " <<
+ store_maxobjsize);
+ return false; // may fit later, but will be rejected now
+ }
+
+ if (store_status != STORE_OK) {
+ const int64_t maxKnownSize = expectedEnd < 0 ?
+ mem_obj->availableForSwapOut() : expectedEnd;
+ debugs(20, 7, HERE << "maxKnownSize= " << maxKnownSize);
+ if (maxKnownSize < store_maxobjsize) {
+ /*
+ * NOTE: the store_maxobjsize here is the max of optional
+ * max-size values from 'cache_dir' lines. It is not the
+ * same as 'maximum_object_size'. By default, store_maxobjsize
+ * will be set to -1. However, I am worried that this
+ * deferance may consume a lot of memory in some cases.
+ * Should we add an option to limit this memory consumption?
+ */
+ debugs(20, 5, HERE << "Deferring swapout start for " <<
+ (store_maxobjsize - maxKnownSize) << " bytes");
+ return false;
+ }
+ }
+ }
+
+ if (mem_obj->inmem_lo > 0) {
+ debugs(20, 3, "storeSwapOut: (inmem_lo > 0) imem_lo:" << mem_obj->inmem_lo);
+ decision = MemObject::SwapOut::swImpossible;
+ return false;
+ }
/*
* If there are DISK clients, we must write to disk
* even if its not cachable
* RBC: Surely we should not create disk client on non cacheable objects?
* therefore this should be an assert?
* RBC 20030708: We can use disk to avoid mem races, so this shouldn't be
* an assert.
+ *
+ * XXX: Not clear what "mem races" the above refers to, especially when
+ * dealing with non-cachable objects that cannot have multiple clients.
+ *
+ * XXX: If STORE_DISK_CLIENT needs SwapOut::swPossible, we have to check
+ * for that flag earlier, but forcing swapping may contradict max-size or
+ * other swapability restrictions. Change storeClientType() and/or its
+ * callers to take swap-in availability into account.
*/
for (node = mem_obj->clients.head; node; node = node->next) {
- if (((store_client *) node->data)->getType() == STORE_DISK_CLIENT)
+ if (((store_client *) node->data)->getType() == STORE_DISK_CLIENT) {
+ debugs(20, 3, HERE << "DISK client found");
+ decision = MemObject::SwapOut::swPossible;
return true;
+ }
}
- /* Don't pollute the disk with icons and other special entries */
- if (EBIT_TEST(flags, ENTRY_SPECIAL))
- return false;
-
- if (!EBIT_TEST(flags, ENTRY_CACHABLE))
- return false;
-
- if (!mem_obj->isContiguous())
+ if (!mem_obj->isContiguous()) {
+ debugs(20, 3, "storeSwapOut: not Contiguous");
+ decision = MemObject::SwapOut::swImpossible;
return false;
+ }
+ decision = MemObject::SwapOut::swPossible;
return true;
}
=== modified file 'src/tests/stub_MemObject.cc'
--- src/tests/stub_MemObject.cc 2011-10-14 16:21:48 +0000
+++ src/tests/stub_MemObject.cc 2012-01-07 10:29:33 +0000
@@ -189,20 +189,27 @@
}
void
MemObject::resetUrls(char const*, char const*)
{
fatal ("MemObject.cc required.");
}
void
MemObject::markEndOfReplyHeaders()
{
fatal ("MemObject.cc required.");
}
size_t
MemObject::inUseCount()
{
fatal ("MemObject.cc required.");
return 0;
}
+
+int64_t
+MemObject::availableForSwapOut() const
+{
+ fatal ("MemObject.cc required.");
+ return 0;
+}
=== modified file 'src/tests/stub_store.cc'
--- src/tests/stub_store.cc 2011-08-10 15:54:51 +0000
+++ src/tests/stub_store.cc 2012-01-07 10:22:54 +0000
@@ -9,56 +9,55 @@
#include "RemovalPolicy.h"
RemovalPolicy * createRemovalPolicy(RemovalPolicySettings * settings) STUB_RETVAL(NULL)
#include "Store.h"
StorePointer Store::CurrentRoot = NULL;
StoreIoStats store_io_stats;
bool StoreEntry::checkDeferRead(int fd) const STUB_RETVAL(false)
const char *StoreEntry::getMD5Text() const STUB_RETVAL(NULL)
StoreEntry::StoreEntry() STUB
StoreEntry::StoreEntry(const char *url, const char *log_url) STUB
StoreEntry::~StoreEntry() STUB
HttpReply const *StoreEntry::getReply() const STUB_RETVAL(NULL)
void StoreEntry::write(StoreIOBuffer) STUB
bool StoreEntry::isAccepting() const STUB_RETVAL(false)
size_t StoreEntry::bytesWanted(Range<size_t> const) const STUB_RETVAL(0)
void StoreEntry::complete() STUB
store_client_t StoreEntry::storeClientType() const STUB_RETVAL(STORE_NON_CLIENT)
char const *StoreEntry::getSerialisedMetaData() STUB_RETVAL(NULL)
void StoreEntry::replaceHttpReply(HttpReply *, bool andStartWriting) STUB
-bool StoreEntry::swapoutPossible() STUB_RETVAL(false)
-void StoreEntry::trimMemory() STUB
+bool StoreEntry::mayStartSwapOut() STUB_RETVAL(false)
+void StoreEntry::trimMemory(const bool preserveSwappable) STUB
void StoreEntry::abort() STUB
void StoreEntry::unlink() STUB
void StoreEntry::makePublic() STUB
void StoreEntry::makePrivate() STUB
void StoreEntry::setPublicKey() STUB
void StoreEntry::setPrivateKey() STUB
void StoreEntry::expireNow() STUB
void StoreEntry::releaseRequest() STUB
void StoreEntry::negativeCache() STUB
void StoreEntry::cacheNegatively() STUB
void StoreEntry::invokeHandlers() STUB
void StoreEntry::purgeMem() STUB
void StoreEntry::swapOut() STUB
-bool StoreEntry::swapOutAble() const STUB_RETVAL(false)
void StoreEntry::swapOutFileClose(int how) STUB
const char *StoreEntry::url() const STUB_RETVAL(NULL)
int StoreEntry::checkCachable() STUB_RETVAL(0)
int StoreEntry::checkNegativeHit() const STUB_RETVAL(0)
int StoreEntry::locked() const STUB_RETVAL(0)
int StoreEntry::validToSend() const STUB_RETVAL(0)
bool StoreEntry::memoryCachable() const STUB_RETVAL(false)
void StoreEntry::createMemObject(const char *, const char *) STUB
void StoreEntry::hideMemObject() STUB
void StoreEntry::dump(int debug_lvl) const STUB
void StoreEntry::hashDelete() STUB
void StoreEntry::hashInsert(const cache_key *) STUB
void StoreEntry::registerAbort(STABH * cb, void *) STUB
void StoreEntry::reset() STUB
void StoreEntry::setMemStatus(mem_status_t) STUB
void StoreEntry::timestampsSet() STUB
void StoreEntry::unregisterAbort() STUB
void StoreEntry::destroyMemObject() STUB
int StoreEntry::checkTooSmall() STUB_RETVAL(0)
void StoreEntry::delayAwareRead(const Comm::ConnectionPointer&, char *buf, int len, AsyncCall::Pointer callback) STUB