[xiph-commits] r15214 - in trunk/cdparanoia: . interface paranoia

xiphmont at svn.xiph.org xiphmont at svn.xiph.org
Thu Aug 28 09:41:44 PDT 2008


Author: xiphmont
Date: 2008-08-28 09:41:43 -0700 (Thu, 28 Aug 2008)
New Revision: 15214

Added:
   trunk/cdparanoia/paranoia/cachetest.c
Removed:
   trunk/cdparanoia/cachetest.c
   trunk/cdparanoia/cachetest.h
Modified:
   trunk/cdparanoia/interface/cdda_interface.h
   trunk/cdparanoia/interface/interface.c
   trunk/cdparanoia/main.c
   trunk/cdparanoia/paranoia/cdda_paranoia.h
   trunk/cdparanoia/paranoia/p_block.h
   trunk/cdparanoia/paranoia/paranoia.c
   trunk/cdparanoia/version.h
Log:
Ignore and certainly do not use this commit-- code refactoring, move
cache test into paranoia lib (so that the analysis will always match
the paranoia version)



Deleted: trunk/cdparanoia/cachetest.c
===================================================================
--- trunk/cdparanoia/cachetest.c	2008-08-26 18:17:29 UTC (rev 15213)
+++ trunk/cdparanoia/cachetest.c	2008-08-28 16:41:43 UTC (rev 15214)
@@ -1,317 +0,0 @@
-/*
- * Copyright: GNU Public License 2 applies
- *
- *   This program is free software; you can redistribute it and/or modify
- *   it under the terms of the GNU General Public License as published by
- *   the Free Software Foundation; either version 2, or (at your option)
- *   any later version.
- *
- *   This program is distributed in the hope that it will be useful,
- *   but WITHOUT ANY WARRANTY; without even the implied warranty of
- *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *   GNU General Public License for more details.
- *
- *   You should have received a copy of the GNU General Public License
- *   along with this program; if not, write to the Free Software
- *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * cdparanoia (C) 2008 Monty <monty at xiph.org>
- *
- */
-
-/* we can ask most drives what their various caches' sizes are, but no
-   drive will tell if it caches redbook data.  None should, many do,
-   and there's no way in (eg) MMAC/ATAPI to tell a drive not to.  SCSI
-   drives have a FUA facility, but it's not clear how many ignore it.
-   MMC does specify some cache side effect as part of SET READ AHEAD,
-   but it's not clear we can rely on them.  For that reason, we need
-   to empirically determine cache size and strategy used for reads. */
-
-#include <string.h>
-#include <stdio.h>
-#include <math.h>
-#include "interface/cdda_interface.h"
-#include "report.h"
-#include "cachetest.h"
-
-int analyze_timing_and_cache(cdrom_drive *d){
-
-  /* Some assumptions about timing: 
-
-     We can't perform cache determination timing based on looking at
-     average transfer times; on slow setups, the speed of a drive
-     reading sectors via PIO will not be reliably distinguishable from
-     the same drive returning data from the cache via pio.  We need
-     something even more noticable and reliable: the seek time. It is
-     unlikely we'd ever see a seek latency of under ~10ms given the
-     synchronization requirements of a CD and the maximum possible
-     rotational velocity. A cache hit would always be faster, even
-     with PIO.
-
-     Further complicating things, we have to watch the data collection
-     carefully as we're not always going to be on an unloaded system,
-     and we even have to guard against other apps accessing the drive
-     (something that should never happen on purpose, but could happen
-     by accident).  As we know in our testing when seeks should never
-     occur, a sudden seek-sized latency popping up in the middle of a
-     collection is an indication that collection is possibly invalid.
-
-     A second cause of 'spurious latency' would be media damage; if
-     we're consistently hitting latency on the same sector during
-     initial collection, may need to move past it. */
-
-  int i,ret;
-  int firstsector=-1;
-  int lastsector=-1;
-  int firsttest=-1;
-  int lasttest=-1;
-  int max_retries=20;
-  float median;
-  int offset;
-
-  /* set up a default pessimal take on drive behavior */
-  //d->private->cache_backseekflush=0;
-  //d->private->cache_sectors=1200;
-
-  reportC("\n=================== Checking drive cache/timing behavior ===================\n");
-
-  /* find the longest stretch of available audio data */
-
-  for(i=0;i<d->tracks;i++){
-    if(cdda_track_audiop(d,i+1)==1){
-      if(firsttest == -1)
-	firsttest=cdda_track_firstsector(d,i+1);
-      lasttest=cdda_track_lastsector(d,i+1);
-      if(lasttest-firsttest > lastsector-firstsector){
-	firstsector=firsttest;
-	lastsector=lasttest;
-      }
-    }else{
-      firsttest=-1;
-      lasttest=-1;
-    }
-  }
-
-  if(firstsector==-1){
-    reportC("\n\tNo audio on disc; Cannot determine timing behavior...");
-    return -1;
-  }
-
-  /* Dump some initial timing data to give a little context for human
-     eyes.  Take readings ten minutes apart (45000 sectors) and at end of disk. */
-  {
-    int x;
-    int current=1000;
-    int latency[current];
-    int sectors[current];
-    double sum;
-    double sumsq;
-    int sofar;
-    int best=0;
-    int bestcount=0;
-    int iterating=0;
-
-    offset = lastsector-firstsector-current-1;
-
-    reportC("\nSeek/read timing:\n");
-
-    while(offset>=firstsector){
-      int m = offset/4500;
-      int s = (offset-m*4500)/75;
-      int f = offset-m*4500-s*75;
-      if(iterating){
-	reportC("\n");
-      }else{
-	printC("\r");
-	logC("\n");
-      }
-      reportC("\t[%02d:%02d.%02d]: ",m,s,f);
-      sum=0;
-      sumsq=0;
-
-      /* initial seek to put at at a small offset past end of upcoming reads */
-      if((ret=cdda_read(d,NULL,offset+current+1,1))<0){
-	/* media error! grr!  retry elsewhere */
-	if(ret==-404)return -1;
-	reportC("\n\tWARNING: media error during setup; continuing at next offset...");
-	goto next;
-      }
-
-      logC("\n");
-      
-      for(i=0,sofar=0;sofar<current;i++){
-	int toread = (i==0?1:current-sofar);
-	int ret;
-	/* first read should also trigger a short seek; one sector so seek duration dominates */
-	if((ret=cdda_read(d,NULL,offset+sofar,toread))<=0){
-	  /* media error! grr!  retry elsewhere */
-	if(ret==-404)return -1;
-	  reportC("\n\tWARNING: media error during read; continuing at next offset...");
-	  goto next;
-	}
-
-	x = cdda_milliseconds(d);
-	if(x>9999)x=9999;
-	if(x<0)x=0;
-	logC("%d:%d ",ret,x);
-
-	latency[i]=x;
-	sectors[i]=ret;
-	sofar+=ret;
-	if(i){
-	  sum+=x;
-	  sumsq+= x*x /(float)ret;
-	}
-      }
-      
-      /* ignore upper outliers; we may have gotten random bursts of latency */
-      {
-	double mean = sum/(float)(current-1);
-	double stddev = sqrt( (sumsq/(float)(current-1) - mean*mean));
-	double upper= mean+((isnan(stddev) || stddev*2<1.)?1.:stddev*2);
-	int j;
-	
-	mean=0;
-	sofar=0;
-	for(j=1;j<i;j++){
-	  double per = latency[j]/(double)sectors[j];
-	  if(per<=upper){
-	    mean+=latency[j];
-	    sofar+=sectors[j];
-	  }
-	}
-	mean/=sofar;
-	
-	printC("%4dms seek, %.2fms/sec read [%.1fx]",latency[0],mean,1000./75./mean);
-	logC("\n\tInitial seek latency (%d sectors): %dms",current,latency[0]);
-	logC("\n\tAverage read latency: %.2fms/sector (raw speed: %.1fx)",mean,1000./75./mean);
-	logC("\n\tRead latency standard deviation: %.2fms/sector",stddev);
-
-	sofar=mean*current;
-	if(!iterating){
-	  if(-sofar<best){
-	    best=-sofar;
-	    bestcount=0;
-	  }else{
-	    bestcount+=sofar;
-	    if(bestcount>sofar && bestcount>2000)
-	      iterating=1;
-	  }
-	}
-      }
-    next:
-
-      if(iterating){
-	offset = (offset-firstsector+44999)/45000*45000+firstsector;
-	offset-=45000;
-	printC("               ");
-      }else{
-	offset--;
-	printC(" spinning up...");
-      }
-    }
-  }
-
-  reportC("\n\nAnalyzing readahead cache access...\n");
-  
-  /* search on cache size; cache hits are fast, seeks are not, so a
-     linear search through cache hits up to a miss are faster than a
-     bisection */
-
-  int hi=15000;
-  int current=0;
-  int under=1;
-  offset = firstsector;
-
-  while(current <= hi && under){
-    int i,j;
-    under=0;
-    current++;
-
-    printC("\r");
-    reportC("\tFast search for approximate cache size... %d sectors            ",current-1);
-    logC("\n");
-
-    for(i=0;i<15 && !under;i++){
-      for(j=0;;j++){
-	int ret1,ret2;
-	if(i>=5){
-	  int sofar=0;
-	  
-	  if(i==5){
-	    printC("\r");
-	    reportC("\tSlow verify for approximate cache size... %d sectors",current-1);
-	    logC("\n");
-
-	    logC("\tAttempting to reduce read speed to 1x... ");
-	    if(cdda_speed_set(d,1)){
-	      logC("failed.\n");
-	    }else{
-	      logC("drive said OK\n");
-	    }
-	  }
-	  printC(".");
-	  logC("\t\t>>> ");
-
-	  while(sofar<current){
-	    ret1 = cdda_read(d,NULL,offset+sofar,current-sofar);
-	    logC("slow_read=%d:%d ",ret1,cdda_milliseconds(d));
-	    if(ret1<=0)break;
-	    sofar+=ret1;
-	  }
-	}else{
-	  ret1 = cdda_read(d,NULL,offset+current-1,1);
-	  logC("\t\t>>> fast_read=%d:%d ",ret1,cdda_milliseconds(d));
-	}
-	ret2 = cdda_read(d,NULL,offset,1);
-	logC("seek_read=%d:%d\n",ret2,cdda_milliseconds(d));
-	
-	if(ret1<=0 || ret2<=0){
-	  offset+=current+100;
-	  if(j==10 || offset+current>lastsector){
-	    reportC("\n\tToo many read errors while performing drive cache checks;"
-		    "\n\t  aborting test.\n\n");
-	    return(-1);
-	  }
-	  reportC("\n\tRead error while performing drive cache checks;"
-		  "\n\t  choosing new offset and trying again.\n");
-	}else{
-	  if(cdda_milliseconds(d)==-1){
-	    reportC("\n\tTiming error while performing drive cache checks; aborting test.\n");
-	    return(-1);
-	  }else{
-	    if(cdda_milliseconds(d)<9)under=1;
-	    break;
-	  }
-	}
-      }
-    }
-  } 
-
-  printC("\r");
-  if(current>1){
-    reportC("\tApproximate random access cache size: %d sectors                 \n",current-1);
-  }else{
-    reportC("\tDrive does not cache nonlinear access                            \n");
-    return 0;
-  }
-   
-  /* this drive caches; Determine if the detailed caching behavior fits our model. */
-
-  /* does the readahead cache exceed the maximum Paranoia currently expects? */
-
-  /* Verify that a read that begins before the cached readahead dumps
-     the entire readahead cache */
-
-  /* Verify that reads that begin after the apparently cached
-     readahead either dump the cache *or* cause the cached area to
-     shift later in one contiguous piece */
-  
-  /* Check to see that cdda_clear_cache clears the specified cache area */
-
-  /* XXXXXX IN PROGRESS */
-  reportC("\n");
-  return 0;
-}
-
-

Deleted: trunk/cdparanoia/cachetest.h
===================================================================
--- trunk/cdparanoia/cachetest.h	2008-08-26 18:17:29 UTC (rev 15213)
+++ trunk/cdparanoia/cachetest.h	2008-08-28 16:41:43 UTC (rev 15214)
@@ -1,22 +0,0 @@
-/*
- * Copyright: GNU Public License 2 applies
- *
- *   This program is free software; you can redistribute it and/or modify
- *   it under the terms of the GNU General Public License as published by
- *   the Free Software Foundation; either version 2, or (at your option)
- *   any later version.
- *
- *   This program is distributed in the hope that it will be useful,
- *   but WITHOUT ANY WARRANTY; without even the implied warranty of
- *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *   GNU General Public License for more details.
- *
- *   You should have received a copy of the GNU General Public License
- *   along with this program; if not, write to the Free Software
- *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * cdparanoia (C) 2008 Monty <monty at xiph.org>
- *
- */
-
-extern int analyze_timing_and_cache(cdrom_drive *d);

Modified: trunk/cdparanoia/interface/cdda_interface.h
===================================================================
--- trunk/cdparanoia/interface/cdda_interface.h	2008-08-26 18:17:29 UTC (rev 15213)
+++ trunk/cdparanoia/interface/cdda_interface.h	2008-08-28 16:41:43 UTC (rev 15214)
@@ -121,6 +121,7 @@
 
 /******** Drive oriented functions */
 
+extern char *cdda_version();
 extern int cdda_speed_set(cdrom_drive *d, int speed);
 extern void cdda_verbose_set(cdrom_drive *d,int err_action, int mes_action);
 extern char *cdda_messages(cdrom_drive *d);

Modified: trunk/cdparanoia/interface/interface.c
===================================================================
--- trunk/cdparanoia/interface/interface.c	2008-08-26 18:17:29 UTC (rev 15213)
+++ trunk/cdparanoia/interface/interface.c	2008-08-28 16:41:43 UTC (rev 15214)
@@ -12,7 +12,12 @@
 #include "low_interface.h"
 #include "common_interface.h"
 #include "utils.h"
+#include "../version.h"
 
+char *cdda_version(void){
+  return VERSIONNUM;
+}
+
 static void _clean_messages(cdrom_drive *d){
   if(d){
     if(d->messagebuf)free(d->messagebuf);

Modified: trunk/cdparanoia/main.c
===================================================================
--- trunk/cdparanoia/main.c	2008-08-26 18:17:29 UTC (rev 15213)
+++ trunk/cdparanoia/main.c	2008-08-28 16:41:43 UTC (rev 15214)
@@ -37,7 +37,6 @@
 #include "report.h"
 #include "version.h"
 #include "header.h"
-#include "cachetest.h"
 
 static long parse_offset(cdrom_drive *d, char *offset, int begin){
   long track=-1;
@@ -892,6 +891,8 @@
     if(reportfile!=logfile){
       fprintf(logfile,VERSION);
       fprintf(logfile,"\n");
+      fprintf(logfile,"Using cdda library version: %s\n",cdda_version());
+      fprintf(logfile,"Using paranoia library version: %s\n",paranoia_version());
     }
     fflush(logfile);
   }
@@ -917,6 +918,8 @@
     span=copystring(argv[optind]);
 
   report(VERSION);
+  report("Using cdda library version: %s",cdda_version());
+  report("Using paranoia library version: %s",paranoia_version());
 
   /* Query the cdrom/disc; we may need to override some settings */
 
@@ -1034,9 +1037,28 @@
     report("\tdrive returned OK.");
   }
   
-  if(run_cache_test)
-    return analyze_timing_and_cache(d);
+  if(run_cache_test){
+    int warn=paranoia_analyze_verify(d, stderr, reportfile);
+    
+    if(warn==0){
+      reportC("\nDrive tests OK with Paranoia.\n");
+      return 0;
+    }
 
+    if(warn==1)
+      reportC("\nWARNING! PARANOIA MAY NOT BE TRUSTWORTHY WITH THIS DRIVE!\n"
+	      "\nThe Paranoia library may not model this CDROM drive's cache"
+	      "\ncorrectly according to this analysis run. Analysis is not"
+	      "\nalways accurate (it can be fooled by machine load or random"
+	      "\nkernel latencies), but if a failed result happens more often"
+	      "\nthan one time in twenty on an unloaded machine, please mail"
+	      "\nthe %s file produced by this failed analysis to"
+	      "\nparanoia-dev at xiph.org to assist developers in extending"
+	      "\nParanoia to handle this CDROM properly.\n\n",reportfile_name);
+    return 1;
+  }
+
+
   /* Dump the TOC */
   if(query_only || verbose)display_toc(d);
   if(query_only)exit(0);

Added: trunk/cdparanoia/paranoia/cachetest.c
===================================================================
--- trunk/cdparanoia/paranoia/cachetest.c	                        (rev 0)
+++ trunk/cdparanoia/paranoia/cachetest.c	2008-08-28 16:41:43 UTC (rev 15214)
@@ -0,0 +1,374 @@
+/*
+ * GNU Lesser General Public License 2.1 applies
+ * Copyright (C) 2008 Monty <monty at xiph.org>
+ *
+ */
+
+/* this is in the paranoia library because the analysis is matched to
+   cache modelling of a specific library version, not matched to the
+   specific application (eg, cdparanoia version, which is simply a
+   wrapper around the libs) */
+
+/* we can ask most drives what their various caches' sizes are, but no
+   drive will tell if it caches redbook data.  None should, many do,
+   and there's no way in (eg) MMC/ATAPI to tell a cdrom drive not to
+   cache when accessing audio.  SCSI drives have a FUA facility, but
+   it's not clear how many ignore it.  MMC does specify some cache
+   side effect as part of SET READ AHEAD, but it's not clear we can
+   rely on them.  For that reason, we need to empirically determine
+   cache size and strategy used for reads. */
+
+#include <string.h>
+#include <stdio.h>
+#include <math.h>
+#include "../interface/cdda_interface.h"
+#include "p_block.h"
+
+#define reportC(...) {if(progress){fprintf(progress, __VA_ARGS__);}	\
+    if(log){fprintf(log, __VA_ARGS__);}}
+#define printC(...) {if(progress){fprintf(progress, __VA_ARGS__);}}
+#define logC(...) {if(log){fprintf(log, __VA_ARGS__);}}
+
+
+int paranoia_analyze_verify(cdrom_drive *d, FILE *progress, FILE *log){
+
+  /* Some assumptions about timing: 
+
+     We can't perform cache determination timing based on looking at
+     average transfer times; on slow setups, the speed of a drive
+     reading sectors via PIO will not be reliably distinguishable from
+     the same drive returning data from the cache via pio.  We need
+     something even more noticable and reliable: the seek time. It is
+     unlikely we'd ever see a seek latency of under ~10ms given the
+     synchronization requirements of a CD and the maximum possible
+     rotational velocity. A cache hit would always be faster, even
+     with PIO.
+
+     Further complicating things, we have to watch the data collection
+     carefully as we're not always going to be on an unloaded system,
+     and we even have to guard against other apps accessing the drive
+     (something that should never happen on purpose, but could happen
+     by accident).  As we know in our testing when seeks should never
+     occur, a sudden seek-sized latency popping up in the middle of a
+     collection is an indication that collection is possibly invalid.
+
+     A second cause of 'spurious latency' would be media damage; if
+     we're consistently hitting latency on the same sector during
+     initial collection, may need to move past it. */
+
+  int i,ret;
+  int firstsector=-1;
+  int lastsector=-1;
+  int firsttest=-1;
+  int lasttest=-1;
+  int max_retries=20;
+  float median;
+  int offset;
+  int warn=0;
+
+  /* set up a default pessimal take on drive behavior */
+  //d->private->cache_backseekflush=0;
+  //d->private->cache_sectors=1200;
+
+  reportC("\n=================== Checking drive cache/timing behavior ===================\n");
+
+  /* find the longest stretch of available audio data */
+
+  for(i=0;i<d->tracks;i++){
+    if(cdda_track_audiop(d,i+1)==1){
+      if(firsttest == -1)
+	firsttest=cdda_track_firstsector(d,i+1);
+      lasttest=cdda_track_lastsector(d,i+1);
+      if(lasttest-firsttest > lastsector-firstsector){
+	firstsector=firsttest;
+	lastsector=lasttest;
+      }
+    }else{
+      firsttest=-1;
+      lasttest=-1;
+    }
+  }
+
+  if(firstsector==-1){
+    reportC("\n\tNo audio on disc; Cannot determine timing behavior...");
+    return -1;
+  }
+
+  /* Dump some initial timing data to give a little context for human
+     eyes.  Take readings ten minutes apart (45000 sectors) and at end of disk. */
+  {
+    int x;
+    int current=1000;
+    int latency[current];
+    int sectors[current];
+    double sum;
+    double sumsq;
+    int sofar;
+    int best=0;
+    int bestcount=0;
+    int iterating=0;
+
+    offset = lastsector-firstsector-current-1;
+
+    reportC("\nSeek/read timing:\n");
+
+    while(offset>=firstsector){
+      int m = offset/4500;
+      int s = (offset-m*4500)/75;
+      int f = offset-m*4500-s*75;
+      if(iterating){
+	reportC("\n");
+      }else{
+	printC("\r");
+	logC("\n");
+      }
+      reportC("\t[%02d:%02d.%02d]: ",m,s,f);
+      sum=0;
+      sumsq=0;
+
+      /* initial seek to put at at a small offset past end of upcoming reads */
+      if((ret=cdda_read(d,NULL,offset+current+1,1))<0){
+	/* media error! grr!  retry elsewhere */
+	if(ret==-404)return -1;
+	reportC("\n\tWARNING: media error during setup; continuing at next offset...");
+	goto next;
+      }
+
+      logC("\n");
+      
+      for(i=0,sofar=0;sofar<current;i++){
+	int toread = (i==0?1:current-sofar);
+	int ret;
+	/* first read should also trigger a short seek; one sector so seek duration dominates */
+	if((ret=cdda_read(d,NULL,offset+sofar,toread))<=0){
+	  /* media error! grr!  retry elsewhere */
+	if(ret==-404)return -1;
+	  reportC("\n\tWARNING: media error during read; continuing at next offset...");
+	  goto next;
+	}
+
+	x = cdda_milliseconds(d);
+	if(x>9999)x=9999;
+	if(x<0)x=0;
+	logC("%d:%d ",ret,x);
+
+	latency[i]=x;
+	sectors[i]=ret;
+	sofar+=ret;
+	if(i){
+	  sum+=x;
+	  sumsq+= x*x /(float)ret;
+	}
+      }
+      
+      /* ignore upper outliers; we may have gotten random bursts of latency */
+      {
+	double mean = sum/(float)(current-1);
+	double stddev = sqrt( (sumsq/(float)(current-1) - mean*mean));
+	double upper= mean+((isnan(stddev) || stddev*2<1.)?1.:stddev*2);
+	int j;
+	
+	mean=0;
+	sofar=0;
+	for(j=1;j<i;j++){
+	  double per = latency[j]/(double)sectors[j];
+	  if(per<=upper){
+	    mean+=latency[j];
+	    sofar+=sectors[j];
+	  }
+	}
+	mean/=sofar;
+	
+	printC("%4dms seek, %.2fms/sec read [%.1fx]",latency[0],mean,1000./75./mean);
+	logC("\n\tInitial seek latency (%d sectors): %dms",current,latency[0]);
+	logC("\n\tAverage read latency: %.2fms/sector (raw speed: %.1fx)",mean,1000./75./mean);
+	logC("\n\tRead latency standard deviation: %.2fms/sector",stddev);
+
+	sofar=mean*current;
+	if(!iterating){
+	  if(-sofar<best){
+	    best=-sofar;
+	    bestcount=0;
+	  }else{
+	    bestcount+=sofar;
+	    if(bestcount>sofar && bestcount>2000)
+	      iterating=1;
+	  }
+	}
+      }
+    next:
+
+      if(iterating){
+	offset = (offset-firstsector+44999)/45000*45000+firstsector;
+	offset-=45000;
+	printC("               ");
+      }else{
+	offset--;
+	printC(" spinning up...");
+      }
+    }
+  }
+
+  reportC("\n\nAnalyzing readahead cache access...\n");
+  
+  /* search on cache size; cache hits are fast, seeks are not, so a
+     linear search through cache hits up to a miss are faster than a
+     bisection */
+
+  int hi=15000;
+  int current=0;
+  int under=1;
+  offset = firstsector;
+
+  while(current <= hi && under){
+    int i,j;
+    under=0;
+    current++;
+
+    printC("\r");
+    reportC("\tFast search for approximate cache size... %d sectors            ",current-1);
+    logC("\n");
+
+    for(i=0;i<15 && !under;i++){
+      for(j=0;;j++){
+	int ret1,ret2;
+	if(i>=5){
+	  int sofar=0;
+	  
+	  if(i==5){
+	    printC("\r");
+	    reportC("\tSlow verify for approximate cache size... %d sectors",current-1);
+	    logC("\n");
+
+	    logC("\tAttempting to reduce read speed to 1x... ");
+	    if(cdda_speed_set(d,1)){
+	      logC("failed.\n");
+	    }else{
+	      logC("drive said OK\n");
+	    }
+	  }
+	  printC(".");
+	  logC("\t\t>>> ");
+
+	  while(sofar<current){
+	    ret1 = cdda_read(d,NULL,offset+sofar,current-sofar);
+	    logC("slow_read=%d:%d ",ret1,cdda_milliseconds(d));
+	    if(ret1<=0)break;
+	    sofar+=ret1;
+	  }
+	}else{
+	  ret1 = cdda_read(d,NULL,offset+current-1,1);
+	  logC("\t\t>>> fast_read=%d:%d ",ret1,cdda_milliseconds(d));
+	}
+	ret2 = cdda_read(d,NULL,offset,1);
+	logC("seek_read=%d:%d\n",ret2,cdda_milliseconds(d));
+	
+	if(ret1<=0 || ret2<=0){
+	  offset+=current+100;
+	  if(j==10 || offset+current>lastsector){
+	    reportC("\n\tToo many read errors while performing drive cache checks;"
+		    "\n\t  aborting test.\n\n");
+	    return(-1);
+	  }
+	  reportC("\n\tRead error while performing drive cache checks;"
+		  "\n\t  choosing new offset and trying again.\n");
+	}else{
+	  if(cdda_milliseconds(d)==-1){
+	    reportC("\n\tTiming error while performing drive cache checks; aborting test.\n");
+	    return(-1);
+	  }else{
+	    if(cdda_milliseconds(d)<9)under=1;
+	    break;
+	  }
+	}
+      }
+    }
+  } 
+
+  printC("\r");
+  if(current==hi){
+    reportC("\tWARNING: Cannot determine drive cache size or behavior!          \n");
+    return 1;
+  }else if(current>1){
+    reportC("\tApproximate random access cache size: %d sectors                 \n",current-1);
+  }else{
+    reportC("\tDrive does not cache nonlinear access                            \n");
+    return 0;
+  }
+   
+  /* this drive caches; Determine if the detailed caching behavior fits our model. */
+
+  /* does the readahead cache exceed the maximum Paranoia currently expects? */
+  if(current-1 > CACHEMODEL_SECTORS){
+    reportC("\nWARNING: This drive appears to be caching more sectors of\n"
+	    "           readahead than Paranoia can currently handle!\n");
+    warn=1;
+
+  }
+
+  /* This is similar to the Fast search above, but just in case the
+     cache is being tracked as multiple areas that are treated
+     differently if non-contiguous.... */
+  {
+    int seekoff = current*3;
+    reportC("\nVerifying that readahead cache is contiguous");
+    under=0;
+  
+    for(i=0;i<30 && !under;i++){
+      printC(".");
+      for(j=0;;j++){
+	int ret1,ret2;
+
+	if(offset+seekoff>lastsector){
+	  reportC("\n\tOut of readable space on CDROM while performing drive checks;"
+		  "\n\t  aborting test.\n\n");
+	  return(-1);
+	}
+	
+
+	ret1 = cdda_read(d,NULL,offset+seekoff,1);
+	logC("\t\t>>> %d:%d ",offset+current,cdda_milliseconds(d));
+	ret2 = cdda_read(d,NULL,offset,1);
+	logC("%d:%d\n",offset,cdda_milliseconds(d));
+	
+	if(ret1<=0 || ret2<=0){
+	  offset+=current+100;
+	  if(j==10){
+	    reportC("\n\tToo many read errors while performing drive cache checks;"
+		    "\n\t  aborting test.\n\n");
+	    return(-1);
+	  }
+	  reportC("\n\tRead error while performing drive cache checks;"
+		  "\n\t  choosing new offset and trying again.\n");
+	}else{
+	  if(cdda_milliseconds(d)==-1){
+	    reportC("\n\tTiming error while performing drive cache checks; aborting test.\n");
+	    return(-1);
+	  }else{
+	    if(cdda_milliseconds(d)<9)under=1;
+	    break;
+	  }
+	}
+      }
+    }
+    if(under){
+      reportC("\nWARNING: Drive cache does not appear to be contiguous!\n");
+      warn=1;
+    }else{
+      reportC("\n\tdone.  Drive cache tests as contiguous.\n");
+    }
+  }
+
+  /* does a read beyond shift the cache or dump it? */
+
+  /* Verify that a read that begins before the cached readahead dumps
+     the entire readahead cache */
+
+  /* Check to see that cdda_clear_cache clears the specified cache area */
+
+  /* Does cdda_clear_cache result in noncontiguous cache areas? */
+
+  return warn;
+}
+
+

Modified: trunk/cdparanoia/paranoia/cdda_paranoia.h
===================================================================
--- trunk/cdparanoia/paranoia/cdda_paranoia.h	2008-08-26 18:17:29 UTC (rev 15213)
+++ trunk/cdparanoia/paranoia/cdda_paranoia.h	2008-08-28 16:41:43 UTC (rev 15214)
@@ -37,6 +37,9 @@
 typedef void cdrom_paranoia;
 #endif
 
+#include <stdio.h>
+
+extern char *paranoia_version();
 extern cdrom_paranoia *paranoia_init(cdrom_drive *d);
 extern void paranoia_modeset(cdrom_paranoia *p,int mode);
 extern long paranoia_seek(cdrom_paranoia *p,long seek,int mode);
@@ -44,5 +47,6 @@
 extern int16_t *paranoia_read_limited(cdrom_paranoia *p,void(*callback)(long,int),int maxretries);
 extern void paranoia_free(cdrom_paranoia *p);
 extern void paranoia_overlapset(cdrom_paranoia *p,long overlap);
+extern int paranoia_analyze_verify(cdrom_drive *d, FILE *progress, FILE *log);
 
 #endif

Modified: trunk/cdparanoia/paranoia/p_block.h
===================================================================
--- trunk/cdparanoia/paranoia/p_block.h	2008-08-26 18:17:29 UTC (rev 15213)
+++ trunk/cdparanoia/paranoia/p_block.h	2008-08-28 16:41:43 UTC (rev 15214)
@@ -16,6 +16,7 @@
 #define MIN_SECTOR_BACKUP    16     /* sectors */
 #define JIGGLE_MODULO        15     /* sectors */
 #define MIN_SILENCE_BOUNDARY 1024   /* 16 bit words */
+#define CACHEMODEL_SECTORS   1200
 
 #define min(x,y) ((x)>(y)?(y):(x))
 #define max(x,y) ((x)<(y)?(y):(x))

Modified: trunk/cdparanoia/paranoia/paranoia.c
===================================================================
--- trunk/cdparanoia/paranoia/paranoia.c	2008-08-26 18:17:29 UTC (rev 15213)
+++ trunk/cdparanoia/paranoia/paranoia.c	2008-08-28 16:41:43 UTC (rev 15214)
@@ -2710,3 +2710,7 @@
   p->dynoverlap=overlap*CD_FRAMEWORDS;
   p->stage1.offpoints=-1; 
 }
+
+char *paranoia_version(void){
+  return VERSIONNUM;
+}

Modified: trunk/cdparanoia/version.h
===================================================================
--- trunk/cdparanoia/version.h	2008-08-26 18:17:29 UTC (rev 15213)
+++ trunk/cdparanoia/version.h	2008-08-28 16:41:43 UTC (rev 15214)
@@ -7,4 +7,5 @@
  ******************************************************************/
 
 
-#define VERSION "cdparanoia III release 10.2pre (August 11, 2008)\n"
+#define VERSIONNUM "10.2pre"
+#define VERSION "cdparanoia III release " VERSIONNUM " (August 11, 2008)\n"



More information about the commits mailing list