1 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
2  * Copyright by The HDF Group.                                               *
3  * Copyright by the Board of Trustees of the University of Illinois.         *
4  * All rights reserved.                                                      *
5  *                                                                           *
6  * This file is part of HDF5.  The full HDF5 copyright notice, including     *
7  * terms governing use, modification, and redistribution, is contained in    *
8  * the files COPYING and Copyright.html.  COPYING can be found at the root   *
9  * of the source code distribution tree; Copyright.html can be found at the  *
10  * root level of an installed copy of the electronic HDF5 document set and   *
11  * is linked from the top-level documents page.  It can also be found at     *
12  * http://hdfgroup.org/HDF5/doc/Copyright.html.  If you do not have          *
13  * access to either file, you may request a copy from help@hdfgroup.org.     *
14  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
15 
16 /*
17  * Programmer:  Quincey Koziol <koziol@hdfgroup.org>
18  *              Monday, April 17, 2000
19  *
20  * Purpose:     The POSIX unbuffered file driver using only the HDF5 public
21  *              API and with a few optimizations: the lseek() call is made
22  *              only when the current file position is unknown or needs to be
23  *              changed based on previous I/O through this driver (don't mix
24  *              I/O from this driver with I/O from other parts of the
25  *              application to the same file).
26  *              With custom modifications...
27  */
28 
29 /* Interface initialization */
30 #define H5_INTERFACE_INIT_FUNC	H5FD_log_init_interface
31 
32 
33 #include "H5private.h"      /* Generic Functions    */
34 #include "H5Eprivate.h"     /* Error handling       */
35 #include "H5Fprivate.h"     /* File access          */
36 #include "H5FDprivate.h"    /* File drivers         */
37 #include "H5FDlog.h"        /* Logging file driver  */
38 #include "H5FLprivate.h"    /* Free Lists           */
39 #include "H5Iprivate.h"     /* IDs                  */
40 #include "H5MMprivate.h"    /* Memory management    */
41 #include "H5Pprivate.h"     /* Property lists       */
42 
43 /* The driver identification number, initialized at runtime */
44 static hid_t H5FD_LOG_g = 0;
45 
46 /* Driver-specific file access properties */
47 typedef struct H5FD_log_fapl_t {
48     char *logfile;              /* Allocated log file name */
49     unsigned long long flags;   /* Flags for logging behavior */
50     size_t buf_size;            /* Size of buffers for track flavor and number of times each byte is accessed */
51 } H5FD_log_fapl_t;
52 
53 /* Define strings for the different file memory types
54  * These are defined in the H5F_mem_t enum from H5Fpublic.h
55  * Note that H5FD_MEM_NOLIST is not listed here since it has
56  * a negative value.
57  */
58 static const char *flavors[]={
59     "H5FD_MEM_DEFAULT",
60     "H5FD_MEM_SUPER",
61     "H5FD_MEM_BTREE",
62     "H5FD_MEM_DRAW",
63     "H5FD_MEM_GHEAP",
64     "H5FD_MEM_LHEAP",
65     "H5FD_MEM_OHDR",
66 };
67 
68 /* The description of a file belonging to this driver. The `eoa' and `eof'
69  * determine the amount of hdf5 address space in use and the high-water mark
70  * of the file (the current size of the underlying filesystem file). The
71  * `pos' value is used to eliminate file position updates when they would be a
72  * no-op. Unfortunately we've found systems that use separate file position
73  * indicators for reading and writing so the lseek can only be eliminated if
74  * the current operation is the same as the previous operation.  When opening
75  * a file the `eof' will be set to the current file size, `eoa' will be set
76  * to zero, `pos' will be set to H5F_ADDR_UNDEF (as it is when an error
77  * occurs), and `op' will be set to H5F_OP_UNKNOWN.
78  */
79 typedef struct H5FD_log_t {
80     H5FD_t          pub;    /* public stuff, must be first      */
81     int             fd;     /* the unix file                    */
82     haddr_t         eoa;    /* end of allocated region          */
83     haddr_t         eof;    /* end of file; current file size   */
84     haddr_t         pos;    /* current file I/O position        */
85     H5FD_file_op_t  op;     /* last operation                   */
86     char            filename[H5FD_MAX_FILENAME_LEN];    /* Copy of file name from open operation */
87 #ifndef H5_HAVE_WIN32_API
88     /* On most systems the combination of device and i-node number uniquely
89      * identify a file.  Note that Cygwin, MinGW and other Windows POSIX
90      * environments have the stat function (which fakes inodes)
91      * and will use the 'device + inodes' scheme as opposed to the
92      * Windows code further below.
93      */
94     dev_t           device;         /* file device number   */
95 #ifdef H5_VMS
96     ino_t           inode[3];       /* file i-node number   */
97 #else
98     ino_t           inode;          /* file i-node number   */
99 #endif /*H5_VMS*/
100 #else
101     /* Files in windows are uniquely identified by the volume serial
102      * number and the file index (both low and high parts).
103      *
104      * There are caveats where these numbers can change, especially
105      * on FAT file systems.  On NTFS, however, a file should keep
106      * those numbers the same until renamed or deleted (though you
107      * can use ReplaceFile() on NTFS to keep the numbers the same
108      * while renaming).
109      *
110      * See the MSDN "BY_HANDLE_FILE_INFORMATION Structure" entry for
111      * more information.
112      *
113      * http://msdn.microsoft.com/en-us/library/aa363788(v=VS.85).aspx
114      */
115     DWORD           nFileIndexLow;
116     DWORD           nFileIndexHigh;
117     DWORD           dwVolumeSerialNumber;
118 
119     HANDLE          hFile;      /* Native windows file handle */
120 #endif  /* H5_HAVE_WIN32_API */
121 
122     /* Information from properties set by 'h5repart' tool
123      *
124      * Whether to eliminate the family driver info and convert this file to
125      * a single file
126      */
127     hbool_t     fam_to_sec2;
128 
129     /* Fields for tracking I/O operations */
130     unsigned char       *nread;                 /* Number of reads from a file location             */
131     unsigned char       *nwrite;                /* Number of write to a file location               */
132     unsigned char       *flavor;                /* Flavor of information written to file location   */
133     unsigned long long  total_read_ops;         /* Total number of read operations                  */
134     unsigned long long  total_write_ops;        /* Total number of write operations                 */
135     unsigned long long  total_seek_ops;         /* Total number of seek operations                  */
136     unsigned long long  total_truncate_ops;     /* Total number of truncate operations              */
137     double              total_read_time;        /* Total time spent in read operations              */
138     double              total_write_time;       /* Total time spent in write operations             */
139     double              total_seek_time;        /* Total time spent in seek operations              */
140     size_t              iosize;                 /* Size of I/O information buffers                  */
141     FILE                *logfp;                 /* Log file pointer                                 */
142     H5FD_log_fapl_t     fa;                     /* Driver-specific file access properties           */
143 } H5FD_log_t;
144 
145 /*
146  * These macros check for overflow of various quantities.  These macros
147  * assume that HDoff_t is signed and haddr_t and size_t are unsigned.
148  *
149  * ADDR_OVERFLOW:   Checks whether a file address of type `haddr_t'
150  *                  is too large to be represented by the second argument
151  *                  of the file seek function.
152  *
153  * SIZE_OVERFLOW:   Checks whether a buffer size of type `hsize_t' is too
154  *                  large to be represented by the `size_t' type.
155  *
156  * REGION_OVERFLOW: Checks whether an address and size pair describe data
157  *                  which can be addressed entirely by the second
158  *                  argument of the file seek function.
159  */
160 #define MAXADDR                 (((haddr_t)1<<(8*sizeof(HDoff_t)-1))-1)
161 #define ADDR_OVERFLOW(A)        (HADDR_UNDEF==(A) || ((A) & ~(haddr_t)MAXADDR))
162 #define SIZE_OVERFLOW(Z)        ((Z) & ~(hsize_t)MAXADDR)
163 #define REGION_OVERFLOW(A,Z)    (ADDR_OVERFLOW(A) || SIZE_OVERFLOW(Z) ||    \
164                                  HADDR_UNDEF==(A)+(Z) ||                    \
165                                 (HDoff_t)((A)+(Z))<(HDoff_t)(A))
166 
167 /* Prototypes */
168 static void *H5FD_log_fapl_get(H5FD_t *file);
169 static void *H5FD_log_fapl_copy(const void *_old_fa);
170 static herr_t H5FD_log_fapl_free(void *_fa);
171 static H5FD_t *H5FD_log_open(const char *name, unsigned flags, hid_t fapl_id,
172             haddr_t maxaddr);
173 static herr_t H5FD_log_close(H5FD_t *_file);
174 static int H5FD_log_cmp(const H5FD_t *_f1, const H5FD_t *_f2);
175 static herr_t H5FD_log_query(const H5FD_t *_f1, unsigned long *flags);
176 static haddr_t H5FD_log_alloc(H5FD_t *_file, H5FD_mem_t type, hid_t dxpl_id, hsize_t size);
177 static haddr_t H5FD_log_get_eoa(const H5FD_t *_file, H5FD_mem_t type);
178 static herr_t H5FD_log_set_eoa(H5FD_t *_file, H5FD_mem_t type, haddr_t addr);
179 static haddr_t H5FD_log_get_eof(const H5FD_t *_file);
180 static herr_t  H5FD_log_get_handle(H5FD_t *_file, hid_t fapl, void** file_handle);
181 static herr_t H5FD_log_read(H5FD_t *_file, H5FD_mem_t type, hid_t fapl_id, haddr_t addr,
182             size_t size, void *buf);
183 static herr_t H5FD_log_write(H5FD_t *_file, H5FD_mem_t type, hid_t fapl_id, haddr_t addr,
184             size_t size, const void *buf);
185 static herr_t H5FD_log_truncate(H5FD_t *_file, hid_t dxpl_id, hbool_t closing);
186 
187 static const H5FD_class_t H5FD_log_g = {
188     "log",					/*name			*/
189     MAXADDR,					/*maxaddr		*/
190     H5F_CLOSE_WEAK,				/* fc_degree		*/
191     NULL,					/*sb_size		*/
192     NULL,					/*sb_encode		*/
193     NULL,					/*sb_decode		*/
194     sizeof(H5FD_log_fapl_t),                    /*fapl_size		*/
195     H5FD_log_fapl_get,		                /*fapl_get		*/
196     H5FD_log_fapl_copy,		                /*fapl_copy		*/
197     H5FD_log_fapl_free,		                /*fapl_free		*/
198     0,						/*dxpl_size		*/
199     NULL,					/*dxpl_copy		*/
200     NULL,					/*dxpl_free		*/
201     H5FD_log_open,				/*open			*/
202     H5FD_log_close,				/*close			*/
203     H5FD_log_cmp,				/*cmp			*/
204     H5FD_log_query,				/*query			*/
205     NULL,					/*get_type_map		*/
206     H5FD_log_alloc,				/*alloc			*/
207     NULL,					/*free			*/
208     H5FD_log_get_eoa,				/*get_eoa		*/
209     H5FD_log_set_eoa, 				/*set_eoa		*/
210     H5FD_log_get_eof,				/*get_eof		*/
211     H5FD_log_get_handle,                        /*get_handle            */
212     H5FD_log_read,				/*read			*/
213     H5FD_log_write,				/*write			*/
214     NULL,					/*flush			*/
215     H5FD_log_truncate,				/*truncate		*/
216     NULL,                                       /*lock                  */
217     NULL,                                       /*unlock                */
218     H5FD_FLMAP_DICHOTOMY			/*fl_map		*/
219 };
220 
221 /* Declare a free list to manage the H5FD_log_t struct */
222 H5FL_DEFINE_STATIC(H5FD_log_t);
223 
224 
225 /*-------------------------------------------------------------------------
226  * Function:    H5FD_log_init_interface
227  *
228  * Purpose:     Initializes any interface-specific data or routines.
229  *
230  * Return:      Success:    The driver ID for the log driver.
231  *              Failure:    Negative.
232  *
233  *-------------------------------------------------------------------------
234  */
235 static herr_t
H5FD_log_init_interface(void)236 H5FD_log_init_interface(void)
237 {
238     FUNC_ENTER_NOAPI_NOINIT_NOERR
239 
240     FUNC_LEAVE_NOAPI(H5FD_log_init())
241 } /* H5FD_log_init_interface() */
242 
243 
244 /*-------------------------------------------------------------------------
245  * Function:    H5FD_log_init
246  *
247  * Purpose:     Initialize this driver by registering the driver with the
248  *              library.
249  *
250  * Return:      Success:    The driver ID for the log driver.
251  *              Failure:    Negative.
252  *
253  * Programmer:  Robb Matzke
254  *              Thursday, July 29, 1999
255  *
256  *-------------------------------------------------------------------------
257  */
258 hid_t
H5FD_log_init(void)259 H5FD_log_init(void)
260 {
261     hid_t ret_value;            /* Return value */
262 
263     FUNC_ENTER_NOAPI(FAIL)
264 
265     if(H5I_VFL != H5I_get_type(H5FD_LOG_g))
266         H5FD_LOG_g = H5FD_register(&H5FD_log_g, sizeof(H5FD_class_t), FALSE);
267 
268     /* Set return value */
269     ret_value = H5FD_LOG_g;
270 
271 done:
272     FUNC_LEAVE_NOAPI(ret_value)
273 } /* end H5FD_log_init() */
274 
275 
276 /*---------------------------------------------------------------------------
277  * Function:    H5FD_log_term
278  *
279  * Purpose:     Shut down the VFD
280  *
281  * Returns:     <none>
282  *
283  * Programmer:  Quincey Koziol
284  *              Friday, Jan 30, 2004
285  *
286  *---------------------------------------------------------------------------
287  */
288 void
H5FD_log_term(void)289 H5FD_log_term(void)
290 {
291     FUNC_ENTER_NOAPI_NOINIT_NOERR
292 
293     /* Reset VFL ID */
294     H5FD_LOG_g = 0;
295 
296     FUNC_LEAVE_NOAPI_VOID
297 } /* end H5FD_log_term() */
298 
299 
300 /*-------------------------------------------------------------------------
301  * Function:    H5Pset_fapl_log
302  *
303  * Purpose:     Modify the file access property list to use the H5FD_LOG
304  *              driver defined in this source file.
305  *
306  * Return:      SUCCEED/FAIL
307  *
308  * Programmer:  Robb Matzke
309  *              Thursday, February 19, 1998
310  *
311  *-------------------------------------------------------------------------
312  */
313 herr_t
H5Pset_fapl_log(hid_t fapl_id,const char * logfile,unsigned long long flags,size_t buf_size)314 H5Pset_fapl_log(hid_t fapl_id, const char *logfile, unsigned long long flags, size_t buf_size)
315 {
316     H5FD_log_fapl_t     fa;         /* File access property list information */
317     H5P_genplist_t      *plist;     /* Property list pointer */
318     herr_t              ret_value;  /* Return value */
319 
320     FUNC_ENTER_API(FAIL)
321     H5TRACE4("e", "i*sULz", fapl_id, logfile, flags, buf_size);
322 
323     /* Check arguments */
324     if(NULL == (plist = H5P_object_verify(fapl_id, H5P_FILE_ACCESS)))
325         HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file access property list")
326 
327     /* This shallow copy is correct! The string will be properly
328      * copied deep down in the H5P code.
329      */
330     fa.logfile = (char *)logfile;
331 
332     fa.flags = flags;
333     fa.buf_size = buf_size;
334     ret_value = H5P_set_driver(plist, H5FD_LOG, &fa);
335 
336 done:
337     FUNC_LEAVE_API(ret_value)
338 } /* end H5Pset_fapl_log() */
339 
340 
341 /*-------------------------------------------------------------------------
342  * Function:    H5FD_log_fapl_get
343  *
344  * Purpose:     Returns a file access property list which indicates how the
345  *              specified file is being accessed. The return list could be
346  *              used to access another file the same way.
347  *
348  * Return:      Success:    Ptr to new file access property list with all
349  *                          members copied from the file struct.
350  *              Failure:    NULL
351  *
352  * Programmer:  Quincey Koziol
353  *              Thursday, April 20, 2000
354  *
355  *-------------------------------------------------------------------------
356  */
357 static void *
H5FD_log_fapl_get(H5FD_t * _file)358 H5FD_log_fapl_get(H5FD_t *_file)
359 {
360     H5FD_log_t  *file = (H5FD_log_t *)_file;
361     void        *ret_value;                     /* Return value */
362 
363     FUNC_ENTER_NOAPI_NOINIT_NOERR
364 
365     /* Set return value */
366     ret_value = H5FD_log_fapl_copy(&(file->fa));
367 
368     FUNC_LEAVE_NOAPI(ret_value)
369 } /* end H5FD_log_fapl_get() */
370 
371 
372 /*-------------------------------------------------------------------------
373  * Function:    H5FD_log_fapl_copy
374  *
375  * Purpose:     Copies the log-specific file access properties.
376  *
377  * Return:      Success:    Ptr to a new property list
378  *              Failure:    NULL
379  *
380  * Programmer:  Quincey Koziol
381  *              Thursday, April 20, 2000
382  *
383  *-------------------------------------------------------------------------
384  */
385 static void *
H5FD_log_fapl_copy(const void * _old_fa)386 H5FD_log_fapl_copy(const void *_old_fa)
387 {
388     const H5FD_log_fapl_t   *old_fa = (const H5FD_log_fapl_t*)_old_fa;
389     H5FD_log_fapl_t         *new_fa = NULL;     /* New FAPL info */
390     void                    *ret_value;         /* Return value */
391 
392     FUNC_ENTER_NOAPI_NOINIT
393 
394     HDassert(old_fa);
395 
396     /* Allocate the new FAPL info */
397     if(NULL == (new_fa = (H5FD_log_fapl_t *)H5MM_calloc(sizeof(H5FD_log_fapl_t))))
398         HGOTO_ERROR(H5E_FILE, H5E_CANTALLOC, NULL, "unable to allocate log file FAPL")
399 
400     /* Copy the general information */
401     HDmemcpy(new_fa, old_fa, sizeof(H5FD_log_fapl_t));
402 
403     /* Deep copy the log file name */
404     if(old_fa->logfile != NULL)
405         if(NULL == (new_fa->logfile = H5MM_xstrdup(old_fa->logfile)))
406             HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "unable to allocate log file name")
407 
408     /* Set return value */
409     ret_value = new_fa;
410 
411 done:
412     if(NULL == ret_value)
413         if(new_fa) {
414             if(new_fa->logfile)
415                 H5MM_free(new_fa->logfile);
416             H5MM_free(new_fa);
417         } /* end if */
418 
419     FUNC_LEAVE_NOAPI(ret_value)
420 } /* end H5FD_log_fapl_copy() */
421 
422 
423 /*-------------------------------------------------------------------------
424  * Function:    H5FD_log_fapl_free
425  *
426  * Purpose:     Frees the log-specific file access properties.
427  *
428  * Return:      SUCCEED (Can't fail)
429  *
430  * Programmer:  Quincey Koziol
431  *              Thursday, April 20, 2000
432  *
433  *-------------------------------------------------------------------------
434  */
435 static herr_t
H5FD_log_fapl_free(void * _fa)436 H5FD_log_fapl_free(void *_fa)
437 {
438     H5FD_log_fapl_t	*fa = (H5FD_log_fapl_t*)_fa;
439 
440     FUNC_ENTER_NOAPI_NOINIT_NOERR
441 
442     /* Free the fapl information */
443     if(fa->logfile)
444         H5MM_xfree(fa->logfile);
445     H5MM_xfree(fa);
446 
447     FUNC_LEAVE_NOAPI(SUCCEED)
448 } /* end H5FD_log_fapl_free() */
449 
450 
451 /*-------------------------------------------------------------------------
452  * Function:    H5FD_log_open
453  *
454  * Purpose:     Create and/or opens a file as an HDF5 file.
455  *
456  * Return:      Success:    A pointer to a new file data structure. The
457  *                          public fields will be initialized by the
458  *                          caller, which is always H5FD_open().
459  *              Failure:    NULL
460  *
461  * Programmer:  Robb Matzke
462  *              Thursday, July 29, 1999
463  *
464  *-------------------------------------------------------------------------
465  */
466 static H5FD_t *
H5FD_log_open(const char * name,unsigned flags,hid_t fapl_id,haddr_t maxaddr)467 H5FD_log_open(const char *name, unsigned flags, hid_t fapl_id, haddr_t maxaddr)
468 {
469     H5FD_log_t      *file = NULL;
470     H5P_genplist_t  *plist;         /* Property list */
471     H5FD_log_fapl_t *fa;            /* File access property list information */
472     int             fd = -1;        /* File descriptor */
473     int             o_flags;        /* Flags for open() call */
474 #ifdef H5_HAVE_WIN32_API
475     struct _BY_HANDLE_FILE_INFORMATION fileinfo;
476 #endif
477 #ifdef H5_HAVE_GETTIMEOFDAY
478     struct timeval timeval_start;
479     struct timeval open_timeval_diff;
480     struct timeval stat_timeval_diff;
481 #endif /* H5_HAVE_GETTIMEOFDAY */
482     h5_stat_t       sb;
483     H5FD_t          *ret_value;     /* Return value */
484 
485     FUNC_ENTER_NOAPI_NOINIT
486 
487     /* Sanity check on file offsets */
488     HDcompile_assert(sizeof(HDoff_t) >= sizeof(size_t));
489 
490     /* Check arguments */
491     if(!name || !*name)
492         HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, NULL, "invalid file name")
493     if(0 == maxaddr || HADDR_UNDEF == maxaddr)
494         HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, NULL, "bogus maxaddr")
495     if(ADDR_OVERFLOW(maxaddr))
496         HGOTO_ERROR(H5E_ARGS, H5E_OVERFLOW, NULL, "bogus maxaddr")
497 
498     /* Build the open flags */
499     o_flags = (H5F_ACC_RDWR & flags) ? O_RDWR : O_RDONLY;
500     if(H5F_ACC_TRUNC & flags)
501         o_flags |= O_TRUNC;
502     if(H5F_ACC_CREAT & flags)
503         o_flags |= O_CREAT;
504     if(H5F_ACC_EXCL & flags)
505         o_flags |= O_EXCL;
506 
507     /* Get the driver specific information */
508     if(NULL == (plist = H5P_object_verify(fapl_id, H5P_FILE_ACCESS)))
509         HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "not a file access property list")
510     if(NULL == (fa = (H5FD_log_fapl_t *)H5P_get_driver_info(plist)))
511         HGOTO_ERROR(H5E_PLIST, H5E_BADVALUE, NULL, "bad VFL driver info")
512 
513 #ifdef H5_HAVE_GETTIMEOFDAY
514     if(fa->flags & H5FD_LOG_TIME_OPEN)
515         HDgettimeofday(&timeval_start, NULL);
516 #endif /* H5_HAVE_GETTIMEOFDAY */
517     /* Open the file */
518     if((fd = HDopen(name, o_flags, 0666)) < 0) {
519         int myerrno = errno;
520 
521         HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, NULL, "unable to open file: name = '%s', errno = %d, error message = '%s', flags = %x, o_flags = %x", name, myerrno, HDstrerror(myerrno), flags, (unsigned)o_flags);
522     } /* end if */
523 #ifdef H5_HAVE_GETTIMEOFDAY
524     if(fa->flags & H5FD_LOG_TIME_OPEN) {
525         struct timeval timeval_stop;
526 
527         HDgettimeofday(&timeval_stop, NULL);
528 
529          /* Calculate the elapsed gettimeofday time */
530          open_timeval_diff.tv_usec = timeval_stop.tv_usec - timeval_start.tv_usec;
531          open_timeval_diff.tv_sec = timeval_stop.tv_sec - timeval_start.tv_sec;
532          if(open_timeval_diff.tv_usec < 0) {
533              open_timeval_diff.tv_usec += 1000000;
534              open_timeval_diff.tv_sec--;
535          } /* end if */
536     } /* end if */
537 #endif /* H5_HAVE_GETTIMEOFDAY */
538 
539 #ifdef H5_HAVE_GETTIMEOFDAY
540     if(fa->flags & H5FD_LOG_TIME_STAT)
541         HDgettimeofday(&timeval_start, NULL);
542 #endif /* H5_HAVE_GETTIMEOFDAY */
543     /* Get the file stats */
544     if(HDfstat(fd, &sb) < 0)
545         HSYS_GOTO_ERROR(H5E_FILE, H5E_BADFILE, NULL, "unable to fstat file")
546 #ifdef H5_HAVE_GETTIMEOFDAY
547     if(fa->flags & H5FD_LOG_TIME_STAT) {
548         struct timeval timeval_stop;
549 
550         HDgettimeofday(&timeval_stop, NULL);
551 
552          /* Calculate the elapsed gettimeofday time */
553          stat_timeval_diff.tv_usec = timeval_stop.tv_usec - timeval_start.tv_usec;
554          stat_timeval_diff.tv_sec = timeval_stop.tv_sec - timeval_start.tv_sec;
555          if(stat_timeval_diff.tv_usec < 0) {
556              stat_timeval_diff.tv_usec += 1000000;
557              stat_timeval_diff.tv_sec--;
558          } /* end if */
559     } /* end if */
560 #endif /* H5_HAVE_GETTIMEOFDAY */
561 
562     /* Create the new file struct */
563     if(NULL == (file = H5FL_CALLOC(H5FD_log_t)))
564         HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "unable to allocate file struct")
565 
566     file->fd = fd;
567     H5_ASSIGN_OVERFLOW(file->eof, sb.st_size, h5_stat_size_t, haddr_t);
568     file->pos = HADDR_UNDEF;
569     file->op = OP_UNKNOWN;
570 #ifdef H5_HAVE_WIN32_API
571     file->hFile = (HANDLE)_get_osfhandle(fd);
572     if(INVALID_HANDLE_VALUE == file->hFile)
573         HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, NULL, "unable to get Windows file handle")
574 
575     if(!GetFileInformationByHandle((HANDLE)file->hFile, &fileinfo))
576         HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, NULL, "unable to get Windows file information")
577 
578     file->nFileIndexHigh = fileinfo.nFileIndexHigh;
579     file->nFileIndexLow = fileinfo.nFileIndexLow;
580     file->dwVolumeSerialNumber = fileinfo.dwVolumeSerialNumber;
581 #else /* H5_HAVE_WIN32_API */
582     file->device = sb.st_dev;
583 #ifdef H5_VMS
584     file->inode[0] = sb.st_ino[0];
585     file->inode[1] = sb.st_ino[1];
586     file->inode[2] = sb.st_ino[2];
587 #else
588     file->inode = sb.st_ino;
589 #endif /*H5_VMS*/
590 
591 #endif /* H5_HAVE_WIN32_API */
592 
593     /* Retain a copy of the name used to open the file, for possible error reporting */
594     HDstrncpy(file->filename, name, sizeof(file->filename));
595     file->filename[sizeof(file->filename) - 1] = '\0';
596 
597     /* Get the flags for logging */
598     file->fa.flags = fa->flags;
599 
600     /* Check if we are doing any logging at all */
601     if(file->fa.flags != 0) {
602         /* Allocate buffers for tracking file accesses and data "flavor" */
603         file->iosize = fa->buf_size;
604         if(file->fa.flags & H5FD_LOG_FILE_READ) {
605             file->nread = (unsigned char *)H5MM_calloc(file->iosize);
606             HDassert(file->nread);
607         } /* end if */
608         if(file->fa.flags & H5FD_LOG_FILE_WRITE) {
609             file->nwrite = (unsigned char *)H5MM_calloc(file->iosize);
610             HDassert(file->nwrite);
611         } /* end if */
612         if(file->fa.flags & H5FD_LOG_FLAVOR) {
613             file->flavor = (unsigned char *)H5MM_calloc(file->iosize);
614             HDassert(file->flavor);
615         } /* end if */
616 
617         /* Set the log file pointer */
618         if(fa->logfile)
619             file->logfp = HDfopen(fa->logfile, "w");
620         else
621             file->logfp = stderr;
622 
623 #ifdef H5_HAVE_GETTIMEOFDAY
624         if(file->fa.flags & H5FD_LOG_TIME_OPEN)
625             HDfprintf(file->logfp, "Open took: (%f s)\n", (double)open_timeval_diff.tv_sec + ((double)open_timeval_diff.tv_usec / (double)1000000.0f));
626         if(file->fa.flags & H5FD_LOG_TIME_STAT)
627             HDfprintf(file->logfp, "Stat took: (%f s)\n", (double)stat_timeval_diff.tv_sec + ((double)stat_timeval_diff.tv_usec / (double)1000000.0f));
628 #endif /* H5_HAVE_GETTIMEOFDAY */
629 
630     } /* end if */
631 
632     /* Check for non-default FAPL */
633     if(H5P_FILE_ACCESS_DEFAULT != fapl_id) {
634         /* This step is for h5repart tool only. If user wants to change file driver from
635          * family to sec2 while using h5repart, this private property should be set so that
636          * in the later step, the library can ignore the family driver information saved
637          * in the superblock.
638          */
639         if(H5P_exist_plist(plist, H5F_ACS_FAMILY_TO_SEC2_NAME) > 0)
640             if(H5P_get(plist, H5F_ACS_FAMILY_TO_SEC2_NAME, &file->fam_to_sec2) < 0)
641                 HGOTO_ERROR(H5E_VFL, H5E_CANTGET, NULL, "can't get property of changing family to sec2")
642     } /* end if */
643 
644     /* Set return value */
645     ret_value = (H5FD_t*)file;
646 
647 done:
648     if(NULL == ret_value) {
649         if(fd >= 0)
650             HDclose(fd);
651         if(file)
652             file = H5FL_FREE(H5FD_log_t, file);
653     } /* end if */
654 
655     FUNC_LEAVE_NOAPI(ret_value)
656 } /* end H5FD_log_open() */
657 
658 
659 /*-------------------------------------------------------------------------
660  * Function:    H5FD_log_close
661  *
662  * Purpose:     Closes an HDF5 file.
663  *
664  * Return:      Success:    SUCCEED
665  *              Failure:    FAIL, file not closed.
666  *
667  * Programmer:  Robb Matzke
668  *              Thursday, July 29, 1999
669  *
670  *-------------------------------------------------------------------------
671  */
672 static herr_t
H5FD_log_close(H5FD_t * _file)673 H5FD_log_close(H5FD_t *_file)
674 {
675     H5FD_log_t	*file = (H5FD_log_t *)_file;
676 #ifdef H5_HAVE_GETTIMEOFDAY
677     struct timeval timeval_start, timeval_stop;
678 #endif /* H5_HAVE_GETTIMEOFDAY */
679     herr_t ret_value = SUCCEED;                 /* Return value */
680 
681     FUNC_ENTER_NOAPI_NOINIT
682 
683     /* Sanity check */
684     HDassert(file);
685 
686 #ifdef H5_HAVE_GETTIMEOFDAY
687     if(file->fa.flags&H5FD_LOG_TIME_CLOSE)
688         HDgettimeofday(&timeval_start, NULL);
689 #endif /* H5_HAVE_GETTIMEOFDAY */
690     /* Close the underlying file */
691     if(HDclose(file->fd) < 0)
692         HSYS_GOTO_ERROR(H5E_IO, H5E_CANTCLOSEFILE, FAIL, "unable to close file")
693 #ifdef H5_HAVE_GETTIMEOFDAY
694     if(file->fa.flags&H5FD_LOG_TIME_CLOSE)
695         HDgettimeofday(&timeval_stop, NULL);
696 #endif /* H5_HAVE_GETTIMEOFDAY */
697 
698     /* Dump I/O information */
699     if(file->fa.flags != 0) {
700         haddr_t addr;
701         haddr_t last_addr;
702         unsigned char last_val;
703 
704 #ifdef H5_HAVE_GETTIMEOFDAY
705         if(file->fa.flags & H5FD_LOG_TIME_CLOSE) {
706             struct timeval timeval_diff;
707 
708              /* Calculate the elapsed gettimeofday time */
709              timeval_diff.tv_usec = timeval_stop.tv_usec - timeval_start.tv_usec;
710              timeval_diff.tv_sec = timeval_stop.tv_sec - timeval_start.tv_sec;
711              if(timeval_diff.tv_usec < 0) {
712                  timeval_diff.tv_usec += 1000000;
713                  timeval_diff.tv_sec--;
714              } /* end if */
715             HDfprintf(file->logfp, "Close took: (%f s)\n", (double)timeval_diff.tv_sec + ((double)timeval_diff.tv_usec / (double)1000000.0f));
716         } /* end if */
717 #endif /* H5_HAVE_GETTIMEOFDAY */
718 
719         /* Dump the total number of seek/read/write operations */
720         if(file->fa.flags & H5FD_LOG_NUM_READ)
721             HDfprintf(file->logfp, "Total number of read operations: %llu\n", file->total_read_ops);
722         if(file->fa.flags & H5FD_LOG_NUM_WRITE)
723             HDfprintf(file->logfp, "Total number of write operations: %llu\n", file->total_write_ops);
724         if(file->fa.flags & H5FD_LOG_NUM_SEEK)
725             HDfprintf(file->logfp, "Total number of seek operations: %llu\n", file->total_seek_ops);
726         if(file->fa.flags & H5FD_LOG_NUM_TRUNCATE)
727             HDfprintf(file->logfp, "Total number of truncate operations: %llu\n", file->total_truncate_ops);
728 
729         /* Dump the total time in seek/read/write */
730         if(file->fa.flags & H5FD_LOG_TIME_READ)
731             HDfprintf(file->logfp, "Total time in read operations: %f s\n", file->total_read_time);
732         if(file->fa.flags & H5FD_LOG_TIME_WRITE)
733             HDfprintf(file->logfp, "Total time in write operations: %f s\n", file->total_write_time);
734         if(file->fa.flags & H5FD_LOG_TIME_SEEK)
735             HDfprintf(file->logfp, "Total time in seek operations: %f s\n", file->total_seek_time);
736 
737         /* Dump the write I/O information */
738         if(file->fa.flags & H5FD_LOG_FILE_WRITE) {
739             HDfprintf(file->logfp, "Dumping write I/O information:\n");
740             last_val = file->nwrite[0];
741             last_addr = 0;
742             addr = 1;
743             while(addr < file->eoa) {
744                 if(file->nwrite[addr] != last_val) {
745                     HDfprintf(file->logfp, "\tAddr %10a-%10a (%10lu bytes) written to %3d times\n", last_addr, (addr - 1), (unsigned long)(addr - last_addr), (int)last_val);
746                     last_val = file->nwrite[addr];
747                     last_addr = addr;
748                 } /* end if */
749                 addr++;
750             } /* end while */
751             HDfprintf(file->logfp, "\tAddr %10a-%10a (%10lu bytes) written to %3d times\n", last_addr, (addr - 1), (unsigned long)(addr - last_addr), (int)last_val);
752         } /* end if */
753 
754         /* Dump the read I/O information */
755         if(file->fa.flags & H5FD_LOG_FILE_READ) {
756             HDfprintf(file->logfp, "Dumping read I/O information:\n");
757             last_val = file->nread[0];
758             last_addr = 0;
759             addr = 1;
760             while(addr < file->eoa) {
761                 if(file->nread[addr] != last_val) {
762                     HDfprintf(file->logfp, "\tAddr %10a-%10a (%10lu bytes) read from %3d times\n", last_addr, (addr - 1), (unsigned long)(addr - last_addr), (int)last_val);
763                     last_val = file->nread[addr];
764                     last_addr = addr;
765                 } /* end if */
766                 addr++;
767             } /* end while */
768             HDfprintf(file->logfp, "\tAddr %10a-%10a (%10lu bytes) read from %3d times\n", last_addr, (addr - 1), (unsigned long)(addr - last_addr), (int)last_val);
769         } /* end if */
770 
771         /* Dump the I/O flavor information */
772         if(file->fa.flags & H5FD_LOG_FLAVOR) {
773             HDfprintf(file->logfp, "Dumping I/O flavor information:\n");
774             last_val = file->flavor[0];
775             last_addr = 0;
776             addr = 1;
777             while(addr < file->eoa) {
778                 if(file->flavor[addr] != last_val) {
779                     HDfprintf(file->logfp, "\tAddr %10a-%10a (%10lu bytes) flavor is %s\n", last_addr, (addr - 1), (unsigned long)(addr - last_addr), flavors[last_val]);
780                     last_val = file->flavor[addr];
781                     last_addr = addr;
782                 } /* end if */
783                 addr++;
784             } /* end while */
785             HDfprintf(file->logfp, "\tAddr %10a-%10a (%10lu bytes) flavor is %s\n", last_addr, (addr - 1), (unsigned long)(addr - last_addr), flavors[last_val]);
786         } /* end if */
787 
788         /* Free the logging information */
789         if(file->fa.flags & H5FD_LOG_FILE_WRITE)
790             file->nwrite = (unsigned char *)H5MM_xfree(file->nwrite);
791         if(file->fa.flags & H5FD_LOG_FILE_READ)
792             file->nread = (unsigned char *)H5MM_xfree(file->nread);
793         if(file->fa.flags & H5FD_LOG_FLAVOR)
794             file->flavor = (unsigned char *)H5MM_xfree(file->flavor);
795         if(file->logfp != stderr)
796             HDfclose(file->logfp);
797     } /* end if */
798 
799     /* Release the file info */
800     file = H5FL_FREE(H5FD_log_t, file);
801 
802 done:
803     FUNC_LEAVE_NOAPI(ret_value)
804 } /* end H5FD_log_close() */
805 
806 
807 /*-------------------------------------------------------------------------
808  * Function:    H5FD_log_cmp
809  *
810  * Purpose:     Compares two files belonging to this driver using an
811  *              arbitrary (but consistent) ordering.
812  *
813  * Return:      Success:    A value like strcmp()
814  *              Failure:    never fails (arguments were checked by the
815  *                          caller).
816  *
817  * Programmer:  Robb Matzke
818  *              Thursday, July 29, 1999
819  *
820  *-------------------------------------------------------------------------
821  */
822 static int
H5FD_log_cmp(const H5FD_t * _f1,const H5FD_t * _f2)823 H5FD_log_cmp(const H5FD_t *_f1, const H5FD_t *_f2)
824 {
825     const H5FD_log_t    *f1 = (const H5FD_log_t *)_f1;
826     const H5FD_log_t    *f2 = (const H5FD_log_t *)_f2;
827     int ret_value = 0;
828 
829     FUNC_ENTER_NOAPI_NOINIT_NOERR
830 
831 #ifdef H5_HAVE_WIN32_API
832     if(f1->dwVolumeSerialNumber < f2->dwVolumeSerialNumber) HGOTO_DONE(-1)
833     if(f1->dwVolumeSerialNumber > f2->dwVolumeSerialNumber) HGOTO_DONE(1)
834 
835     if(f1->nFileIndexHigh < f2->nFileIndexHigh) HGOTO_DONE(-1)
836     if(f1->nFileIndexHigh > f2->nFileIndexHigh) HGOTO_DONE(1)
837 
838     if(f1->nFileIndexLow < f2->nFileIndexLow) HGOTO_DONE(-1)
839     if(f1->nFileIndexLow > f2->nFileIndexLow) HGOTO_DONE(1)
840 #else
841 #ifdef H5_DEV_T_IS_SCALAR
842     if(f1->device < f2->device) HGOTO_DONE(-1)
843     if(f1->device > f2->device) HGOTO_DONE(1)
844 #else /* H5_DEV_T_IS_SCALAR */
845     /* If dev_t isn't a scalar value on this system, just use memcmp to
846      * determine if the values are the same or not.  The actual return value
847      * shouldn't really matter...
848      */
849     if(HDmemcmp(&(f1->device),&(f2->device),sizeof(dev_t)) < 0) HGOTO_DONE(-1)
850     if(HDmemcmp(&(f1->device),&(f2->device),sizeof(dev_t)) > 0) HGOTO_DONE(1)
851 #endif /* H5_DEV_T_IS_SCALAR */
852 
853 #ifndef H5_VMS
854     if(f1->inode < f2->inode) HGOTO_DONE(-1)
855     if(f1->inode > f2->inode) HGOTO_DONE(1)
856 #else
857     if(HDmemcmp(&(f1->inode), &(f2->inode), 3 * sizeof(ino_t)) < 0) HGOTO_DONE(-1)
858     if(HDmemcmp(&(f1->inode), &(f2->inode), 3 * sizeof(ino_t)) > 0) HGOTO_DONE(1)
859 #endif /*H5_VMS*/
860 
861 #endif
862 
863 done:
864     FUNC_LEAVE_NOAPI(ret_value)
865 } /* end H5FD_log_cmp() */
866 
867 
868 /*-------------------------------------------------------------------------
869  * Function:    H5FD_log_query
870  *
871  * Purpose:     Set the flags that this VFL driver is capable of supporting.
872  *              (listed in H5FDpublic.h)
873  *
874  * Return:      SUCCEED (Can't fail)
875  *
876  * Programmer:  Quincey Koziol
877  *              Friday, August 25, 2000
878  *
879  *-------------------------------------------------------------------------
880  */
881 static herr_t
H5FD_log_query(const H5FD_t * _file,unsigned long * flags)882 H5FD_log_query(const H5FD_t *_file, unsigned long *flags /* out */)
883 {
884     const H5FD_log_t    *file = (const H5FD_log_t *)_file;
885 
886     FUNC_ENTER_NOAPI_NOINIT_NOERR
887 
888     /* Set the VFL feature flags that this driver supports */
889     if(flags) {
890         *flags = 0;
891         *flags |= H5FD_FEAT_AGGREGATE_METADATA; /* OK to aggregate metadata allocations */
892         *flags |= H5FD_FEAT_ACCUMULATE_METADATA; /* OK to accumulate metadata for faster writes */
893         *flags |= H5FD_FEAT_DATA_SIEVE;       /* OK to perform data sieving for faster raw data reads & writes */
894         *flags |= H5FD_FEAT_AGGREGATE_SMALLDATA; /* OK to aggregate "small" raw data allocations */
895         *flags |= H5FD_FEAT_POSIX_COMPAT_HANDLE; /* VFD handle is POSIX I/O call compatible */
896 
897         /* Check for flags that are set by h5repart */
898         if(file && file->fam_to_sec2)
899             *flags |= H5FD_FEAT_IGNORE_DRVRINFO; /* Ignore the driver info when file is opened (which eliminates it) */
900     } /* end if */
901 
902     FUNC_LEAVE_NOAPI(SUCCEED)
903 } /* end H5FD_log_query() */
904 
905 
906 /*-------------------------------------------------------------------------
907  * Function:    H5FD_log_alloc
908  *
909  * Purpose:     Allocate file memory.
910  *
911  * Return:      Success:    Address of new memory
912  *              Failure:    HADDR_UNDEF
913  *
914  * Programmer:  Quincey Koziol
915  *              Monday, April 17, 2000
916  *
917  *-------------------------------------------------------------------------
918  */
919 static haddr_t
H5FD_log_alloc(H5FD_t * _file,H5FD_mem_t type,hid_t UNUSED dxpl_id,hsize_t size)920 H5FD_log_alloc(H5FD_t *_file, H5FD_mem_t type, hid_t UNUSED dxpl_id, hsize_t size)
921 {
922     H5FD_log_t	*file = (H5FD_log_t *)_file;
923     haddr_t addr;
924     haddr_t ret_value;          /* Return value */
925 
926     FUNC_ENTER_NOAPI_NOINIT_NOERR
927 
928     /* Compute the address for the block to allocate */
929     addr = file->eoa;
930 
931     /* Check if we need to align this block */
932     if(size >= file->pub.threshold) {
933         /* Check for an already aligned block */
934         if(addr % file->pub.alignment != 0)
935             addr = ((addr / file->pub.alignment) + 1) * file->pub.alignment;
936     } /* end if */
937 
938     file->eoa = addr + size;
939 
940     /* Retain the (first) flavor of the information written to the file */
941     if(file->fa.flags != 0) {
942         if(file->fa.flags & H5FD_LOG_FLAVOR) {
943             HDassert(addr < file->iosize);
944             H5_CHECK_OVERFLOW(size, hsize_t, size_t);
945             HDmemset(&file->flavor[addr], (int)type, (size_t)size);
946         } /* end if */
947 
948         if(file->fa.flags & H5FD_LOG_ALLOC)
949             HDfprintf(file->logfp, "%10a-%10a (%10Hu bytes) (%s) Allocated\n", addr, (addr + size) - 1, size, flavors[type]);
950     } /* end if */
951 
952     /* Set return value */
953     ret_value = addr;
954 
955     FUNC_LEAVE_NOAPI(ret_value)
956 } /* end H5FD_log_alloc() */
957 
958 
959 /*-------------------------------------------------------------------------
960  * Function:    H5FD_log_get_eoa
961  *
962  * Purpose:     Gets the end-of-address marker for the file. The EOA marker
963  *              is the first address past the last byte allocated in the
964  *              format address space.
965  *
966  * Return:      Success:    The end-of-address marker.
967  *              Failure:    HADDR_UNDEF
968  *
969  * Programmer:  Robb Matzke
970  *              Monday, August  2, 1999
971  *
972  *-------------------------------------------------------------------------
973  */
974 static haddr_t
H5FD_log_get_eoa(const H5FD_t * _file,H5FD_mem_t UNUSED type)975 H5FD_log_get_eoa(const H5FD_t *_file, H5FD_mem_t UNUSED type)
976 {
977     const H5FD_log_t    *file = (const H5FD_log_t *)_file;
978 
979     FUNC_ENTER_NOAPI_NOINIT_NOERR
980 
981     FUNC_LEAVE_NOAPI(file->eoa)
982 } /* end H5FD_log_get_eoa() */
983 
984 
985 /*-------------------------------------------------------------------------
986  * Function:    H5FD_log_set_eoa
987  *
988  * Purpose:     Set the end-of-address marker for the file. This function is
989  *              called shortly after an existing HDF5 file is opened in order
990  *              to tell the driver where the end of the HDF5 data is located.
991  *
992  * Return:      SUCCEED (Can't fail)
993  *
994  * Programmer:  Robb Matzke
995  *              Thursday, July 29, 1999
996  *
997  *-------------------------------------------------------------------------
998  */
999 static herr_t
H5FD_log_set_eoa(H5FD_t * _file,H5FD_mem_t type,haddr_t addr)1000 H5FD_log_set_eoa(H5FD_t *_file, H5FD_mem_t type, haddr_t addr)
1001 {
1002     H5FD_log_t  *file = (H5FD_log_t *)_file;
1003 
1004     FUNC_ENTER_NOAPI_NOINIT_NOERR
1005 
1006     if(file->fa.flags != 0) {
1007         if(H5F_addr_gt(addr, file->eoa) && H5F_addr_gt(addr, 0)) {
1008             hsize_t size = addr - file->eoa;
1009 
1010             /* Retain the flavor of the space allocated by the extension */
1011             if(file->fa.flags & H5FD_LOG_FLAVOR) {
1012                 HDassert(addr < file->iosize);
1013                 H5_CHECK_OVERFLOW(size, hsize_t, size_t);
1014                 HDmemset(&file->flavor[file->eoa], (int)type, (size_t)size);
1015             } /* end if */
1016 
1017             /* Log the extension like an allocation */
1018             if(file->fa.flags & H5FD_LOG_ALLOC)
1019                 HDfprintf(file->logfp, "%10a-%10a (%10Hu bytes) (%s) Allocated\n", file->eoa, addr, size, flavors[type]);
1020         } /* end if */
1021     } /* end if */
1022 
1023     file->eoa = addr;
1024 
1025     FUNC_LEAVE_NOAPI(SUCCEED)
1026 } /* end H5FD_log_set_eoa() */
1027 
1028 
1029 /*-------------------------------------------------------------------------
1030  * Function:    H5FD_log_get_eof
1031  *
1032  * Purpose:     Returns the end-of-file marker, which is the greater of
1033  *              either the filesystem end-of-file or the HDF5 end-of-address
1034  *              markers.
1035  *
1036  * Return:      Success:    End of file address, the first address past
1037  *                          the end of the "file", either the filesystem file
1038  *                          or the HDF5 file.
1039  *              Failure:    HADDR_UNDEF
1040  *
1041  * Programmer:  Robb Matzke
1042  *              Thursday, July 29, 1999
1043  *
1044  *-------------------------------------------------------------------------
1045  */
1046 static haddr_t
H5FD_log_get_eof(const H5FD_t * _file)1047 H5FD_log_get_eof(const H5FD_t *_file)
1048 {
1049     const H5FD_log_t	*file = (const H5FD_log_t *)_file;
1050 
1051     FUNC_ENTER_NOAPI_NOINIT_NOERR
1052 
1053     FUNC_LEAVE_NOAPI(MAX(file->eof, file->eoa))
1054 } /* end H5FD_log_get_eof() */
1055 
1056 
1057 /*-------------------------------------------------------------------------
1058  * Function:       H5FD_log_get_handle
1059  *
1060  * Purpose:        Returns the file handle of LOG file driver.
1061  *
1062  * Returns:        SUCCEED/FAIL
1063  *
1064  * Programmer:     Raymond Lu
1065  *                 Sept. 16, 2002
1066  *
1067  *-------------------------------------------------------------------------
1068  */
1069 static herr_t
H5FD_log_get_handle(H5FD_t * _file,hid_t UNUSED fapl,void ** file_handle)1070 H5FD_log_get_handle(H5FD_t *_file, hid_t UNUSED fapl, void **file_handle)
1071 {
1072     H5FD_log_t          *file = (H5FD_log_t *)_file;
1073     herr_t              ret_value = SUCCEED;
1074 
1075     FUNC_ENTER_NOAPI_NOINIT
1076 
1077     if(!file_handle)
1078         HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "file handle not valid")
1079 
1080     *file_handle = &(file->fd);
1081 
1082 done:
1083     FUNC_LEAVE_NOAPI(ret_value)
1084 } /* end H5FD_log_get_handle() */
1085 
1086 
1087 /*-------------------------------------------------------------------------
1088  * Function:    H5FD_log_read
1089  *
1090  * Purpose:     Reads SIZE bytes of data from FILE beginning at address ADDR
1091  *              into buffer BUF according to data transfer properties in
1092  *              DXPL_ID.
1093  *
1094  * Return:      Success:    SUCCEED. Result is stored in caller-supplied
1095  *                          buffer BUF.
1096  *              Failure:    FAIL, Contents of buffer BUF are undefined.
1097  *
1098  * Programmer:  Robb Matzke
1099  *              Thursday, July 29, 1999
1100  *
1101  *-------------------------------------------------------------------------
1102  */
1103 static herr_t
H5FD_log_read(H5FD_t * _file,H5FD_mem_t type,hid_t UNUSED dxpl_id,haddr_t addr,size_t size,void * buf)1104 H5FD_log_read(H5FD_t *_file, H5FD_mem_t type, hid_t UNUSED dxpl_id, haddr_t addr,
1105             size_t size, void *buf/*out*/)
1106 {
1107     H5FD_log_t          *file = (H5FD_log_t *)_file;
1108     size_t              orig_size = size; /* Save the original size for later */
1109     haddr_t             orig_addr = addr;
1110 #ifdef H5_HAVE_GETTIMEOFDAY
1111     struct timeval      timeval_start, timeval_stop;
1112 #endif /* H5_HAVE_GETTIMEOFDAY */
1113     herr_t              ret_value = SUCCEED;       /* Return value */
1114 
1115     FUNC_ENTER_NOAPI_NOINIT
1116 
1117     HDassert(file && file->pub.cls);
1118     HDassert(buf);
1119 
1120     /* Check for overflow conditions */
1121     if(!H5F_addr_defined(addr))
1122         HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "addr undefined, addr = %llu", (unsigned long long)addr)
1123     if(REGION_OVERFLOW(addr, size))
1124         HGOTO_ERROR(H5E_ARGS, H5E_OVERFLOW, FAIL, "addr overflow, addr = %llu", (unsigned long long)addr)
1125     if((addr + size) > file->eoa)
1126         HGOTO_ERROR(H5E_ARGS, H5E_OVERFLOW, FAIL, "addr overflow, addr = %llu", (unsigned long long)addr)
1127 
1128     /* Log the I/O information about the read */
1129     if(file->fa.flags != 0) {
1130         size_t tmp_size = size;
1131         haddr_t tmp_addr = addr;
1132 
1133         /* Log information about the number of times these locations are read */
1134         if(file->fa.flags & H5FD_LOG_FILE_READ) {
1135             HDassert((addr + size) < file->iosize);
1136             while(tmp_size-- > 0)
1137                 file->nread[tmp_addr++]++;
1138         } /* end if */
1139     } /* end if */
1140 
1141     /* Seek to the correct location */
1142     if(addr != file->pos || OP_READ != file->op) {
1143 #ifdef H5_HAVE_GETTIMEOFDAY
1144         if(file->fa.flags & H5FD_LOG_TIME_SEEK)
1145             HDgettimeofday(&timeval_start, NULL);
1146 #endif /* H5_HAVE_GETTIMEOFDAY */
1147         if(HDlseek(file->fd, (HDoff_t)addr, SEEK_SET) < 0)
1148             HSYS_GOTO_ERROR(H5E_IO, H5E_SEEKERROR, FAIL, "unable to seek to proper position")
1149 #ifdef H5_HAVE_GETTIMEOFDAY
1150         if(file->fa.flags & H5FD_LOG_TIME_SEEK)
1151             HDgettimeofday(&timeval_stop, NULL);
1152 #endif /* H5_HAVE_GETTIMEOFDAY */
1153 
1154         /* Log information about the seek */
1155         if(file->fa.flags & H5FD_LOG_NUM_SEEK)
1156             file->total_seek_ops++;
1157         if(file->fa.flags & H5FD_LOG_LOC_SEEK) {
1158             HDfprintf(file->logfp, "Seek: From %10a To %10a", file->pos, addr);
1159 #ifdef H5_HAVE_GETTIMEOFDAY
1160             if(file->fa.flags & H5FD_LOG_TIME_SEEK) {
1161                 struct timeval timeval_diff;
1162                 double time_diff;
1163 
1164                 /* Calculate the elapsed gettimeofday time */
1165                 timeval_diff.tv_usec = timeval_stop.tv_usec - timeval_start.tv_usec;
1166                 timeval_diff.tv_sec = timeval_stop.tv_sec - timeval_start.tv_sec;
1167                 if(timeval_diff.tv_usec < 0) {
1168                     timeval_diff.tv_usec += 1000000;
1169                     timeval_diff.tv_sec--;
1170                 } /* end if */
1171                 time_diff = (double)timeval_diff.tv_sec + ((double)timeval_diff.tv_usec / (double)1000000.0f);
1172                 HDfprintf(file->logfp, " (%f s)\n", time_diff);
1173 
1174                 /* Add to total seek time */
1175                 file->total_seek_time += time_diff;
1176             } /* end if */
1177             else
1178                 HDfprintf(file->logfp, "\n");
1179 #else /* H5_HAVE_GETTIMEOFDAY */
1180             HDfprintf(file->logfp, "\n");
1181 #endif /* H5_HAVE_GETTIMEOFDAY */
1182         } /* end if */
1183     } /* end if */
1184 
1185     /*
1186      * Read data, being careful of interrupted system calls, partial results,
1187      * and the end of the file.
1188      */
1189 #ifdef H5_HAVE_GETTIMEOFDAY
1190     if(file->fa.flags & H5FD_LOG_TIME_READ)
1191         HDgettimeofday(&timeval_start, NULL);
1192 #endif /* H5_HAVE_GETTIMEOFDAY */
1193     while(size > 0) {
1194 
1195         h5_posix_io_t       bytes_in        = 0;    /* # of bytes to read       */
1196         h5_posix_io_ret_t   bytes_read      = -1;   /* # of bytes actually read */
1197 
1198         /* Trying to read more bytes than the return type can handle is
1199          * undefined behavior in POSIX.
1200          */
1201         if(size > H5_POSIX_MAX_IO_BYTES)
1202             bytes_in = H5_POSIX_MAX_IO_BYTES;
1203         else
1204             bytes_in = (h5_posix_io_t)size;
1205 
1206         do {
1207             bytes_read = HDread(file->fd, buf, bytes_in);
1208         } while(-1 == bytes_read && EINTR == errno);
1209 
1210         if(-1 == bytes_read) { /* error */
1211             int myerrno = errno;
1212             time_t mytime = HDtime(NULL);
1213             HDoff_t myoffset = HDlseek(file->fd, (HDoff_t)0, SEEK_CUR);
1214 
1215             if(file->fa.flags & H5FD_LOG_LOC_READ)
1216                 HDfprintf(file->logfp, "Error! Reading: %10a-%10a (%10Zu bytes)\n", orig_addr, (orig_addr + orig_size) - 1, orig_size);
1217 
1218             HGOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "file read failed: time = %s, filename = '%s', file descriptor = %d, errno = %d, error message = '%s', buf = %p, total read size = %llu, bytes this sub-read = %llu, bytes actually read = %llu, offset = %llu", HDctime(&mytime), file->filename, file->fd, myerrno, HDstrerror(myerrno), buf, (unsigned long long)size, (unsigned long long)bytes_in, (unsigned long long)bytes_read, (unsigned long long)myoffset);
1219         } /* end if */
1220 
1221         if(0 == bytes_read) {
1222             /* end of file but not end of format address space */
1223             HDmemset(buf, 0, size);
1224             break;
1225         } /* end if */
1226 
1227         HDassert(bytes_read >= 0);
1228         HDassert((size_t)bytes_read <= size);
1229 
1230         size -= (size_t)bytes_read;
1231         addr += (haddr_t)bytes_read;
1232         buf = (char *)buf + bytes_read;
1233 
1234     } /* end while */
1235 #ifdef H5_HAVE_GETTIMEOFDAY
1236     if(file->fa.flags & H5FD_LOG_TIME_READ)
1237         HDgettimeofday(&timeval_stop, NULL);
1238 #endif /* H5_HAVE_GETTIMEOFDAY */
1239 
1240     /* Log information about the read */
1241     if(file->fa.flags & H5FD_LOG_NUM_READ)
1242         file->total_read_ops++;
1243     if(file->fa.flags & H5FD_LOG_LOC_READ) {
1244         HDfprintf(file->logfp, "%10a-%10a (%10Zu bytes) (%s) Read", orig_addr, (orig_addr + orig_size) - 1, orig_size, flavors[type]);
1245 
1246         /* XXX: Verify the flavor information, if we have it? */
1247 
1248 #ifdef H5_HAVE_GETTIMEOFDAY
1249         if(file->fa.flags & H5FD_LOG_TIME_READ) {
1250             struct timeval timeval_diff;
1251             double time_diff;
1252 
1253             /* Calculate the elapsed gettimeofday time */
1254             timeval_diff.tv_usec = timeval_stop.tv_usec - timeval_start.tv_usec;
1255             timeval_diff.tv_sec = timeval_stop.tv_sec - timeval_start.tv_sec;
1256             if(timeval_diff.tv_usec < 0) {
1257                 timeval_diff.tv_usec += 1000000;
1258                 timeval_diff.tv_sec--;
1259             } /* end if */
1260             time_diff = (double)timeval_diff.tv_sec + ((double)timeval_diff.tv_usec / (double)1000000.0f);
1261             HDfprintf(file->logfp, " (%f s)\n", time_diff);
1262 
1263             /* Add to total read time */
1264             file->total_read_time += time_diff;
1265         } /* end if */
1266         else
1267             HDfprintf(file->logfp, "\n");
1268 #else /* H5_HAVE_GETTIMEOFDAY */
1269         HDfprintf(file->logfp, "\n");
1270 #endif /* H5_HAVE_GETTIMEOFDAY */
1271     } /* end if */
1272 
1273     /* Update current position */
1274     file->pos = addr;
1275     file->op = OP_READ;
1276 
1277 done:
1278     if(ret_value < 0) {
1279         /* Reset last file I/O information */
1280         file->pos = HADDR_UNDEF;
1281         file->op = OP_UNKNOWN;
1282     } /* end if */
1283 
1284     FUNC_LEAVE_NOAPI(ret_value)
1285 } /* end H5FD_log_read() */
1286 
1287 
1288 /*-------------------------------------------------------------------------
1289  * Function:    H5FD_log_write
1290  *
1291  * Purpose:     Writes SIZE bytes of data to FILE beginning at address ADDR
1292  *              from buffer BUF according to data transfer properties in
1293  *              DXPL_ID.
1294  *
1295  * Return:      SUCCEED/FAIL
1296  *
1297  * Programmer:  Robb Matzke
1298  *              Thursday, July 29, 1999
1299  *
1300  *-------------------------------------------------------------------------
1301  */
1302 static herr_t
H5FD_log_write(H5FD_t * _file,H5FD_mem_t type,hid_t UNUSED dxpl_id,haddr_t addr,size_t size,const void * buf)1303 H5FD_log_write(H5FD_t *_file, H5FD_mem_t type, hid_t UNUSED dxpl_id, haddr_t addr,
1304             size_t size, const void *buf)
1305 {
1306     H5FD_log_t          *file = (H5FD_log_t *)_file;
1307     size_t              orig_size = size; /* Save the original size for later */
1308     haddr_t             orig_addr = addr;
1309 #ifdef H5_HAVE_GETTIMEOFDAY
1310     struct timeval      timeval_start, timeval_stop;
1311 #endif /* H5_HAVE_GETTIMEOFDAY */
1312     herr_t              ret_value = SUCCEED;       /* Return value */
1313 
1314     FUNC_ENTER_NOAPI_NOINIT
1315 
1316     HDassert(file && file->pub.cls);
1317     HDassert(size > 0);
1318     HDassert(buf);
1319 
1320     /* Verify that we are writing out the type of data we allocated in this location */
1321     if(file->flavor) {
1322         HDassert(type == H5FD_MEM_DEFAULT || type == (H5FD_mem_t)file->flavor[addr] || (H5FD_mem_t)file->flavor[addr] == H5FD_MEM_DEFAULT);
1323         HDassert(type == H5FD_MEM_DEFAULT || type == (H5FD_mem_t)file->flavor[(addr + size) - 1] || (H5FD_mem_t)file->flavor[(addr + size) - 1] == H5FD_MEM_DEFAULT);
1324     } /* end if */
1325 
1326     /* Check for overflow conditions */
1327     if(!H5F_addr_defined(addr))
1328         HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "addr undefined, addr = %llu", (unsigned long long)addr)
1329     if(REGION_OVERFLOW(addr, size))
1330         HGOTO_ERROR(H5E_ARGS, H5E_OVERFLOW, FAIL, "addr overflow, addr = %llu, size = %llu", (unsigned long long)addr, (unsigned long long)size)
1331     if((addr + size) > file->eoa)
1332         HGOTO_ERROR(H5E_ARGS, H5E_OVERFLOW, FAIL, "addr overflow, addr = %llu, size = %llu, eoa = %llu", (unsigned long long)addr, (unsigned long long)size, (unsigned long long)file->eoa)
1333 
1334     /* Log the I/O information about the write */
1335     if(file->fa.flags & H5FD_LOG_FILE_WRITE) {
1336         size_t tmp_size = size;
1337         haddr_t tmp_addr = addr;
1338 
1339         /* Log information about the number of times these locations are read */
1340         HDassert((addr + size) < file->iosize);
1341         while(tmp_size-- > 0)
1342             file->nwrite[tmp_addr++]++;
1343     } /* end if */
1344 
1345     /* Seek to the correct location */
1346     if(addr != file->pos || OP_WRITE != file->op) {
1347 #ifdef H5_HAVE_GETTIMEOFDAY
1348         if(file->fa.flags & H5FD_LOG_TIME_SEEK)
1349             HDgettimeofday(&timeval_start, NULL);
1350 #endif /* H5_HAVE_GETTIMEOFDAY */
1351         if(HDlseek(file->fd, (HDoff_t)addr, SEEK_SET) < 0)
1352             HSYS_GOTO_ERROR(H5E_IO, H5E_SEEKERROR, FAIL, "unable to seek to proper position")
1353 #ifdef H5_HAVE_GETTIMEOFDAY
1354         if(file->fa.flags & H5FD_LOG_TIME_SEEK)
1355             HDgettimeofday(&timeval_stop, NULL);
1356 #endif /* H5_HAVE_GETTIMEOFDAY */
1357 
1358         /* Log information about the seek */
1359         if(file->fa.flags & H5FD_LOG_NUM_SEEK)
1360             file->total_seek_ops++;
1361         if(file->fa.flags & H5FD_LOG_LOC_SEEK) {
1362             HDfprintf(file->logfp, "Seek: From %10a To %10a", file->pos, addr);
1363 #ifdef H5_HAVE_GETTIMEOFDAY
1364             if(file->fa.flags & H5FD_LOG_TIME_SEEK) {
1365                 struct timeval timeval_diff;
1366                 double time_diff;
1367 
1368                 /* Calculate the elapsed gettimeofday time */
1369                 timeval_diff.tv_usec = timeval_stop.tv_usec - timeval_start.tv_usec;
1370                 timeval_diff.tv_sec = timeval_stop.tv_sec - timeval_start.tv_sec;
1371                 if(timeval_diff.tv_usec < 0) {
1372                     timeval_diff.tv_usec += 1000000;
1373                     timeval_diff.tv_sec--;
1374                 } /* end if */
1375                 time_diff = (double)timeval_diff.tv_sec + ((double)timeval_diff.tv_usec / (double)1000000.0f);
1376                 HDfprintf(file->logfp, " (%f s)\n", time_diff);
1377 
1378                 /* Add to total seek time */
1379                 file->total_seek_time += time_diff;
1380             } /* end if */
1381             else
1382                 HDfprintf(file->logfp, "\n");
1383 #else /* H5_HAVE_GETTIMEOFDAY */
1384             HDfprintf(file->logfp, "\n");
1385 #endif /* H5_HAVE_GETTIMEOFDAY */
1386         } /* end if */
1387     } /* end if */
1388 
1389     /*
1390      * Write the data, being careful of interrupted system calls and partial
1391      * results
1392      */
1393 #ifdef H5_HAVE_GETTIMEOFDAY
1394     if(file->fa.flags&H5FD_LOG_TIME_WRITE)
1395         HDgettimeofday(&timeval_start, NULL);
1396 #endif /* H5_HAVE_GETTIMEOFDAY */
1397     while(size > 0) {
1398 
1399         h5_posix_io_t       bytes_in        = 0;    /* # of bytes to write  */
1400         h5_posix_io_ret_t   bytes_wrote     = -1;   /* # of bytes written   */
1401 
1402         /* Trying to write more bytes than the return type can handle is
1403          * undefined behavior in POSIX.
1404          */
1405         if(size > H5_POSIX_MAX_IO_BYTES)
1406             bytes_in = H5_POSIX_MAX_IO_BYTES;
1407         else
1408             bytes_in = (h5_posix_io_t)size;
1409 
1410         do {
1411             bytes_wrote = HDwrite(file->fd, buf, bytes_in);
1412         } while(-1 == bytes_wrote && EINTR == errno);
1413 
1414         if(-1 == bytes_wrote) { /* error */
1415             int myerrno = errno;
1416             time_t mytime = HDtime(NULL);
1417             HDoff_t myoffset = HDlseek(file->fd, (HDoff_t)0, SEEK_CUR);
1418 
1419             if(file->fa.flags & H5FD_LOG_LOC_WRITE)
1420                 HDfprintf(file->logfp, "Error! Writing: %10a-%10a (%10Zu bytes)\n", orig_addr, (orig_addr + orig_size) - 1, orig_size);
1421 
1422             HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "file write failed: time = %s, filename = '%s', file descriptor = %d, errno = %d, error message = '%s', buf = %p, total write size = %llu, bytes this sub-write = %llu, bytes actually written = %llu, offset = %llu", HDctime(&mytime), file->filename, file->fd, myerrno, HDstrerror(myerrno), buf, (unsigned long long)size, (unsigned long long)bytes_in, (unsigned long long)bytes_wrote, (unsigned long long)myoffset);
1423         } /* end if */
1424 
1425         HDassert(bytes_wrote > 0);
1426         HDassert((size_t)bytes_wrote <= size);
1427 
1428         size -= (size_t)bytes_wrote;
1429         addr += (haddr_t)bytes_wrote;
1430         buf = (const char *)buf + bytes_wrote;
1431     } /* end while */
1432 #ifdef H5_HAVE_GETTIMEOFDAY
1433     if(file->fa.flags & H5FD_LOG_TIME_WRITE)
1434         HDgettimeofday(&timeval_stop, NULL);
1435 #endif /* H5_HAVE_GETTIMEOFDAY */
1436 
1437     /* Log information about the write */
1438     if(file->fa.flags & H5FD_LOG_NUM_WRITE)
1439         file->total_write_ops++;
1440     if(file->fa.flags & H5FD_LOG_LOC_WRITE) {
1441         HDfprintf(file->logfp, "%10a-%10a (%10Zu bytes) (%s) Written", orig_addr, (orig_addr + orig_size) - 1, orig_size, flavors[type]);
1442 
1443         /* Check if this is the first write into a "default" section, grabbed by the metadata agregation algorithm */
1444         if(file->fa.flags & H5FD_LOG_FLAVOR) {
1445             if((H5FD_mem_t)file->flavor[orig_addr] == H5FD_MEM_DEFAULT)
1446                 HDmemset(&file->flavor[orig_addr], (int)type, orig_size);
1447         } /* end if */
1448 
1449 #ifdef H5_HAVE_GETTIMEOFDAY
1450         if(file->fa.flags & H5FD_LOG_TIME_WRITE) {
1451             struct timeval timeval_diff;
1452             double time_diff;
1453 
1454             /* Calculate the elapsed gettimeofday time */
1455             timeval_diff.tv_usec = timeval_stop.tv_usec - timeval_start.tv_usec;
1456             timeval_diff.tv_sec = timeval_stop.tv_sec - timeval_start.tv_sec;
1457             if(timeval_diff.tv_usec < 0) {
1458                 timeval_diff.tv_usec += 1000000;
1459                 timeval_diff.tv_sec--;
1460             } /* end if */
1461             time_diff = (double)timeval_diff.tv_sec + ((double)timeval_diff.tv_usec / (double)1000000.0f);
1462             HDfprintf(file->logfp, " (%f s)\n", time_diff);
1463 
1464             /* Add to total write time */
1465             file->total_write_time += time_diff;
1466         } /* end if */
1467         else
1468             HDfprintf(file->logfp, "\n");
1469 #else /* H5_HAVE_GETTIMEOFDAY */
1470         HDfprintf(file->logfp, "\n");
1471 #endif /* H5_HAVE_GETTIMEOFDAY */
1472     } /* end if */
1473 
1474     /* Update current position and eof */
1475     file->pos = addr;
1476     file->op = OP_WRITE;
1477     if(file->pos > file->eof)
1478         file->eof = file->pos;
1479 
1480 done:
1481     if(ret_value < 0) {
1482         /* Reset last file I/O information */
1483         file->pos = HADDR_UNDEF;
1484         file->op = OP_UNKNOWN;
1485     } /* end if */
1486 
1487     FUNC_LEAVE_NOAPI(ret_value)
1488 } /* end H5FD_log_write() */
1489 
1490 
1491 /*-------------------------------------------------------------------------
1492  * Function:    H5FD_log_truncate
1493  *
1494  * Purpose:     Makes sure that the true file size is the same (or larger)
1495  *              than the end-of-address.
1496  *
1497  * Return:      SUCCEED/FAIL
1498  *
1499  * Programmer:  Robb Matzke
1500  *              Wednesday, August  4, 1999
1501  *
1502  *-------------------------------------------------------------------------
1503  */
1504 static herr_t
H5FD_log_truncate(H5FD_t * _file,hid_t UNUSED dxpl_id,hbool_t UNUSED closing)1505 H5FD_log_truncate(H5FD_t *_file, hid_t UNUSED dxpl_id, hbool_t UNUSED closing)
1506 {
1507     H5FD_log_t  *file = (H5FD_log_t *)_file;
1508     herr_t      ret_value = SUCCEED;                /* Return value */
1509 
1510     FUNC_ENTER_NOAPI_NOINIT
1511 
1512     HDassert(file);
1513 
1514     /* Extend the file to make sure it's large enough */
1515     if(!H5F_addr_eq(file->eoa, file->eof)) {
1516 #ifdef H5_HAVE_WIN32_API
1517         LARGE_INTEGER   li;         /* 64-bit (union) integer for SetFilePointer() call */
1518         DWORD           dwPtrLow;   /* Low-order pointer bits from SetFilePointer()
1519                                      * Only used as an error code here.
1520                                      */
1521         DWORD           dwError;    /* DWORD error code from GetLastError() */
1522         BOOL            bError;     /* Boolean error flag */
1523 
1524         /* Windows uses this odd QuadPart union for 32/64-bit portability */
1525         li.QuadPart = (__int64)file->eoa;
1526 
1527         /* Extend the file to make sure it's large enough.
1528          *
1529          * Since INVALID_SET_FILE_POINTER can technically be a valid return value
1530          * from SetFilePointer(), we also need to check GetLastError().
1531          */
1532         dwPtrLow = SetFilePointer(file->hFile, li.LowPart, &li.HighPart, FILE_BEGIN);
1533         if(INVALID_SET_FILE_POINTER == dwPtrLow) {
1534             dwError = GetLastError();
1535             if(dwError != NO_ERROR )
1536                 HGOTO_ERROR(H5E_FILE, H5E_FILEOPEN, FAIL, "unable to set file pointer")
1537         }
1538 
1539         bError = SetEndOfFile(file->hFile);
1540         if(0 == bError)
1541             HGOTO_ERROR(H5E_IO, H5E_SEEKERROR, FAIL, "unable to extend file properly")
1542 #else /* H5_HAVE_WIN32_API */
1543 #ifdef H5_VMS
1544         /* Reset seek offset to the beginning of the file, so that the file isn't
1545          * re-extended later.  This may happen on Open VMS. */
1546         if(-1 == HDlseek(file->fd, (HDoff_t)0, SEEK_SET))
1547             HSYS_GOTO_ERROR(H5E_IO, H5E_SEEKERROR, FAIL, "unable to seek to proper position")
1548 #endif
1549 
1550         if(-1 == HDftruncate(file->fd, (HDoff_t)file->eoa))
1551             HSYS_GOTO_ERROR(H5E_IO, H5E_SEEKERROR, FAIL, "unable to extend file properly")
1552 #endif /* H5_HAVE_WIN32_API */
1553 
1554         /* Log information about the truncate */
1555         if(file->fa.flags & H5FD_LOG_NUM_TRUNCATE)
1556             file->total_truncate_ops++;
1557 
1558         /* Update the eof value */
1559         file->eof = file->eoa;
1560 
1561         /* Reset last file I/O information */
1562         file->pos = HADDR_UNDEF;
1563         file->op = OP_UNKNOWN;
1564     } /* end if */
1565 
1566 done:
1567     FUNC_LEAVE_NOAPI(ret_value)
1568 } /* end H5FD_log_truncate() */
1569