From: Alex Rousskov Date: Tue, 25 Jun 2013 19:19:28 +0000 (-0600) Subject: Do not broadcast changes if there are no remote readers. X-Git-Tag: SQUID_3_5_0_1~444^2~46 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=d366a7fab6835a63ad6917f661251878b56ce47b;p=thirdparty%2Fsquid.git Do not broadcast changes if there are no remote readers. New/future readers should anchor themselves to the cache in order to get the earlier updates they missed. --- diff --git a/src/CollapsedForwarding.cc b/src/CollapsedForwarding.cc index 629327d546..345f1b340f 100644 --- a/src/CollapsedForwarding.cc +++ b/src/CollapsedForwarding.cc @@ -8,6 +8,7 @@ #include "ipc/Messages.h" #include "ipc/Port.h" #include "ipc/TypedMsgHdr.h" +#include "MemObject.h" #include "CollapsedForwarding.h" #include "globals.h" #include "SquidConfig.h" @@ -50,6 +51,12 @@ CollapsedForwarding::Broadcast(const StoreEntry &e) if (!queue.get()) return; + if (!e.mem_obj || e.mem_obj->xitTable.index < 0 || + !Store::Root().transientReaders(e)) { + debugs(17, 7, "not broadcasting " << e << " changes to nobody"); + return; + } + CollapsedForwardingMsg msg; msg.sender = KidIdentifier; memcpy(msg.key, e.key, sizeof(msg.key)); diff --git a/src/Store.h b/src/Store.h index d2131fe388..e689680f3d 100644 --- a/src/Store.h +++ b/src/Store.h @@ -392,6 +392,11 @@ public: /// calls Root().transients->abandon() if transients are tracked virtual void transientsAbandon(StoreEntry &e) {} + // XXX: This method belongs to Store::Root/StoreController, but it is here + // to avoid casting Root() to StoreController until Root() API is fixed. + /// number of the transient entry readers some time ago + virtual int transientReaders(const StoreEntry &e) const { return 0; } + // XXX: This method belongs to Store::Root/StoreController, but it is here // to avoid casting Root() to StoreController until Root() API is fixed. /// disassociates the entry from the intransit table diff --git a/src/SwapDir.h b/src/SwapDir.h index fc2ed8f749..68fe0beeb2 100644 --- a/src/SwapDir.h +++ b/src/SwapDir.h @@ -64,6 +64,7 @@ public: virtual void handleIdleEntry(StoreEntry &e); virtual void transientsCompleteWriting(StoreEntry &e); virtual void transientsAbandon(StoreEntry &e); + virtual int transientReaders(const StoreEntry &e) const; virtual void transientsDisconnect(MemObject &mem_obj); virtual void memoryOut(StoreEntry &e, const bool preserveSwappable); virtual void memoryUnlink(StoreEntry &e); diff --git a/src/Transients.cc b/src/Transients.cc index 340f2ee599..c6967b8409 100644 --- a/src/Transients.cc +++ b/src/Transients.cc @@ -306,6 +306,16 @@ Transients::completeWriting(const StoreEntry &e) } } +int +Transients::readers(const StoreEntry &e) const +{ + if (e.mem_obj && e.mem_obj->xitTable.index >= 0) { + assert(map); + return map->peekAtEntry(e.mem_obj->xitTable.index).lock.readers; + } + return 0; +} + void Transients::disconnect(MemObject &mem_obj) { diff --git a/src/Transients.h b/src/Transients.h index 12d784d2b5..cbe2138f6c 100644 --- a/src/Transients.h +++ b/src/Transients.h @@ -36,6 +36,9 @@ public: /// whether an in-transit entry is now abandoned by its writer bool abandoned(const StoreEntry &e) const; + /// number of entry readers some time ago + int readers(const StoreEntry &e) const; + /// the caller is done writing or reading this entry void disconnect(MemObject &mem_obj); diff --git a/src/ipc/StoreMap.cc b/src/ipc/StoreMap.cc index 7c602fb1c7..db26250d0f 100644 --- a/src/ipc/StoreMap.cc +++ b/src/ipc/StoreMap.cc @@ -212,6 +212,13 @@ Ipc::StoreMap::peekAtReader(const sfileno fileno) const return NULL; } +const Ipc::StoreMap::Anchor & +Ipc::StoreMap::peekAtEntry(const sfileno fileno) const +{ + assert(valid(fileno)); + return shared->slots[fileno].anchor; +} + void Ipc::StoreMap::freeEntry(const sfileno fileno) { diff --git a/src/ipc/StoreMap.h b/src/ipc/StoreMap.h index ddcf88afb9..c1edb2378b 100644 --- a/src/ipc/StoreMap.h +++ b/src/ipc/StoreMap.h @@ -152,6 +152,9 @@ public: /// only works on locked entries; returns nil unless the slice is readable const Anchor *peekAtReader(const sfileno fileno) const; + /// only works on locked entries; returns the corresponding Anchor + const Anchor &peekAtEntry(const sfileno fileno) const; + /// free the entry if possible or mark it as waiting to be freed if not void freeEntry(const sfileno fileno); /// free the entry if possible or mark it as waiting to be freed if not diff --git a/src/store_dir.cc b/src/store_dir.cc index f1197c2ca3..6584f360dc 100644 --- a/src/store_dir.cc +++ b/src/store_dir.cc @@ -918,6 +918,13 @@ StoreController::transientsCompleteWriting(StoreEntry &e) } } +int +StoreController::transientReaders(const StoreEntry &e) const +{ + return (transients && e.mem_obj && e.mem_obj->xitTable.index >= 0) ? + transients->readers(e) : 0; +} + void StoreController::transientsDisconnect(MemObject &mem_obj) {