libisoburn-0.2.2/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 41 of file data_source.c.

Referenced by ds_inc_age(), ds_read_block(), and isoburn_data_source_new().

#define Libisoburn_max_agE   2000000000

Definition at line 64 of file data_source.c.

Referenced by ds_inc_age(), and ds_read_block().

#define Libisoburn_tile_blockS   32

Definition at line 37 of file data_source.c.

Referenced by ds_read_block().


Function Documentation

static int ds_close ( IsoDataSource *  src  )  [static]

Definition at line 191 of file data_source.c.

Referenced by isoburn_data_source_new().

00192 {
00193  /* nothing to do, device is always grabbed */
00194  return 1;
00195 }

static void ds_free_data ( IsoDataSource *  src  )  [static]

Definition at line 197 of file data_source.c.

Referenced by isoburn_data_source_new().

00198 {
00199  /* nothing to do */;
00200  if(src->data != NULL)
00201    free(src->data);
00202  src->data= NULL;
00203 }

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

Definition at line 249 of file data_source.c.

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

Referenced by ds_read_block().

00250 {
00251  int i;
00252 
00253  (icd->current_age)++;
00254  if(icd->current_age>=Libisoburn_max_agE) { /* reset all ages (allow waste) */
00255    for(i= 0; i<Libisoburn_cache_tileS; i++)
00256      (icd->tiles)[i].age= 0;
00257    icd->current_age= 1;
00258  }
00259  (icd->tiles)[idx].age= icd->current_age;
00260  return(1);
00261 }

static int ds_open ( IsoDataSource *  src  )  [static]

Definition at line 185 of file data_source.c.

Referenced by isoburn_data_source_new().

00186 {
00187  /* nothing to do, device is always grabbed */
00188  return 1;
00189 }

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

Definition at line 69 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_cache_tileS, Libisoburn_max_agE, Libisoburn_tile_blockS, and isoburn_cached_drive::tiles.

Referenced by isoburn_data_source_new().

00070 {
00071  int ret, i, oldest, oldest_age;
00072  struct burn_drive *d;
00073  off_t count;
00074  uint32_t aligned_lba;
00075  char msg[80];
00076  struct isoburn_cache_tile *tiles;
00077  struct isoburn_cached_drive *icd;
00078 
00079  if(src == NULL || buffer == NULL)
00080    /* It is not required by the specs of libisofs but implicitely assumed
00081       by its current implementation that a data source read result <0 is
00082       a valid libisofs error code.
00083    */
00084    return ISO_NULL_POINTER;
00085 
00086  icd = (struct isoburn_cached_drive *) src->data;
00087  d = (struct burn_drive*) icd->drive;
00088 
00089  if(d == NULL) {
00090    /* This would happen if libisoburn saw output data in the fifo and
00091       performed early drive release and afterwards libisofs still tries
00092       to read data.
00093       That would constitute a bad conceptual problem in libisoburn.
00094    */
00095    isoburn_msgs_submit(NULL, 0x00060000,
00096      "Programming error: Drive released while libisofs still attempts to read",
00097      0, "FATAL", 0);
00098    return ISO_ASSERT_FAILURE;
00099  }
00100 
00101  tiles = (struct isoburn_cache_tile *) icd->tiles;
00102 
00103  aligned_lba= lba & ~(Libisoburn_tile_blockS - 1);
00104 
00105  for(i=0; i<Libisoburn_cache_tileS; i++) {
00106    if(aligned_lba == tiles[i].cache_lba && tiles[i].cache_lba != 0xffffffff) {
00107      (tiles[i].cache_hits)++;
00108      memcpy(buffer, tiles[i].cache_data + (lba - aligned_lba) * 2048, 2048);
00109      count= 2048;
00110      ds_inc_age(icd, i, 0);
00111      return 1;
00112    }
00113  }
00114 
00115  /* find oldest tile */
00116  oldest_age= Libisoburn_max_agE;
00117  oldest= 0;
00118  for(i= 0; i<Libisoburn_cache_tileS; i++) {
00119    if(tiles[i].cache_lba == 0xffffffff) {
00120      oldest= i;
00121  break;
00122    }
00123    if(tiles[i].age<oldest_age) {
00124      oldest_age= tiles[i].age;
00125      oldest= i;
00126    }
00127  }
00128 
00129  tiles[oldest].cache_lba= 0xffffffff; /* invalidate cache */
00130  if(tiles[oldest].last_aligned_error_lba == aligned_lba) {
00131    ret = 0;
00132  } else {
00133    ret = burn_read_data(d, (off_t) aligned_lba * (off_t) 2048,
00134                         (char *) tiles[oldest].cache_data,
00135                         Libisoburn_tile_blockS * 2048, &count, 2);
00136  }
00137  if (ret <= 0 ) {
00138    tiles[oldest].last_aligned_error_lba = aligned_lba;
00139 
00140    /* Read-ahead failure ? Try to read 2048 directly. */
00141    if(tiles[oldest].last_error_lba == lba)
00142      ret = 0;
00143    else
00144      ret = burn_read_data(d, (off_t) lba * (off_t) 2048, (char *) buffer,
00145                         2048, &count, 0);
00146    if (ret > 0)
00147      return 1;
00148    tiles[oldest].last_error_lba = lba;
00149 
00150    /* It is not required by the specs of libisofs but implicitely assumed
00151       ...
00152       But it is not possible to ignore FAILURE.
00153       libisofs insists in original error codes, i.e. libisoburn cannot
00154       change severity FAILURE associated with ISO_FILE_READ_ERROR.
00155       So ISO_FILE_READ_ERROR is not an option and libisoburn has to
00156       misuse ISO_FILE_CANT_WRITE, which is actually for image generation
00157       and not for image reading.
00158       This is quite wrong, although the error message text is unclear
00159       enough to make it appear plausible.
00160    */
00161    ret= ISO_FILE_CANT_WRITE;
00162    if(ret >= 0)
00163      ret = -1;
00164    sprintf(msg, "ds_read_block(%lu) returns %d", (unsigned long) lba, ret);
00165    isoburn_msgs_submit(NULL, 0x00060000, msg, 0, "DEBUG", 0);
00166    return ret; 
00167  }
00168 
00169 #ifdef Libisoburn_read_cache_reporT
00170  fprintf(stderr, "Tile %2.2d : After %3d hits, new load from %8x , count= %d\n",
00171          oldest, tiles[oldest].cache_hits, aligned_lba, (int) count);
00172 #endif
00173 
00174  tiles[oldest].cache_lba= aligned_lba;
00175  tiles[oldest].cache_hits= 1;
00176  ds_inc_age(icd, oldest, 0);
00177 
00178  memcpy(buffer, tiles[oldest].cache_data + (lba - aligned_lba) * 2048, 2048);
00179  count= 2048;
00180 
00181  return 1;
00182 }

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 218 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, ds_close(), ds_free_data(), ds_open(), ds_read_block(), isoburn_cache_tile::last_aligned_error_lba, isoburn_cache_tile::last_error_lba, Libisoburn_cache_tileS, and isoburn_cached_drive::tiles.

Referenced by isoburn_read_image().

00219 {
00220  IsoDataSource *ret;
00221  struct isoburn_cached_drive *icd= NULL;
00222  int i;
00223 
00224  if (d==NULL)
00225    return NULL;
00226  ret = malloc(sizeof(IsoDataSource));
00227  icd = calloc(1,sizeof(struct isoburn_cached_drive));
00228  if (ret == NULL || icd == NULL)
00229    return NULL;
00230  ret->refcount = 1;
00231  ret->read_block = ds_read_block;
00232  ret->open = ds_open;
00233  ret->close = ds_close;
00234  ret->free_data = ds_free_data;
00235  ret->data = icd;
00236  icd->drive = d;
00237  icd->current_age= 0;
00238  for(i= 0; i<Libisoburn_cache_tileS; i++) {
00239    icd->tiles[i].cache_lba = 0xffffffff;
00240    icd->tiles[i].cache_hits = 0;
00241    icd->tiles[i].last_error_lba = 0xffffffff;
00242    icd->tiles[i].last_aligned_error_lba = 0xffffffff;
00243    icd->tiles[i].age= 0;
00244  }
00245  return ret;
00246 }

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 206 of file data_source.c.

References isoburn_cached_drive::drive.

Referenced by isoburn_prepare_disc_aux().

00207 {
00208  struct isoburn_cached_drive *icd;
00209 
00210  if(src==NULL)
00211    return(0);
00212  icd= (struct isoburn_cached_drive *) src->data;
00213  icd->drive= NULL;
00214  return(1);
00215 }


Generated on Sat Nov 8 02:08:48 2008 for libisoburn by  doxygen 1.5.6