]>
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"
11 #include "SquidTime.h"
13 CBDATA_NAMESPACED_CLASS_INIT(Rock
, Rebuild
);
15 Rock::Rebuild::Rebuild(SwapDir
*dir
): AsyncJob("Rock::Rebuild"),
25 memset(&counts
, 0, sizeof(counts
));
26 dbSize
= sd
->diskOffsetLimit(); // we do not care about the trailer waste
27 dbEntrySize
= sd
->max_objsize
;
28 dbEntryLimit
= sd
->entryLimit();
31 Rock::Rebuild::~Rebuild()
37 /// prepares and initiates entry loading sequence
39 Rock::Rebuild::start()
41 // in SMP mode, only the disker is responsible for populating the map
42 if (UsingSmp() && !IamDiskProcess()) {
43 debugs(47, 2, "Non-disker skips rebuilding of cache_dir #" <<
44 sd
->index
<< " from " << sd
->filePath
);
45 mustStop("non-disker");
49 debugs(47, DBG_IMPORTANT
, "Loading cache_dir #" << sd
->index
<<
50 " from " << sd
->filePath
);
52 fd
= file_open(sd
->filePath
, O_RDONLY
| O_BINARY
);
54 failure("cannot open db", errno
);
56 char buf
[SwapDir::HeaderSize
];
57 if (read(fd
, buf
, sizeof(buf
)) != SwapDir::HeaderSize
)
58 failure("cannot read db header", errno
);
60 dbOffset
= SwapDir::HeaderSize
;
66 /// continues after a pause if not done
68 Rock::Rebuild::checkpoint()
71 eventAdd("Rock::Rebuild", Rock::Rebuild::Steps
, this, 0.01, 1, true);
75 Rock::Rebuild::doneAll() const
77 return dbOffset
>= dbSize
&& AsyncJob::doneAll();
81 Rock::Rebuild::Steps(void *data
)
83 // use async call to enable job call protection that time events lack
84 CallJobHere(47, 5, static_cast<Rebuild
*>(data
), Rock::Rebuild
, steps
);
88 Rock::Rebuild::steps()
90 debugs(47,5, HERE
<< sd
->index
<< " filen " << filen
<< " at " <<
91 dbOffset
<< " <= " << dbSize
);
93 // Balance our desire to maximize the number of entries processed at once
94 // (and, hence, minimize overheads and total rebuild time) with a
95 // requirement to also process Coordinator events, disk I/Os, etc.
96 const int maxSpentMsec
= 50; // keep small: most RAM I/Os are under 1ms
97 const timeval loopStart
= current_time
;
100 while (loaded
< dbEntryLimit
&& dbOffset
< dbSize
) {
102 dbOffset
+= dbEntrySize
;
106 if (counts
.scancount
% 1000 == 0)
107 storeRebuildProgress(sd
->index
, dbEntryLimit
, counts
.scancount
);
109 if (opt_foreground_rebuild
)
110 continue; // skip "few entries at a time" check below
113 const double elapsedMsec
= tvSubMsec(loopStart
, current_time
);
114 if (elapsedMsec
> maxSpentMsec
|| elapsedMsec
< 0) {
115 debugs(47, 5, HERE
<< "pausing after " << loaded
<< " entries in " <<
116 elapsedMsec
<< "ms; " << (elapsedMsec
/loaded
) << "ms per entry");
125 Rock::Rebuild::doOneEntry()
127 debugs(47,5, HERE
<< sd
->index
<< " filen " << filen
<< " at " <<
128 dbOffset
<< " <= " << dbSize
);
132 if (lseek(fd
, dbOffset
, SEEK_SET
) < 0)
133 failure("cannot seek to db entry", errno
);
136 buf
.init(SM_PAGE_SIZE
, SM_PAGE_SIZE
);
138 if (!storeRebuildLoadEntry(fd
, sd
->index
, buf
, counts
))
143 if (buf
.contentSize() < static_cast<mb_size_t
>(sizeof(header
))) {
144 debugs(47, DBG_IMPORTANT
, "WARNING: cache_dir[" << sd
->index
<< "]: " <<
145 "Ignoring truncated cache entry meta data at " << dbOffset
);
149 memcpy(&header
, buf
.content(), sizeof(header
));
151 if (!header
.sane()) {
152 debugs(47, DBG_IMPORTANT
, "WARNING: cache_dir[" << sd
->index
<< "]: " <<
153 "Ignoring malformed cache entry meta data at " << dbOffset
);
157 buf
.consume(sizeof(header
)); // optimize to avoid memmove()
159 cache_key key
[SQUID_MD5_DIGEST_LENGTH
];
161 if (!storeRebuildParseEntry(buf
, loadedE
, key
, counts
, header
.payloadSize
)) {
163 if (loadedE
.swap_filen
> 0 || loadedE
.swap_file_sz
> 0) {
165 //sd->unlink(filen); leave garbage on disk, it should not hurt
170 assert(loadedE
.swap_filen
< dbEntryLimit
);
171 if (!storeRebuildKeepEntry(loadedE
, key
, counts
))
177 sd
->addEntry(filen
, header
, loadedE
);
181 Rock::Rebuild::swanSong()
183 debugs(47,3, HERE
<< "cache_dir #" << sd
->index
<< " rebuild level: " <<
184 StoreController::store_dirs_rebuilding
);
185 --StoreController::store_dirs_rebuilding
;
186 storeRebuildComplete(&counts
);
190 Rock::Rebuild::failure(const char *msg
, int errNo
)
192 debugs(47,5, HERE
<< sd
->index
<< " filen " << filen
<< " at " <<
193 dbOffset
<< " <= " << dbSize
);
196 debugs(47, DBG_CRITICAL
, "ERROR: Rock cache_dir rebuild failure: " << xstrerr(errNo
));
197 debugs(47, DBG_CRITICAL
, "Do you need to run 'squid -z' to initialize storage?");
200 fatalf("Rock cache_dir[%d] rebuild of %s failed: %s.",
201 sd
->index
, sd
->filePath
, msg
);