Ошибка fwrite(): EDC5024i: Предпринята попытка закрыть файл, открытый в другом потоке
Я отправляю задание JCL для размещения набора данных VB в мейнфрейме. После отправки задания набор данных будет успешно создан.
Затем я запускаю Java-программу в области OMVS мэйнфрейма, чтобы открыть файл и записать в него некоторое содержимое. Когда я пытаюсь записать данные в файл, я получаю сообщение об ошибке ниже.
// DD: SYS00011: ошибка fwrite(). EDC5024I Была предпринята попытка закрыть файл, открытый другим потоком.; errno = 24 errno2 = 0xc0640021 last_op = 0 errorCode = 0x0.
JCL передал для размещения набора данных:
//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
код для записи файла:
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++;
}
1 ответ
Суть вашей проблемы в том, что вам нужно вызывать метод ZFile.close() после того, как вы закончите писать. Это гарантирует, что все операции открытия, записи и закрытия будут происходить в одном потоке, и все будет в порядке. Это побочный эффект использования обычных наборов данных вместо файлов USS.
Причина этого сложна, но это связано с тем, что в z/OS "обычные" наборы данных QSAM/BSAM/VSAM ведут себя немного иначе, чем файлы файловой системы UNIX.
Если вы выполняете запись в файл UNIX (HFS, ZFS, NFS и т. Д.) Вместо обычного набора данных, то все, что вы делаете, будет работать отлично... это потому, что USS по-разному относится к владению ресурсами - файловые дескрипторы принадлежат уровень процесса, а не поток. Когда вы открываете файл USS, этот дескриптор файла может использоваться или закрываться любым потоком в процессе... это предусмотрено различными стандартами UNIX, поэтому у z/OS нет другого выбора, кроме как работать таким образом.
Обычные наборы данных немного отличаются. Когда вы открываете обычный набор данных, структуры операционной системы, которые определяют открытый файл, сохраняются в памяти, привязанной к потоку, где файл был открыт. В дескрипторе файла достаточно информации, чтобы вы могли выполнять ввод-вывод из других потоков, но закрытие файла должно происходить из потока, в котором он был открыт.
Теперь, поскольку в вашем коде нет функции close (), файл остается открытым до тех пор, пока не закончится ваш поток Java. Когда ваш поток Java заканчивается, среда выполнения системы получает контроль, чтобы очистить любые ресурсы, которые вы могли выделить. Он видит длительный открытый файл и пытается закрыть его, но теперь он не работает в потоке, открывшем файл, поэтому вы получаете ошибку, которую видите.
Обычно файлы UNIX и наборы данных z/OS работают практически одинаково, но эта проблема является одним из небольших отличий. IBM сходит с рук с точки зрения соответствия стандартам, поскольку наборы данных z/OS не являются частью какого-либо стандарта, и, как правило, их взаимозаменяемость является отличной возможностью.
Кстати, все это прописано в мелком шрифте ссылок LE (Language Environment) и C Runtime.