]>
git.ipfire.org Git - thirdparty/squid.git/blob - src/fs/rock/RockRebuild.cc
4 * DEBUG: section 79 Disk IO Routines
9 #include "fs/rock/RockRebuild.h"
10 #include "fs/rock/RockSwapDir.h"
11 #include "fs/rock/RockDbCell.h"
15 #include "SquidTime.h"
21 CBDATA_NAMESPACED_CLASS_INIT(Rock
, Rebuild
);
23 Rock::Rebuild::Rebuild(SwapDir
*dir
): AsyncJob("Rock::Rebuild"),
33 memset(&counts
, 0, sizeof(counts
));
34 dbSize
= sd
->diskOffsetLimit(); // we do not care about the trailer waste
35 dbEntrySize
= sd
->max_objsize
;
36 dbEntryLimit
= sd
->entryLimit();
39 Rock::Rebuild::~Rebuild()
45 /// prepares and initiates entry loading sequence
47 Rock::Rebuild::start()
49 // in SMP mode, only the disker is responsible for populating the map
50 if (UsingSmp() && !IamDiskProcess()) {
51 debugs(47, 2, "Non-disker skips rebuilding of cache_dir #" <<
52 sd
->index
<< " from " << sd
->filePath
);
53 mustStop("non-disker");
57 debugs(47, DBG_IMPORTANT
, "Loading cache_dir #" << sd
->index
<<
58 " from " << sd
->filePath
);
60 fd
= file_open(sd
->filePath
, O_RDONLY
| O_BINARY
);
62 failure("cannot open db", errno
);
64 char buf
[SwapDir::HeaderSize
];
65 if (read(fd
, buf
, sizeof(buf
)) != SwapDir::HeaderSize
)
66 failure("cannot read db header", errno
);
68 dbOffset
= SwapDir::HeaderSize
;
74 /// continues after a pause if not done
76 Rock::Rebuild::checkpoint()
79 eventAdd("Rock::Rebuild", Rock::Rebuild::Steps
, this, 0.01, 1, true);
83 Rock::Rebuild::doneAll() const
85 return dbOffset
>= dbSize
&& AsyncJob::doneAll();
89 Rock::Rebuild::Steps(void *data
)
91 // use async call to enable job call protection that time events lack
92 CallJobHere(47, 5, static_cast<Rebuild
*>(data
), Rock::Rebuild
, steps
);
96 Rock::Rebuild::steps()
98 debugs(47,5, HERE
<< sd
->index
<< " filen " << filen
<< " at " <<
99 dbOffset
<< " <= " << dbSize
);
101 // Balance our desire to maximize the number of entries processed at once
102 // (and, hence, minimize overheads and total rebuild time) with a
103 // requirement to also process Coordinator events, disk I/Os, etc.
104 const int maxSpentMsec
= 50; // keep small: most RAM I/Os are under 1ms
105 const timeval loopStart
= current_time
;
108 while (loaded
< dbEntryLimit
&& dbOffset
< dbSize
) {
110 dbOffset
+= dbEntrySize
;
114 if (counts
.scancount
% 1000 == 0)
115 storeRebuildProgress(sd
->index
, dbEntryLimit
, counts
.scancount
);
117 if (opt_foreground_rebuild
)
118 continue; // skip "few entries at a time" check below
121 const double elapsedMsec
= tvSubMsec(loopStart
, current_time
);
122 if (elapsedMsec
> maxSpentMsec
|| elapsedMsec
< 0) {
123 debugs(47, 5, HERE
<< "pausing after " << loaded
<< " entries in " <<
124 elapsedMsec
<< "ms; " << (elapsedMsec
/loaded
) << "ms per entry");
133 Rock::Rebuild::doOneEntry()
135 debugs(47,5, HERE
<< sd
->index
<< " filen " << filen
<< " at " <<
136 dbOffset
<< " <= " << dbSize
);
140 if (lseek(fd
, dbOffset
, SEEK_SET
) < 0)
141 failure("cannot seek to db entry", errno
);
144 buf
.init(SM_PAGE_SIZE
, SM_PAGE_SIZE
);
146 if (!storeRebuildLoadEntry(fd
, sd
->index
, buf
, counts
))
151 if (buf
.contentSize() < static_cast<mb_size_t
>(sizeof(header
))) {
152 debugs(47, DBG_IMPORTANT
, "WARNING: cache_dir[" << sd
->index
<< "]: " <<
153 "Ignoring truncated cache entry meta data at " << dbOffset
);
157 memcpy(&header
, buf
.content(), sizeof(header
));
159 if (!header
.sane()) {
160 debugs(47, DBG_IMPORTANT
, "WARNING: cache_dir[" << sd
->index
<< "]: " <<
161 "Ignoring malformed cache entry meta data at " << dbOffset
);
165 buf
.consume(sizeof(header
)); // optimize to avoid memmove()
167 cache_key key
[SQUID_MD5_DIGEST_LENGTH
];
169 if (!storeRebuildParseEntry(buf
, loadedE
, key
, counts
, header
.payloadSize
)) {
171 if (loadedE
.swap_filen
> 0 || loadedE
.swap_file_sz
> 0) {
173 //sd->unlink(filen); leave garbage on disk, it should not hurt
178 assert(loadedE
.swap_filen
< dbEntryLimit
);
179 if (!storeRebuildKeepEntry(loadedE
, key
, counts
))
185 sd
->addEntry(filen
, header
, loadedE
);
189 Rock::Rebuild::swanSong()
191 debugs(47,3, HERE
<< "cache_dir #" << sd
->index
<< " rebuild level: " <<
192 StoreController::store_dirs_rebuilding
);
193 --StoreController::store_dirs_rebuilding
;
194 storeRebuildComplete(&counts
);
198 Rock::Rebuild::failure(const char *msg
, int errNo
)
200 debugs(47,5, HERE
<< sd
->index
<< " filen " << filen
<< " at " <<
201 dbOffset
<< " <= " << dbSize
);
204 debugs(47, DBG_CRITICAL
, "ERROR: Rock cache_dir rebuild failure: " << xstrerr(errNo
));
205 debugs(47, DBG_CRITICAL
, "Do you need to run 'squid -z' to initialize storage?");
208 fatalf("Rock cache_dir[%d] rebuild of %s failed: %s.",
209 sd
->index
, sd
->filePath
, msg
);