]>
git.ipfire.org Git - thirdparty/squid.git/blob - src/fs/rock/RockRebuild.cc
4 * DEBUG: section 79 Disk IO Routines
8 #include "fs/rock/RockRebuild.h"
9 #include "fs/rock/RockSwapDir.h"
10 #include "fs/rock/RockDbCell.h"
14 #include "SquidTime.h"
20 CBDATA_NAMESPACED_CLASS_INIT(Rock
, Rebuild
);
22 Rock::Rebuild::Rebuild(SwapDir
*dir
): AsyncJob("Rock::Rebuild"),
32 memset(&counts
, 0, sizeof(counts
));
33 dbSize
= sd
->diskOffsetLimit(); // we do not care about the trailer waste
34 dbEntrySize
= sd
->max_objsize
;
35 dbEntryLimit
= sd
->entryLimit();
38 Rock::Rebuild::~Rebuild()
44 /// prepares and initiates entry loading sequence
46 Rock::Rebuild::start()
48 // in SMP mode, only the disker is responsible for populating the map
49 if (UsingSmp() && !IamDiskProcess()) {
50 debugs(47, 2, "Non-disker skips rebuilding of cache_dir #" <<
51 sd
->index
<< " from " << sd
->filePath
);
52 mustStop("non-disker");
56 debugs(47, DBG_IMPORTANT
, "Loading cache_dir #" << sd
->index
<<
57 " from " << sd
->filePath
);
59 fd
= file_open(sd
->filePath
, O_RDONLY
| O_BINARY
);
61 failure("cannot open db", errno
);
63 char buf
[SwapDir::HeaderSize
];
64 if (read(fd
, buf
, sizeof(buf
)) != SwapDir::HeaderSize
)
65 failure("cannot read db header", errno
);
67 dbOffset
= SwapDir::HeaderSize
;
73 /// continues after a pause if not done
75 Rock::Rebuild::checkpoint()
78 eventAdd("Rock::Rebuild", Rock::Rebuild::Steps
, this, 0.01, 1, true);
82 Rock::Rebuild::doneAll() const
84 return dbOffset
>= dbSize
&& AsyncJob::doneAll();
88 Rock::Rebuild::Steps(void *data
)
90 // use async call to enable job call protection that time events lack
91 CallJobHere(47, 5, static_cast<Rebuild
*>(data
), Rock::Rebuild
, steps
);
95 Rock::Rebuild::steps()
97 debugs(47,5, HERE
<< sd
->index
<< " filen " << filen
<< " at " <<
98 dbOffset
<< " <= " << dbSize
);
100 // Balance our desire to maximize the number of entries processed at once
101 // (and, hence, minimize overheads and total rebuild time) with a
102 // requirement to also process Coordinator events, disk I/Os, etc.
103 const int maxSpentMsec
= 50; // keep small: most RAM I/Os are under 1ms
104 const timeval loopStart
= current_time
;
107 while (loaded
< dbEntryLimit
&& dbOffset
< dbSize
) {
109 dbOffset
+= dbEntrySize
;
113 if (counts
.scancount
% 1000 == 0)
114 storeRebuildProgress(sd
->index
, dbEntryLimit
, counts
.scancount
);
116 if (opt_foreground_rebuild
)
117 continue; // skip "few entries at a time" check below
120 const double elapsedMsec
= tvSubMsec(loopStart
, current_time
);
121 if (elapsedMsec
> maxSpentMsec
|| elapsedMsec
< 0) {
122 debugs(47, 5, HERE
<< "pausing after " << loaded
<< " entries in " <<
123 elapsedMsec
<< "ms; " << (elapsedMsec
/loaded
) << "ms per entry");
132 Rock::Rebuild::doOneEntry()
134 debugs(47,5, HERE
<< sd
->index
<< " filen " << filen
<< " at " <<
135 dbOffset
<< " <= " << dbSize
);
139 if (lseek(fd
, dbOffset
, SEEK_SET
) < 0)
140 failure("cannot seek to db entry", errno
);
143 buf
.init(SM_PAGE_SIZE
, SM_PAGE_SIZE
);
145 if (!storeRebuildLoadEntry(fd
, sd
->index
, buf
, counts
))
150 if (buf
.contentSize() < static_cast<mb_size_t
>(sizeof(header
))) {
151 debugs(47, DBG_IMPORTANT
, "WARNING: cache_dir[" << sd
->index
<< "]: " <<
152 "Ignoring truncated cache entry meta data at " << dbOffset
);
156 memcpy(&header
, buf
.content(), sizeof(header
));
158 if (!header
.sane()) {
159 debugs(47, DBG_IMPORTANT
, "WARNING: cache_dir[" << sd
->index
<< "]: " <<
160 "Ignoring malformed cache entry meta data at " << dbOffset
);
164 buf
.consume(sizeof(header
)); // optimize to avoid memmove()
166 cache_key key
[SQUID_MD5_DIGEST_LENGTH
];
168 if (!storeRebuildParseEntry(buf
, loadedE
, key
, counts
, header
.payloadSize
)) {
170 if (loadedE
.swap_filen
> 0 || loadedE
.swap_file_sz
> 0) {
172 //sd->unlink(filen); leave garbage on disk, it should not hurt
177 assert(loadedE
.swap_filen
< dbEntryLimit
);
178 if (!storeRebuildKeepEntry(loadedE
, key
, counts
))
184 sd
->addEntry(filen
, header
, loadedE
);
188 Rock::Rebuild::swanSong()
190 debugs(47,3, HERE
<< "cache_dir #" << sd
->index
<< " rebuild level: " <<
191 StoreController::store_dirs_rebuilding
);
192 --StoreController::store_dirs_rebuilding
;
193 storeRebuildComplete(&counts
);
197 Rock::Rebuild::failure(const char *msg
, int errNo
)
199 debugs(47,5, HERE
<< sd
->index
<< " filen " << filen
<< " at " <<
200 dbOffset
<< " <= " << dbSize
);
203 debugs(47, DBG_CRITICAL
, "ERROR: Rock cache_dir rebuild failure: " << xstrerr(errNo
));
204 debugs(47, DBG_CRITICAL
, "Do you need to run 'squid -z' to initialize storage?");
207 fatalf("Rock cache_dir[%d] rebuild of %s failed: %s.",
208 sd
->index
, sd
->filePath
, msg
);