Changeset 919 for 1.8.3/trunk/src/chunk.c
- Timestamp:
- 06/12/07 15:21:47 (1 year ago)
- Files:
-
- 1.8.3/trunk/src/chunk.c (modified) (60 diffs)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
1.8.3/trunk/src/chunk.c
r846 r919 238 238 239 239 #ifdef WIN32 240 #pragma warning( disable : 4761) /* disable warning re conversion */240 #pragma warning( disable : 4761) /* disable warning re conversion */ 241 241 #endif 242 242 … … 265 265 #ifdef CHUNK_DEBUG 266 266 #define ASSERT(x) assert(x) 267 #else /* CHUNK_DEBUG */268 static int ignore; /**< Used to shut up compiler warnings when not asserting */267 #else /* CHUNK_DEBUG */ 268 static int ignore; /**< Used to shut up compiler warnings when not asserting */ 269 269 #define ASSERT(x) ignore++ 270 #endif /* CHUNK_DEBUG */270 #endif /* CHUNK_DEBUG */ 271 271 272 272 /* … … 531 531 */ 532 532 typedef struct region_header { 533 uint16_t region_id; /**< will be INVALID_REGION_ID if not in use */534 uint16_t first_free; /**< offset of 1st free chunk */535 struct region_header *prev; /**< linked list prev for LRU cache */536 struct region_header *next; /**< linked list next for LRU cache */533 uint16_t region_id; /**< will be INVALID_REGION_ID if not in use */ 534 uint16_t first_free; /**< offset of 1st free chunk */ 535 struct region_header *prev; /**< linked list prev for LRU cache */ 536 struct region_header *next; /**< linked list next for LRU cache */ 537 537 } RegionHeader; 538 538 … … 541 541 /** In-memory (never paged) region info. */ 542 542 typedef struct region { 543 uint16_t used_count; /**< number of used chunks */544 uint16_t free_count; /**< number of free chunks */545 uint16_t free_bytes; /**< number of free bytes (with headers) */546 uint16_t largest_free_chunk; /**< largest single free chunk */547 uint32_t total_derefs; /**< total of all used chunk derefs */548 uint32_t period_last_touched; /**< "this" period, for deref counts;543 uint16_t used_count; /**< number of used chunks */ 544 uint16_t free_count; /**< number of free chunks */ 545 uint16_t free_bytes; /**< number of free bytes (with headers) */ 546 uint16_t largest_free_chunk; /**< largest single free chunk */ 547 uint32_t total_derefs; /**< total of all used chunk derefs */ 548 uint32_t period_last_touched; /**< "this" period, for deref counts; 549 549 we don't page in regions to update 550 550 counts on period change! */ 551 RegionHeader *in_memory; /**< cache entry; NULL if paged out */552 uint16_t oddballs[NUM_ODDBALLS]; /**< chunk offsets with odd derefs */551 RegionHeader *in_memory; /**< cache entry; NULL if paged out */ 552 uint16_t oddballs[NUM_ODDBALLS]; /**< chunk offsets with odd derefs */ 553 553 } Region; 554 554 … … 588 588 * Info about all regions 589 589 */ 590 static uint32_t region_count; /**< regions in use */591 static uint32_t region_array_len; /**< length of regions array */592 static Region *regions; /**< regions array, realloced as (rarely) needed */590 static uint32_t region_count; /**< regions in use */ 591 static uint32_t region_array_len; /**< length of regions array */ 592 static Region *regions; /**< regions array, realloced as (rarely) needed */ 593 593 594 594 /* 595 595 * regions presently in memory 596 596 */ 597 static uint32_t cached_region_count; /**< number of regions in cache */598 static RegionHeader *cache_head; /**< most recently used region */599 static RegionHeader *cache_tail; /**< least recently used region */597 static uint32_t cached_region_count; /**< number of regions in cache */ 598 static RegionHeader *cache_head; /**< most recently used region */ 599 static RegionHeader *cache_tail; /**< least recently used region */ 600 600 601 601 /* 602 602 * statistics 603 603 */ 604 static int stat_used_short_count; /**< How many short chunks? */605 static int stat_used_short_bytes; /**< How much space in short chunks? */606 static int stat_used_medium_count; /**< How many medium chunks? */607 static int stat_used_medium_bytes; /**< How much space in medium chunks? */608 static int stat_used_long_count; /**< How many long chunks? */609 static int stat_used_long_bytes; /**< How much space in long chunks? */610 static int stat_deref_count; /**< Dereferences this period */611 static int stat_deref_maxxed; /**< Number of chunks with max derefs */604 static int stat_used_short_count; /**< How many short chunks? */ 605 static int stat_used_short_bytes; /**< How much space in short chunks? */ 606 static int stat_used_medium_count; /**< How many medium chunks? */ 607 static int stat_used_medium_bytes; /**< How much space in medium chunks? */ 608 static int stat_used_long_count; /**< How many long chunks? */ 609 static int stat_used_long_bytes; /**< How much space in long chunks? */ 610 static int stat_deref_count; /**< Dereferences this period */ 611 static int stat_deref_maxxed; /**< Number of chunks with max derefs */ 612 612 /** histogram for average derefs of regions being paged in/out */ 613 613 static int stat_paging_histogram[CHUNK_DEREF_MAX + 1]; 614 static int stat_page_out; /**< Number of page-outs */615 static int stat_page_in; /**< Number of page-ins */616 static int stat_migrate_slide; /**< Number of slide migrations */617 static int stat_migrate_move; /**< Number of move migrations */618 static int stat_migrate_away; /**< Number of chunk evictions */619 static int stat_create; /**< Number of chunk creations */620 static int stat_delete; /**< Number of chunk deletions */614 static int stat_page_out; /**< Number of page-outs */ 615 static int stat_page_in; /**< Number of page-ins */ 616 static int stat_migrate_slide; /**< Number of slide migrations */ 617 static int stat_migrate_move; /**< Number of move migrations */ 618 static int stat_migrate_away; /**< Number of chunk evictions */ 619 static int stat_create; /**< Number of chunk creations */ 620 static int stat_delete; /**< Number of chunk deletions */ 621 621 622 622 … … 625 625 * migration globals that are used for holding relevant data... 626 626 */ 627 static int m_count; /**< The used length for the arrays. */627 static int m_count; /**< The used length for the arrays. */ 628 628 static chunk_reference_t **m_references; /**< The passed-in references array. */ 629 629 … … 662 662 #else 663 663 if (format) 664 return; /* shut up the compiler warning */664 return; /* shut up the compiler warning */ 665 665 #endif 666 666 } … … 717 717 718 718 fprintf(fp, "region: id:%04x period:%-8x deref:%-8x (%-2x per chunk)\n", 719 region, rp->period_last_touched, rp->total_derefs,720 RegionDerefs(region));719 region, rp->period_last_touched, rp->total_derefs, 720 RegionDerefs(region)); 721 721 fprintf(fp, " #used:%-4x #free:%-4x fbytes:%-4x hole:%-4x ", 722 rp->used_count, rp->free_count, rp->free_bytes,723 rp->largest_free_chunk);722 rp->used_count, rp->free_count, rp->free_bytes, 723 rp->largest_free_chunk); 724 724 if (rhp) 725 725 fprintf(fp, "first:%-4x h_id:%-4x\n", rhp->first_free, rhp->region_id); … … 730 730 if (rhp) { 731 731 for (offset = FIRST_CHUNK_OFFSET_IN_REGION; 732 offset < REGION_SIZE; offset += ChunkFullLen(region, offset)) {732 offset < REGION_SIZE; offset += ChunkFullLen(region, offset)) { 733 733 fprintf(fp, "chunk:%c%4s %-6s off:%04x full:%04x ", 734 migratable(region, offset) ? '*' : ' ',735 ChunkIsFree(region, offset) ? "FREE" : "",736 ChunkIsShort(region, offset) ? "SHORT" :737 (ChunkIsMedium(region, offset) ? "MEDIUM" : "LONG"),738 offset, ChunkFullLen(region, offset));734 migratable(region, offset) ? '*' : ' ', 735 ChunkIsFree(region, offset) ? "FREE" : "", 736 ChunkIsShort(region, offset) ? "SHORT" : 737 (ChunkIsMedium(region, offset) ? "MEDIUM" : "LONG"), 738 offset, ChunkFullLen(region, offset)); 739 739 if (ChunkIsFree(region, offset)) { 740 fprintf(fp, "next:%04x\n", ChunkNextFree(region, offset));740 fprintf(fp, "next:%04x\n", ChunkNextFree(region, offset)); 741 741 } else { 742 fprintf(fp, "doff:%04x len:%04x ",743 ChunkDataPtr(region, offset) - (unsigned char *) rhp,744 ChunkLen(region, offset));745 count = ChunkDerefs(region, offset);746 if (count == 0xFF) {747 fprintf(fp, "deref:many\n");748 } else {749 fprintf(fp, "deref:%04x\n", count);750 }742 fprintf(fp, "doff:%04x len:%04x ", 743 ChunkDataPtr(region, offset) - (unsigned char *) rhp, 744 ChunkLen(region, offset)); 745 count = ChunkDerefs(region, offset); 746 if (count == 0xFF) { 747 fprintf(fp, "deref:many\n"); 748 } else { 749 fprintf(fp, "deref:%04x\n", count); 750 } 751 751 } 752 752 } … … 770 770 if (pos == offset) { 771 771 if (ChunkIsFree(region, pos)) 772 mush_panic("Invalid reference to free chunk as used");772 mush_panic("Invalid reference to free chunk as used"); 773 773 return; 774 774 } … … 803 803 if (region >= region_count) { 804 804 do_rawlog(LT_ERR, "region 0x%04x is not valid: region_count is 0x%04x", 805 region, region_count);805 region, region_count); 806 806 return 0; 807 807 } … … 811 811 if (rp->used_count > REGION_SIZE / MIN_REMNANT_LEN) { 812 812 do_rawlog(LT_ERR, 813 "region 0x%04x is not valid: chunk count is ludicrous: 0x%04x",814 region, rp->used_count);813 "region 0x%04x is not valid: chunk count is ludicrous: 0x%04x", 814 region, rp->used_count); 815 815 result = 0; 816 816 } 817 817 if (rp->free_count > REGION_SIZE / MIN_REMNANT_LEN) { 818 818 do_rawlog(LT_ERR, 819 "region 0x%04x is not valid: free count is ludicrous: 0x%04x",820 region, rp->free_count);819 "region 0x%04x is not valid: free count is ludicrous: 0x%04x", 820 region, rp->free_count); 821 821 result = 0; 822 822 } 823 823 if (rp->largest_free_chunk > rp->free_bytes) { 824 824 do_rawlog(LT_ERR, 825 "region 0x%04x is not valid: largest free chunk > free bytes:"826 " 0x%04x > 0x%04x",827 region, rp->largest_free_chunk, rp->free_bytes);825 "region 0x%04x is not valid: largest free chunk > free bytes:" 826 " 0x%04x > 0x%04x", 827 region, rp->largest_free_chunk, rp->free_bytes); 828 828 result = 0; 829 829 } … … 835 835 if (rhp->region_id != region) { 836 836 do_rawlog(LT_ERR, "region 0x%04x is not valid: region in cache is 0x%04x", 837 region, rhp->region_id);837 region, rhp->region_id); 838 838 result = 0; 839 839 } … … 850 850 if (was_free && ChunkIsFree(region, offset)) { 851 851 do_rawlog(LT_ERR, 852 "region 0x%04x is not valid: uncoalesced free chunk:"853 " 0x%04x (see map)", region, offset);852 "region 0x%04x is not valid: uncoalesced free chunk:" 853 " 0x%04x (see map)", region, offset); 854 854 result = 0; 855 855 dump = 1; … … 861 861 free_bytes += len; 862 862 if (largest_free < len) 863 largest_free = len;863 largest_free = len; 864 864 if (next_free != offset) { 865 do_rawlog(LT_ERR,866 "region 0x%04x is not valid: free chain broken:"867 " 0x%04x, expecting 0x%04x (see map)",868 region, offset, next_free);869 result = 0;870 dump = 1;865 do_rawlog(LT_ERR, 866 "region 0x%04x is not valid: free chain broken:" 867 " 0x%04x, expecting 0x%04x (see map)", 868 region, offset, next_free); 869 result = 0; 870 dump = 1; 871 871 } 872 872 next_free = ChunkNextFree(region, offset); … … 875 875 total_derefs += ChunkDerefs(region, offset); 876 876 if (ChunkIsMedium(region, offset) && 877 ChunkLen(region, offset) <= MAX_SHORT_CHUNK_LEN) {878 do_rawlog(LT_ERR,879 "region 0x%04x is not valid: medium chunk too small:"880 " 0x%04x (see map)", region, offset);881 result = 0;882 dump = 1;877 ChunkLen(region, offset) <= MAX_SHORT_CHUNK_LEN) { 878 do_rawlog(LT_ERR, 879 "region 0x%04x is not valid: medium chunk too small:" 880 " 0x%04x (see map)", region, offset); 881 result = 0; 882 dump = 1; 883 883 } 884 884 if (ChunkIsLong(region, offset) && 885 ChunkLen(region, offset) <= MAX_MEDIUM_CHUNK_LEN) {886 do_rawlog(LT_ERR,887 "region 0x%04x is not valid: long chunk too small:"888 " 0x%04x (see map)", region, offset);889 result = 0;890 dump = 1;885 ChunkLen(region, offset) <= MAX_MEDIUM_CHUNK_LEN) { 886 do_rawlog(LT_ERR, 887 "region 0x%04x is not valid: long chunk too small:" 888 " 0x%04x (see map)", region, offset); 889 result = 0; 890 dump = 1; 891 891 } 892 892 } … … 894 894 if (offset != REGION_SIZE) { 895 895 do_rawlog(LT_ERR, 896 "region 0x%04x is not valid: last chunk past bounds (see map)",897 region);896 "region 0x%04x is not valid: last chunk past bounds (see map)", 897 region); 898 898 result = 0; 899 899 } 900 900 if (next_free != 0) { 901 901 do_rawlog(LT_ERR, 902 "region 0x%04x is not valid: free chain unterminated:"903 " expecting 0x%04x (see map)", region, next_free);902 "region 0x%04x is not valid: free chain unterminated:" 903 " expecting 0x%04x (see map)", region, next_free); 904 904 result = 0; 905 905 dump = 1; … … 907 907 if (rp->used_count != used_count) { 908 908 do_rawlog(LT_ERR, 909 "region 0x%04x is not valid: used count is wrong:"910 " 0x%04x should be 0x%04x", region, rp->used_count, used_count);909 "region 0x%04x is not valid: used count is wrong:" 910 " 0x%04x should be 0x%04x", region, rp->used_count, used_count); 911 911 result = 0; 912 912 } 913 913 if (rp->total_derefs != total_derefs) { 914 914 do_rawlog(LT_ERR, 915 "region 0x%04x is not valid: total derefs is wrong:"916 " 0x%04x should be 0x%04x",917 region, rp->total_derefs, total_derefs);915 "region 0x%04x is not valid: total derefs is wrong:" 916 " 0x%04x should be 0x%04x", 917 region, rp->total_derefs, total_derefs); 918 918 result = 0; 919 919 } 920 920 if (rp->free_count != free_count) { 921 921 do_rawlog(LT_ERR, 922 "region 0x%04x is not valid: free count is wrong:"923 " 0x%04x should be 0x%04x", region, rp->free_count, free_count);922 "region 0x%04x is not valid: free count is wrong:" 923 " 0x%04x should be 0x%04x", region, rp->free_count, free_count); 924 924 result = 0; 925 925 } 926 926 if (rp->free_bytes != free_bytes) { 927 927 do_rawlog(LT_ERR, 928 "region 0x%04x is not valid: free bytes is wrong:"929 " 0x%04x should be 0x%04x", region, rp->free_bytes, free_bytes);928 "region 0x%04x is not valid: free bytes is wrong:" 929 " 0x%04x should be 0x%04x", region, rp->free_bytes, free_bytes); 930 930 result = 0; 931 931 } 932 932 if (rp->largest_free_chunk != largest_free) { 933 933 do_rawlog(LT_ERR, 934 "region 0x%04x is not valid: largest free is wrong:"935 " 0x%04x should be 0x%04x",936 region, rp->largest_free_chunk, largest_free);934 "region 0x%04x is not valid: largest free is wrong:" 935 " 0x%04x should be 0x%04x", 936 region, rp->largest_free_chunk, largest_free); 937 937 result = 0; 938 938 } … … 958 958 static void 959 959 write_used_chunk(uint16_t region, uint16_t offset, uint16_t full_len, 960 unsigned char const *data, uint16_t data_len, uint8_t derefs)960 unsigned char const *data, uint16_t data_len, uint8_t derefs) 961 961 { 962 962 unsigned char *cptr = ChunkPointer(region, offset); … … 993 993 static void 994 994 write_free_chunk(uint16_t region, uint16_t offset, uint16_t full_len, 995 uint16_t next)995 uint16_t next) 996 996 { 997 997 unsigned char *cptr = ChunkPointer(region, offset); … … 1178 1178 uint16_t hole; 1179 1179 for (hole = rp->in_memory->first_free; 1180 hole; hole = ChunkNextFree(region, hole))1181 if (ChunkNextFree(region, hole) == offset)1182 break;1180 hole; hole = ChunkNextFree(region, hole)) 1181 if (ChunkNextFree(region, hole) == offset) 1182 break; 1183 1183 ASSERT(hole); 1184 1184 write_next_free(region, hole, ChunkNextFree(region, offset)); … … 1199 1199 rp->free_bytes -= full_len; 1200 1200 write_free_chunk(region, offset + full_len, 1201 hole_len - full_len, ChunkNextFree(region, offset));1201 hole_len - full_len, ChunkNextFree(region, offset)); 1202 1202 if (rp->in_memory->first_free == offset) 1203 1203 rp->in_memory->first_free += full_len; … … 1205 1205 uint16_t hole; 1206 1206 for (hole = rp->in_memory->first_free; 1207 hole; hole = ChunkNextFree(region, hole))1208 if (ChunkNextFree(region, hole) == offset)1209 break;1207 hole; hole = ChunkNextFree(region, hole)) 1208 if (ChunkNextFree(region, hole) == offset) 1209 break; 1210 1210 ASSERT(hole); 1211 1211 write_next_free(region, hole, offset + full_len); … … 1217 1217 rp->free_bytes -= full_len; 1218 1218 write_free_chunk(region, offset, 1219 hole_len - full_len, ChunkNextFree(region, offset));1219 hole_len - full_len, ChunkNextFree(region, offset)); 1220 1220 if (rp->largest_free_chunk == hole_len) 1221 1221 rp->largest_free_chunk = largest_hole(region); … … 1275 1275 pos += done; 1276 1276 if (!remaining) 1277 return;1277 return; 1278 1278 } 1279 1279 #ifndef WIN32 … … 1284 1284 #ifdef WIN32 1285 1285 mush_panicf("chunk swap file read, %lu remaining, GetLastError %d", 1286 (unsigned long) remaining, GetLastError());1286 (unsigned long) remaining, GetLastError()); 1287 1287 #else 1288 1288 mush_panicf("chunk swap file read, %lu remaining, errno %d: %s", 1289 (unsigned long) remaining, errno, strerror(errno));1289 (unsigned long) remaining, errno, strerror(errno)); 1290 1290 #endif 1291 1291 } … … 1340 1340 pos += done; 1341 1341 if (!remaining) 1342 return;1342 return; 1343 1343 } 1344 1344 #ifndef WIN32 … … 1349 1349 #ifdef WIN32 1350 1350 mush_panicf("chunk swap file write, %lu remaining, GetLastError %d", 1351 (unsigned long) remaining, GetLastError());1351 (unsigned long) remaining, GetLastError()); 1352 1352 #else 1353 1353 mush_panicf("chunk swap file write, %lu remaining, errno %d: %s", 1354 (unsigned long) remaining, errno, strerror(errno));1354 (unsigned long) remaining, errno, strerror(errno)); 1355 1355 #endif 1356 1356 } … … 1417 1417 #ifdef DEBUG_CHUNK_PAGING 1418 1418 do_rawlog(LT_TRACE, "CHUNK: Paging out region %04x (offset %08x)", 1419 rhp->region_id, (unsigned) file_offset);1419 rhp->region_id, (unsigned) file_offset); 1420 1420 #endif 1421 1421 write_cache_region(swap_fd, rhp, rhp->region_id); … … 1459 1459 #ifdef DEBUG_CHUNK_PAGING 1460 1460 do_rawlog(LT_TRACE, "CHUNK: Paging in region %04x (offset %08x)", 1461 region, (unsigned) file_offset);1461 region, (unsigned) file_offset); 1462 1462 #endif 1463 1463 read_cache_region(swap_fd, rhp, region); … … 1476 1476 rp->total_derefs = 0; 1477 1477 for (offset = FIRST_CHUNK_OFFSET_IN_REGION; 1478 offset < REGION_SIZE; offset += ChunkFullLen(region, offset)) {1479 ChunkDerefs(region, offset) = 0;1478 offset < REGION_SIZE; offset += ChunkFullLen(region, offset)) { 1479 ChunkDerefs(region, offset) = 0; 1480 1480 } 1481 1481 } else { 1482 1482 rp->total_derefs = 0; 1483 1483 for (offset = FIRST_CHUNK_OFFSET_IN_REGION; 1484 offset < REGION_SIZE; offset += ChunkFullLen(region, offset)) {1485 if (ChunkIsFree(region, offset))1486 continue;1487 ChunkDerefs(region, offset) >>= shift;1488 rp->total_derefs += ChunkDerefs(region, offset);1484 offset < REGION_SIZE; offset += ChunkFullLen(region, offset)) { 1485 if (ChunkIsFree(region, offset)) 1486 continue; 1487 ChunkDerefs(region, offset) >>= shift; 1488 rp->total_derefs += ChunkDerefs(region, offset); 1489 1489 } 1490 1490 } … … 1521 1521 regions = (Region *) realloc(regions, region_array_len * sizeof(Region)); 1522 1522 if (!regions) 1523 mush_panic("chunk: region array realloc failure");1523 mush_panic("chunk: region array realloc failure"); 1524 1524 } 1525 1525 region = region_count; … … 1539 1539 regions[region].in_memory->first_free = FIRST_CHUNK_OFFSET_IN_REGION; 1540 1540 write_free_chunk(region, FIRST_CHUNK_OFFSET_IN_REGION, 1541 regions[region].free_bytes, 0);1541 regions[region].free_bytes, 0); 1542 1542 1543 1543 touch_cache_region(regions[region].in_memory); … … 1572 1572 while (j--) { 1573 1573 if (!rp->oddballs[j]) 1574 continue;1574 continue; 1575 1575 d2 = abs(mean - ChunkDerefs(region, rp->oddballs[j])); 1576 1576 if (d1 < d2) 1577 break;1577 break; 1578 1578 if (j < NUM_ODDBALLS - 1) 1579 rp->oddballs[j + 1] = rp->oddballs[j];1579 rp->oddballs[j + 1] = rp->oddballs[j]; 1580 1580 } 1581 1581 j++; … … 1612 1612 free_bytes += rp->free_bytes; 1613 1613 if (!FitsInSpace(full_len, rp->largest_free_chunk) && 1614 !(rp->free_count == 2 &&1615 rp->free_bytes - rp->largest_free_chunk == full_len))1614 !(rp->free_count == 2 && 1615 rp->free_bytes - rp->largest_free_chunk == full_len)) 1616 1616 continue; 1617 1617 … … 1639 1639 best_region = create_region(); 1640 1640 } else if (best_score > (1 << LONLINESS_LIMIT) + IN_MEMORY_BIAS && 1641 (free_bytes * 100 / (REGION_CAPACITY * region_count)) <1642 FREE_PERCENT_LIMIT) {1641 (free_bytes * 100 / (REGION_CAPACITY * region_count)) < 1642 FREE_PERCENT_LIMIT) { 1643 1643 #ifdef DEBUG_CHUNK_REGION_CREATE 1644 1644 do_rawlog(LT_TRACE, "find_best_region chose to create region %04x", region); … … 1657 1657 static uint16_t 1658 1658 find_best_offset(uint16_t full_len, uint16_t region, 1659 uint16_t old_region, uint16_t old_offset)1659 uint16_t old_region, uint16_t old_offset) 1660 1660 { 1661 1661 uint16_t fits, offset; … … 1668 1668 if (region == old_region) { 1669 1669 if (offset > old_offset) 1670 break;1670 break; 1671 1671 if (offset + ChunkFullLen(region, offset) == old_offset) 1672 return fits ? fits : offset;1672 return fits ? fits : offset; 1673 1673 } 1674 1674 if (ChunkFullLen(region, offset) == full_len) … … 1759 1759 stat_used_long_count * CHUNK_LONG_DATA_OFFSET; 1760 1760 STAT_OUT(tprintf 1761 ("Chunks: %10d allocated (%10d bytes, %10d (%2d%%) overhead)",1762 used_count, used_bytes, overhead,1763 used_bytes ? overhead * 100 / used_bytes : 0));1761 ("Chunks: %10d allocated (%10d bytes, %10d (%2d%%) overhead)", 1762 used_count, used_bytes, overhead, 1763 used_bytes ? overhead * 100 / used_bytes : 0)); 1764 1764 overhead = stat_used_short_count * CHUNK_SHORT_DATA_OFFSET; 1765 1765 STAT_OUT(tprintf 1766 (" %10d short (%10d bytes, %10d (%2d%%) overhead)",1767 stat_used_short_count, stat_used_short_bytes, overhead,1768 stat_used_short_bytes ? overhead * 100 /1769 stat_used_short_bytes : 0));1766 (" %10d short (%10d bytes, %10d (%2d%%) overhead)", 1767 stat_used_short_count, stat_used_short_bytes, overhead, 1768 stat_used_short_bytes ? overhead * 100 / 1769 stat_used_short_bytes : 0)); 1770 1770 overhead = stat_used_medium_count * CHUNK_MEDIUM_DATA_OFFSET; 1771 1771 STAT_OUT(tprintf 1772 (" %10d medium (%10d bytes, %10d (%2d%%) overhead)",1773 stat_used_medium_count, stat_used_medium_bytes, overhead,1774 stat_used_medium_bytes ? overhead * 100 /1775 stat_used_medium_bytes : 0));1772 (" %10d medium (%10d bytes, %10d (%2d%%) overhead)", 1773 stat_used_medium_count, stat_used_medium_bytes, overhead, 1774 stat_used_medium_bytes ? overhead * 100 / 1775 stat_used_medium_bytes : 0)); 1776 1776 overhead = stat_used_long_count * CHUNK_LONG_DATA_OFFSET; 1777 1777 STAT_OUT(tprintf 1778 (" %10d long (%10d bytes, %10d (%2d%%) overhead)",1779 stat_used_long_count, stat_used_long_bytes, overhead,1780 stat_used_long_bytes ? overhead * 100 / stat_used_long_bytes : 0));1778 (" %10d long (%10d bytes, %10d (%2d%%) overhead)", 1779 stat_used_long_count, stat_used_long_bytes, overhead, 1780 stat_used_long_bytes ? overhead * 100 / stat_used_long_bytes : 0)); 1781 1781 STAT_OUT(tprintf 1782 (" %10d free (%10d bytes, %10d (%2d%%) fragmented)",1783 free_count, free_bytes, free_bytes - free_large,1784 free_bytes ? (free_bytes - free_large) * 100 / free_bytes : 0));1782 (" %10d free (%10d bytes, %10d (%2d%%) fragmented)", 1783 free_count, free_bytes, free_bytes - free_large, 1784 free_bytes ? (free_bytes - free_large) * 100 / free_bytes : 0)); 1785 1785 overhead = region_count * REGION_SIZE + region_array_len * sizeof(Region); 1786 1786 STAT_OUT(tprintf("Storage: %10d total (%2d%% saturation)", 1787 overhead, used_bytes * 100 / overhead));1787 overhead, used_bytes * 100 / overhead)); 1788 1788 STAT_OUT(tprintf("Regions: %10d total, %8d cached", 1789 region_count, cached_region_count));1789 region_count, cached_region_count)); 1790 1790 STAT_OUT(tprintf("Paging: %10d out, %10d in", 1791 stat_page_out, stat_page_in));1791 stat_page_out, stat_page_in)); 1792 1792 STAT_OUT(" "); 1793 1793 STAT_OUT(tprintf("Period: %10d (%10d accesses so far, %10d chunks at max)", 1794 curr_period, stat_deref_count, stat_deref_maxxed));1794 curr_period, stat_deref_count, stat_deref_maxxed)); 1795 1795 STAT_OUT(tprintf("Activity: %10d creates, %10d deletes this period", 1796 stat_create, stat_delete));1796 stat_create, stat_delete)); 1797 1797 STAT_OUT(tprintf("Migration: %10d moves this period", 1798 stat_migrate_slide + stat_migrate_move));1798 stat_migrate_slide + stat_migrate_move)); 1799 1799 STAT_OUT(tprintf(" %10d slide %10d move", 1800 stat_migrate_slide, stat_migrate_move));1800 stat_migrate_slide, stat_migrate_move)); 1801 1801 STAT_OUT(tprintf(" %10d in region%10d out of region", 1802 stat_migrate_slide + stat_migrate_move - stat_migrate_away,1803 stat_migrate_away));1802 stat_migrate_slide + stat_migrate_move - stat_migrate_away, 1803 stat_migrate_away)); 1804 1804 } 1805 1805 … … 1812 1812 const char *s; 1813 1813 STAT_OUT(tprintf("Paging: %10d out, %10d in", 1814 stat_page_out, stat_page_in));1814 stat_page_out, stat_page_in)); 1815 1815 } 1816 1816 … … 1829 1829 for (rid = 0; rid < region_count; rid++) { 1830 1830 STAT_OUT(tprintf 1831 ("region:%4d #used:%5d #free:%5d "1832 "fbytes:%04x largest:%04x deref:%3d",1833 rid, regions[rid].used_count, regions[rid].free_count,1834 regions[rid].free_bytes, regions[rid].largest_free_chunk,1835 RegionDerefs(rid)));1831 ("region:%4d #used:%5d #free:%5d " 1832 "fbytes:%04x largest:%04x deref:%3d", 1833 rid, regions[rid].used_count, regions[rid].free_count, 1834 regions[rid].free_bytes, regions[rid].largest_free_chunk, 1835 RegionDerefs(rid))); 1836 1836 } 1837 1837 } … … 1894 1894 sprintf(num, "(%d)", k); 1895 1895 if (j < 32) { 1896 if (j < pen)1897 ante = 18;1898 else1899 ante = 19;1900 memcpy(buffer[ante] + j + 1, num, strlen(num));1901 pen = j + strlen(num) + 1;1896 if (j < pen) 1897 ante = 18; 1898 else 1899 ante = 19; 1900 memcpy(buffer[ante] + j + 1, num, strlen(num)); 1901 pen = j + strlen(num) + 1; 1902 1902 } else { 1903 if (j - (int) strlen(num) < pen)1904 ante = 18;1905 else1906 ante = 19;1907 memcpy(buffer[ante] + j - strlen(num), num, strlen(num));1908 pen = j;1903 if (j - (int) strlen(num) < pen) 1904 ante = 18; 1905 else 1906 ante = 19; 1907 memcpy(buffer[ante] + j - strlen(num), num, strlen(num)); 1908 pen = j; 1909 1909 } 1910 1910 } … … 1940 1940 for (k = j; k--;) { 1941 1941 if (m_references[k][0] < t[0]) 1942 break;1942 break; 1943 1943 m_references[k + 1] = m_references[k]; 1944 1944 } … … 1959 1959 1960 1960 debug_log("migrate_slide %d (%08x) to %04x%04x", 1961 which, m_references[which][0], region, offset);1961 which, m_references[which][0], region, offset); 1962 1962 1963 1963 bring_in_region(region); … … 1974 1974 #ifdef DEBUG_CHUNK_MIGRATE 1975 1975 do_rawlog(LT_TRACE, "CHUNK: Sliding chunk %08x to %04x%04x", 1976 m_references[which][0], region, offset);1976 m_references[which][0], region, offset); 1977 1977 #endif 1978 1978 m_references[which][0] = ChunkReference(region, offset); … … 1983 1983 #ifdef DEBUG_CHUNK_MIGRATE 1984 1984 do_rawlog(LT_TRACE, "CHUNK: Sliding chunk %08x to %04x%04x", 1985 m_references[which][0], region, prev);1985 m_references[which][0], region, prev); 1986 1986 #endif 1987 1987 m_references[which][0] = ChunkReference(region, prev); … … 2005 2005 do_rawlog(LT_TRACE, "Invalid region after migrate_slide!"); 2006 2006 do_rawlog(LT_TRACE, "Was moving %04x%04x to %04x%04x (became %08x)...", 2007 region, o_oth, region, o_off, m_references[which][0]);2007 region, o_oth, region, o_off, m_references[which][0]); 2008 2008 do_rawlog(LT_TRACE, "Chunk length %04x into hole length %04x", o_len, len); 2009 2009 debug_dump_region(region, tracelog_fp); … … 2028 2028 2029 2029 debug_log("migrate_move %d (%08x) to %04x%04x, alignment %d", 2030 which, m_references[which][0], region, offset, align);2030 which, m_references[which][0], region, offset, align); 2031 2031 2032 2032 s_reg = ChunkReferenceToRegion(m_references[which][0]); … … 2052 2052 dump_debug_log(tracelog_fp); 2053 2053 mush_panicf("Trying to migrate into too small a hole: %04x into %04x!", 2054 s_len, length);2054 s_len, length); 2055 2055 } 2056 2056 #endif … … 2061 2061 #ifdef DEBUG_CHUNK_MIGRATE 2062 2062 do_rawlog(LT_TRACE, "CHUNK: moving chunk %08x to %04x%04x", 2063 m_references[which][0], region, offset);2063 m_references[which][0], region, offset); 2064 2064 #endif 2065 2065 m_references[which][0] = ChunkReference(region, offset); … … 2073 2073 do_rawlog(LT_TRACE, "Invalid region after migrate_move!"); 2074 2074 do_rawlog(LT_TRACE, "Was moving %04x%04x to %04x%04x (became %04x%04x)...", 2075 s_reg, s_off, region, o_off, region, offset);2075 s_reg, s_off, region, o_off, region, offset); 2076 2076 do_rawlog(LT_TRACE, "Chunk length %04x into hole length %04x, alignment %d", 2077 s_len, length, align);2077 s_len, length, align); 2078 2078 debug_dump_region(region, tracelog_fp); 2079 2079 mush_panic("Invalid region after migrate_move!"); … … 2102 2102 best_offset = find_best_offset(length, best_region, region, offset); 2103 2103 if (best_offset) 2104 migrate_move(best_region, best_offset, j, 1);2104 migrate_move(best_region, best_offset, j, 1); 2105 2105 if (best_region != region) 2106 stat_migrate_away++;2106 stat_migrate_away++; 2107 2107 } 2108 2108 } … … 2186 2186 uint16_t 2187 2187 chunk_fetch(chunk_reference_t reference, 2188 unsigned char *buffer, uint16_t buffer_len)2188 unsigned char *buffer, uint16_t buffer_len) 2189 2189 { 2190 2190 uint16_t region, offset, len; … … 2276 2276 for (k = 0; k < m_count; k++) 2277 2277 if (ChunkReferenceToRegion(m_references[k][0]) == region) 2278 break;2278 break; 2279 2279 if (k >= m_count) 2280 2280 continue; … … 2283 2283 /* If not in memory, see if we've got an oddball. */ 2284 2284 while (k < m_count) { 2285 if (ChunkReferenceToRegion(m_references[k][0]) != region)2286 break;2287 offset = ChunkReferenceToOffset(m_references[k][0]);2288 for (l = 0; l < NUM_ODDBALLS; l++) {2289 if (regions[region].oddballs[l] == offset) {2290 /* Yup, have an oddball... that's worth bringing it in. */2291 bring_in_region(region);2292 goto do_migrate;2293 }2294 }2295 k++;2285 if (ChunkReferenceToRegion(m_references[k][0]) != region) 2286 break; 2287 offset = ChunkReferenceToOffset(m_references[k][0]); 2288 for (l = 0; l < NUM_ODDBALLS; l++) { 2289 if (regions[region].oddballs[l] == offset) { 2290 /* Yup, have an oddball... that's worth bringing it in. */ 2291 bring_in_region(region); 2292 goto do_migrate; 2293 } 2294 } 2295 k++; 2296 2296 } 2297 2297 } else { … … 2338 2338 #ifdef WIN32 2339 2339 swap_fd = CreateFile(CHUNK_SWAP_FILE, GENERIC_READ | GENERIC_WRITE, 2340 0, NULL, CREATE_ALWAYS, FILE_FLAG_DELETE_ON_CLOSE, NULL);2340 0, NULL, CREATE_ALWAYS, FILE_FLAG_DELETE_ON_CLOSE, NULL); 2341 2341 if (swap_fd == INVALID_HANDLE_VALUE) 2342 2342 mush_panicf("Cannot open swap file: %d", GetLastError()); … … 2357 2357 do_rawlog(LT_TRACE, "CHUNK: malloc()ing initial region array"); 2358 2358 #endif 2359 regions = mush_ malloc(region_array_len *sizeof(Region), "chunk region list");2359 regions = mush_calloc(region_array_len, sizeof(Region), "chunk region list"); 2360 2360 if (!regions) 2361 2361 mush_panic("cannot malloc space for chunk region list"); … … 2382 2382 case CSTATS_REGIONG: 2383 2383 chunk_histogram(player, chunk_regionhist(), 2384 "Chart number of regions (y) vs. references (x)");2384 "Chart number of regions (y) vs. references (x)"); 2385 2385 break; 2386 2386 case CSTATS_PAGINGG: 2387 2387 chunk_histogram(player, stat_paging_histogram, 2388 "Chart pages in/out (y) vs. references (x)");2388 "Chart pages in/out (y) vs. references (x)"); 2389 2389 break; 2390 2390 case CSTATS_FREESPACEG: 2391 2391 chunk_histogram(player, chunk_freehist(), 2392 "Chart region free space (y) vs. references (x)");2392 "Chart region free space (y) vs. references (x)"); 2393 2393 break; 2394 2394 case CSTATS_REGION: … … 2440 2440 rp->total_derefs = 0; 2441 2441 for (offset = FIRST_CHUNK_OFFSET_IN_REGION; 2442 offset < REGION_SIZE; offset += ChunkFullLen(region, offset)) {2443 ChunkDerefs(region, offset) = 0;2442 offset < REGION_SIZE; offset += ChunkFullLen(region, offset)) { 2443 ChunkDerefs(region, offset) = 0; 2444 2444 } 2445 2445 } else { 2446 2446 rp->total_derefs = 0; 2447 2447 for (offset = FIRST_CHUNK_OFFSET_IN_REGION; 2448 offset < REGION_SIZE; offset += ChunkFullLen(region, offset)) {2449 if (ChunkIsFree(region, offset))2450 continue;2451 ChunkDerefs(region, offset) >>= shift;2452 rp->total_derefs += ChunkDerefs(region, offset);2448 offset < REGION_SIZE; offset += ChunkFullLen(region, offset)) { 2449 if (ChunkIsFree(region, offset)) 2450 continue; 2451 ChunkDerefs(region, offset) >>= shift; 2452 rp->total_derefs += ChunkDerefs(region, offset); 2453 2453 } 2454 2454 } … … 2538 2538 swap_fd_child = -1; 2539 2539 } 2540 #endif /* !WIN32 */2540 #endif /* !WIN32 */
