| Title: | RMS asks, 'R U Journaled?' |
| Moderator: | STAR::TSPEER UVEL |
| Created: | Tue Mar 11 1986 |
| Last Modified: | Wed Jun 04 1997 |
| Last Successful Update: | Fri Jun 06 1997 |
| Number of topics: | 3031 |
| Total number of notes: | 12302 |
I'm looking for an explanation of why this behavior is happening.
Given an indexed file when adding a record using SYS$PUT then
executing a SYS$FLUSH, the next record retrieved will be the
first record of the file and not the record just added. However,
the SYS$FLUSH is not executed, the record retrieved will be
the record just added.
Here is the C code used to demonstrate the situation:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <rms.h>
#include <starlet.h>
#include <lib$routines.h>
main(int ac, char **av)
{
static struct FAB idxfab;
static struct RAB idxrab;
static char *idxname = "TSTIDX.DAT";
static char idxrec[84];
static int st;
/* Open file and connect */
idxfab = cc$rms_fab;
idxfab.fab$l_fna = idxname;
idxfab.fab$b_fns = strlen(idxname);
idxfab.fab$b_fac = FAB$M_GET|FAB$M_PUT|FAB$M_DEL|FAB$M_UPD;
if (!(1&( st = sys$open(&idxfab) ))) lib$signal(st);
idxrab = cc$rms_rab;
idxrab.rab$l_fab = &idxfab;
idxrab.rab$l_ubf = idxrec;
idxrab.rab$w_usz = sizeof(idxrec);
idxrab.rab$l_kbf = idxrec;
idxrab.rab$b_ksz = 12;
if (!(1&( st = sys$connect(&idxrab) ))) lib$signal(st);
/* Retrieve and display first record */
idxrab.rab$b_rac = RAB$C_SEQ;
if (!(1&( st = sys$get(&idxrab) ))) lib$signal(st);
printf("First record of file:\n%.41s\n",idxrab.rab$l_rbf);
/* Store a new record */
strcpy(idxrec,"1B1E INITIAL");
idxrab.rab$b_rac = RAB$C_KEY;
idxrab.rab$l_rbf = idxrec;
idxrab.rab$w_rsz = 84;
if (!(1&( st = sys$put(&idxrab) ))) lib$signal(st);
/* The application in which this problem originally arose expects
the stream's sequential context to point to the record following
the one added. This was the intention of the following sys$find.
The adverse effect of the sys$flush does not manifest without
this sys$find. */
idxrab.rab$l_rop |= RAB$M_KGT;
if (!(1&( st = sys$find(&idxrab) ))) lib$signal(st);
/* Call sys$flush if any argument is given to the command. */
if (ac > 1) {
puts(" calling sys$flush");
if (!(1&( st = sys$flush(&idxrab) ))) lib$signal(st);
}
/* The following sys$get is supposed to retrieve (by key) and
display the record previously added. However, if sys$flush
was executed above, it incorrectly retrieves the first
record of the file instead. */
idxrab.rab$l_rop &= ~RAB$M_KGT;
printf("Key buffer before sys$get:\n%d bytes: %.*s\n",
idxrab.rab$b_ksz, idxrab.rab$b_ksz, idxrab.rab$l_kbf);
if (!(1&( st = sys$get(&idxrab) ))) lib$signal(st);
printf("Record buffer after sys$get:\n%.41s\n",idxrab.rab$l_rbf);
}
Thanks given to any assistance.
Jayna Rabke
Digital Customer Support/Colorado
| T.R | Title | User | Personal Name | Date | Lines |
|---|---|---|---|---|---|
| 3028.1 | next record context | STAR::EWOODS | Wed May 07 1997 12:37 | 45 | |
First, the user is going through unneeded contortions to accomplish
what he wants according to his comments. He hasn't capitalized on
his making the keybuffer an overlay of the record buffer. After the
$put, there is no need to do a $find before the $flush. Do the $put
and then the $flush.
After the $flush, the keybuffer (overlaying the record buffer) still
contains the key value of the record just $put.
o If he wants the same record to be retrieved, there is no need
to change the ROP field. RAC is still set to RAB$C_KEY. Simply
issue the keyed $GET. The record just put will be returned and
the record context reestablished.
o If instead he wishes the next record after the record just put to
be returned, then he needs to set the KGT option in the rop before
the $get (but again only once after the $flush):
idxrab.rab$l_rop |= RAB$M_KGT;
if (!(1&( st = sys$get(&idxrab) ))) lib$signal(st);
After either $get, he can switch rac to RAB$C_SEQ if he wishes to retrieve
more records sequentially.
As to the $flush resetting the next record context to the first record in
the file, this was an artifact of his example. If you change his example
to do one more sequential $get at the beginning of the program, then
after the $flush, the record retrieved will be the second record in
the file. The next record position it is using is the one last associated
with the sequential $get. In other words, he has not only the $put but
the $gets interacting with the $flush.
There is a table in the Guide to File Applications in Chapter 8 (Table 8-3
Record Access Stream Context) that documents the effect of RMS services on
the next record context. Well, it at least documents the effect of
a number of services -- particularly, gets and puts. Flush isn't documented
in this table. I'll make a note to research it and add it for next release.
But the response for this customer is that he needs to reset the record
context after the $flush; he should assume that it is undefined. And as
I indicated above, there are more direct ways to do this than the
attempts in his example.
-- Elinor
| |||||
| 3028.2 | CSC32::J_RABKE | Wed May 07 1997 14:38 | 7 | ||
Elinor,
Thanks for the answer. I'll let customer know.
Regards,
Jayna
| |||||