0

I am submitting a JCL job to allocate a VB dataset in Mainframe. After submitting the job, the dataset gets created successfully.

Then I am running a java program in omvs region of mainframe, to open the file and write some contents into it. When I try to write the data into the file I am getting the below error.

//DD:SYS00011 : fwrite() failed. EDC5024I An attempt was made to close a file that had been opened by another thread.; errno=24 errno2=0xc0640021 last_op=0 errorCode=0x0.

JCL submitted to allocate the dataset:

//USERNAME JOB ABC,,NOTIFY=&SYSUID,CLASS=F,MSGLEVEL=(1,1),MSGCLASS=X 
//STEP1 EXEC PGM=IEFBR14 
//STEP DD DSN=ASD00T.SM.ULRL, 
// DISP=(NEW,CATLG,DELETE), 
// UNIT=SYSDA,SPACE=(1,(10,60),RLSE),AVGREC=M, 
// DCB=(RECFM=VB), 
// DSORG=PS

code to write the file:

zFileIn = new ZFile("//'ASD00T.INPUT.ULRL'", "rb,type=record,noseek");
if (zFileIn.getDsorg() != ZFile.DSORG_PS) {
throw new IllegalStateException("Input dataset must be DSORG=PS");
 }
zFileOut = new ZFile("//'ASD00T.SM.ULRL'", "wb,type=record,noseek, recfm="+ zFileIn.getRecfm()+ ", lrecl="+ zFileIn.getLrecl());
long count = 0;
byte[] recBuf = new byte[zFileIn.getLrecl()];
int nRead;
while((nRead = zFileIn.read(recBuf)) >= 0) {
zFileOut.write(recBuf, 0, nRead);
count++;
}
Vel
  • 67
  • 11
  • @valerie-r please let me know if you have encountered this issue? – Vel Mar 20 '17 at 17:56
  • Can you post the code for it? It will impossible to debug otherwise, it sounds like the file is either in use, or wasn't opened properly. We can't really tell without seeing how the file was opened. – SaggingRufus Mar 20 '17 at 18:43
  • 2
    We need to see the JCL, which will resolve what you mean about allocate (which means something) and created (which means something else). Also the minimum Java code from your program which shows the problem. Also, how are you doing the timing? You manually execute the Java after you know the z/OS JOB has completed? – Bill Woodger Mar 20 '17 at 19:57
  • 2
    You have some sort of multi-tasking occuring; the message implies that one thread opened a file and another thread is trying to close it, which is forbidden. How are you invoking the Java program: JZOS, BPXBATCH, TSO OMVS, tty? Is the Java program home-grown or part of a package? – zarchasmpgmr Mar 20 '17 at 21:32
  • @zarchasmpgmr I am submitting the jcl job manually to allocate the dataset. once it its successfull i am triggering the java jar file manually. I am running the java program from tso omvs....i am using zfile class provided by ibmjzos.jar.... – Vel Mar 21 '17 at 05:24
  • @SaggingRufus I have posted the JCL and the java code used by me. Please have a look. is there any other way to write data into Variable Block file in Mainframe using Java? – Vel Mar 21 '17 at 13:17
  • please put it in the question using code blocks – SaggingRufus Mar 21 '17 at 13:21
  • @SaggingRufus I have update the question with the code I am using. – Vel Mar 21 '17 at 13:46
  • @SaggingRufus yes the username is in capital letters. After submitting the job, i am able to see the output file that is getting created. I have to do it in java only. Is there any other way I can write data into a VB file in mainframe using java? – Vel Mar 21 '17 at 13:51
  • just curious, why are you doing this in JAVA. If all you are doing is copying one file to another this seems much easier to do in JCL. – SaggingRufus Mar 21 '17 at 13:51
  • @SaggingRufus After reading, i have to process the data, like removing few specific numbers and then i will be writing. – Vel Mar 21 '17 at 13:53
  • if you were to run the above code, would that work? Or would you get the same error? – SaggingRufus Mar 21 '17 at 13:55
  • @SaggingRufus Even if i run the above code it is giving me the same error. – Vel Mar 21 '17 at 13:56
  • Im not seeing a close file anywhere in there. Is it possible that after you ran the first time that the file is still in use? Can you edit the file in the mainframe, or is it locked? – SaggingRufus Mar 21 '17 at 14:02
  • @SaggingRufus i do have a close() method call. The first time itself it is throwing the error. Even after the error I am able to open and edit the file from mainframe , the file is not locked. – Vel Mar 21 '17 at 14:05
  • I'm familiar with that error and it's only happened in multi-threaded environments, in our case a Tomcat servlet. You really need to pos the entire program with main() etc. – David Crayford Mar 28 '17 at 03:33

1 Answers1

1

The heart of your problem is that you need to invoke the ZFile.close() method after you're done writing. Doing so will guarantee that the open, writes and close all happen under the same thread and you should be fine. This is a side-effect of using conventional datasets instead of USS files.

The reason for this is complicated, but it has to do with the fact that in z/OS, "conventional" QSAM/BSAM/VSAM datasets behave slightly differently than do UNIX filesystem files.

If you were writing to a UNIX file (HFS, ZFS, NFS, etc) instead of a conventional dataset, what you're doing would work perfectly fine...this is because USS treats resource ownership differently - file handles are owned at a process level, not a thread. When you open a USS file, that file handle can be used or closed by any thread in the process...this is mandated by the various UNIX standards, so z/OS has no choice but to work this way.

Conventional datasets are a bit different. When you open a conventional dataset, the operating system structures that define the open file are stored in memory anchored to the thread where the file was opened. There's enough information in the file handle that you can do I/O from other threads, but closing the file needs to happen from the thread where the file was opened.

Now, since you don't seem to have a close() in your code, the file stays open until your Java thread ends. When your Java thread ends, the system runtime gets control in order to clean up any resources you might have allocated. It sees the lingering open file and tries to close it, but now it's not running under the thread that opened the file, so you get the failure you're seeing.

Normally, UNIX files and z/OS datasets work almost exactly the same, but this issue is one of the slight differences. IBM gets away with it from a standards compliance perspective since z/OS datasets aren't part of any standard, and generally, the way they can be used interchangeably is a great feature.

By the way, all of this is spelled out in the fine print of the LE (Language Environment) and C Runtime references.

Valerie R
  • 1,769
  • 9
  • 29
  • thanks for the reply. My code does have a close() call. I havenot mentioned it here. I am getting the error when it tries to call write() method for the first time itself – Vel Apr 07 '17 at 15:21
  • Curious if you solved this problem? If not and you're closing the file properly, then you might have an issue in the ZFile package itself...might be a good idea to add some debugging messages showing the thread id on all your ZFile calls - use java.lang.Thread.getId(). If you're doing everything as you say and all your calls from open, writes and closes are under the same thread, there may be a bug in the ZFile package. – Valerie R May 08 '17 at 19:24
  • Curious if you ever got this ironed out? The information you need is available in a dump - if you have someone that can take and read mainframe system dumps, you could probably figure this out in a few moments. – Valerie R May 24 '17 at 19:41
  • Also, there's no need for your allocation batch job - with creative use of the standard Java file I/O functions, you can certainly allocate a conventional file dynamically. IBM overloads file names so you can use // as a prefix to your filename to specify a conventional dataset. The fopen options are also a bit nonstandard in that they allow allocation parameters like you have in your JCL statement...read the C/C++ programming reference - lots of goodies in there that also apply to Java (and of course, you can always call things like fopen via JNI if needed). – Valerie R May 24 '17 at 19:48