diff --git a/libisoburn/data_source.c b/libisoburn/data_source.c index f48d8c99..256d0e46 100644 --- a/libisoburn/data_source.c +++ b/libisoburn/data_source.c @@ -4,8 +4,10 @@ Copyright 2007 Vreixo Formoso Lopes */ -#include #include +#include + +#include #ifndef Xorriso_standalonE @@ -24,6 +26,81 @@ #include "isoburn.h" + +/* Cached reading of image tree data */ +/* Current implementation : single tile 128 kB */ + +/* powers of 2 only ! */ +#define Libisoburn_cache_blockS 64 + +struct isoburn_cached_drive { + struct burn_drive *drive; + + char cache_data[Libisoburn_cache_blockS * 2048]; + uint32_t cache_lba; + int cache_hits; +}; + + +/* Debugging only: This reports cache loads on stderr. +#define Libisoburn_read_cache_reporT 1 +*/ +#define Libisoburn_read_cache_experimenT + +#ifdef Libisoburn_read_cache_experimenT + +int +ds_read_block(IsoDataSource *src, uint32_t lba, uint8_t *buffer) +{ + int ret; + struct burn_drive *d; + off_t count; + uint32_t aligned_lba; + + 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; + + aligned_lba= lba & ~(Libisoburn_cache_blockS - 1); + if(aligned_lba == icd->cache_lba && icd->cache_lba != 0xffffffff) { + (icd->cache_hits)++; + memcpy(buffer, icd->cache_data + (lba - aligned_lba) * 2048, 2048); + count= 2048; + return 1; + } + + icd->cache_lba= 0xffffffff; /* invalidate cache */ + ret = burn_read_data(d, (off_t) aligned_lba * (off_t) 2048, + (char *) icd->cache_data, + Libisoburn_cache_blockS * 2048, &count, 0); + if (ret <= 0 ) { + /* Read-ahead failure ? Try to read 2048 directly. */ + ret = burn_read_data(d, (off_t) lba * (off_t) 2048, (char *) buffer, + 2048, &count, 0); + if (ret > 0) + return 1; + return -1; + } + +#ifdef Libisoburn_read_cache_reporT + fprintf(stderr, "After %3d hits, new load from %8x , count= %d\n", + icd->cache_hits, aligned_lba, (int) count); +#endif + + icd->cache_lba= aligned_lba; + icd->cache_hits= 1; + memcpy(buffer, icd->cache_data + (lba - aligned_lba) * 2048, 2048); + count= 2048; + + return 1; +} + +#else /* Libisoburn_read_cache_experimenT */ + static int ds_read_block(IsoDataSource *src, uint32_t lba, uint8_t *buffer) { @@ -31,9 +108,10 @@ ds_read_block(IsoDataSource *src, uint32_t lba, uint8_t *buffer) struct burn_drive *d; off_t count; - assert(src && buffer); + if(src == NULL || buffer == NULL) + return -1; - d = (struct burn_drive*)src->data; + 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); @@ -42,6 +120,9 @@ ds_read_block(IsoDataSource *src, uint32_t lba, uint8_t *buffer) return 1; } + +#endif /* ! Libisoburn_read_cache_experimenT */ + static int ds_open(IsoDataSource *src) @@ -67,17 +148,23 @@ IsoDataSource * isoburn_data_source_new(struct burn_drive *d) { IsoDataSource *ret; + struct isoburn_cached_drive *icd= NULL; + if (d==NULL) return NULL; ret = malloc(sizeof(IsoDataSource)); - if (!ret) + 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 = d; + ret->data = icd; + icd->drive = d; + icd->cache_lba = 0xffffffff; + icd->cache_hits = 0; return ret; } diff --git a/xorriso/xorriso_timestamp.h b/xorriso/xorriso_timestamp.h index cf741265..5d997de4 100644 --- a/xorriso/xorriso_timestamp.h +++ b/xorriso/xorriso_timestamp.h @@ -1 +1 @@ -#define Xorriso_timestamP "2008.02.07.074248" +#define Xorriso_timestamP "2008.02.07.154947"