T.R | Title | User | Personal Name | Date | Lines |
---|
2108.1 | Please install latest ECO kit and retest | TLE::D_SMITH | Duane Smith -- DEC C RTL | Wed Feb 26 1997 16:44 | 22 |
| My first attempt was using the DEC C RTL which shipped with OpenVMS
V7.0. The problem reproduced during the fifth run.
I then defined DECC$SHR to point to the DEC C RTL which is shipping
with the latest ECO kit. After reinitiating the test, it has now
completed 18 runs without a hitch.
Based on this observation, I suggest that you retest after installing
the latest DEC C Runtime Library ECO kit available for OpenVMS V7.0 for
VAX. The latest kit is called VAXACRT05_070.
There have been several problems corrected in that kit, some of which
were related to I/O. A quick scan of the release notes did not show
an exact match.
Instructions for obtaining ECO kits can be found at our web site:
http://hndymn.zko.dec.com:80/~crtl/
Thanks,
Duane Smith
|
2108.2 | | TLE::D_SMITH | Duane Smith -- DEC C RTL | Thu Feb 27 1997 06:37 | 4 |
| While I couldn't reproduce, another member of my team can. It still
never hurts to try the latest ECO kits prior to reporting problems.
Duane
|
2108.3 | Use RMS Directly... | XDELTA::HOFFMAN | Steve, OpenVMS Engineering | Thu Feb 27 1997 13:42 | 257 |
|
Since this program is laced with OpenVMS calls, I'd look at replacing
the C file-I/O calls with RMS calls -- I've got to get one of the local
C RMS I/O libraries onto the next freeware CD-ROM. While more recent
versions of the C RTL are dramatically improving, it's still a UNIX
emulation on top of OpenVMS, with all the idiosyncrasies that result.
(UNIX doesn't have anything like RMS's multi-process and interlocking
and record-management capabilities...)
/*
** COPYRIGHT (c) 1992 BY
** DIGITAL EQUIPMENT CORPORATION, MAYNARD, MASSACHUSETTS.
** ALL RIGHTS RESERVED.
**
** THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY BE USED AND COPIED
** ONLY IN ACCORDANCE OF THE TERMS OF SUCH LICENSE AND WITH THE
** INCLUSION OF THE ABOVE COPYRIGHT NOTICE. THIS SOFTWARE OR ANY OTHER
** COPIES THEREOF MAY NOT BE PROVIDED OR OTHERWISE MADE AVAILABLE TO ANY
** OTHER PERSON. NO TITLE TO AND OWNERSHIP OF THE SOFTWARE IS HEREBY
** TRANSFERRED.
**
** THE INFORMATION IN THIS SOFTWARE IS SUBJECT TO CHANGE WITHOUT NOTICE
** AND SHOULD NOT BE CONSTRUED AS A COMMITMENT BY DIGITAL EQUIPMENT
** CORPORATION.
**
** DIGITAL ASSUMES NO RESPONSIBILITY FOR THE USE OR RELIABILITY OF ITS
** SOFTWARE ON EQUIPMENT WHICH IS NOT SUPPLIED BY DIGITAL.
*/
/*
**++
** Facility:
**
** Examples
**
** Version: V1.1
**
** Abstract:
**
** Example of working with RMS calls from C
**
** Author:
** Steve Hoffman (XDELTA::HOFFMAN)
**
** Creation Date: 1-Jan-1990
**
** Modification History:
** Hoffman 15-Oct-1994 Updates for DEC C
**--
*/
/*
// RMS_EXAMPLES.C
//
// Program displays some RMS calls made from the c language. Types out
// the calling process's SYS$LOGIN:LOGIN.COM file to SYS$OUTPUT.
//
// Included is a main and three subroutines. The subroutines open,
// read a record, and close the file. Several hooks, such as the
// use of the NAM block to obtain the specification of the file that
// was actually opened, are included but are not currently used.
//
// To build:
//
// $ CC [/DECC] [/DEBUG/NOOPTIM] RMS_EXAMPLES
// $ LINK [/DEBUG] RMS_EXAMPLES
// $ RUN [/[NO]DEBUG] RMS_EXAMPLES
*/
#include <lib$routines.h>
#include <rms.h>
#include <starlet.h>
#include <string.h>
#include <ssdef.h>
#include <stdio.h>
#include <stsdef.h>
/*
// RMS_MRS is the maximum record size that can be read (and thus
// displayed) by this program.
*/
#define RMS_MRS 255
/*
// The following is the core data structure for the program.
// The various RMS subroutines all communicate via a pointer
// referencing this struct.
*/
struct RmsFileContext
{
struct FAB fab;
struct RAB rab;
struct NAM nam;
char rss[NAM$C_MAXRSS];
short max_rec_siz;
char *data_buffer;
};
RmsFileOpen( void **CtxArg,
char *FileName, char *DefFileName, int flags, int rss )
{
int RetStat;
struct RmsFileContext *Ctx;
int howbig = sizeof( struct RmsFileContext );
/*
// acquire some space for a Context block.
*/
RetStat = lib$get_vm( &howbig, &Ctx, 0 );
if ( !$VMS_STATUS_SUCCESS( RetStat ) )
return RetStat;
*CtxArg = (void *) Ctx;
/*
// Fill in the various fields of the Context block.
// -- Builds the File Access Block (FAB), the Record Access
// Block (RAB) and the Name (NAM) Block. Along with some
// other miscellaneous housekeeping stuff.
*/
Ctx->fab = cc$rms_fab;
Ctx->rab = cc$rms_rab;
Ctx->nam = cc$rms_nam;
Ctx->fab.fab$l_nam = &Ctx->nam;
Ctx->fab.fab$l_fop = FAB$M_NAM;
Ctx->fab.fab$b_fac = FAB$M_GET;
Ctx->fab.fab$l_fna = FileName;
Ctx->fab.fab$b_fns = strlen( FileName );
Ctx->fab.fab$l_dna = DefFileName;
Ctx->fab.fab$b_dns = strlen( DefFileName );
Ctx->rab.rab$l_fab = &Ctx->fab;
Ctx->nam.nam$b_rss = NAM$C_MAXRSS;
Ctx->nam.nam$l_rsa = Ctx->rss;
Ctx->rab.rab$b_rac = RAB$C_SEQ;
/*
// Attempt to open the file...
*/
RetStat = sys$open( &Ctx->fab, 0, 0 );
if ( !$VMS_STATUS_SUCCESS( RetStat ) )
return RetStat;
/*
// Allocate a buffer large enough for the biggest record.
*/
RetStat = lib$get_vm( &RMS_MRS, &Ctx->data_buffer, 0 );
if ( !$VMS_STATUS_SUCCESS( RetStat ) )
return RetStat;
/*
// Attempt to connect the record stream to the file...
*/
RetStat = sys$connect( &Ctx->rab, 0, 0 );
if ( !$VMS_STATUS_SUCCESS( RetStat ) )
return RetStat;
return RetStat;
}
RmsFileRead( void **CtxArg, char **BufAdr, int *BufLen )
{
int RetStat;
struct RmsFileContext *Ctx = *CtxArg;
Ctx->rab.rab$l_ubf = Ctx->data_buffer;
Ctx->rab.rab$w_usz = RMS_MRS;
RetStat = sys$get( &Ctx->rab, 0, 0 );
if ( !$VMS_STATUS_SUCCESS( RetStat ) )
{
*BufLen = (char) 0;
*BufAdr = (char) 0;
return RetStat;
}
*BufAdr = Ctx->rab.rab$l_rbf;
*BufLen = Ctx->rab.rab$w_rsz;
return RetStat;
}
RmsFileClose( void **CtxArg )
{
int RetStat;
struct RmsFileContext *Ctx = *CtxArg;
/*
// Free up the record buffer...
*/
RetStat = lib$free_vm( &RMS_MRS, &Ctx->data_buffer, 0 );
if ( !$VMS_STATUS_SUCCESS( RetStat ) )
return RetStat;
/*
// Be nice and clean up the record stream...
*/
RetStat = sys$disconnect( &Ctx->rab, 0, 0 );
if ( !$VMS_STATUS_SUCCESS( RetStat ) )
return RetStat;
/*
// And close the file...
*/
RetStat = sys$close( &Ctx->fab, 0, 0 );
if ( !$VMS_STATUS_SUCCESS( RetStat ) )
return RetStat;
/*
// And free up the allocated memory...
*/
RetStat = lib$free_vm( &sizeof( struct RmsFileContext ), CtxArg, 0 );
if ( !$VMS_STATUS_SUCCESS( RetStat ) )
return RetStat;
return RetStat;
}
main()
{
int RetStat;
void *Context;
char *BufAdr;
int BufLen;
/*
// Open the file. Minimal checking is performed. Read access only.
*/
RetStat = RmsFileOpen( &Context, "LOGIN", "SYS$LOGIN:.COM", 0, 0 );
/*
// Read the file. Minimal checking is performed.
*/
for (;;)
{
RetStat = RmsFileRead( &Context, &BufAdr, &BufLen );
if ( $VMS_STATUS_SUCCESS( RetStat ) )
printf("%*.*s\n", BufLen, BufLen, BufAdr );
else
break;
}
/*
// Close up shop.
*/
RetStat = RmsFileClose( &Context );
return RetStat;
}
|
2108.4 | - Well, it works better.... | CSC32::V_HAVER | | Thu Feb 27 1997 20:40 | 12 |
| I installed VAXACRT05_070 and it seemed to help. But from note 2108.2 it
appears that it isn't the complete solution, and the real recommendation at
this time is to use RMS calls directly. Hopefully, I am not misunderstanding
the previous responses.
So, I'll suggest that the customer upgrade (since he should do that anyway)
and install the current ECOs. However, will let him know that using RMS calls
directly is the best option.
Thx,
Vic
|
2108.5 | RMS record locking options are missing | TAVENG::BORIS | Boris Gubenko, ISE | Mon Mar 03 1997 12:08 | 38 |
|
The %RMS-F-CUR error you got on fprintf() was caused by the failure to
position the file at end-of-file. The nature of append access mode is that
the file opened for append is positioned at end-of-file before any output.
To position a file at end-of-file, the DEC C RTL reads the file records in
a loop until EOF is reached.
In your test program you're opening shared file for append specifying only
"shr=put" without any RMS record locking option. What happened is that the
default RMS record locking was applied and when two or more streams called
the $GET service to read the same record while positioning the file at
end-of-file, one of more requests failed with "%RMS-E-RLK, target record
currently locked by another stream" status. This explains why the problem
is "random as to which message is missing" and why the problem not always
is reproducible.
There are a number of RMS record locking options which may be specified in
fopen() statement to fix the problem: RAB$V_REA, RAB$V_RLK, RAB$V_RRL etc.
The problem went away, for example, after adding the "shr=put" and "rop=rea"
options to fopen() statement.
We decided, that the right thing to do would be to let the caller to choose
the most suitable record locking option and not to try to add record locking
options on the open call on behalf the user.
We consider this as a documentation issue and are planning to add the
following text to the next release of the DEC C RTL Reference Manual:
. If you intend to share a file opened for append, you must specify
appropriate share and record locking options, allowing other
accessors to read the record. This is because the file is positioned
at end-of-file through reading records in a loop until end-of-file
is reached.
Thank you for reporting this. We are sorry for any inconveniences this may
have caused to you and your customer.
Boris
|
2108.6 | - followup questions | CSC32::V_HAVER | | Tue Mar 04 1997 16:30 | 11 |
| re: .5
Thanks for the informative response. It certainly makes the CUR error and the
results understandable. Just a couple of (hopefully simple) follow up questions.
DEC C RTL behavior on positioning to EOF: Does rop=eof have any affect on this
behavior, or is it basically the same as saying append "a" access? Assuming
rop=eof has no affect, then using RMS calls directly would be the only way
around the DEC C RTL behavior. Is that correct?
vicky
|
2108.7 | reply to .6 | TAVENG::BORIS | Boris Gubenko, ISE | Wed Mar 05 1997 00:58 | 55 |
| > [...] Just a couple of (hopefully simple) follow up questions.
>
> DEC C RTL behavior on positioning to EOF: Does rop=eof have any affect on this
> behavior, or is it basically the same as saying append "a" access? Assuming
> rop=eof has no affect, then using RMS calls directly would be the only way
> around the DEC C RTL behavior. Is that correct?
>
The problem is not positioning the file to the end of the file for the
connect operation for shared append access, but, rather, in seeking to EOF
performed by the DEC C RTL before each output which, in your case, is not
needed at all.
While opening the file for append ("a") or append update ("a+") access mode,
the DEC C RTL sets the RAB$V_EOF bit in the RAB$L_ROP field before calling
the $CONNECT service, so the file is positioned at EOF before the first
output. For your test example this is enough because RMS itself handles the
logical end of the file for shared write operation.
From the description of $PUT RMS service:
Inserting Records into Sequential Files
RMS also provides for establishing the logical end of the file when
two or more processes are doing shared write operation. For example,
assume that processes A and B are sharing a sequential file and each
process is putting data into the file. Process A puts a record at the
end of the file and intends to put another record at the new end-of-file
location. However, before process A can put the record in the file,
process B gains access to the file and puts a record at the end of the
file. In order to ensure, that the next record from process A does not
overwrite the record just inserted by process B, RMS updates process
A's pointer to the new end-of-file position; that is, the location
immediately following the location of process B's record.
Unfortunately, the DEC C RTL does not detect the case when seeking at EOF
is not needed. This seeking, implemented as calling the $GET in a loop, may
result in the situation when process A is trying to read the record which is
currently read and locked for read by process B.
There is no way to prevent the DEC C RTL from performing this (meaningless
in your case) seeking at EOF and calling the RMS directly is always a good
idea.
However, for your test example, the simple cure is to specify RMS record
locking option in fopen() statement allowing other accessors to read the
record. I think, that in your case the most appropriate option is RAB$V_REA -
lock record for read. As stated in .5, the problem goes away if "shr=get,put"
and "rop=rea" are specified.
Note, that seeking at EOF is not always meaningless - consider the case when
rewind() or fseek() is called between two successive fputs() calls for a file
opened for append.
Boris
|
2108.8 | | CSC64::BLAYLOCK | If at first you doubt,doubt again. | Wed Mar 05 1997 18:43 | 27 |
| . Unfortunately, the DEC C RTL does not detect the case when seeking at EOF
. is not needed. This seeking, implemented as calling the $GET in a loop, may
. result in the situation when process A is trying to read the record which is
. currently read and locked for read by process B.
.
. There is no way to prevent the DEC C RTL from performing this (meaningless
. in your case) seeking at EOF and calling the RMS directly is always a good
. idea.
The RMS solution in this case is:
rab$b_rac = RAB$C_RFA ;
rab$l_rfa0 = -1 ;
rab$w_rfa4 = 511 ; /* Must be less than devblocksize */
status = sys$find( &rab ) ;
if ( (!(status&1)) && (status != RMS$_EOF)) {
/* do error processing */
}
rab$b_rac = RAB$C_SEQ ;
status = sys$put( rab ) ;
the $find positions you at EOF and saves a bit of I/O for what would appear
to be the common case usage of fprintf and append mode.
However, the use of sharing options on the open/fopen calls probably
indicates the use of direct RMS calls instead anyway; as has been suggested.
|