From: Alex Rousskov Date: Fri, 4 Feb 2011 18:18:12 +0000 (-0700) Subject: Provide a method to abnormally terminate slot writing. X-Git-Tag: take02~14 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=db4548675106f820673bc41350fda66558f51a17;p=thirdparty%2Fsquid.git Provide a method to abnormally terminate slot writing. It efficiently resets the slot while the slot is still exclusively locked. Polished slot cleaning code to be able to reuse it more. Added comments. Fixed switchExclusiveToSharedLock() definition profile. --- diff --git a/src/fs/rock/RockDirMap.cc b/src/fs/rock/RockDirMap.cc index 63ef20cfa8..b014bdce5f 100644 --- a/src/fs/rock/RockDirMap.cc +++ b/src/fs/rock/RockDirMap.cc @@ -68,6 +68,17 @@ Rock::DirMap::closeForWriting(const sfileno fileno) s.switchExclusiveToSharedLock(); } +void +Rock::DirMap::abortWriting(const sfileno fileno) +{ + debugs(79, 5, HERE << " abort writing slot at " << fileno << + " in map [" << path << ']'); + assert(valid(fileno)); + Slot &s = shared->slots[fileno]; + assert(s.state == Slot::Writeable); + freeLocked(s); +} + bool Rock::DirMap::putAt(const StoreEntry &e, const sfileno fileno) { @@ -214,25 +225,32 @@ Rock::DirMap::slot(const cache_key *const key) return shared->slots[slotIdx(key)]; } +/// frees the slot if (b) it is waiting to be freed and (a) we can lock it void Rock::DirMap::freeIfNeeded(Slot &s) { - const int idx = &s - shared->slots; if (s.exclusiveLock()) { - if (s.waitingToBeFreed.swap_if(true, false)) { - memset(s.key_, 0, sizeof(s.key_)); - memset(&s.seBasics, 0, sizeof(s.seBasics)); - s.state = Slot::Empty; + if (s.waitingToBeFreed == true) + freeLocked(s); + else s.releaseExclusiveLock(); - --shared->count; - debugs(79, 5, HERE << " freed slot at " << idx << " in map [" << - path << ']'); - } else { - s.releaseExclusiveLock(); - } } } +/// unconditionally frees the already exclusively locked slot and releases lock +void +Rock::DirMap::freeLocked(Slot &s) +{ + memset(s.key_, 0, sizeof(s.key_)); + memset(&s.seBasics, 0, sizeof(s.seBasics)); + s.waitingToBeFreed = false; + s.state = Slot::Empty; + s.releaseExclusiveLock(); + --shared->count; + debugs(79, 5, HERE << " freed slot at " << (&s - shared->slots) << + " in map [" << path << ']'); +} + String Rock::DirMap::sharedMemoryName() { @@ -307,7 +325,7 @@ Rock::Slot::releaseExclusiveLock() } void -Rock::Slot::switchExclusiveToSharedLock() const +Rock::Slot::switchExclusiveToSharedLock() { ++readers; // must be done before we release exclusive control releaseExclusiveLock(); diff --git a/src/fs/rock/RockDirMap.h b/src/fs/rock/RockDirMap.h index e85ee3df89..586800b63e 100644 --- a/src/fs/rock/RockDirMap.h +++ b/src/fs/rock/RockDirMap.h @@ -60,10 +60,12 @@ public: DirMap(const char *const aPath, const int limit); ///< create a new shared DirMap DirMap(const char *const aPath); ///< open an existing shared DirMap - /// finds space for writing a new entry or returns nil + /// finds/reservers space for writing a new entry or returns nil StoreEntryBasics *openForWriting(const cache_key *const key, sfileno &fileno); - /// finish writing a new entry, leaves the entry opened for reading + /// successfully finish writing the entry, leaving it opened for reading void closeForWriting(const sfileno fileno); + /// terminate writing the entry, freeing its slot for others to use + void abortWriting(const sfileno fileno); /// stores entry info at the requested slot or returns false bool putAt(const StoreEntry &e, const sfileno fileno); @@ -99,6 +101,7 @@ private: Slot &slot(const cache_key *const key); const StoreEntryBasics *openForReading(Slot &s); void freeIfNeeded(Slot &s); + void freeLocked(Slot &s); String sharedMemoryName(); static int SharedSize(const int limit);