blockcache.cc (e6449f52) blockcache.cc (2534ac38)
1/*
2 * Copyright 2013 Jung-Sang Ahn <jungsang.ahn@gmail.com>.
3 * All Rights Reserved.
4 */
5
6#include <stdlib.h>
7#include <string.h>
8#include <stdint.h>

--- 42 unchanged lines hidden (view full) ---

51 //file_status_t status;
52
53 // current opened filemgr instance (can be changed on-the-fly when file is closed and re-opened)
54 struct filemgr *curfile;
55 // cache last accessed bcache_item (if hit, we can bypass hash retrieval)
56 struct hash_elem hash_elem;
57 struct rb_root rbtree;
58 // spin lock
1/*
2 * Copyright 2013 Jung-Sang Ahn <jungsang.ahn@gmail.com>.
3 * All Rights Reserved.
4 */
5
6#include <stdlib.h>
7#include <string.h>
8#include <stdint.h>

--- 42 unchanged lines hidden (view full) ---

51 //file_status_t status;
52
53 // current opened filemgr instance (can be changed on-the-fly when file is closed and re-opened)
54 struct filemgr *curfile;
55 // cache last accessed bcache_item (if hit, we can bypass hash retrieval)
56 struct hash_elem hash_elem;
57 struct rb_root rbtree;
58 // spin lock
59 //spin_t lock;
59 spin_t lock;
60};
61
62struct bcache_item {
63 // BID
64 bid_t bid;
65 // contents address
66 void *addr;
67 struct fnamedic_item *fname;

--- 241 unchanged lines hidden (view full) ---

309 #ifdef __MEMORY_ALIGN
310 ret = posix_memalign(&buf, FDB_SECTOR_SIZE, bcache_flush_unit);
311 #else
312 buf = (void *)malloc(bcache_flush_unit);
313 #endif
314 //assert(ret == 0);
315 }
316
60};
61
62struct bcache_item {
63 // BID
64 bid_t bid;
65 // contents address
66 void *addr;
67 struct fnamedic_item *fname;

--- 241 unchanged lines hidden (view full) ---

309 #ifdef __MEMORY_ALIGN
310 ret = posix_memalign(&buf, FDB_SECTOR_SIZE, bcache_flush_unit);
311 #else
312 buf = (void *)malloc(bcache_flush_unit);
313 #endif
314 //assert(ret == 0);
315 }
316
317 spin_lock(&bcache_lock);
318
319 prev_bid = start_bid = BLK_NOT_FOUND;
320 count = 0;
321
322 r = rb_first(&fname_item->rbtree);
323 while(r) {
324 ditem = _get_entry(r, struct dirty_item, rb);
325 // if BID of next dirty block is not consecutive .. stop
326 if (ditem->item->bid != prev_bid + 1 && prev_bid != BLK_NOT_FOUND && sync) break;

--- 13 unchanged lines hidden (view full) ---

340 _bcache_count(ditem->item->list, -1);
341
342 // when the file is undergoing compaction, blocks for documents are discarded
343 if ( (sync && filemgr_get_file_status(fname_item->curfile) != FILE_COMPACT_OLD) ||
344 (sync && filemgr_get_file_status(fname_item->curfile) == FILE_COMPACT_OLD
345 && marker == BLK_MARKER_BNODE) ) {
346 // if file is not COMPACT_OLD, OR
347 // file is COMPACT_OLD but current block is b-tree node
317 prev_bid = start_bid = BLK_NOT_FOUND;
318 count = 0;
319
320 r = rb_first(&fname_item->rbtree);
321 while(r) {
322 ditem = _get_entry(r, struct dirty_item, rb);
323 // if BID of next dirty block is not consecutive .. stop
324 if (ditem->item->bid != prev_bid + 1 && prev_bid != BLK_NOT_FOUND && sync) break;

--- 13 unchanged lines hidden (view full) ---

338 _bcache_count(ditem->item->list, -1);
339
340 // when the file is undergoing compaction, blocks for documents are discarded
341 if ( (sync && filemgr_get_file_status(fname_item->curfile) != FILE_COMPACT_OLD) ||
342 (sync && filemgr_get_file_status(fname_item->curfile) == FILE_COMPACT_OLD
343 && marker == BLK_MARKER_BNODE) ) {
344 // if file is not COMPACT_OLD, OR
345 // file is COMPACT_OLD but current block is b-tree node
348
349 // insert into the front of cleanlist
350 ditem->item->list = &cleanlist;
351 list_push_front(ditem->item->list, &ditem->item->list_elem);
352 _bcache_count(ditem->item->list, 1);
353
354 }else{
346 // insert into the front of cleanlist
347 ditem->item->list = &cleanlist;
348 list_push_front(ditem->item->list, &ditem->item->list_elem);
349 _bcache_count(ditem->item->list, 1);
350
351 }else{
355 // not committed dirty blocks of COMPACTION_OLD file .. just remove?
352 // not committed dirty blocks of COMPACTION_OLD file .. just remove (insert into freelist)?
356 hash_remove(&bhash, &ditem->item->hash_elem);
357
358 ditem->item->list = &freelist;
359 list_push_front(ditem->item->list, &ditem->item->list_elem);
360 _bcache_count(ditem->item->list, 1);
361 }
362 spin_lock(&ditem->item->lock);
353 hash_remove(&bhash, &ditem->item->hash_elem);
354
355 ditem->item->list = &freelist;
356 list_push_front(ditem->item->list, &ditem->item->list_elem);
357 _bcache_count(ditem->item->list, 1);
358 }
359 spin_lock(&ditem->item->lock);
363 spin_unlock(&bcache_lock);
364
365 if (sync) {
366 #ifdef __CRC32
367 if (marker == BLK_MARKER_BNODE ) {
368 // b-tree node .. calculate crc32 and put it into 8th byte of the block
369 memset(ptr + 8, 0xff, sizeof(void *));
370 uint32_t crc = crc32_8(ptr, bcache_blocksize, 0);
371 memcpy(ptr + 8, &crc, sizeof(crc));
372 }
373 #endif
374 memcpy(buf + count*bcache_blocksize, ditem->item->addr, bcache_blocksize);
375 }
376 spin_unlock(&ditem->item->lock);
360
361 if (sync) {
362 #ifdef __CRC32
363 if (marker == BLK_MARKER_BNODE ) {
364 // b-tree node .. calculate crc32 and put it into 8th byte of the block
365 memset(ptr + 8, 0xff, sizeof(void *));
366 uint32_t crc = crc32_8(ptr, bcache_blocksize, 0);
367 memcpy(ptr + 8, &crc, sizeof(crc));
368 }
369 #endif
370 memcpy(buf + count*bcache_blocksize, ditem->item->addr, bcache_blocksize);
371 }
372 spin_unlock(&ditem->item->lock);
377 spin_lock(&bcache_lock);
378
373
379 count++;
380
381 DBGCMD(_dirty--);
382 mempool_free(ditem);
383
374 mempool_free(ditem);
375
376 count++;
384 if (count*bcache_blocksize >= bcache_flush_unit && sync) break;
385 }
386
377 if (count*bcache_blocksize >= bcache_flush_unit && sync) break;
378 }
379
387 spin_unlock(&bcache_lock);
388
389 // synchronize
380 // synchronize
390 if (sync) {
381 if (sync && count>0) {
391 ret = fname_item->curfile->ops->pwrite(
392 fname_item->curfile->fd, buf, count * bcache_blocksize, start_bid * bcache_blocksize);
382 ret = fname_item->curfile->ops->pwrite(
383 fname_item->curfile->fd, buf, count * bcache_blocksize, start_bid * bcache_blocksize);
393 assert(ret != 0);
384
385 assert(ret == count * bcache_blocksize);
394 free(buf);
395
396 #ifdef __O_DIRECT
397 fname_item->curfile->last_commit = (start_bid + count) * bcache_blocksize;
398 #endif
399 }
400}
401
402struct list_elem * _bcache_evict(struct filemgr *file)
403{
404 struct list_elem *e = NULL;
405 struct bcache_item *item;
406 struct hash_elem *h;
407 struct fnamedic_item query, *fname_item = NULL;
408
386 free(buf);
387
388 #ifdef __O_DIRECT
389 fname_item->curfile->last_commit = (start_bid + count) * bcache_blocksize;
390 #endif
391 }
392}
393
394struct list_elem * _bcache_evict(struct filemgr *file)
395{
396 struct list_elem *e = NULL;
397 struct bcache_item *item;
398 struct hash_elem *h;
399 struct fnamedic_item query, *fname_item = NULL;
400
409 spin_lock(&bcache_lock);
410
411 // ratio check
412 if ( nclean >= BCACHE_EVICT_RATIO * ndirty ) {
413 // evict clean block
414 e = list_pop_back(&cleanlist);
415 if (e) _bcache_count(&cleanlist, -1);
416 }
417
418 while (e == NULL) {
419 // when there is no item in clean list .. evict dirty block
420 e = list_end(&dirtylist);
421 item = _get_entry(e, struct bcache_item, list_elem);
422
401 // ratio check
402 if ( nclean >= BCACHE_EVICT_RATIO * ndirty ) {
403 // evict clean block
404 e = list_pop_back(&cleanlist);
405 if (e) _bcache_count(&cleanlist, -1);
406 }
407
408 while (e == NULL) {
409 // when there is no item in clean list .. evict dirty block
410 e = list_end(&dirtylist);
411 item = _get_entry(e, struct bcache_item, list_elem);
412
423 spin_unlock(&bcache_lock);
424 _bcache_evict_dirty(item->fname, 1);
413 _bcache_evict_dirty(item->fname, 1);
425 spin_lock(&bcache_lock);
426
427 // pop back from cleanlist
428 e = list_pop_back(&cleanlist);
429 if (e) _bcache_count(&cleanlist, -1);
430 }
431
432 item = _get_entry(e, struct bcache_item, list_elem);
433 fname_item = item->fname;
434
435 // remove from hash and insert into freelist
436 hash_remove(&bhash, &item->hash_elem);
437
438 item->list = &freelist;
439
440 // add to freelist
441 list_push_front(item->list, &item->list_elem);
442 _bcache_count(item->list, 1);
443
414
415 // pop back from cleanlist
416 e = list_pop_back(&cleanlist);
417 if (e) _bcache_count(&cleanlist, -1);
418 }
419
420 item = _get_entry(e, struct bcache_item, list_elem);
421 fname_item = item->fname;
422
423 // remove from hash and insert into freelist
424 hash_remove(&bhash, &item->hash_elem);
425
426 item->list = &freelist;
427
428 // add to freelist
429 list_push_front(item->list, &item->list_elem);
430 _bcache_count(item->list, 1);
431
444 spin_unlock(&bcache_lock);
445
446 return &item->list_elem;
447}
448
449struct fnamedic_item * _fname_create(struct filemgr *file) {
450 struct fnamedic_item *fname_new;
451 fname_new = (struct fnamedic_item *)malloc(sizeof(struct fnamedic_item));
452
453 fname_new->filename_len = strlen(file->filename);
454 fname_new->filename = (char *)malloc(fname_new->filename_len + 1);
455 memcpy(fname_new->filename, file->filename, fname_new->filename_len);
456 //strcpy(fname_new->filename, file->filename);
457 fname_new->filename[fname_new->filename_len] = 0;
458
459 // calculate hash value
460 //fname_new->hash = hash_djb2_last8(fname_new->filename, fname_new->filename_len);
461 fname_new->hash = crc32_8_last8(fname_new->filename, fname_new->filename_len, 0);
432 return &item->list_elem;
433}
434
435struct fnamedic_item * _fname_create(struct filemgr *file) {
436 struct fnamedic_item *fname_new;
437 fname_new = (struct fnamedic_item *)malloc(sizeof(struct fnamedic_item));
438
439 fname_new->filename_len = strlen(file->filename);
440 fname_new->filename = (char *)malloc(fname_new->filename_len + 1);
441 memcpy(fname_new->filename, file->filename, fname_new->filename_len);
442 //strcpy(fname_new->filename, file->filename);
443 fname_new->filename[fname_new->filename_len] = 0;
444
445 // calculate hash value
446 //fname_new->hash = hash_djb2_last8(fname_new->filename, fname_new->filename_len);
447 fname_new->hash = crc32_8_last8(fname_new->filename, fname_new->filename_len, 0);
448 fname_new->lock = SPIN_INITIALIZER;
462
463 // initialize rb-tree
464 rbwrap_init(&fname_new->rbtree, NULL);
465
466 // insert into fname dictionary
467 hash_insert(&fnamedic, &fname_new->hash_elem);
468
469 return fname_new;

--- 48 unchanged lines hidden (view full) ---

518
519 h = hash_find(&bhash, &query.hash_elem);
520
521 if (h == NULL) {
522 // cache miss
523
524 e = list_pop_front(&freelist);
525 while (e == NULL) {
449
450 // initialize rb-tree
451 rbwrap_init(&fname_new->rbtree, NULL);
452
453 // insert into fname dictionary
454 hash_insert(&fnamedic, &fname_new->hash_elem);
455
456 return fname_new;

--- 48 unchanged lines hidden (view full) ---

505
506 h = hash_find(&bhash, &query.hash_elem);
507
508 if (h == NULL) {
509 // cache miss
510
511 e = list_pop_front(&freelist);
512 while (e == NULL) {
526 spin_unlock(&bcache_lock);
527 _bcache_evict(file);
513 _bcache_evict(file);
528 spin_lock(&bcache_lock);
529
530 e = list_pop_front(&freelist);
531 }
532 _bcache_count(&freelist, -1);
533
534 item = _get_entry(e, struct bcache_item, list_elem);
535 assert(item->list == &freelist);
536
537 item->bid = bid;
538 item->fname = query.fname;
539 hash_insert(&bhash, &item->hash_elem);
514
515 e = list_pop_front(&freelist);
516 }
517 _bcache_count(&freelist, -1);
518
519 item = _get_entry(e, struct bcache_item, list_elem);
520 assert(item->list == &freelist);
521
522 item->bid = bid;
523 item->fname = query.fname;
524 hash_insert(&bhash, &item->hash_elem);
525
540 }else{
526 }else{
527
541 item = _get_entry(h, struct bcache_item, hash_elem);
528 item = _get_entry(h, struct bcache_item, hash_elem);
542
543 list_remove(item->list, &item->list_elem);
544 _bcache_count(item->list, -1);
545 }
546
547 if (dirty == BCACHE_DIRTY) {
529 list_remove(item->list, &item->list_elem);
530 _bcache_count(item->list, -1);
531 }
532
533 if (dirty == BCACHE_DIRTY) {
534 // to avoid re-insert already exist item into rb-tree
548 if (item->list != &dirtylist) {
549 struct dirty_item *ditem;
550
551 item->list = &dirtylist;
535 if (item->list != &dirtylist) {
536 struct dirty_item *ditem;
537
538 item->list = &dirtylist;
552 DBGCMD(_dirty++;)
553
554 ditem = (struct dirty_item *)mempool_alloc(sizeof(struct dirty_item));
555 ditem->item = item;
556
557 rbwrap_insert(&item->fname->rbtree, &ditem->rb, _dirty_cmp);
558 }
559 }else{
560 item->list = &cleanlist;

--- 60 unchanged lines hidden (view full) ---

621
622 list_remove(item->list, &item->list_elem);
623 _bcache_count(item->list, -1);
624
625 if (item->list != &dirtylist) {
626 struct dirty_item *ditem;
627
628 item->list = &dirtylist;
539
540 ditem = (struct dirty_item *)mempool_alloc(sizeof(struct dirty_item));
541 ditem->item = item;
542
543 rbwrap_insert(&item->fname->rbtree, &ditem->rb, _dirty_cmp);
544 }
545 }else{
546 item->list = &cleanlist;

--- 60 unchanged lines hidden (view full) ---

607
608 list_remove(item->list, &item->list_elem);
609 _bcache_count(item->list, -1);
610
611 if (item->list != &dirtylist) {
612 struct dirty_item *ditem;
613
614 item->list = &dirtylist;
629 DBGCMD(_dirty++;)
630
631 ditem = (struct dirty_item *)mempool_alloc(sizeof(struct dirty_item));
632 ditem->item = item;
633
634 rbwrap_insert(&item->fname->rbtree, &ditem->rb, _dirty_cmp);
635 }
636
637 marker = *((uint8_t*)(item->addr) + bcache_blocksize-1);
638 if ( filemgr_get_file_status(item->fname->curfile) != FILE_COMPACT_OLD ||

--- 35 unchanged lines hidden (view full) ---

674 fname.hash = crc32_8_last8(fname.filename, fname.filename_len, 0);
675 h = hash_find(&fnamedic, &fname.hash_elem);
676
677 if (h) {
678 // file exists
679 fname_item = _get_entry(h, struct fnamedic_item, hash_elem);
680
681 while(rb_first(&fname_item->rbtree)) {
615 ditem = (struct dirty_item *)mempool_alloc(sizeof(struct dirty_item));
616 ditem->item = item;
617
618 rbwrap_insert(&item->fname->rbtree, &ditem->rb, _dirty_cmp);
619 }
620
621 marker = *((uint8_t*)(item->addr) + bcache_blocksize-1);
622 if ( filemgr_get_file_status(item->fname->curfile) != FILE_COMPACT_OLD ||

--- 35 unchanged lines hidden (view full) ---

658 fname.hash = crc32_8_last8(fname.filename, fname.filename_len, 0);
659 h = hash_find(&fnamedic, &fname.hash_elem);
660
661 if (h) {
662 // file exists
663 fname_item = _get_entry(h, struct fnamedic_item, hash_elem);
664
665 while(rb_first(&fname_item->rbtree)) {
682 spin_unlock(&bcache_lock);
683 _bcache_evict_dirty(fname_item, 0);
666 _bcache_evict_dirty(fname_item, 0);
684 spin_lock(&bcache_lock);
685 }
686 }
687
688 spin_unlock(&bcache_lock);
689
690 DBGCMD(
691 gettimeofday(&_b_, NULL);
692 _rr_ = _utime_gap(_a_,_b_);

--- 77 unchanged lines hidden (view full) ---

770 _file_to_fname_query(file, &fname);
771 h = hash_find(&fnamedic, &fname.hash_elem);
772
773 if (h) {
774 // file exists
775 fname_item = _get_entry(h, struct fnamedic_item, hash_elem);
776
777 while(rb_first(&fname_item->rbtree)) {
667 }
668 }
669
670 spin_unlock(&bcache_lock);
671
672 DBGCMD(
673 gettimeofday(&_b_, NULL);
674 _rr_ = _utime_gap(_a_,_b_);

--- 77 unchanged lines hidden (view full) ---

752 _file_to_fname_query(file, &fname);
753 h = hash_find(&fnamedic, &fname.hash_elem);
754
755 if (h) {
756 // file exists
757 fname_item = _get_entry(h, struct fnamedic_item, hash_elem);
758
759 while(rb_first(&fname_item->rbtree)) {
778 spin_unlock(&bcache_lock);
779 _bcache_evict_dirty(fname_item, 1);
760 _bcache_evict_dirty(fname_item, 1);
780 spin_lock(&bcache_lock);
781 }
782 }
783
784 spin_unlock(&bcache_lock);
785
786 DBGCMD(
787 gettimeofday(&_b_, NULL);
788 _rr_ = _utime_gap(_a_,_b_);

--- 92 unchanged lines hidden ---
761 }
762 }
763
764 spin_unlock(&bcache_lock);
765
766 DBGCMD(
767 gettimeofday(&_b_, NULL);
768 _rr_ = _utime_gap(_a_,_b_);

--- 92 unchanged lines hidden ---