]>
Commit | Line | Data |
---|---|---|
cd748f27 | 1 | |
2 | /* | |
b9ae18aa | 3 | * $Id: store_io_coss.cc,v 1.26 2004/12/20 16:30:43 robertc Exp $ |
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. | |
2b6662ba | 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. | |
2b6662ba | 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; | |
66 | size_t allocsize; | |
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 |
62e76326 | 83 | allocsize = objectLen(e) + 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 */ |
87 | if ((current_offset + allocsize) > ((size_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 */ | |
97 | debug(79, 2) ("CossSwapDir::allocate: wrap to 0\n"); | |
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); | |
111 | debug(79, 2) ("CossSwapDir::allocate: New offset - %ld\n", | |
112 | (long int) current_offset); | |
113 | newmb = createMemBuf(current_offset, checkf, &coll); | |
114 | current_membuf = newmb; | |
cd748f27 | 115 | } |
62e76326 | 116 | |
1a224843 | 117 | /* |
118 | * If we didn't get a collision, then update the current offset | |
119 | * and return it | |
120 | */ | |
cd748f27 | 121 | if (coll == 0) { |
b9ae18aa | 122 | retofs = current_offset; |
123 | current_offset = retofs + allocsize; | |
1a224843 | 124 | /* round up to our blocksize */ |
b9ae18aa | 125 | current_offset = ((current_offset + blksz_mask) >> blksz_bits ) << blksz_bits; |
126 | return storeCossDiskOffsetToFileno(retofs); | |
cd748f27 | 127 | } else { |
b9ae18aa | 128 | StoreFScoss::GetInstance().stats.alloc.collisions++; |
129 | debug(79, 3) ("CossSwapDir::allocate: Collision\n"); | |
62e76326 | 130 | return -1; |
cd748f27 | 131 | } |
132 | } | |
133 | ||
134 | void | |
d3b3ab85 | 135 | CossSwapDir::unlink(StoreEntry & e) |
cd748f27 | 136 | { |
d3b3ab85 | 137 | debug(79, 3) ("storeCossUnlink: offset %d\n", e.swap_filen); |
b9ae18aa | 138 | StoreFScoss::GetInstance().stats.unlink.ops++; |
139 | StoreFScoss::GetInstance().stats.unlink.success++; | |
d3b3ab85 | 140 | storeCossRemove(this, &e); |
cd748f27 | 141 | } |
142 | ||
d3b3ab85 | 143 | StoreIOState::Pointer |
144 | CossSwapDir::createStoreIO(StoreEntry &e, STFNCB * file_callback, STIOCB * callback, void *callback_data) | |
cd748f27 | 145 | { |
146 | CossState *cstate; | |
d3b3ab85 | 147 | StoreIOState::Pointer sio = new CossState(this); |
148 | cstate = dynamic_cast<CossState *>(sio.getRaw()); | |
149 | sio->offset_ = 0; | |
5d1a7121 | 150 | sio->mode = O_WRONLY | O_BINARY; |
cd748f27 | 151 | |
c94af0b9 | 152 | /* |
153 | * If we get handed an object with a size of -1, | |
154 | * the squid code is broken | |
155 | */ | |
d3b3ab85 | 156 | assert(e.mem_obj->object_sz != -1); |
b9ae18aa | 157 | StoreFScoss::GetInstance().stats.create.ops++; |
c94af0b9 | 158 | |
cd748f27 | 159 | /* |
b9ae18aa | 160 | * this one is kinda strange - Eric called allocate(), then |
cd748f27 | 161 | * storeCossOpen(O_RDONLY) .. weird. Anyway, I'm allocating this now. |
162 | */ | |
d3b3ab85 | 163 | cstate->st_size = objectLen(&e) + e.mem_obj->swap_hdr_sz; |
164 | sio->swap_dirn = index; | |
b9ae18aa | 165 | sio->swap_filen = allocate(&e, COSS_ALLOC_ALLOCATE); |
1a224843 | 166 | debug(79, 3) ("storeCossCreate: offset %ld, size %ld, end %ld\n", |
167 | (long int) storeCossFilenoToDiskOffset(sio->swap_filen), | |
168 | (long int) cstate->st_size, | |
169 | (long int) (sio->swap_filen + cstate->st_size)); | |
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 |
192 | CossSwapDir::openStoreIO(StoreEntry & e, STFNCB * file_callback, | |
62e76326 | 193 | STIOCB * callback, void *callback_data) |
cd748f27 | 194 | { |
cd748f27 | 195 | char *p; |
196 | CossState *cstate; | |
d3b3ab85 | 197 | sfileno f = e.swap_filen; |
cd748f27 | 198 | |
17bb3486 | 199 | debug(79, 3) ("storeCossOpen: offset %d\n", 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 | |
229 | * read the whole object into memory, then return the | |
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++; |
246 | debug(79, 2) ("storeCossOpen: Reallocation of %d/%d failed\n", e.swap_dirn, e.swap_filen); | |
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 */ | |
252 | sio->file_callback(sio->callback_data, 0, sio.getRaw()); | |
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 | { |
d3b3ab85 | 281 | debug(79, 3) ("storeCossClose: offset %d\n", 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); | |
17bb3486 | 300 | debug(79, 3) ("storeCossRead: offset %ld\n", (long int) offset); |
d3b3ab85 | 301 | offset_ = offset; |
302 | flags.reading = 1; | |
62e76326 | 303 | |
d3b3ab85 | 304 | if ((offset + 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( |
323 | (char *)readbuffer,st_size, 0), this); | |
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 | |
d3b3ab85 | 342 | debug(79, 3) ("storeCossWrite: offset %ld, len %lu\n", (long int) offset_, (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; |
b9ae18aa | 424 | debug(79, 3) ("CossState::doCallback: errflag=%d\n", errflag); |
425 | assert(NULL == locked_membuf); | |
426 | xfree(readbuffer); | |
427 | this->callback = NULL; | |
62e76326 | 428 | |
b9ae18aa | 429 | if (cbdataReferenceValidDone(callback_data, &cbdata)) |
430 | callback(cbdata, errflag, this); | |
cd748f27 | 431 | } |
432 | ||
b9ae18aa | 433 | char * |
434 | CossSwapDir::storeCossMemPointerFromDiskOffset(size_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); |
460 | debug(79, 3) ("CossState::lockMemBuf: locking %p, lockcount %d\n", t, t->lockcount); | |
461 | locked_membuf = t; | |
462 | ++t->lockcount; | |
cd748f27 | 463 | } |
464 | ||
b9ae18aa | 465 | void |
466 | CossSwapDir::storeCossMemBufUnlock(storeIOState * sio) | |
cd748f27 | 467 | { |
b9ae18aa | 468 | CossMemBuf *t = storeCossFilenoToMembuf(sio->swap_filen); |
1a224843 | 469 | CossState *cstate = dynamic_cast<CossState *>(sio); |
cd748f27 | 470 | |
1a224843 | 471 | if (NULL == t) |
472 | return; | |
62e76326 | 473 | |
1a224843 | 474 | debug(79, 3) ("storeCossMemBufUnlock: unlocking %p, lockcount %d\n", t, 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; |
6a566b9c | 488 | int 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) { |
502 | debug(79, 1) ("WARNING: sleeping for 5 seconds in storeCossSync()\n"); | |
62e76326 | 503 | sleep(5); /* XXX EEEWWW! */ |
1a224843 | 504 | } |
62e76326 | 505 | |
62e76326 | 506 | end = (t == current_membuf) ? current_offset : t->diskend; |
507 | ||
b9ae18aa | 508 | if ((size_t)end > t->diskstart) |
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) | |
522 | debug(79, 3) ("membuf %p not full\n", this); | |
523 | else if (flags.writing) | |
524 | debug(79, 3) ("membuf %p writing\n", this); | |
525 | else if (lockcount) | |
526 | debug(79, 3) ("membuf %p lockcount=%d\n", this, 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++; |
535 | debug(79, 3) ("CossMemBuf::write: offset %ld, len %ld\n", | |
536 | (long int) diskstart, (long int) (diskend - diskstart)); | |
537 | flags.writing = 1; | |
538 | /* XXX Remember that diskstart/diskend are block offsets! */ | |
539 | SD->theFile->write(new CossWrite(WriteRequest((char const *)&buffer, diskstart, diskend - diskstart, NULL), this)); | |
cd748f27 | 540 | } |
541 | ||
b9ae18aa | 542 | CossMemBuf * |
543 | CossSwapDir::createMemBuf(size_t start, sfileno curfn, int *collision) | |
cd748f27 | 544 | { |
1a224843 | 545 | CossMemBuf *newmb; |
546 | CossMemBuf *t; | |
cd748f27 | 547 | StoreEntry *e; |
a4b8110e | 548 | dlink_node *m, *prev; |
549 | int numreleased = 0; | |
cd748f27 | 550 | |
c94af0b9 | 551 | CBDATA_INIT_TYPE_FREECB(CossMemBuf, NULL); |
72711e31 | 552 | newmb = cbdataAlloc(CossMemBuf); |
cd748f27 | 553 | newmb->diskstart = start; |
b9ae18aa | 554 | debug(79, 3) ("CossSwapDir::createMemBuf: creating new membuf at %ld\n", (long int) newmb->diskstart); |
555 | debug(79, 3) ("CossSwapDir::createMemBuf: at %p\n", newmb); | |
1a224843 | 556 | newmb->diskend = newmb->diskstart + COSS_MEMBUF_SZ; |
cd748f27 | 557 | newmb->flags.full = 0; |
558 | newmb->flags.writing = 0; | |
559 | newmb->lockcount = 0; | |
b9ae18aa | 560 | newmb->SD = this; |
6a566b9c | 561 | /* XXX This should be reversed, with the new buffer last in the chain */ |
b9ae18aa | 562 | dlinkAdd(newmb, &newmb->node, &membufs); |
c94af0b9 | 563 | |
564 | /* Print out the list of membufs */ | |
62e76326 | 565 | |
b9ae18aa | 566 | debug(79, 3) ("CossSwapDir::createMemBuf: membuflist:\n"); |
1a224843 | 567 | |
b9ae18aa | 568 | for (m = membufs.head; m; m = m->next) { |
62e76326 | 569 | t = (CossMemBuf *)m->data; |
b9ae18aa | 570 | t->describe(3, __LINE__); |
c94af0b9 | 571 | } |
cd748f27 | 572 | |
573 | /* | |
6a566b9c | 574 | * Kill objects from the tail to make space for a new chunk |
cd748f27 | 575 | */ |
b9ae18aa | 576 | for (m = cossindex.tail; m; m = prev) { |
1a224843 | 577 | off_t o; |
62e76326 | 578 | prev = m->prev; |
579 | e = (StoreEntry *)m->data; | |
b9ae18aa | 580 | o = storeCossFilenoToDiskOffset(e->swap_filen); |
62e76326 | 581 | |
582 | if (curfn == e->swap_filen) | |
583 | *collision = 1; /* Mark an object alloc collision */ | |
584 | ||
4989878c | 585 | if ((o >= (off_t)newmb->diskstart) && (o < (off_t)newmb->diskend)) { |
62e76326 | 586 | storeRelease(e); |
587 | numreleased++; | |
588 | } else | |
589 | break; | |
cd748f27 | 590 | } |
62e76326 | 591 | |
cd748f27 | 592 | if (numreleased > 0) |
b9ae18aa | 593 | debug(79, 3) ("CossSwapDir::createMemBuf: this allocation released %d storeEntries\n", numreleased); |
62e76326 | 594 | |
b9ae18aa | 595 | StoreFScoss::GetInstance().stats.stripes++; |
1a224843 | 596 | |
a4b8110e | 597 | return newmb; |
cd748f27 | 598 | } |
599 | ||
6a566b9c | 600 | /* |
601 | * Creates the initial membuf after rebuild | |
602 | */ | |
603 | void | |
b9ae18aa | 604 | CossSwapDir::startMembuf() |
6a566b9c | 605 | { |
1a224843 | 606 | CossMemBuf *newmb; |
b9ae18aa | 607 | newmb = createMemBuf(current_offset, -1, NULL); |
608 | assert(!current_membuf); | |
609 | current_membuf = newmb; | |
6a566b9c | 610 | } |
611 | ||
cd748f27 | 612 | /* |
34fdf670 | 613 | * Clean up any references from the SIO before it get's released. |
cd748f27 | 614 | */ |
d3b3ab85 | 615 | CossState::~CossState() |
62e76326 | 616 | {} |
1a224843 | 617 | |
b9ae18aa | 618 | void |
619 | CossMemBuf::describe(int level, int line) | |
1a224843 | 620 | { |
621 | debug(79, level) ("membuf %p, LC:%02d, ST:%010lu, FL:%c%c\n", | |
b9ae18aa | 622 | this, |
623 | lockcount, | |
624 | (unsigned long) diskstart, | |
625 | flags.full ? 'F' : '.', | |
626 | flags.writing ? 'W' : '.'); | |
1a224843 | 627 | } |
628 |