]> git.ipfire.org Git - thirdparty/squid.git/commitdiff
Made Rock::Rebuild an AsyncJob because it is.
authorAlex Rousskov <rousskov@measurement-factory.com>
Mon, 7 Feb 2011 17:59:28 +0000 (10:59 -0700)
committerAlex Rousskov <rousskov@measurement-factory.com>
Mon, 7 Feb 2011 17:59:28 +0000 (10:59 -0700)
Increment StoreController::store_dirs_rebuilding early, when SwapDir is
created and before the disk db file is opened and the actual rebuild starts.
Otherwise, if one SwapDir finishes rebuild before others start,
storeRebuildComplete() will see StoreController::store_dirs_rebuilding equal
to one, and think the rebuild is over.

This was not a problem for cache_dirs using blocking I/O because they either
did not try to open some file at SwapDir::init() time or did so synchronously,
resulting in "immediate" StoreController::store_dirs_rebuilding increment from
Store init loop point of view.

src/fs/rock/RockRebuild.cc
src/fs/rock/RockRebuild.h
src/fs/rock/RockSwapDir.cc

index 6778c12b4ab46fab3aeeef03a489fca164aec7b8..b28bee415b3de5912ab570655400adfa780fd3a7 100644 (file)
@@ -9,7 +9,7 @@
 
 CBDATA_NAMESPACED_CLASS_INIT(Rock, Rebuild);
 
-Rock::Rebuild::Rebuild(SwapDir *dir):
+Rock::Rebuild::Rebuild(SwapDir *dir): AsyncJob("Rock::Rebuild"),
     sd(dir),
     dbSize(0),
     dbEntrySize(0),
@@ -34,6 +34,14 @@ Rock::Rebuild::~Rebuild()
 /// prepares and initiates entry loading sequence
 void
 Rock::Rebuild::start() {
+    // in SMP mode, only the disker is responsible for populating the map
+    if (UsingSmp() && !IamDiskProcess()) {
+        debugs(47, 2, "Non-disker skips rebuilding of cache_dir #" <<
+           sd->index << " from " << sd->filePath);
+        mustStop("non-disker");
+        return;
+    }
+
     debugs(47, DBG_IMPORTANT, "Loading cache_dir #" << sd->index <<
            " from " << sd->filePath);
 
@@ -51,20 +59,25 @@ Rock::Rebuild::start() {
     checkpoint();
 }
 
-/// quits if done; otherwise continues after a pause
+/// continues after a pause if not done
 void
 Rock::Rebuild::checkpoint()
 {
-    if (dbOffset < dbSize)
+    if (!done())
         eventAdd("Rock::Rebuild", Rock::Rebuild::Steps, this, 0.01, 1, true);
-    else
-        complete();
+}
+
+bool
+Rock::Rebuild::doneAll() const
+{
+    return dbOffset >= dbSize && AsyncJob::doneAll();
 }
 
 void
 Rock::Rebuild::Steps(void *data)
 {
-    static_cast<Rebuild*>(data)->steps();
+    // use async call to enable job call protection that time events lack
+    CallJobHere(47, 5, static_cast<Rebuild*>(data), Rock::Rebuild, steps);
 }
 
 void
@@ -116,12 +129,11 @@ Rock::Rebuild::doOneEntry() {
 }
 
 void
-Rock::Rebuild::complete() {
-    debugs(47,3, HERE << sd->index);
-    close(fd);
-    StoreController::store_dirs_rebuilding--;
+Rock::Rebuild::swanSong() {
+    debugs(47,3, HERE << "cache_dir #" << sd->index << " rebuild level: " <<
+        StoreController::store_dirs_rebuilding);
+    --StoreController::store_dirs_rebuilding;
     storeRebuildComplete(&counts);
-    delete this; // same as cbdataFree
 }
 
 void
index 1f7a9fe991477b0f59f104b3adec5e1c51d64bcd..f9bd43ab2a116aa0562a5468fe4ab6fd4e080c39 100644 (file)
@@ -2,6 +2,7 @@
 #define SQUID_FS_ROCK_REBUILD_H
 
 #include "config.h"
+#include "base/AsyncJob.h"
 #include "structs.h"
 
 namespace Rock {
@@ -10,19 +11,21 @@ class SwapDir;
 
 /// \ingroup Rock
 /// manages store rebuild process: loading meta information from db on disk
-class Rebuild {
+class Rebuild: public AsyncJob {
 public:
     Rebuild(SwapDir *dir);
     ~Rebuild();
-    void start();
 
-private:
-    CBDATA_CLASS2(Rebuild);
+protected:
+    /* AsyncJob API */
+    virtual void start();
+    virtual bool doneAll() const;
+    virtual void swanSong();
 
+private:
     void checkpoint();
     void steps();
     void doOneEntry();
-    void complete();
     void failure(const char *msg, int errNo = 0);
 
     SwapDir *sd;
@@ -38,6 +41,8 @@ private:
     struct _store_rebuild_data counts;
 
     static void Steps(void *data);
+
+    CBDATA_CLASS2(Rebuild);
 };
 
 } // namespace Rock
index 16ea34c4746309f4629be63ddadb44457451e102..f13187556623cb3fb8cfb261637864e6c098f8d4 100644 (file)
@@ -192,6 +192,11 @@ Rock::SwapDir::init()
 
     theFile = io->newFile(filePath);
     theFile->open(O_RDWR, 0644, this);
+
+    // Increment early. Otherwise, if one SwapDir finishes rebuild before
+    // others start, storeRebuildComplete() will think the rebuild is over!
+    // TODO: move store_dirs_rebuilding hack to store modules that need it.
+    ++StoreController::store_dirs_rebuilding;
 }
 
 bool
@@ -288,13 +293,8 @@ Rock::SwapDir::validateOptions()
 
 void
 Rock::SwapDir::rebuild() {
-    // in SMP mode, only the disker is responsible for populating the map
-    if (UsingSmp() && !IamDiskProcess())
-        return;
-
-    ++StoreController::store_dirs_rebuilding;
-    Rebuild *r = new Rebuild(this);
-    r->start(); // will delete self when done
+    //++StoreController::store_dirs_rebuilding; // see Rock::SwapDir::init()
+    AsyncJob::Start(new Rebuild(this));
 }
 
 /* Add a new object to the cache with empty memory copy and pointer to disk