Data Structures | Defines | Functions

libisoburn-0.5.6.pl00/libisoburn/data_source.c File Reference

#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <libburn/libburn.h>
#include <libisofs/libisofs.h>
#include "isoburn.h"
Include dependency graph for data_source.c:

Go to the source code of this file.

Data Structures

struct  isoburn_cache_tile
struct  isoburn_cached_drive

Defines

#define Libisoburn_tile_blockS   32
#define Libisoburn_cache_tileS   32
#define Libisoburn_max_agE   2000000000

Functions

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)
static int ds_open (IsoDataSource *src)
static int ds_close (IsoDataSource *src)
static void ds_free_data (IsoDataSource *src)
int isoburn_data_source_shutdown (IsoDataSource *src, int flag)
 Disable read capabilities of a data source which was originally created by isoburn_data_source_new().
IsoDataSource * isoburn_data_source_new (struct burn_drive *d)
 Get a data source suitable for read from a drive using burn_read_data() function.

Define Documentation

#define Libisoburn_cache_tileS   32

Definition at line 42 of file data_source.c.

#define Libisoburn_max_agE   2000000000

Definition at line 65 of file data_source.c.

Referenced by ds_inc_age().

#define Libisoburn_tile_blockS   32

Definition at line 38 of file data_source.c.

Referenced by ds_read_block().


Function Documentation

static int ds_close ( IsoDataSource *  src  )  [static]

Definition at line 198 of file data_source.c.

{
 /* nothing to do, device is always grabbed */
 return 1;
}

static void ds_free_data ( IsoDataSource *  src  )  [static]

Definition at line 204 of file data_source.c.

{
 /* nothing to do */;
 if(src->data != NULL)
   free(src->data);
 src->data= NULL;
}

static int ds_inc_age ( struct isoburn_cached_drive icd,
int  idx,
int  flag 
) [static]

Definition at line 256 of file data_source.c.

References isoburn_cached_drive::current_age, Libisoburn_max_agE, and isoburn_cached_drive::tiles.

Referenced by ds_read_block().

{
 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);
}

static int ds_open ( IsoDataSource *  src  )  [static]

Definition at line 192 of file data_source.c.

{
 /* nothing to do, device is always grabbed */
 return 1;
}

int ds_read_block ( IsoDataSource *  src,
uint32_t  lba,
uint8_t *  buffer 
)

Definition at line 70 of file data_source.c.

References isoburn_cache_tile::age, isoburn_cache_tile::cache_data, isoburn_cache_tile::cache_hits, isoburn_cache_tile::cache_lba, isoburn_cached_drive::drive, ds_inc_age(), isoburn_msgs_submit(), isoburn_cache_tile::last_aligned_error_lba, isoburn_cache_tile::last_error_lba, Libisoburn_tile_blockS, and isoburn_cached_drive::tiles.

{
 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)
   /* It is not required by the specs of libisofs but implicitely assumed
      by its current implementation that a data source read result <0 is
      a valid libisofs error code.
   */
   return ISO_NULL_POINTER;

 icd = (struct isoburn_cached_drive *) src->data;
 d = (struct burn_drive*) icd->drive;

 if(d == NULL) {
   /* This would happen if libisoburn saw output data in the fifo and
      performed early drive release and afterwards libisofs still tries
      to read data.
      That would constitute a bad conceptual problem in libisoburn.
   */
   isoburn_msgs_submit(NULL, 0x00060000,
     "Programming error: Drive released while libisofs still attempts to read",
     0, "FATAL", 0);
   return ISO_ASSERT_FAILURE;
 }

 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, 2);
 }
 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;

#ifdef ISO_DATA_SOURCE_MISHAP
   ret= ISO_DATA_SOURCE_MISHAP;
#else
   /* <<< pre libisofs-0.6.7 */
   /* It is not required by the specs of libisofs but implicitely assumed
      ...
      But it is not possible to ignore FAILURE.
      libisofs insists in original error codes, i.e. libisoburn cannot
      change severity FAILURE associated with ISO_FILE_READ_ERROR.
      So ISO_FILE_READ_ERROR is not an option and libisoburn has to
      misuse ISO_FILE_CANT_WRITE, which is actually for image generation
      and not for image reading.
      This is quite wrong, although the error message text is unclear
      enough to make it appear plausible.
   */
   ret= ISO_FILE_CANT_WRITE;
#endif

   if(ret >= 0)
     ret = -1;
   sprintf(msg, "ds_read_block(%lu) returns %d", (unsigned long) lba, ret);
   isoburn_msgs_submit(NULL, 0x00060000, msg, 0, "DEBUG", 0);
   return ret; 
 }

#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;
}

IsoDataSource* isoburn_data_source_new ( struct burn_drive *  d  ) 

Get a data source suitable for read from a drive using burn_read_data() function.

Parameters:
d drive to read from. Must be grabbed.
Returns:
the data source, NULL on error. Must be freed with libisofs iso_data_source_unref() function. Note: this doesn't release the drive.

Definition at line 225 of file data_source.c.

References isoburn_cache_tile::age, isoburn_cache_tile::cache_hits, isoburn_cache_tile::cache_lba, isoburn_cached_drive::current_age, isoburn_cached_drive::drive, isoburn_cache_tile::last_aligned_error_lba, isoburn_cache_tile::last_error_lba, and isoburn_cached_drive::tiles.

Referenced by isoburn_read_image().

{
 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;
}

int isoburn_data_source_shutdown ( IsoDataSource *  src,
int  flag 
)

Disable read capabilities of a data source which was originally created by isoburn_data_source_new().

After this any attempt to read will yield a FATAL programming error event. This is usually done to allow libburn to release the drive while libisofs still holds a reference to the data source object. libisofs is not supposed to use this object for reading any more, nevertheless. The disabled state of the data source is a safety fence around this daring situation.

Parameters:
src The data source to be disabled
flag unused yet
Returns:
<=0 is failure , >0 success

Definition at line 213 of file data_source.c.

References isoburn_cached_drive::drive.

Referenced by isoburn_prepare_disc_aux().

{
 struct isoburn_cached_drive *icd;

 if(src==NULL)
   return(0);
 icd= (struct isoburn_cached_drive *) src->data;
 icd->drive= NULL;
 return(1);
}