| 385 | | static void *lookup_mem(struct mem_table_s *mtbl, uint64_t offset) |
| 386 | | { |
| | 408 | static void *lookup_mem(struct mem_table_s *mtbl, |
| | 409 | uint64_t offset, |
| | 410 | uint32_t *item_index, |
| | 411 | uint16_t *mem_ent_index, |
| | 412 | uint16_t *mem_ent_prev_index) |
| | 413 | { |
| | 414 | if(DBG)fprintf(out, "performing ment lookup...\n"); |
| | 415 | /* index into mem hash table */ |
| | 416 | unsigned int index = offset % MEM_TABLE_HASH_MAX; |
| | 417 | if(DBG)fprintf(out, "\toffset: 0X%llX hashes to index: %u\n", offset, index); |
| | 418 | struct mem_ent_s *current = &(mtbl->mem[index]); |
| | 419 | int16_t p,c,n; /* previous, current, next memory entry index in mtbl */ |
| | 420 | p = NIL; c = index; n = current->next; |
| | 421 | while(1){ |
| | 422 | //if(DBG)fprintf(out, "\tp=%d\tc=%d\tn=%d\n", (int)p, (int)c, (int)n); |
| | 423 | //tags match? |
| | 424 | if(offset==current->tag){ |
| | 425 | if(DBG)fprintf(out, "\tmatch located: 0X%llX==0X%llX\n", offset, current->tag); |
| | 426 | //possibly update LRU list based on lookup? |
| | 427 | |
| | 428 | /* If params !NULL, set their values */ |
| | 429 | if(item_index!=NULL && mem_ent_index!=NULL && |
| | 430 | mem_ent_prev_index!=NULL){ |
| | 431 | *item_index = current->item; |
| | 432 | *mem_ent_index = c; |
| | 433 | *mem_ent_prev_index = p; |
| | 434 | } |
| | 435 | return (void *)(&ucache->b[current->item].mblk); |
| | 436 | } |
| | 437 | else{ |
| | 438 | //if(DBG)fprintf(out, "\t0X%llX!=0X%llX\n", offset, current->tag); |
| | 439 | //if next available iterate |
| | 440 | if((int16_t)current->next==NIL){ |
| | 441 | if(DBG)fprintf(out, "\tmemory entry not found\n"); |
| | 442 | return (struct mem_table_s *)NIL; |
| | 443 | } |
| | 444 | else{ |
| | 445 | //fprintf(out, "\tnext really not null: %d!=-1\n", (int)(current->next)); |
| | 446 | current = &(mtbl->mem[current->next]); |
| | 447 | p=c; c=n; n=current->next; |
| | 448 | //if(DBG)fprintf(out, "\titerating across chain: next index = %d\n", (int16_t)n); |
| | 449 | } |
| | 450 | } |
| | 451 | } |
| | 452 | } |
| | 453 | |
| | 454 | |
| | 455 | void print_lru(struct mem_table_s *mtbl){ |
| | 456 | if(DBG)fprintf(out, "\tno ment\n"); |
| | 457 | if(DBG)fprintf(out, "\tprinting lru list:\n"); |
| | 458 | if(DBG)fprintf(out, "\t\tlru: %d\n", (int16_t)mtbl->lru_last); |
| | 459 | uint16_t current= mtbl->lru_last; |
| | 460 | while((int16_t)current!=NIL){ |
| | 461 | current = mtbl->mem[current].lru_prev; |
| | 462 | if(DBG)fprintf(out, "\t\tprev: %d\n", (int16_t)current); |
| | 463 | } |
| | 464 | } |
| | 465 | |
| | 466 | void update_lru(struct mem_table_s *mtbl, |
| | 467 | uint16_t index){ |
| | 468 | if(DBG)fprintf(out, "updating lru...\n"); |
| | 469 | if((int16_t)index<MEM_TABLE_HASH_MAX){ |
| | 470 | if(DBG)fprintf(out, "\t%d<MEM_TABLE_HASH_MAX, not adding to LRU\n", index); |
| | 471 | return; |
| | 472 | } |
| | 473 | /* update LRU List */ |
| | 474 | if((int16_t)mtbl->lru_first==NIL && (int16_t)mtbl->lru_last==NIL){ |
| | 475 | if(DBG)fprintf(out, "\tsetting lru first and last\n"); |
| | 476 | mtbl->lru_first = index; |
| | 477 | mtbl->lru_last = index; |
| | 478 | mtbl->mem[index].lru_prev = NIL; |
| | 479 | mtbl->mem[index].lru_next = NIL; |
| | 480 | } |
| | 481 | else if(mtbl->lru_first==mtbl->lru_last){ |
| | 482 | if(mtbl->lru_first!=index){//if not already the first and last |
| | 483 | if(DBG)fprintf(out, "\tinserting second record in LRU\n"); |
| | 484 | mtbl->mem[mtbl->lru_last].lru_prev = index; //point tail.prev to new |
| | 485 | mtbl->mem[index].lru_prev = NIL; //point new.prev to nil |
| | 486 | mtbl->mem[index].lru_next = mtbl->lru_last; //point the new.next to the tail |
| | 487 | mtbl->lru_first = index; //point the head to the new |
| | 488 | } |
| | 489 | } |
| | 490 | else{ |
| | 491 | if(DBG)fprintf(out, "\trepairing previous LRU links and inserting record in LRU\n"); |
| | 492 | /* repair links */ |
| | 493 | if((int16_t)mtbl->mem[index].lru_prev!=NIL){ |
| | 494 | mtbl->mem[mtbl->mem[index].lru_prev].lru_next = |
| | 495 | mtbl->mem[index].lru_next; |
| | 496 | } |
| | 497 | if((int16_t)mtbl->mem[index].lru_next!=NIL){ |
| | 498 | mtbl->mem[mtbl->mem[index].lru_next].lru_prev = |
| | 499 | mtbl->mem[index].lru_prev; |
| | 500 | } |
| | 501 | /* update nodes own link */ |
| | 502 | mtbl->mem[mtbl->lru_first].lru_prev = index; |
| | 503 | mtbl->mem[index].lru_next = mtbl->lru_first; |
| | 504 | mtbl->mem[index].lru_prev = NIL; |
| | 505 | /* Finally, establish this entry as the first on lru */ |
| | 506 | mtbl->lru_first = index; |
| | 507 | } |
| | 508 | } |
| | 509 | |
| | 510 | /* Set the block index where data is stored */ |
| | 511 | static void *set_item(struct mem_table_s *mtbl, |
| | 512 | uint64_t offset, |
| | 513 | uint16_t index){ |
| | 514 | int free_blk = get_free_blk(); |
| | 515 | if(free_blk!=NIL){ /* got block */ |
| | 516 | /* increment num_blocks used by this mtbl */ |
| | 517 | mtbl->num_blocks++; |
| | 518 | update_lru(mtbl, index); |
| | 519 | if(DBG)fprintf(out, "\tsuccessfully inserted into ment\n"); |
| | 520 | /* set item to block number */ |
| | 521 | mtbl->mem[index].tag = offset; |
| | 522 | mtbl->mem[index].item = free_blk; |
| | 523 | return (void *)&(ucache->b[free_blk]); |
| | 524 | } |
| | 525 | else{ /* NIL */ |
| | 526 | if(DBG)fprintf(out, "\tno blk\n"); |
| | 527 | return (void *)NIL; |
| | 528 | } |
| | 533 | if(DBG)fprintf(out, "trying to insert mem...\n"); |
| | 534 | /* index into mem hash table */ |
| | 535 | unsigned int index = offset % MEM_TABLE_HASH_MAX; |
| | 536 | if(DBG)fprintf(out, "\toffset: 0X%llX hashes to index: %u\n", offset, index); |
| | 537 | struct mem_ent_s *current = &(mtbl->mem[index]); |
| | 538 | /* lookup first */ |
| | 539 | void *returnValue = lookup_mem(mtbl, offset, NULL, NULL, NULL); |
| | 540 | if((int)returnValue!=NIL){ |
| | 541 | if(DBG)fprintf(out, "\tblock for this offset already exists @ 0X%X", (unsigned int)returnValue); |
| | 542 | return returnValue; |
| | 543 | } |
| | 544 | if(DBG)fprintf(out, "\tlookup returned NIL\n"); |
| | 545 | if((int64_t)mtbl->mem[index].tag!=NIL){ /* if head occupied, need to get free ment */ |
| | 546 | int mentIndex = get_free_ment(mtbl); |
| | 547 | if(mentIndex==NIL){ /* no free memory entry available */ |
| | 548 | //print_lru(mtbl); |
| | 549 | uint16_t lru = mtbl->lru_last; |
| | 550 | if(DBG)fprintf(out, "evicting memory entry = %d\n", lru); |
| | 551 | remove_mem(mtbl, mtbl->mem[lru].tag); /* evict LRU ment */ |
| | 552 | mentIndex = get_free_ment(mtbl); /* try to get ment again */ |
| | 553 | |
| | 554 | } |
| | 555 | if(mentIndex!=NIL){ |
| | 556 | if(DBG)fprintf(out, "\tfound free memory entry @ index = %d\n", mentIndex); |
| | 557 | /* insert after head of chain */ |
| | 558 | uint16_t next_ment = current->next; |
| | 559 | current->next = mentIndex; |
| | 560 | mtbl->mem[mentIndex].next = next_ment; |
| | 561 | return set_item(mtbl, offset, mentIndex); |
| | 562 | } |
| | 563 | } |
| | 564 | else{ /* No need to iterate to next in chain, just use head */ |
| | 565 | return set_item(mtbl, offset, index); |
| | 566 | } |
| 395 | | } |
| 396 | | |
| 397 | | /* externally visible API */ |
| 398 | | #if 0 |
| 399 | | int ucache_open_file(PVFS_object_ref *handle) |
| 400 | | { |
| 401 | | } |
| 402 | | |
| 403 | | void *ucache_lookup(PVFS_object_ref *handle, uint64_t offset) |
| 404 | | { |
| 405 | | } |
| 406 | | |
| 407 | | void *ucache_insert(PVFS_object_ref *handle, uint64_t offset) |
| 408 | | { |
| 409 | | } |
| 410 | | |
| 411 | | int ucache_remove(PVFS_object_ref *handle, uint64_t offset) |
| 412 | | { |
| 413 | | } |
| 414 | | |
| 415 | | int ucache_flush(PVFS_object_ref *handle) |
| 416 | | { |
| 417 | | } |
| 418 | | |
| 419 | | int ucache_close_file(PVFS_object_ref *handle) |
| 420 | | { |
| 421 | | } |
| 422 | | #endif |
| | 571 | if(DBG)fprintf(out, "trying to remove memory entry...\n"); |
| | 572 | //some indexes... |
| | 573 | int32_t item_index; |
| | 574 | int16_t mem_ent_index; |
| | 575 | int16_t mem_ent_prev_index; |
| | 576 | |
| | 577 | void *retValue = lookup_mem(mtbl, offset, &item_index, &mem_ent_index, &mem_ent_prev_index); |
| | 578 | |
| | 579 | /* Verify we've recieved the necessary info */ |
| | 580 | if((int)retValue==NIL){ |
| | 581 | if(DBG)fprintf(out, "\tremoval error: memory entry not found matching offset"); |
| | 582 | return NIL; |
| | 583 | } |
| | 584 | |
| | 585 | /* Remove from LRU */ |
| | 586 | /* update each of adjacent nodes' link */ |
| | 587 | if((int16_t)mtbl->mem[mem_ent_index].lru_prev!=NIL){ |
| | 588 | mtbl->mem[mtbl->mem[mem_ent_index].lru_prev].lru_next = mtbl->mem[mem_ent_index].lru_next; |
| | 589 | } |
| | 590 | if((int16_t)mtbl->mem[mem_ent_index].lru_next!=NIL){ |
| | 591 | mtbl->mem[mtbl->mem[mem_ent_index].lru_next].lru_prev = mtbl->mem[mem_ent_index].lru_prev; |
| | 592 | } |
| | 593 | |
| | 594 | if(mem_ent_index==mtbl->lru_first){ /* is node the head */ |
| | 595 | mtbl->lru_first = mtbl->mem[mem_ent_index].lru_next; |
| | 596 | } |
| | 597 | if(mem_ent_index==mtbl->lru_last){ /* is node the tail */ |
| | 598 | mtbl->lru_last = mtbl->mem[mem_ent_index].lru_prev; |
| | 599 | } |
| | 600 | /* Remove from Dirty if Dirty */ |
| | 601 | |
| | 602 | /* add memory block back to free list */ |
| | 603 | put_free_blk(item_index); |
| | 604 | |
| | 605 | /* Repair link */ |
| | 606 | if((int16_t)mem_ent_prev_index!=NIL){ |
| | 607 | mtbl->mem[mem_ent_prev_index].next = mtbl->mem[mem_ent_index].next; |
| | 608 | } |
| | 609 | /* newly free mem entry becomes new head of free mem entry list if less than hash table max */ |
| | 610 | put_free_ment(mtbl, mem_ent_index); |
| | 611 | mtbl->num_blocks--; |
| | 612 | if(DBG)fprintf(out, "\tmemory entry removal sucessful\n"); |
| | 613 | return(1); |
| | 614 | } |
| | 615 | |