]> git.ipfire.org Git - thirdparty/squid.git/commitdiff
Provide a method to abnormally terminate slot writing.
authorAlex Rousskov <rousskov@measurement-factory.com>
Fri, 4 Feb 2011 18:18:12 +0000 (11:18 -0700)
committerAlex Rousskov <rousskov@measurement-factory.com>
Fri, 4 Feb 2011 18:18:12 +0000 (11:18 -0700)
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.

src/fs/rock/RockDirMap.cc
src/fs/rock/RockDirMap.h

index 63ef20cfa8946c9e0a18891d159c19ec604e17d4..b014bdce5fe63e6f435cf458094a6a0c4571250f 100644 (file)
@@ -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();
index e85ee3df89136606c53e9f97d3a27f91a215da93..586800b63e63d1d32f25c652939405c268d2ebcb 100644 (file)
@@ -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);