libisoburn-0.4.8.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 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 197 of file data_source.c.

Referenced by isoburn_data_source_new().

00198 {
00199  /* nothing to do, device is always grabbed */
00200  return 1;
00201 }

static void ds_free_data ( IsoDataSource *  src  )  [static]

Definition at line 203 of file data_source.c.

Referenced by isoburn_data_source_new().

00204 {
00205  /* nothing to do */;
00206  if(src->data != NULL)
00207    free(src->data);
00208  src->data= NULL;
00209 }

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

Definition at line 255 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().

00256 {
00257  int i;
00258 
00259  (icd->current_age)++;
00260  if(icd->current_age>=Libisoburn_max_agE) { /* reset all ages (allow waste) */
00261    for(i= 0; i<Libisoburn_cache_tileS; i++)
00262      (icd->tiles)[i].age= 0;
00263    icd->current_age= 1;
00264  }
00265  (icd->tiles)[idx].age= icd->current_age;
00266  return(1);
00267 }

static int ds_open ( 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 }

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 #ifdef ISO_DATA_SOURCE_MISHAP
00151    ret= ISO_DATA_SOURCE_MISHAP;
00152 #else
00153    /* <<< pre libisofs-0.6.7 */
00154    /* It is not required by the specs of libisofs but implicitely assumed
00155       ...
00156       But it is not possible to ignore FAILURE.
00157       libisofs insists in original error codes, i.e. libisoburn cannot
00158       change severity FAILURE associated with ISO_FILE_READ_ERROR.
00159       So ISO_FILE_READ_ERROR is not an option and libisoburn has to
00160       misuse ISO_FILE_CANT_WRITE, which is actually for image generation
00161       and not for image reading.
00162       This is quite wrong, although the error message text is unclear
00163       enough to make it appear plausible.
00164    */
00165    ret= ISO_FILE_CANT_WRITE;
00166 #endif
00167 
00168    if(ret >= 0)
00169      ret = -1;
00170    sprintf(msg, "ds_read_block(%lu) returns %d", (unsigned long) lba, ret);
00171    isoburn_msgs_submit(NULL, 0x00060000, msg, 0, "DEBUG", 0);
00172    return ret; 
00173  }
00174 
00175 #ifdef Libisoburn_read_cache_reporT
00176  fprintf(stderr, "Tile %2.2d : After %3d hits, new load from %8x , count= %d\n",
00177          oldest, tiles[oldest].cache_hits, aligned_lba, (int) count);
00178 #endif
00179 
00180  tiles[oldest].cache_lba= aligned_lba;
00181  tiles[oldest].cache_hits= 1;
00182  ds_inc_age(icd, oldest, 0);
00183 
00184  memcpy(buffer, tiles[oldest].cache_data + (lba - aligned_lba) * 2048, 2048);
00185  count= 2048;
00186 
00187  return 1;
00188 }

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 224 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().

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

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

References isoburn_cached_drive::drive.

Referenced by isoburn_prepare_disc_aux().

00213 {
00214  struct isoburn_cached_drive *icd;
00215 
00216  if(src==NULL)
00217    return(0);
00218  icd= (struct isoburn_cached_drive *) src->data;
00219  icd->drive= NULL;
00220  return(1);
00221 }


Generated by  doxygen 1.6.2