home *** CD-ROM | disk | FTP | other *** search
/ NetNews Usenet Archive 1993 #3 / NN_1993_3.iso / spool / comp / os / vms / 21876 < prev    next >
Encoding:
Text File  |  1993-01-24  |  5.6 KB  |  143 lines

  1. Path: sparky!uunet!ukma!usenet.ins.cwru.edu!agate!ucbvax!lrw.com!leichter
  2. From: leichter@lrw.com (Jerry Leichter)
  3. Newsgroups: comp.os.vms
  4. Subject: re: Flushing file buffers to disk in VAX C
  5. Message-ID: <9301231826.AA03802@uu3.psi.com>
  6. Date: 23 Jan 93 17:15:07 GMT
  7. Sender: daemon@ucbvax.BERKELEY.EDU
  8. Distribution: world
  9. Organization: The Internet
  10. Lines: 131
  11.  
  12.  
  13.     The problem:
  14.     ------------
  15.     I am running VMS 5.5-1 on a VAXstation 4000 model 60. I find that the
  16.     C library call fsync() does not write the file buffers to disk as it
  17.     is supposed to. Could someone else run the program below on  this or
  18.     earlier versions of VMS and check it? Run the program on  one
  19.     terminal, and when it stops to wait for input, kill the process using
  20.     the STOP command from another terminal. If I understand the
  21.     functionality of fsync() correctly, the buffers should have been
  22.     flushed to disk - but when you look at the file after stopping the
  23.     process, it is still empty. Is this a bug? 
  24.  
  25. Well, no.  Since fsync() is neither documented nor supported, it can't
  26. possibly have any bugs; if its effect were to delete every other file in
  27. your directory, that might be rather undesireable behavior, but it wouldn't
  28. really be a BUG.  :-)
  29.  
  30.     Some more details:
  31.     -----------------
  32.  
  33.     I am using VAX C version 3.2 - earlier versions of the RTL may not
  34.     support the fsync() call. It is not documented in the RTL reference
  35.     manual even in the current version,
  36.  
  37. As you see....  Could it be that perhaps you've found a REASON why it isn't 
  38. documented or supported?
  39.  
  40.                         but it is available in the
  41.     library. There is no other way to ensure that C file data has been
  42.     written to disk and the disk version is up-to-date (short of closing
  43.     the file).
  44.  
  45.     I do not think the bug is in the fsync() routine itself; you can
  46.     verify  that the routine calls the RMS routine sys$flush() internally,
  47.     as you might expect. (You can check this out by stepping through the
  48.     assembly instructions with the debugger). I have tried calling
  49.     sys$flush() directly, and it returns without error - still without
  50.     writing the buffers to the file. So is the error in RMS?
  51.  
  52. No.  There's no error; you're just seeing an unexpected side effect of the
  53. implementation.
  54.  
  55. In Unix, write() is a system call, and the standard I/O library is layered on
  56. top of it (and a few other system calls).  VMS has not write() call; like all
  57. the other Unix calls, it is emulated by the VAX C RTL.  However, for various
  58. reasons the emulation does NOT follow the design used in Unix:  The standard
  59. I/O library is NOT implemented on top of the emulated write().  Instead, some
  60. common code ultimately underlies both.
  61.  
  62. When you do a write() with the VAX C RTL, the data goes into a buffer managed
  63. by the RTL.  Later, the RTL will pass the data off to RMS - but not right
  64. away.  As a result, when you do a SYS$FLUSH, either through fsync() or by
  65. a direct call, RMS happily confirms that it has written out all the 0 bytes
  66. it has been handed so far.
  67.  
  68. Even on Unix, if you want fsync() to work for a file opened through the stan-
  69. dard I/O library, you have to use fflush() first to get the data out of the
  70. stdio buffers and into the Unix system buffers, and only then do an fsync() to
  71. force the data to the disk.  With the current VAX C RTL implementation, you
  72. have to do the same thing - but you also have to do it for data written with
  73. a write() call.
  74.  
  75. Unfortunately, however, there does not exist a call to flush a file described
  76. by number, as opposed to one described by a FILE * - such a call would make no
  77. sense on Unix.  There is a work-around, though:  By using fdopen(), you can
  78. create a FILE * that points to a file opened using the "lower level" Unix I/O
  79. functions, then use fflush() on that.  The resulting code - I've included a
  80. modified version of the posted source below - works as you wanted.  (It should
  81. also work on Unix, where the fflush() will always be a no-op.)
  82.  
  83.     Another puzzle which I wonder if someone could explain to me - the C
  84.     write() routine does not call RMS sys$write() at all. It calls
  85.     sys$read() instead! Is there something wrong with my debugger symbols
  86.     or is this the right thing for write() to do? It works, i.e.  the file
  87.     does get written to normally. Does this have something to do with the
  88.     above problem?
  89.  
  90. No.  I suspect you are misinterpreting some Debugger display, but without all
  91. the details I can't be sure.  (It's probably not worth it to try and resolve
  92. this.)
  93.                             -- Jerry
  94.  
  95. ---------------- Modified source code begins here ---------------------------
  96. #include <stdio.h>
  97. #include <file.h>
  98.  
  99. main()
  100. {
  101.     int fd;
  102.     FILE *fdf;            /* Dummy FILE * for fd    */
  103.     char buf[] = "This is a test record\n";
  104.     char testFileName[] = "chks.out";
  105.  
  106.     if ( (fd = open(testFileName, O_RDWR | O_CREAT)) < 0) {
  107.         fprintf(stderr, "Error opening file. Exiting... \n");
  108.         exit(0);
  109.     }
  110.  
  111.     /*
  112.      * Associate a FILE * with fd.
  113.      */
  114.     if ((fdf = fdopen(fd,"r+")) == NULL) {
  115.         fprintf(stderr, "Error making FILE pointer. Exiting... \n");
  116.         exit(0);
  117.     }
  118.  
  119.     fprintf(stderr, "The file being used is %s\n\n", testFileName);
  120.     fprintf(stderr, "%s%s%s%s%s",
  121.     "A record has been written to the file and sync'ed. If the fsync()\n",
  122.     "call works correctly the data should be in the file even if the\n",
  123.     "process is stopped. You can now halt the process from another\n",
  124.     "terminal or window using the STOP command, or hit any key to let\n",
  125.     "it run to completion...\n"
  126.         );
  127.     fflush(stderr);
  128.  
  129.     write(fd, buf, sizeof(buf));
  130.     fflush(fdf);            /* Get the record to RMS    */
  131.     fsync(fd);            /* Get it to the disk        */
  132.  
  133.     /**
  134.         You can now stop the process from another terminal or
  135.         window while it waits, or let it complete.
  136.     **/
  137.     getchar();
  138.  
  139.     close(fd);
  140.     fprintf(stderr, "Wrote the record and closed the file\n");
  141. }
  142.  
  143.