Replaced single 128 kB cache tile by 32 tiles of 64 kB each

This commit is contained in:
Thomas Schmitt 2008-04-01 21:31:25 +00:00
parent 27cde95ca0
commit 0e394bca6a
2 changed files with 198 additions and 35 deletions

View File

@ -27,16 +27,204 @@
#include "isoburn.h" #include "isoburn.h"
/* Cached reading of image tree data */ /* Powers of 2 only ! Less than 16 makes not much sense. */
/* Current implementation : single tile 128 kB */ #define Libisoburn_tile_blockS 32
/* Undef to get to older single tile version
*/
#define Libisoburn_cache_tileS 32
/* Debugging only: This reports cache loads on stderr.
#define Libisoburn_read_cache_reporT 1
*/
/* Cached reading of image tree data */
#ifdef Libisoburn_cache_tileS
/* Multi tile: 32 * 64 kB */
struct isoburn_cache_tile {
char cache_data[Libisoburn_tile_blockS * 2048];
uint32_t cache_lba;
uint32_t last_error_lba;
uint32_t last_aligned_error_lba;
int cache_hits;
int age;
};
struct isoburn_cached_drive {
struct burn_drive *drive;
struct isoburn_cache_tile tiles[Libisoburn_cache_tileS];
int current_age;
};
#define Libisoburn_max_agE 2000000
static int ds_inc_age(struct isoburn_cached_drive *icd, int idx, int flag);
int ds_read_block(IsoDataSource *src, uint32_t lba, uint8_t *buffer)
{
int ret, i, oldest, oldest_age;
struct burn_drive *d;
off_t count;
uint32_t aligned_lba;
char msg[80];
struct isoburn_cache_tile *tiles;
struct isoburn_cached_drive *icd;
if(src == NULL || buffer == NULL)
return -1;
icd = (struct isoburn_cached_drive *) src->data;
d = (struct burn_drive*) icd->drive;
tiles = (struct isoburn_cache_tile *) icd->tiles;
aligned_lba= lba & ~(Libisoburn_tile_blockS - 1);
for(i=0; i<Libisoburn_cache_tileS; i++) {
if(aligned_lba == tiles[i].cache_lba && tiles[i].cache_lba != 0xffffffff) {
(tiles[i].cache_hits)++;
memcpy(buffer, tiles[i].cache_data + (lba - aligned_lba) * 2048, 2048);
count= 2048;
ds_inc_age(icd, i, 0);
return 1;
}
}
/* find oldest tile */
oldest_age= Libisoburn_max_agE;
oldest= 0;
for(i= 0; i<Libisoburn_cache_tileS; i++) {
if(tiles[i].cache_lba == 0xffffffff) {
oldest= i;
break;
}
if(tiles[i].age<oldest_age) {
oldest_age= tiles[i].age;
oldest= i;
}
}
tiles[oldest].cache_lba= 0xffffffff; /* invalidate cache */
if(tiles[oldest].last_aligned_error_lba == aligned_lba) {
ret = 0;
} else {
ret = burn_read_data(d, (off_t) aligned_lba * (off_t) 2048,
(char *) tiles[oldest].cache_data,
Libisoburn_tile_blockS * 2048, &count, 0);
}
if (ret <= 0 ) {
tiles[oldest].last_aligned_error_lba = aligned_lba;
/* Read-ahead failure ? Try to read 2048 directly. */
if(tiles[oldest].last_error_lba == lba)
ret = 0;
else
ret = burn_read_data(d, (off_t) lba * (off_t) 2048, (char *) buffer,
2048, &count, 0);
if (ret > 0)
return 1;
tiles[oldest].last_error_lba = lba;
sprintf(msg, "ds_read_block(%lu) returns -1", (unsigned long) lba);
burn_msgs_submit(0x00060000, msg, 0, "DEBUG", NULL);
return -1;
}
#ifdef Libisoburn_read_cache_reporT
fprintf(stderr, "Tile %2.2d : After %3d hits, new load from %8x , count= %d\n",
oldest, tiles[oldest].cache_hits, aligned_lba, (int) count);
#endif
tiles[oldest].cache_lba= aligned_lba;
tiles[oldest].cache_hits= 1;
ds_inc_age(icd, oldest, 0);
memcpy(buffer, tiles[oldest].cache_data + (lba - aligned_lba) * 2048, 2048);
count= 2048;
return 1;
}
static int ds_open(IsoDataSource *src)
{
/* nothing to do, device is always grabbed */
return 1;
}
static int ds_close(IsoDataSource *src)
{
/* nothing to do, device is always grabbed */
return 1;
}
static void ds_free_data(IsoDataSource *src)
{
/* nothing to do */;
if(src->data != NULL)
free(src->data);
src->data= NULL;
}
IsoDataSource *isoburn_data_source_new(struct burn_drive *d)
{
IsoDataSource *ret;
struct isoburn_cached_drive *icd= NULL;
int i;
if (d==NULL)
return NULL;
ret = malloc(sizeof(IsoDataSource));
icd = calloc(1,sizeof(struct isoburn_cached_drive));
if (ret == NULL || icd == NULL)
return NULL;
ret->refcount = 1;
ret->read_block = ds_read_block;
ret->open = ds_open;
ret->close = ds_close;
ret->free_data = ds_free_data;
ret->data = icd;
icd->drive = d;
icd->current_age= 0;
for(i= 0; i<Libisoburn_cache_tileS; i++) {
icd->tiles[i].cache_lba = 0xffffffff;
icd->tiles[i].cache_hits = 0;
icd->tiles[i].last_error_lba = 0xffffffff;
icd->tiles[i].last_aligned_error_lba = 0xffffffff;
icd->tiles[i].age= 0;
}
return ret;
}
static int ds_inc_age(struct isoburn_cached_drive *icd, int idx, int flag)
{
int i;
(icd->current_age)++;
if(icd->current_age>=Libisoburn_max_agE) { /* reset all ages (allow waste) */
for(i= 0; i<Libisoburn_cache_tileS; i++)
(icd->tiles)[i].age= 0;
icd->current_age= 1;
}
(icd->tiles)[idx].age= icd->current_age;
return(1);
}
#else /* Libisoburn_cache_tileS */
/* Single tile 128 kB */
/* powers of 2 only ! */
#define Libisoburn_cache_blockS 64
struct isoburn_cached_drive { struct isoburn_cached_drive {
struct burn_drive *drive; struct burn_drive *drive;
char cache_data[Libisoburn_cache_blockS * 2048]; char cache_data[Libisoburn_tile_blockS * 2048];
uint32_t cache_lba; uint32_t cache_lba;
uint32_t last_error_lba; uint32_t last_error_lba;
uint32_t last_aligned_error_lba; uint32_t last_aligned_error_lba;
@ -47,9 +235,6 @@ struct isoburn_cached_drive {
/* Debugging only: This reports cache loads on stderr. /* Debugging only: This reports cache loads on stderr.
#define Libisoburn_read_cache_reporT 1 #define Libisoburn_read_cache_reporT 1
*/ */
#define Libisoburn_use_read_cachE
#ifdef Libisoburn_use_read_cachE
int int
ds_read_block(IsoDataSource *src, uint32_t lba, uint8_t *buffer) ds_read_block(IsoDataSource *src, uint32_t lba, uint8_t *buffer)
@ -68,7 +253,7 @@ ds_read_block(IsoDataSource *src, uint32_t lba, uint8_t *buffer)
icd = (struct isoburn_cached_drive *) src->data; icd = (struct isoburn_cached_drive *) src->data;
d = (struct burn_drive*) icd->drive; d = (struct burn_drive*) icd->drive;
aligned_lba= lba & ~(Libisoburn_cache_blockS - 1); aligned_lba= lba & ~(Libisoburn_tile_blockS - 1);
if(aligned_lba == icd->cache_lba && icd->cache_lba != 0xffffffff) { if(aligned_lba == icd->cache_lba && icd->cache_lba != 0xffffffff) {
(icd->cache_hits)++; (icd->cache_hits)++;
memcpy(buffer, icd->cache_data + (lba - aligned_lba) * 2048, 2048); memcpy(buffer, icd->cache_data + (lba - aligned_lba) * 2048, 2048);
@ -82,7 +267,7 @@ ds_read_block(IsoDataSource *src, uint32_t lba, uint8_t *buffer)
} else { } else {
ret = burn_read_data(d, (off_t) aligned_lba * (off_t) 2048, ret = burn_read_data(d, (off_t) aligned_lba * (off_t) 2048,
(char *) icd->cache_data, (char *) icd->cache_data,
Libisoburn_cache_blockS * 2048, &count, 0); Libisoburn_tile_blockS * 2048, &count, 0);
} }
if (ret <= 0 ) { if (ret <= 0 ) {
icd->last_aligned_error_lba = aligned_lba; icd->last_aligned_error_lba = aligned_lba;
@ -114,30 +299,6 @@ ds_read_block(IsoDataSource *src, uint32_t lba, uint8_t *buffer)
return 1; return 1;
} }
#else /* Libisoburn_use_read_cachE */
static int
ds_read_block(IsoDataSource *src, uint32_t lba, uint8_t *buffer)
{
int ret;
struct burn_drive *d;
off_t count;
if(src == NULL || buffer == NULL)
return -1;
d = (struct burn_drive*) ((struct isoburn_cached_drive *) src->data)->drive;
ret = burn_read_data(d, (off_t) lba * (off_t) 2048, (char *) buffer,
2048, &count, 0);
if (ret <= 0 )
return -1;
return 1;
}
#endif /* ! Libisoburn_use_read_cachE */
static int static int
ds_open(IsoDataSource *src) ds_open(IsoDataSource *src)
@ -188,3 +349,5 @@ isoburn_data_source_new(struct burn_drive *d)
return ret; return ret;
} }
#endif /* ! Libisoburn_cache_tileS */

View File

@ -1 +1 @@
#define Xorriso_timestamP "2008.03.31.081347" #define Xorriso_timestamP "2008.04.01.213121"