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),
/// 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);
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
}
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
#define SQUID_FS_ROCK_REBUILD_H
#include "config.h"
+#include "base/AsyncJob.h"
#include "structs.h"
namespace Rock {
/// \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;
struct _store_rebuild_data counts;
static void Steps(void *data);
+
+ CBDATA_CLASS2(Rebuild);
};
} // namespace Rock
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
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