[Search for users] [Overall Top Noters] [List of all Conferences] [Download this site]

Conference vmszoo::rms_openvms

Title:RMS asks, 'R U Journaled?'
Moderator:STAR::TSPEERUVEL
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

3028.0. "SYS$FLUSH Unexepect Behavior" by CSC32::J_RABKE () Tue May 06 1997 18:43

    
    	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.RTitleUserPersonal
Name
DateLines
3028.1next record contextSTAR::EWOODSWed May 07 1997 13:3745
 
  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.2CSC32::J_RABKEWed May 07 1997 15:387
    
    	Elinor,
    	
    	Thanks for the answer.  I'll let customer know.
    
    	Regards,
    	Jayna