]>
Commit | Line | Data |
---|---|---|
cd748f27 | 1 | |
2 | /* | |
262a0e14 | 3 | * $Id$ |
cd748f27 | 4 | * |
17bb3486 | 5 | * DEBUG: section 79 Storage Manager COSS Interface |
cd748f27 | 6 | * AUTHOR: Eric Stern |
7 | * | |
2b6662ba | 8 | * SQUID Web Proxy Cache http://www.squid-cache.org/ |
cd748f27 | 9 | * ---------------------------------------------------------- |
10 | * | |
2b6662ba | 11 | * Squid is the result of efforts by numerous individuals from |
12 | * the Internet community; see the CONTRIBUTORS file for full | |
13 | * details. Many organizations have provided support for Squid's | |
14 | * development; see the SPONSORS file for full details. Squid is | |
15 | * Copyrighted (C) 2001 by the Regents of the University of | |
16 | * California; see the COPYRIGHT file for full details. Squid | |
17 | * incorporates software developed and/or copyrighted by other | |
18 | * sources; see the CREDITS file for full details. | |
cd748f27 | 19 | * |
20 | * This program is free software; you can redistribute it and/or modify | |
21 | * it under the terms of the GNU General Public License as published by | |
22 | * the Free Software Foundation; either version 2 of the License, or | |
23 | * (at your option) any later version. | |
26ac0430 | 24 | * |
cd748f27 | 25 | * This program is distributed in the hope that it will be useful, |
26 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
27 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
28 | * GNU General Public License for more details. | |
26ac0430 | 29 | * |
cd748f27 | 30 | * You should have received a copy of the GNU General Public License |
31 | * along with this program; if not, write to the Free Software | |
32 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA. | |
33 | * | |
34 | */ | |
35 | ||
36 | #include "squid.h" | |
b9ae18aa | 37 | #include "CossSwapDir.h" |
e6ccf245 | 38 | #include "Store.h" |
cd748f27 | 39 | #include "store_coss.h" |
528b2c61 | 40 | #include "MemObject.h" |
41 | #include "fde.h" | |
d3b3ab85 | 42 | #include "SwapDir.h" |
b9ae18aa | 43 | #include "StoreFScoss.h" |
44 | #include "DiskIO/DiskIOStrategy.h" | |
cd748f27 | 45 | |
c94af0b9 | 46 | CBDATA_TYPE(CossMemBuf); |
72711e31 | 47 | |
cd748f27 | 48 | /* === PUBLIC =========================================================== */ |
49 | ||
d3b3ab85 | 50 | CossState::CossState(CossSwapDir *aCSD):SD (aCSD) |
62e76326 | 51 | {} |
d3b3ab85 | 52 | |
53 | ||
cd748f27 | 54 | /* |
55 | * This routine sucks. I want to rewrite it when possible, and I also think | |
56 | * that we should check after creatmembuf() to see if the object has a | |
57 | * RELEASE_REQUEST set on it (thanks Eric!) rather than this way which seems | |
58 | * to work.. | |
59 | * -- Adrian | |
60 | */ | |
b9ae18aa | 61 | sfileno |
62 | CossSwapDir::allocate(const StoreEntry * e, int which) | |
cd748f27 | 63 | { |
cd748f27 | 64 | CossMemBuf *newmb; |
65 | off_t retofs; | |
47f6e231 | 66 | off_t allocsize; |
cd748f27 | 67 | int coll = 0; |
68 | sfileno checkf; | |
69 | ||
a4b8110e | 70 | /* Make sure we chcek collisions if reallocating */ |
62e76326 | 71 | |
1a224843 | 72 | if (which == COSS_ALLOC_REALLOC) { |
62e76326 | 73 | checkf = e->swap_filen; |
b9ae18aa | 74 | StoreFScoss::GetInstance().stats.alloc.realloc++; |
1a224843 | 75 | } else { |
62e76326 | 76 | checkf = -1; |
b9ae18aa | 77 | StoreFScoss::GetInstance().stats.alloc.alloc++; |
1a224843 | 78 | } |
cd748f27 | 79 | |
80 | if (e->swap_file_sz > 0) | |
62e76326 | 81 | allocsize = e->swap_file_sz; |
cd748f27 | 82 | else |
6056fb29 | 83 | allocsize = e->objectLen() + e->mem_obj->swap_hdr_sz; |
cd748f27 | 84 | |
c94af0b9 | 85 | /* Check if we have overflowed the disk .. */ |
b9ae18aa | 86 | /* max_size is int, so cast to (off_t) *before* bit-shifting */ |
47f6e231 | 87 | if ((current_offset + allocsize) > ((off_t)max_size << 10)) { |
62e76326 | 88 | /* |
89 | * tried to allocate past the end of the disk, so wrap | |
90 | * back to the beginning | |
91 | */ | |
b9ae18aa | 92 | StoreFScoss::GetInstance().stats.disk_overflows++; |
93 | current_membuf->flags.full = 1; | |
94 | current_membuf->diskend = current_offset; | |
95 | current_membuf->maybeWrite(this); | |
96 | current_offset = 0; /* wrap back to beginning */ | |
bf8fe701 | 97 | debugs(79, 2, "CossSwapDir::allocate: wrap to 0"); |
62e76326 | 98 | |
b9ae18aa | 99 | newmb = createMemBuf(0, checkf, &coll); |
100 | current_membuf = newmb; | |
62e76326 | 101 | |
102 | /* Check if we have overflowed the MemBuf */ | |
b9ae18aa | 103 | } else if ((current_offset + allocsize) >= current_membuf->diskend) { |
62e76326 | 104 | /* |
105 | * Skip the blank space at the end of the stripe. start over. | |
106 | */ | |
b9ae18aa | 107 | StoreFScoss::GetInstance().stats.stripe_overflows++; |
108 | current_membuf->flags.full = 1; | |
109 | current_offset = current_membuf->diskend; | |
110 | current_membuf->maybeWrite(this); | |
4a7a3d56 | 111 | debugs(79, 2, "CossSwapDir::allocate: New offset - " << current_offset); |
b9ae18aa | 112 | newmb = createMemBuf(current_offset, checkf, &coll); |
113 | current_membuf = newmb; | |
cd748f27 | 114 | } |
62e76326 | 115 | |
1a224843 | 116 | /* |
117 | * If we didn't get a collision, then update the current offset | |
118 | * and return it | |
119 | */ | |
cd748f27 | 120 | if (coll == 0) { |
b9ae18aa | 121 | retofs = current_offset; |
122 | current_offset = retofs + allocsize; | |
1a224843 | 123 | /* round up to our blocksize */ |
b9ae18aa | 124 | current_offset = ((current_offset + blksz_mask) >> blksz_bits ) << blksz_bits; |
125 | return storeCossDiskOffsetToFileno(retofs); | |
cd748f27 | 126 | } else { |
b9ae18aa | 127 | StoreFScoss::GetInstance().stats.alloc.collisions++; |
bf8fe701 | 128 | debugs(79, 3, "CossSwapDir::allocate: Collision"); |
62e76326 | 129 | return -1; |
cd748f27 | 130 | } |
131 | } | |
132 | ||
133 | void | |
d3b3ab85 | 134 | CossSwapDir::unlink(StoreEntry & e) |
cd748f27 | 135 | { |
bf8fe701 | 136 | debugs(79, 3, "storeCossUnlink: offset " << e.swap_filen); |
b9ae18aa | 137 | StoreFScoss::GetInstance().stats.unlink.ops++; |
138 | StoreFScoss::GetInstance().stats.unlink.success++; | |
d3b3ab85 | 139 | storeCossRemove(this, &e); |
cd748f27 | 140 | } |
141 | ||
d3b3ab85 | 142 | StoreIOState::Pointer |
c6ee6676 | 143 | CossSwapDir::createStoreIO(StoreEntry &e, StoreIOState::STFNCB * file_callback, StoreIOState::STIOCB * callback, void *callback_data) |
cd748f27 | 144 | { |
145 | CossState *cstate; | |
d3b3ab85 | 146 | StoreIOState::Pointer sio = new CossState(this); |
147 | cstate = dynamic_cast<CossState *>(sio.getRaw()); | |
148 | sio->offset_ = 0; | |
5d1a7121 | 149 | sio->mode = O_WRONLY | O_BINARY; |
cd748f27 | 150 | |
c94af0b9 | 151 | /* |
152 | * If we get handed an object with a size of -1, | |
153 | * the squid code is broken | |
154 | */ | |
d3b3ab85 | 155 | assert(e.mem_obj->object_sz != -1); |
b9ae18aa | 156 | StoreFScoss::GetInstance().stats.create.ops++; |
c94af0b9 | 157 | |
cd748f27 | 158 | /* |
b9ae18aa | 159 | * this one is kinda strange - Eric called allocate(), then |
cd748f27 | 160 | * storeCossOpen(O_RDONLY) .. weird. Anyway, I'm allocating this now. |
161 | */ | |
6056fb29 | 162 | cstate->st_size = e.objectLen() + e.mem_obj->swap_hdr_sz; |
d3b3ab85 | 163 | sio->swap_dirn = index; |
b9ae18aa | 164 | sio->swap_filen = allocate(&e, COSS_ALLOC_ALLOCATE); |
bf8fe701 | 165 | debugs(79, 3, "storeCossCreate: offset " << |
47f6e231 | 166 | storeCossFilenoToDiskOffset(sio->swap_filen) << |
bf8fe701 | 167 | ", size " << (long int) cstate->st_size << ", end " << |
47f6e231 | 168 | (sio->swap_filen + cstate->st_size)); |
bf8fe701 | 169 | |
b9ae18aa | 170 | /* assume allocate() always succeeds */ |
1a224843 | 171 | assert(-1 != sio->swap_filen); |
cd748f27 | 172 | |
173 | sio->callback = callback; | |
c94af0b9 | 174 | sio->file_callback = file_callback; |
fa80a8ef | 175 | sio->callback_data = cbdataReference(callback_data); |
d3b3ab85 | 176 | sio->e = &e; |
cd748f27 | 177 | |
178 | cstate->flags.writing = 0; | |
179 | cstate->flags.reading = 0; | |
180 | cstate->readbuffer = NULL; | |
181 | cstate->reqdiskoffset = -1; | |
182 | ||
6a566b9c | 183 | /* Now add it into the index list */ |
d3b3ab85 | 184 | storeCossAdd(this, &e); |
cd748f27 | 185 | |
b9ae18aa | 186 | cstate->lockMemBuf(); |
187 | StoreFScoss::GetInstance().stats.create.success++; | |
cd748f27 | 188 | return sio; |
189 | } | |
190 | ||
d3b3ab85 | 191 | StoreIOState::Pointer |
c6ee6676 | 192 | CossSwapDir::openStoreIO(StoreEntry & e, StoreIOState::STFNCB * file_callback, |
193 | StoreIOState::STIOCB * callback, void *callback_data) | |
cd748f27 | 194 | { |
cd748f27 | 195 | char *p; |
196 | CossState *cstate; | |
d3b3ab85 | 197 | sfileno f = e.swap_filen; |
cd748f27 | 198 | |
bf8fe701 | 199 | debugs(79, 3, "storeCossOpen: offset " << f); |
b9ae18aa | 200 | StoreFScoss::GetInstance().stats.open.ops++; |
cd748f27 | 201 | |
d3b3ab85 | 202 | StoreIOState::Pointer sio = new CossState (this); |
203 | cstate = dynamic_cast<CossState *>(sio.getRaw()); | |
cd748f27 | 204 | |
cd748f27 | 205 | sio->swap_filen = f; |
d3b3ab85 | 206 | sio->swap_dirn = index; |
207 | sio->offset_ = 0; | |
5d1a7121 | 208 | sio->mode = O_RDONLY | O_BINARY; |
cd748f27 | 209 | sio->callback = callback; |
210 | sio->file_callback = file_callback; | |
fa80a8ef | 211 | sio->callback_data = cbdataReference(callback_data); |
d3b3ab85 | 212 | cstate->st_size = e.swap_file_sz; |
213 | sio->e = &e; | |
cd748f27 | 214 | |
215 | cstate->flags.writing = 0; | |
216 | cstate->flags.reading = 0; | |
217 | cstate->readbuffer = NULL; | |
218 | cstate->reqdiskoffset = -1; | |
b9ae18aa | 219 | p = storeCossMemPointerFromDiskOffset(storeCossFilenoToDiskOffset(f), NULL); |
a4b8110e | 220 | /* make local copy so we don't have to lock membuf */ |
62e76326 | 221 | |
cd748f27 | 222 | if (p) { |
62e76326 | 223 | cstate->readbuffer = (char *)xmalloc(cstate->st_size); |
224 | xmemcpy(cstate->readbuffer, p, cstate->st_size); | |
b9ae18aa | 225 | StoreFScoss::GetInstance().stats.open_mem_hits++; |
cd748f27 | 226 | } else { |
62e76326 | 227 | /* Do the allocation */ |
228 | /* this is the first time we've been called on a new sio | |
26ac0430 | 229 | * read the whole object into memory, then return the |
62e76326 | 230 | * requested amount |
231 | */ | |
b9ae18aa | 232 | StoreFScoss::GetInstance().stats.open_mem_misses++; |
62e76326 | 233 | /* |
234 | * This bit of code actually does the LRU disk thing - we realloc | |
235 | * a place for the object here, and the file_read() reads the object | |
236 | * into the cossmembuf for later writing .. | |
237 | */ | |
1a224843 | 238 | cstate->reqdiskoffset = storeCossFilenoToDiskOffset(sio->swap_filen); |
62e76326 | 239 | sio->swap_filen = -1; |
b9ae18aa | 240 | sio->swap_filen = allocate(&e, COSS_ALLOC_REALLOC); |
62e76326 | 241 | |
242 | if (sio->swap_filen == -1) { | |
243 | /* We have to clean up neatly .. */ | |
b9ae18aa | 244 | StoreFScoss::GetInstance().stats.open.fail++; |
62e76326 | 245 | numcollisions++; |
bf8fe701 | 246 | debugs(79, 2, "storeCossOpen: Reallocation of " << e.swap_dirn << "/" << e.swap_filen << " failed"); |
62e76326 | 247 | /* XXX XXX XXX Will squid call storeUnlink for this object? */ |
248 | return NULL; | |
249 | } | |
250 | ||
251 | /* Notify the upper levels that we've changed file number */ | |
c6ee6676 | 252 | sio->file_callback(sio->callback_data, 0, sio); |
62e76326 | 253 | |
254 | /* | |
255 | * lock the buffer so it doesn't get swapped out on us | |
1a224843 | 256 | * this will get unlocked in storeCossClose |
62e76326 | 257 | */ |
b9ae18aa | 258 | cstate->lockMemBuf(); |
62e76326 | 259 | |
260 | /* | |
261 | * Do the index magic to keep the disk and memory LRUs identical | |
262 | */ | |
263 | storeCossRemove(this, &e); | |
264 | ||
265 | storeCossAdd(this, &e); | |
266 | ||
267 | /* | |
1a224843 | 268 | * NOTE cstate->readbuffer is NULL. We'll actually read |
269 | * the disk data into the MemBuf in storeCossRead() and | |
270 | * return that pointer back to the caller | |
271 | */ | |
cd748f27 | 272 | } |
62e76326 | 273 | |
b9ae18aa | 274 | StoreFScoss::GetInstance().stats.open.success++; |
cd748f27 | 275 | return sio; |
276 | } | |
277 | ||
278 | void | |
d3b3ab85 | 279 | CossState::close() |
cd748f27 | 280 | { |
bf8fe701 | 281 | debugs(79, 3, "storeCossClose: offset " << swap_filen); |
62e76326 | 282 | |
b9ae18aa | 283 | StoreFScoss::GetInstance().stats.close.ops++; |
284 | StoreFScoss::GetInstance().stats.close.success++; | |
285 | SD->storeCossMemBufUnlock(this); | |
286 | doCallback(0); | |
cd748f27 | 287 | } |
288 | ||
289 | void | |
d3b3ab85 | 290 | CossState::read_(char *buf, size_t size, off_t offset, STRCB * callback, void *callback_data) |
cd748f27 | 291 | { |
292 | char *p; | |
d3b3ab85 | 293 | CossSwapDir *SD = (CossSwapDir *)INDEXSD(swap_dirn); |
cd748f27 | 294 | |
b9ae18aa | 295 | StoreFScoss::GetInstance().stats.read.ops++; |
d3b3ab85 | 296 | assert(read.callback == NULL); |
297 | assert(read.callback_data == NULL); | |
298 | read.callback = callback; | |
299 | read.callback_data = cbdataReference(callback_data); | |
4a7a3d56 | 300 | debugs(79, 3, "storeCossRead: offset " << offset); |
d3b3ab85 | 301 | offset_ = offset; |
302 | flags.reading = 1; | |
62e76326 | 303 | |
47f6e231 | 304 | if ((offset + (off_t)size) > st_size) |
62e76326 | 305 | size = st_size - offset; |
306 | ||
d3b3ab85 | 307 | requestlen = size; |
62e76326 | 308 | |
d3b3ab85 | 309 | requestbuf = buf; |
62e76326 | 310 | |
d3b3ab85 | 311 | requestoffset = offset; |
62e76326 | 312 | |
d3b3ab85 | 313 | if (readbuffer == NULL) { |
b9ae18aa | 314 | p = SD->storeCossMemPointerFromDiskOffset(SD->storeCossFilenoToDiskOffset(swap_filen), NULL); |
315 | sfileno tempReqdiskoffset = reqdiskoffset; | |
62e76326 | 316 | reqdiskoffset = 0; /* XXX */ |
b9ae18aa | 317 | SD->theFile->read(new CossRead(ReadRequest(p, st_size, tempReqdiskoffset), this)); |
cd748f27 | 318 | } else { |
1a224843 | 319 | /* |
320 | * It was copied from memory in storeCossOpen() | |
321 | */ | |
b9ae18aa | 322 | ReadRequest::Pointer readRequest = new CossRead(ReadRequest( |
26ac0430 | 323 | (char *)readbuffer,st_size, 0), this); |
b9ae18aa | 324 | SD->readCompleted(readbuffer, st_size, 0, readRequest); |
a4b8110e | 325 | } |
cd748f27 | 326 | } |
327 | ||
328 | void | |
528b2c61 | 329 | CossState::write(char const *buf, size_t size, off_t offset, FREE * free_func) |
cd748f27 | 330 | { |
331 | char *dest; | |
332 | CossMemBuf *membuf; | |
333 | off_t diskoffset; | |
a4b8110e | 334 | |
c94af0b9 | 335 | /* |
336 | * If we get handed an object with a size of -1, | |
337 | * the squid code is broken | |
338 | */ | |
d3b3ab85 | 339 | assert(e->mem_obj->object_sz != -1); |
b9ae18aa | 340 | StoreFScoss::GetInstance().stats.write.ops++; |
c94af0b9 | 341 | |
4a7a3d56 | 342 | debugs(79, 3, "storeCossWrite: offset " << offset_ << ", len " << (unsigned long int) size); |
1a224843 | 343 | diskoffset = SD->storeCossFilenoToDiskOffset(swap_filen) + offset_; |
d3b3ab85 | 344 | CossSwapDir *SD = (CossSwapDir *)INDEXSD(swap_dirn); |
b9ae18aa | 345 | dest = SD->storeCossMemPointerFromDiskOffset(diskoffset, &membuf); |
cd748f27 | 346 | assert(dest != NULL); |
cac03dd2 | 347 | xmemcpy(dest, buf, size); |
d3b3ab85 | 348 | offset_ += size; |
62e76326 | 349 | |
cd748f27 | 350 | if (free_func) |
62e76326 | 351 | (free_func) ((char *)buf); |
1a224843 | 352 | |
b9ae18aa | 353 | StoreFScoss::GetInstance().stats.write.success++; |
cd748f27 | 354 | } |
355 | ||
1a224843 | 356 | off_t |
357 | CossSwapDir::storeCossFilenoToDiskOffset(sfileno f) | |
358 | { | |
359 | return (off_t) f << blksz_bits; | |
360 | } | |
361 | ||
362 | sfileno | |
363 | CossSwapDir::storeCossDiskOffsetToFileno(off_t o) | |
364 | { | |
365 | assert(0 == (o & blksz_mask)); | |
366 | return o >> blksz_bits; | |
367 | } | |
368 | ||
369 | CossMemBuf * | |
370 | CossSwapDir::storeCossFilenoToMembuf(sfileno f) | |
371 | { | |
372 | CossMemBuf *t = NULL; | |
373 | dlink_node *m; | |
374 | off_t o = storeCossFilenoToDiskOffset(f); | |
375 | ||
376 | for (m = membufs.head; m; m = m->next) { | |
377 | t = (CossMemBuf *)m->data; | |
378 | ||
4989878c | 379 | if ((o >= (off_t)t->diskstart) && (o < (off_t)t->diskend)) |
1a224843 | 380 | break; |
381 | } | |
382 | ||
383 | assert(t); | |
384 | return t; | |
385 | } | |
cd748f27 | 386 | |
387 | /* === STATIC =========================================================== */ | |
388 | ||
b9ae18aa | 389 | CBDATA_CLASS_INIT(CossRead); |
390 | void * | |
391 | CossRead::operator new (size_t) | |
cd748f27 | 392 | { |
b9ae18aa | 393 | CBDATA_INIT_TYPE(CossRead); |
394 | CossRead *result = cbdataAlloc(CossRead); | |
395 | return result; | |
396 | } | |
62e76326 | 397 | |
b9ae18aa | 398 | void |
399 | CossRead::operator delete (void *address) | |
400 | { | |
401 | cbdataFree(address); | |
402 | } | |
62e76326 | 403 | |
b9ae18aa | 404 | CBDATA_CLASS_INIT(CossWrite); |
405 | void * | |
406 | CossWrite::operator new (size_t) | |
407 | { | |
408 | CBDATA_INIT_TYPE(CossWrite); | |
409 | CossWrite *result = cbdataAlloc(CossWrite); | |
410 | return result; | |
411 | } | |
62e76326 | 412 | |
b9ae18aa | 413 | void |
414 | CossWrite::operator delete (void *address) | |
415 | { | |
416 | cbdataFree(address); | |
cd748f27 | 417 | } |
418 | ||
b9ae18aa | 419 | void |
420 | CossState::doCallback(int errflag) | |
cd748f27 | 421 | { |
b9ae18aa | 422 | STIOCB *callback = this->callback; |
fa80a8ef | 423 | void *cbdata; |
bf8fe701 | 424 | debugs(79, 3, "CossState::doCallback: errflag=" << errflag); |
b9ae18aa | 425 | assert(NULL == locked_membuf); |
426 | xfree(readbuffer); | |
427 | this->callback = NULL; | |
62e76326 | 428 | |
b9ae18aa | 429 | if (cbdataReferenceValidDone(callback_data, &cbdata)) |
c6ee6676 | 430 | callback(cbdata, errflag, this); |
cd748f27 | 431 | } |
432 | ||
b9ae18aa | 433 | char * |
47f6e231 | 434 | CossSwapDir::storeCossMemPointerFromDiskOffset(off_t offset, CossMemBuf ** mb) |
cd748f27 | 435 | { |
436 | CossMemBuf *t; | |
c94af0b9 | 437 | dlink_node *m; |
a4b8110e | 438 | |
b9ae18aa | 439 | for (m = membufs.head; m; m = m->next) { |
62e76326 | 440 | t = (CossMemBuf *)m->data; |
441 | ||
1a224843 | 442 | if ((offset >= t->diskstart) && (offset < t->diskend)) { |
62e76326 | 443 | if (mb) |
444 | *mb = t; | |
445 | ||
446 | return &t->buffer[offset - t->diskstart]; | |
447 | } | |
c94af0b9 | 448 | } |
449 | ||
cd748f27 | 450 | if (mb) |
62e76326 | 451 | *mb = NULL; |
452 | ||
cd748f27 | 453 | return NULL; |
454 | } | |
455 | ||
b9ae18aa | 456 | void |
457 | CossState::lockMemBuf() | |
cd748f27 | 458 | { |
b9ae18aa | 459 | CossMemBuf *t = SD->storeCossFilenoToMembuf(swap_filen); |
bf8fe701 | 460 | debugs(79, 3, "CossState::lockMemBuf: locking " << t << ", lockcount " << t->lockcount); |
b9ae18aa | 461 | locked_membuf = t; |
462 | ++t->lockcount; | |
cd748f27 | 463 | } |
464 | ||
b9ae18aa | 465 | void |
ea75a4c8 | 466 | CossSwapDir::storeCossMemBufUnlock(StoreIOState::Pointer sio) |
cd748f27 | 467 | { |
b9ae18aa | 468 | CossMemBuf *t = storeCossFilenoToMembuf(sio->swap_filen); |
ea75a4c8 | 469 | CossState *cstate = dynamic_cast<CossState *>(sio.getRaw()); |
cd748f27 | 470 | |
1a224843 | 471 | if (NULL == t) |
472 | return; | |
62e76326 | 473 | |
bf8fe701 | 474 | debugs(79, 3, "storeCossMemBufUnlock: unlocking " << t << ", lockcount " << t->lockcount); |
62e76326 | 475 | |
1a224843 | 476 | t->lockcount--; |
477 | ||
478 | cstate->locked_membuf = NULL; | |
479 | ||
b9ae18aa | 480 | t->maybeWrite(this); |
cd748f27 | 481 | } |
482 | ||
6a566b9c | 483 | void |
d3b3ab85 | 484 | CossSwapDir::sync() |
6a566b9c | 485 | { |
6a566b9c | 486 | CossMemBuf *t; |
c94af0b9 | 487 | dlink_node *m; |
47f6e231 | 488 | off_t end; |
0b30d52d | 489 | |
490 | /* First, flush pending IO ops */ | |
b9ae18aa | 491 | io->sync(); |
0b30d52d | 492 | |
493 | /* Then, flush any in-memory partial membufs */ | |
62e76326 | 494 | |
d3b3ab85 | 495 | if (!membufs.head) |
62e76326 | 496 | return; |
497 | ||
d3b3ab85 | 498 | for (m = membufs.head; m; m = m->next) { |
62e76326 | 499 | t = (CossMemBuf *)m->data; |
500 | ||
1a224843 | 501 | if (t->flags.writing) { |
bf8fe701 | 502 | debugs(79, 1, "WARNING: sleeping for 5 seconds in storeCossSync()"); |
62e76326 | 503 | sleep(5); /* XXX EEEWWW! */ |
1a224843 | 504 | } |
62e76326 | 505 | |
62e76326 | 506 | end = (t == current_membuf) ? current_offset : t->diskend; |
507 | ||
47f6e231 | 508 | if (end > t->diskstart) |
b9ae18aa | 509 | theFile->write(new CossWrite(WriteRequest((char const *)&t->buffer, t->diskstart, end - t->diskstart, NULL), t)); |
510 | ||
511 | /* and flush */ | |
512 | io->sync(); | |
6a566b9c | 513 | } |
514 | } | |
cd748f27 | 515 | |
b9ae18aa | 516 | void |
517 | CossMemBuf::maybeWrite(CossSwapDir * SD) | |
1a224843 | 518 | { |
b9ae18aa | 519 | describe(3, __LINE__); |
520 | ||
521 | if (!flags.full) | |
bf8fe701 | 522 | debugs(79, 3, "membuf " << this << " not full"); |
b9ae18aa | 523 | else if (flags.writing) |
bf8fe701 | 524 | debugs(79, 3, "membuf " << this << " writing"); |
b9ae18aa | 525 | else if (lockcount) |
bf8fe701 | 526 | debugs(79, 3, "membuf " << this << " lockcount=" << lockcount); |
1a224843 | 527 | else |
b9ae18aa | 528 | write(SD); |
cd748f27 | 529 | } |
530 | ||
b9ae18aa | 531 | void |
532 | CossMemBuf::write(CossSwapDir * SD) | |
cd748f27 | 533 | { |
b9ae18aa | 534 | StoreFScoss::GetInstance().stats.stripe_write.ops++; |
4a7a3d56 | 535 | debugs(79, 3, "CossMemBuf::write: offset " << diskstart << ", len " << (diskend - diskstart)); |
b9ae18aa | 536 | flags.writing = 1; |
537 | /* XXX Remember that diskstart/diskend are block offsets! */ | |
538 | SD->theFile->write(new CossWrite(WriteRequest((char const *)&buffer, diskstart, diskend - diskstart, NULL), this)); | |
cd748f27 | 539 | } |
540 | ||
b9ae18aa | 541 | CossMemBuf * |
47f6e231 | 542 | CossSwapDir::createMemBuf(off_t start, sfileno curfn, int *collision) |
cd748f27 | 543 | { |
1a224843 | 544 | CossMemBuf *newmb; |
545 | CossMemBuf *t; | |
cd748f27 | 546 | StoreEntry *e; |
a4b8110e | 547 | dlink_node *m, *prev; |
548 | int numreleased = 0; | |
cd748f27 | 549 | |
c94af0b9 | 550 | CBDATA_INIT_TYPE_FREECB(CossMemBuf, NULL); |
72711e31 | 551 | newmb = cbdataAlloc(CossMemBuf); |
cd748f27 | 552 | newmb->diskstart = start; |
4a7a3d56 | 553 | debugs(79, 3, "CossSwapDir::createMemBuf: creating new membuf at " << newmb->diskstart); |
bf8fe701 | 554 | debugs(79, 3, "CossSwapDir::createMemBuf: at " << newmb); |
1a224843 | 555 | newmb->diskend = newmb->diskstart + COSS_MEMBUF_SZ; |
cd748f27 | 556 | newmb->flags.full = 0; |
557 | newmb->flags.writing = 0; | |
558 | newmb->lockcount = 0; | |
b9ae18aa | 559 | newmb->SD = this; |
6a566b9c | 560 | /* XXX This should be reversed, with the new buffer last in the chain */ |
b9ae18aa | 561 | dlinkAdd(newmb, &newmb->node, &membufs); |
c94af0b9 | 562 | |
563 | /* Print out the list of membufs */ | |
62e76326 | 564 | |
bf8fe701 | 565 | debugs(79, 3, "CossSwapDir::createMemBuf: membuflist:"); |
1a224843 | 566 | |
b9ae18aa | 567 | for (m = membufs.head; m; m = m->next) { |
62e76326 | 568 | t = (CossMemBuf *)m->data; |
b9ae18aa | 569 | t->describe(3, __LINE__); |
c94af0b9 | 570 | } |
cd748f27 | 571 | |
572 | /* | |
6a566b9c | 573 | * Kill objects from the tail to make space for a new chunk |
cd748f27 | 574 | */ |
b9ae18aa | 575 | for (m = cossindex.tail; m; m = prev) { |
1a224843 | 576 | off_t o; |
62e76326 | 577 | prev = m->prev; |
578 | e = (StoreEntry *)m->data; | |
b9ae18aa | 579 | o = storeCossFilenoToDiskOffset(e->swap_filen); |
62e76326 | 580 | |
581 | if (curfn == e->swap_filen) | |
582 | *collision = 1; /* Mark an object alloc collision */ | |
583 | ||
4989878c | 584 | if ((o >= (off_t)newmb->diskstart) && (o < (off_t)newmb->diskend)) { |
5f33b71d | 585 | e->release(); |
62e76326 | 586 | numreleased++; |
587 | } else | |
588 | break; | |
cd748f27 | 589 | } |
62e76326 | 590 | |
cd748f27 | 591 | if (numreleased > 0) |
bf8fe701 | 592 | debugs(79, 3, "CossSwapDir::createMemBuf: this allocation released " << numreleased << " storeEntries"); |
62e76326 | 593 | |
b9ae18aa | 594 | StoreFScoss::GetInstance().stats.stripes++; |
1a224843 | 595 | |
a4b8110e | 596 | return newmb; |
cd748f27 | 597 | } |
598 | ||
6a566b9c | 599 | /* |
600 | * Creates the initial membuf after rebuild | |
601 | */ | |
602 | void | |
b9ae18aa | 603 | CossSwapDir::startMembuf() |
6a566b9c | 604 | { |
1a224843 | 605 | CossMemBuf *newmb; |
b9ae18aa | 606 | newmb = createMemBuf(current_offset, -1, NULL); |
607 | assert(!current_membuf); | |
608 | current_membuf = newmb; | |
6a566b9c | 609 | } |
610 | ||
cd748f27 | 611 | /* |
34fdf670 | 612 | * Clean up any references from the SIO before it get's released. |
cd748f27 | 613 | */ |
d3b3ab85 | 614 | CossState::~CossState() |
62e76326 | 615 | {} |
1a224843 | 616 | |
b9ae18aa | 617 | void |
618 | CossMemBuf::describe(int level, int line) | |
1a224843 | 619 | { |
26ac0430 AJ |
620 | debugs(79, level, "membuf " << this << ", LC:" << std::setfill('0') << |
621 | std::setw(2) << lockcount << ", ST:" << | |
622 | std::setw(10) << (unsigned long) diskstart << ", FL:" << | |
623 | (flags.full ? 'F' : '.') << (flags.writing ? 'W' : '.')); | |
1a224843 | 624 | } |
625 |