ferror()

General discussion on the JZOS batch launcher and toolkit
Post Reply
Yellowcake
Posts: 8
Joined: Sat Aug 05, 2006 4:49 pm

ferror()

Post by Yellowcake »

Files that give the Error Message: "I/O error reading data" in ISPF do not seem to throw any Exceptions in JZOS.
JZOS seems to act as if the file was succesfully opened, and contains no data.

I noticed that the C ferror() function was not implemented anywhere in ZFile. I don't know if this will solve my problem, but I intend to try.

----------------------------------
Cyrus Katrak
IBM Systems &Technology Group, Development
dovetail
Site Admin
Posts: 2022
Joined: Thu Jul 29, 2004 12:12 pm

Post by dovetail »

In JZOS, the ZFile wraps the C-Library routines will throw exceptions if any fopen(), fclose(), fread(), fwrite() etc get an error. Perhaps there is a difference in how the C-library handles your particular error....

Please send us more detailed information, and if possible a way to reproduce the scenario and we will take a look.
Yellowcake
Posts: 8
Joined: Sat Aug 05, 2006 4:49 pm

Blocksize of death

Post by Yellowcake »

I am still confirming how this occured on our system, but the current explanation is that a member was allocated to a PDS with an incorrect blocksize. This will cause the I/O errors from ISPF, and the above mentioned behaviour from JZOS.
----------------------------------
Cyrus Katrak
IBM Systems &Technology Group, Development
Yellowcake
Posts: 8
Joined: Sat Aug 05, 2006 4:49 pm

Post by Yellowcake »

Some jcl for creating a corrupted pds member. (Should cause "I/O error reading data") from ISPF for &SYSUID..PDSGOOD(DATAGOOD).

Code: Select all

//BLOCKSZ  JOB  CLASS=J,MSGCLASS=H,MSGLEVEL=(1,1)                
//*************************************************************//
//ALLOC    EXEC PGM=IEFBR14                                      
//SYSPRINT DD   SYSOUT=(*,,STD)                                  
//PDSGOOD  DD   DISP=(NEW,CATLG),DSN=&SYSUID..PDSGOOD,RECFM=FB,  
//  SPACE=(CYL,(1,1,10)),UNIT=3390,LRECL=80,BLKSIZE=27920        
//PDSBAD   DD   DISP=(NEW,CATLG),DSN=&SYSUID..PDSBAD,RECFM=FB,   
//  SPACE=(CYL,(1,1,10)),UNIT=3390,LRECL=80,BLKSIZE=6400         
//*************************************************************//
//IEBDG1   EXEC PGM=IEBDG                                        
//SYSPRINT DD   SYSOUT=A                                         
//PDSGOOD  DD   DISP=SHR,DSN=&SYSUID..PDSGOOD(DATAGOOD)          
//PDSBAD   DD   DISP=SHR,DSN=&SYSUID..PDSBAD(DATABAD)            
//SYSIN    DD   *                                                
  DSD OUTPUT=(PDSGOOD)                                           
  FD NAME=F1,LENGTH=80,PICTURE=10,P'0123456789'                  
  CREATE QUANTITY=1000,NAME=F1,FILL=X'FF'                        
  END                                                            
                                                                 
  DSD OUTPUT=(PDSBAD)                                            
  CREATE QUANTITY=1000,NAME=F1,FILL=X'FF'                        
  END                                                            
//*************************************************************//
//INJCTERR EXEC PGM=IEBCOPY                                      
//SYSPRINT DD   SYSOUT=(*,,STD)                                  
//SYSUT1   DD   DISP=SHR,DSN=&SYSUID..PDSBAD(DATABAD)            
//SYSUT2   DD   DISP=SHR,DSN=&SYSUID..PDSGOOD(DATABAD),          
//  UNIT=3390,DCB=&SYSUID..PDSBAD                                
//*************************************************************//
jar up the following code:

Code: Select all

import com.dovetail.jzos.ZFile;

public class test {
	public static int MAX_LEN = 5000;
	public static void main (String args[]) {
		String DDNAME = args[0];
		StringBuffer buf = new StringBuffer();
		buf.ensureCapacity(MAX_LEN);
		ZFile inf = null;
		try {
			inf = new ZFile("//DD:" + DDNAME, "rb,type=record,noseek");
			int s = inf.getLrecl();
			byte[] record = new byte[s];
			int nRead;
			// Read record by record
			while ((nRead = inf.read(record)) > 0) {
				// Append ASCII contents to string
				buf.append(new String(record, 0, nRead,
						ZFile.DEFAULT_EBCDIC_CODE_PAGE));
				buf.append("\n");
				// Don't read really long files
				if ((buf.length() + s) > MAX_LEN) {
					// We read to much, just stop here
					buf = null;
					break;
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
			buf = null;
		} finally {
			try {
				inf.close();
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		if (buf != null)
			System.out.println("File Success (Size: "+buf.length()+") Contents:\n"+buf.toString());
		else
			System.out.println("Read Failure.");
	}	
}
execute it (correct paths obviously):

Code: Select all

//JZOST JOB  'JZOS: PDS TEST',CLASS=J,MSGCLASS=H,NOTIFY=&SYSUID,
// REGION=0M,TIME=NOLIMIT                                       
//PROCLIB JCLLIB ORDER=BLAME.JZOS.SAMPJCL                       
//JAVA EXEC PROC=EXJZOSVM,VERSION='14',                         
// JAVACLS='test'                                               
//PDSL1   DD DSN=&SYSUID..PDSGOOD(DATAGOOD),DISP=SHR            
//STDENV DD *                                                   
. /etc/profile                                                  
export JZOS_HOME=/u/blame/jzos                                  
export JAVA_HOME=/java/J1.4                                     
export PATH=/bin:"${JAVA_HOME}"/bin:                            
LIBPATH=/lib:/usr/lib:"${JAVA_HOME}"/bin                        
LIBPATH="$LIBPATH":"${JAVA_HOME}"/bin/classic                   
LIBPATH="$LIBPATH":"${JZOS_HOME}"                               
export LIBPATH="$LIBPATH":                                      
CLASSPATH="/u/blame/test.jar"                                   
for i in "${JZOS_HOME}"/*.jar; do                               
    CLASSPATH="$CLASSPATH":"$i"                                 
    done                                                        
export CLASSPATH="$CLASSPATH":                                  
IJO="-Xms512m -Xmx1400m"                                        
IJO="$IJO -verbose:class"                                       
IJO="$IJO -Djzos.home=${JZOS_HOME}"                             
#IJO="$IJO -Djava.compiler=NONE"                                
export IBM_JAVA_OPTIONS="$IJO "                                 
export JAVA_DUMP_HEAP=false                                     
export JAVA_PROPAGATE=NO                                        
export IBM_JAVA_ZOS_TDUMP=NO                                    
                                                                
export JZOS_MAIN_ARGS="PDSL1"                                   
//                                                              
Should produce this output:

Code: Select all

File Success (Size: 0) Contents:            
                                            
dovetail
Site Admin
Posts: 2022
Joined: Thu Jul 29, 2004 12:12 pm

Post by dovetail »

I was able to reproduce your problem.

First, you can use this system property to enable tracing in the JZOS toolkit native code:

Code: Select all

IJO="$IJO -Djzos.logging=T"
If you do that, you will see that the first call to ZFile.read() is returning a 0-length record. Per the ZFile javadoc, ZFile returns -1 on EOF. Here's the trace that shows that the fread() C-library routine is returning a zero length record:

Code: Select all

 -> read(3422F608, 80, 0, 80)                              
about to fread length=80                                   
name=//DD:INPUT, mode=rb,type=record,noseek, recordCount=1,
bytes read=0                                               
<- read()       


The ZFile native code looks something like this:

Code: Select all

        t.msgln("about to fread length=%d", length);	
	int nRead = fread(buffer+offset, 1, length, file);

	if (nRead < 0) {
		throw "fread failed";
	} else {
		//Need to check feof() if nRead=0 because we may have
		//read a 0 length record which is not the same as EOF.
		if (nRead == 0 && feof(file)) {
			nRead = -1; 	/* protocol consistent with Stream.read() */
		} else {  /* We read something */
			recordCount++;
			byteCount += nRead;
		}
	}	
	printOn(t);
	t.msgln("bytes read=%d", nRead);	
	return nRead;                                   
So, we can conclude that a 0-length record was returned by fread() and not EOF.

So, actually your program has a small problem with it. The while loop should say:

Code: Select all

         while ((nRead = inf.read(record)) >= 0) { 
If you make this change, and up the MAX_LEN to say 100000, then I see that the program reads 240 records, and prints this:

Code: Select all

File Success (Size: 19200) Contents:   
And then gets an EOF from fread(). No error is ever returned to fread, and the data read seems to be all blank.

So, I conclude that there are problems in the C-library fread() routine when reading a messed up PDS such as this. You can reproduce the problem with a simple C-program that uses fopen(), fread(), and fclose().

Also, I think that we need to update our sample programs shipped with JZOS that do record-mode processing (ZFileCopy, ZFilePrint) to handle zero-length records which, although uncommon, can occur in RECFM=V* datasets. It should never occur in a RECFM=F* dataset though.
Post Reply