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: Raymond Lu <slu@hdfgroup.uiuc.edu>
18 * Wednesday, 20 September 2006
19 *
20 * Purpose: The Direct I/O file driver forces the data to be written to
21 * the file directly without being copied into system kernel
22 * buffer. The main system support this feature is Linux.
23 */
24
25 /* Interface initialization */
26 #define H5_INTERFACE_INIT_FUNC H5FD_direct_init_interface
27
28 /* For system function posix_memalign - Commented it out because copper isn't able to compile
29 * this file. */
30 /* #define _XOPEN_SOURCE 600 */
31
32 #include "H5private.h" /* Generic Functions */
33 #include "H5Eprivate.h" /* Error handling */
34 #include "H5Fprivate.h" /* File access */
35 #include "H5FDprivate.h" /* File drivers */
36 #include "H5FDdirect.h" /* Direct file driver */
37 #include "H5FLprivate.h" /* Free Lists */
38 #include "H5Iprivate.h" /* IDs */
39 #include "H5MMprivate.h" /* Memory management */
40 #include "H5Pprivate.h" /* Property lists */
41
42 #ifdef H5_HAVE_DIRECT
43
44 /* The driver identification number, initialized at runtime */
45 static hid_t H5FD_DIRECT_g = 0;
46
47 /* File operations */
48 #define OP_UNKNOWN 0
49 #define OP_READ 1
50 #define OP_WRITE 2
51
52 /* Driver-specific file access properties */
53 typedef struct H5FD_direct_fapl_t {
54 size_t mboundary; /* Memory boundary for alignment */
55 size_t fbsize; /* File system block size */
56 size_t cbsize; /* Maximal buffer size for copying user data */
57 hbool_t must_align; /* Decides if data alignment is required */
58 } H5FD_direct_fapl_t;
59
60 /*
61 * The description of a file belonging to this driver. The `eoa' and `eof'
62 * determine the amount of hdf5 address space in use and the high-water mark
63 * of the file (the current size of the underlying Unix file). The `pos'
64 * value is used to eliminate file position updates when they would be a
65 * no-op. Unfortunately we've found systems that use separate file position
66 * indicators for reading and writing so the lseek can only be eliminated if
67 * the current operation is the same as the previous operation. When opening
68 * a file the `eof' will be set to the current file size, `eoa' will be set
69 * to zero, `pos' will be set to H5F_ADDR_UNDEF (as it is when an error
70 * occurs), and `op' will be set to H5F_OP_UNKNOWN.
71 */
72 typedef struct H5FD_direct_t {
73 H5FD_t pub; /*public stuff, must be first */
74 int fd; /*the unix file */
75 haddr_t eoa; /*end of allocated region */
76 haddr_t eof; /*end of file; current file size*/
77 haddr_t pos; /*current file I/O position */
78 int op; /*last operation */
79 H5FD_direct_fapl_t fa; /*file access properties */
80 #ifndef H5_HAVE_WIN32_API
81 /*
82 * On most systems the combination of device and i-node number uniquely
83 * identify a file.
84 */
85 dev_t device; /*file device number */
86 #ifdef H5_VMS
87 ino_t inode[3]; /*file i-node number */
88 #else
89 ino_t inode; /*file i-node number */
90 #endif /*H5_VMS*/
91 #else
92 /*
93 * On H5_HAVE_WIN32_API the low-order word of a unique identifier associated with the
94 * file and the volume serial number uniquely identify a file. This number
95 * (which, both? -rpm) may change when the system is restarted or when the
96 * file is opened. After a process opens a file, the identifier is
97 * constant until the file is closed. An application can use this
98 * identifier and the volume serial number to determine whether two
99 * handles refer to the same file.
100 */
101 DWORD fileindexlo;
102 DWORD fileindexhi;
103 #endif
104 } H5FD_direct_t;
105
106 /*
107 * These macros check for overflow of various quantities. These macros
108 * assume that HDoff_t is signed and haddr_t and size_t are unsigned.
109 *
110 * ADDR_OVERFLOW: Checks whether a file address of type `haddr_t'
111 * is too large to be represented by the second argument
112 * of the file seek function.
113 *
114 * SIZE_OVERFLOW: Checks whether a buffer size of type `hsize_t' is too
115 * large to be represented by the `size_t' type.
116 *
117 * REGION_OVERFLOW: Checks whether an address and size pair describe data
118 * which can be addressed entirely by the second
119 * argument of the file seek function.
120 */
121 #define MAXADDR (((haddr_t)1<<(8*sizeof(HDoff_t)-1))-1)
122 #define ADDR_OVERFLOW(A) (HADDR_UNDEF==(A) || \
123 ((A) & ~(haddr_t)MAXADDR))
124 #define SIZE_OVERFLOW(Z) ((Z) & ~(hsize_t)MAXADDR)
125 #define REGION_OVERFLOW(A,Z) (ADDR_OVERFLOW(A) || SIZE_OVERFLOW(Z) || \
126 HADDR_UNDEF==(A)+(Z) || \
127 (HDoff_t)((A)+(Z))<(HDoff_t)(A))
128
129 /* Prototypes */
130 static void *H5FD_direct_fapl_get(H5FD_t *file);
131 static void *H5FD_direct_fapl_copy(const void *_old_fa);
132 static H5FD_t *H5FD_direct_open(const char *name, unsigned flags, hid_t fapl_id,
133 haddr_t maxaddr);
134 static herr_t H5FD_direct_close(H5FD_t *_file);
135 static int H5FD_direct_cmp(const H5FD_t *_f1, const H5FD_t *_f2);
136 static herr_t H5FD_direct_query(const H5FD_t *_f1, unsigned long *flags);
137 static haddr_t H5FD_direct_get_eoa(const H5FD_t *_file, H5FD_mem_t type);
138 static herr_t H5FD_direct_set_eoa(H5FD_t *_file, H5FD_mem_t type, haddr_t addr);
139 static haddr_t H5FD_direct_get_eof(const H5FD_t *_file);
140 static herr_t H5FD_direct_get_handle(H5FD_t *_file, hid_t fapl, void** file_handle);
141 static herr_t H5FD_direct_read(H5FD_t *_file, H5FD_mem_t type, hid_t fapl_id, haddr_t addr,
142 size_t size, void *buf);
143 static herr_t H5FD_direct_write(H5FD_t *_file, H5FD_mem_t type, hid_t fapl_id, haddr_t addr,
144 size_t size, const void *buf);
145 static herr_t H5FD_direct_truncate(H5FD_t *_file, hid_t dxpl_id, hbool_t closing);
146
147 static const H5FD_class_t H5FD_direct_g = {
148 "direct", /*name */
149 MAXADDR, /*maxaddr */
150 H5F_CLOSE_WEAK, /* fc_degree */
151 NULL, /*sb_size */
152 NULL, /*sb_encode */
153 NULL, /*sb_decode */
154 sizeof(H5FD_direct_fapl_t), /*fapl_size */
155 H5FD_direct_fapl_get, /*fapl_get */
156 H5FD_direct_fapl_copy, /*fapl_copy */
157 NULL, /*fapl_free */
158 0, /*dxpl_size */
159 NULL, /*dxpl_copy */
160 NULL, /*dxpl_free */
161 H5FD_direct_open, /*open */
162 H5FD_direct_close, /*close */
163 H5FD_direct_cmp, /*cmp */
164 H5FD_direct_query, /*query */
165 NULL, /*get_type_map */
166 NULL, /*alloc */
167 NULL, /*free */
168 H5FD_direct_get_eoa, /*get_eoa */
169 H5FD_direct_set_eoa, /*set_eoa */
170 H5FD_direct_get_eof, /*get_eof */
171 H5FD_direct_get_handle, /*get_handle */
172 H5FD_direct_read, /*read */
173 H5FD_direct_write, /*write */
174 NULL, /*flush */
175 H5FD_direct_truncate, /*truncate */
176 NULL, /*lock */
177 NULL, /*unlock */
178 H5FD_FLMAP_DICHOTOMY /*fl_map */
179 };
180
181 /* Declare a free list to manage the H5FD_direct_t struct */
182 H5FL_DEFINE_STATIC(H5FD_direct_t);
183
184
185 /*--------------------------------------------------------------------------
186 NAME
187 H5FD_direct_init_interface -- Initialize interface-specific information
188 USAGE
189 herr_t H5FD_direct_init_interface()
190
191 RETURNS
192 Non-negative on success/Negative on failure
193 DESCRIPTION
194 Initializes any interface-specific data or routines. (Just calls
195 H5FD_direct_init currently).
196
197 --------------------------------------------------------------------------*/
198 static herr_t
H5FD_direct_init_interface(void)199 H5FD_direct_init_interface(void)
200 {
201 FUNC_ENTER_NOAPI_NOINIT_NOERR
202
203 FUNC_LEAVE_NOAPI(H5FD_direct_init())
204 } /* H5FD_direct_init_interface() */
205
206
207 /*-------------------------------------------------------------------------
208 * Function: H5FD_direct_init
209 *
210 * Purpose: Initialize this driver by registering the driver with the
211 * library.
212 *
213 * Return: Success: The driver ID for the direct driver.
214 *
215 * Failure: Negative.
216 *
217 * Programmer: Raymond Lu
218 * Wednesday, 20 September 2006
219 *
220 * Modifications:
221 *
222 *-------------------------------------------------------------------------
223 */
224 hid_t
H5FD_direct_init(void)225 H5FD_direct_init(void)
226 {
227 hid_t ret_value; /* Return value */
228
229 FUNC_ENTER_NOAPI(FAIL)
230
231 if (H5I_VFL!=H5I_get_type(H5FD_DIRECT_g))
232 H5FD_DIRECT_g = H5FD_register(&H5FD_direct_g,sizeof(H5FD_class_t),FALSE);
233
234 /* Set return value */
235 ret_value=H5FD_DIRECT_g;
236
237 done:
238 FUNC_LEAVE_NOAPI(ret_value)
239 }
240
241
242 /*---------------------------------------------------------------------------
243 * Function: H5FD_direct_term
244 *
245 * Purpose: Shut down the VFD
246 *
247 * Return: <none>
248 *
249 * Programmer: Raymond Lu
250 * Wednesday, 20 September 2006
251 *
252 * Modification:
253 *
254 *---------------------------------------------------------------------------
255 */
256 void
H5FD_direct_term(void)257 H5FD_direct_term(void)
258 {
259 FUNC_ENTER_NOAPI_NOINIT_NOERR
260
261 /* Reset VFL ID */
262 H5FD_DIRECT_g=0;
263
264 FUNC_LEAVE_NOAPI_VOID
265 } /* end H5FD_direct_term() */
266
267
268 /*-------------------------------------------------------------------------
269 * Function: H5Pset_fapl_direct
270 *
271 * Purpose: Modify the file access property list to use the H5FD_DIRECT
272 * driver defined in this source file. There are no driver
273 * specific properties.
274 *
275 * Return: Non-negative on success/Negative on failure
276 *
277 * Programmer: Raymond Lu
278 * Wednesday, 20 September 2006
279 *
280 * Modifications:
281 *
282 *-------------------------------------------------------------------------
283 */
284 herr_t
H5Pset_fapl_direct(hid_t fapl_id,size_t boundary,size_t block_size,size_t cbuf_size)285 H5Pset_fapl_direct(hid_t fapl_id, size_t boundary, size_t block_size, size_t cbuf_size)
286 {
287 H5P_genplist_t *plist; /* Property list pointer */
288 H5FD_direct_fapl_t fa;
289 herr_t ret_value;
290
291 FUNC_ENTER_API(FAIL)
292 H5TRACE4("e", "izzz", fapl_id, boundary, block_size, cbuf_size);
293
294 if(NULL == (plist = H5P_object_verify(fapl_id,H5P_FILE_ACCESS)))
295 HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file access property list")
296
297 if(boundary != 0)
298 fa.mboundary = boundary;
299 else
300 fa.mboundary = MBOUNDARY_DEF;
301 if(block_size != 0)
302 fa.fbsize = block_size;
303 else
304 fa.fbsize = FBSIZE_DEF;
305 if(cbuf_size != 0)
306 fa.cbsize = cbuf_size;
307 else
308 fa.cbsize = CBSIZE_DEF;
309
310 /* Set the default to be true for data alignment */
311 fa.must_align = TRUE;
312
313 /* Copy buffer size must be a multiple of file block size */
314 if(fa.cbsize % fa.fbsize != 0)
315 HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "copy buffer size must be a multiple of block size")
316
317 ret_value= H5P_set_driver(plist, H5FD_DIRECT, &fa);
318
319 done:
320 FUNC_LEAVE_API(ret_value)
321 }
322
323
324 /*-------------------------------------------------------------------------
325 * Function: H5Pget_fapl_direct
326 *
327 * Purpose: Returns information about the direct file access property
328 * list though the function arguments.
329 *
330 * Return: Success: Non-negative
331 *
332 * Failure: Negative
333 *
334 * Programmer: Raymond Lu
335 * Wednesday, October 18, 2006
336 *
337 * Modifications:
338 *
339 *-------------------------------------------------------------------------
340 */
341 herr_t
H5Pget_fapl_direct(hid_t fapl_id,size_t * boundary,size_t * block_size,size_t * cbuf_size)342 H5Pget_fapl_direct(hid_t fapl_id, size_t *boundary/*out*/, size_t *block_size/*out*/,
343 size_t *cbuf_size/*out*/)
344 {
345 H5FD_direct_fapl_t *fa;
346 H5P_genplist_t *plist; /* Property list pointer */
347 herr_t ret_value=SUCCEED; /* Return value */
348
349 FUNC_ENTER_API(FAIL)
350 H5TRACE4("e", "ixxx", fapl_id, boundary, block_size, cbuf_size);
351
352 if(NULL == (plist = H5P_object_verify(fapl_id,H5P_FILE_ACCESS)))
353 HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file access list")
354 if (H5FD_DIRECT!=H5P_get_driver(plist))
355 HGOTO_ERROR(H5E_PLIST, H5E_BADVALUE, FAIL, "incorrect VFL driver")
356 if (NULL==(fa=H5P_get_driver_info(plist)))
357 HGOTO_ERROR(H5E_PLIST, H5E_BADVALUE, FAIL, "bad VFL driver info")
358 if (boundary)
359 *boundary = fa->mboundary;
360 if (block_size)
361 *block_size = fa->fbsize;
362 if (cbuf_size)
363 *cbuf_size = fa->cbsize;
364
365 done:
366 FUNC_LEAVE_API(ret_value)
367 }
368
369
370 /*-------------------------------------------------------------------------
371 * Function: H5FD_direct_fapl_get
372 *
373 * Purpose: Returns a file access property list which indicates how the
374 * specified file is being accessed. The return list could be
375 * used to access another file the same way.
376 *
377 * Return: Success: Ptr to new file access property list with all
378 * members copied from the file struct.
379 *
380 * Failure: NULL
381 *
382 * Programmer: Raymond Lu
383 * Wednesday, 18 October 2006
384 *
385 * Modifications:
386 *
387 *-------------------------------------------------------------------------
388 */
389 static void *
H5FD_direct_fapl_get(H5FD_t * _file)390 H5FD_direct_fapl_get(H5FD_t *_file)
391 {
392 H5FD_direct_t *file = (H5FD_direct_t*)_file;
393 void *ret_value; /* Return value */
394
395 FUNC_ENTER_NOAPI_NOINIT
396
397 /* Set return value */
398 ret_value= H5FD_direct_fapl_copy(&(file->fa));
399
400 done:
401 FUNC_LEAVE_NOAPI(ret_value)
402 } /* end H5FD_direct_fapl_get() */
403
404
405 /*-------------------------------------------------------------------------
406 * Function: H5FD_direct_fapl_copy
407 *
408 * Purpose: Copies the direct-specific file access properties.
409 *
410 * Return: Success: Ptr to a new property list
411 *
412 * Failure: NULL
413 *
414 * Programmer: Raymond Lu
415 * Wednesday, 18 October 2006
416 *
417 * Modifications:
418 *
419 *-------------------------------------------------------------------------
420 */
421 static void *
H5FD_direct_fapl_copy(const void * _old_fa)422 H5FD_direct_fapl_copy(const void *_old_fa)
423 {
424 const H5FD_direct_fapl_t *old_fa = (const H5FD_direct_fapl_t*)_old_fa;
425 H5FD_direct_fapl_t *new_fa = H5MM_malloc(sizeof(H5FD_direct_fapl_t));
426
427 FUNC_ENTER_NOAPI_NOINIT_NOERR
428
429 HDassert(new_fa);
430
431 /* Copy the general information */
432 HDmemcpy(new_fa, old_fa, sizeof(H5FD_direct_fapl_t));
433
434 FUNC_LEAVE_NOAPI(new_fa)
435 } /* end H5FD_direct_fapl_copy() */
436
437
438 /*-------------------------------------------------------------------------
439 * Function: H5FD_direct_open
440 *
441 * Purpose: Create and/or opens a Unix file for direct I/O as an HDF5 file.
442 *
443 * Return: Success: A pointer to a new file data structure. The
444 * public fields will be initialized by the
445 * caller, which is always H5FD_open().
446 *
447 * Failure: NULL
448 *
449 * Programmer: Raymond Lu
450 * Wednesday, 20 September 2006
451 *
452 * Modifications:
453 *
454 *-------------------------------------------------------------------------
455 */
456 static H5FD_t *
H5FD_direct_open(const char * name,unsigned flags,hid_t fapl_id,haddr_t maxaddr)457 H5FD_direct_open(const char *name, unsigned flags, hid_t fapl_id, haddr_t maxaddr)
458 {
459 int o_flags;
460 int fd=(-1);
461 H5FD_direct_t *file=NULL;
462 H5FD_direct_fapl_t *fa;
463 #ifdef H5_HAVE_WIN32_API
464 HFILE filehandle;
465 struct _BY_HANDLE_FILE_INFORMATION fileinfo;
466 #endif
467 h5_stat_t sb;
468 H5P_genplist_t *plist; /* Property list */
469 int *buf1, *buf2;
470 H5FD_t *ret_value;
471
472 FUNC_ENTER_NOAPI_NOINIT
473
474 /* Sanity check on file offsets */
475 HDassert(sizeof(HDoff_t)>=sizeof(size_t));
476
477 /* Check arguments */
478 if (!name || !*name)
479 HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, NULL, "invalid file name")
480 if (0==maxaddr || HADDR_UNDEF==maxaddr)
481 HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, NULL, "bogus maxaddr")
482 if (ADDR_OVERFLOW(maxaddr))
483 HGOTO_ERROR(H5E_ARGS, H5E_OVERFLOW, NULL, "bogus maxaddr")
484
485 /* Build the open flags */
486 o_flags = (H5F_ACC_RDWR & flags) ? O_RDWR : O_RDONLY;
487 if (H5F_ACC_TRUNC & flags) o_flags |= O_TRUNC;
488 if (H5F_ACC_CREAT & flags) o_flags |= O_CREAT;
489 if (H5F_ACC_EXCL & flags) o_flags |= O_EXCL;
490
491 /* Flag for Direct I/O */
492 o_flags |= O_DIRECT;
493
494 /* Open the file */
495 if ((fd=HDopen(name, o_flags, 0666))<0)
496 HSYS_GOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, NULL, "unable to open file")
497
498 if (HDfstat(fd, &sb)<0)
499 HSYS_GOTO_ERROR(H5E_FILE, H5E_BADFILE, NULL, "unable to fstat file")
500
501 /* Create the new file struct */
502 if (NULL==(file=H5FL_CALLOC(H5FD_direct_t)))
503 HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "unable to allocate file struct")
504
505 /* Get the driver specific information */
506 if(NULL == (plist = H5P_object_verify(fapl_id,H5P_FILE_ACCESS)))
507 HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "not a file access property list")
508 if(NULL == (fa = (H5FD_direct_fapl_t *)H5P_get_driver_info(plist)))
509 HGOTO_ERROR(H5E_PLIST, H5E_BADVALUE, NULL, "bad VFL driver info")
510
511 file->fd = fd;
512 H5_ASSIGN_OVERFLOW(file->eof,sb.st_size,h5_stat_size_t,haddr_t);
513 file->pos = HADDR_UNDEF;
514 file->op = OP_UNKNOWN;
515 #ifdef H5_HAVE_WIN32_API
516 filehandle = _get_osfhandle(fd);
517 (void)GetFileInformationByHandle((HANDLE)filehandle, &fileinfo);
518 file->fileindexhi = fileinfo.nFileIndexHigh;
519 file->fileindexlo = fileinfo.nFileIndexLow;
520 #else
521 file->device = sb.st_dev;
522 #ifdef H5_VMS
523 file->inode[0] = sb.st_ino[0];
524 file->inode[1] = sb.st_ino[1];
525 file->inode[2] = sb.st_ino[2];
526 #else
527 file->inode = sb.st_ino;
528 #endif /*H5_VMS*/
529 #endif /*H5_HAVE_WIN32_API*/
530 file->fa.mboundary = fa->mboundary;
531 file->fa.fbsize = fa->fbsize;
532 file->fa.cbsize = fa->cbsize;
533
534 /* Try to decide if data alignment is required. The reason to check it here
535 * is to handle correctly the case that the file is in a different file system
536 * than the one where the program is running.
537 */
538 buf1 = (int *)HDmalloc(sizeof(int));
539 if(HDposix_memalign(&buf2, file->fa.mboundary, file->fa.fbsize) != 0)
540 HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, NULL, "HDposix_memalign failed")
541
542 if(o_flags & O_CREAT) {
543 if(HDwrite(file->fd, (void*)buf1, sizeof(int))<0) {
544 if(HDwrite(file->fd, (void*)buf2, file->fa.fbsize)<0)
545 HGOTO_ERROR(H5E_FILE, H5E_WRITEERROR, NULL, "file system may not support Direct I/O")
546 else
547 file->fa.must_align = TRUE;
548 } else {
549 file->fa.must_align = FALSE;
550 HDftruncate(file->fd, (HDoff_t)0);
551 }
552 } else {
553 if(HDread(file->fd, (void*)buf1, sizeof(int))<0) {
554 if(HDread(file->fd, (void*)buf2, file->fa.fbsize)<0)
555 HGOTO_ERROR(H5E_FILE, H5E_READERROR, NULL, "file system may not support Direct I/O")
556 else
557 file->fa.must_align = TRUE;
558 } else {
559 if(o_flags & O_RDWR) {
560 if(HDlseek(file->fd, (HDoff_t)0, SEEK_SET) < 0)
561 HSYS_GOTO_ERROR(H5E_IO, H5E_SEEKERROR, NULL, "unable to seek to proper position")
562 if(HDwrite(file->fd, (void *)buf1, sizeof(int))<0)
563 file->fa.must_align = TRUE;
564 else
565 file->fa.must_align = FALSE;
566 } else
567 file->fa.must_align = FALSE;
568 }
569 }
570
571 if(buf1)
572 HDfree(buf1);
573 if(buf2)
574 HDfree(buf2);
575
576 /* Set return value */
577 ret_value=(H5FD_t*)file;
578
579 done:
580 if(ret_value==NULL) {
581 if(fd>=0)
582 HDclose(fd);
583 } /* end if */
584
585 FUNC_LEAVE_NOAPI(ret_value)
586 }
587
588
589 /*-------------------------------------------------------------------------
590 * Function: H5FD_direct_close
591 *
592 * Purpose: Closes the file.
593 *
594 * Return: Success: 0
595 *
596 * Failure: -1, file not closed.
597 *
598 * Programmer: Raymond Lu
599 * Wednesday, 20 September 2006
600 *
601 * Modifications:
602 *
603 *-------------------------------------------------------------------------
604 */
605 static herr_t
H5FD_direct_close(H5FD_t * _file)606 H5FD_direct_close(H5FD_t *_file)
607 {
608 H5FD_direct_t *file = (H5FD_direct_t*)_file;
609 herr_t ret_value=SUCCEED; /* Return value */
610
611 FUNC_ENTER_NOAPI_NOINIT
612
613 if (HDclose(file->fd)<0)
614 HSYS_GOTO_ERROR(H5E_IO, H5E_CANTCLOSEFILE, FAIL, "unable to close file")
615
616 H5FL_FREE(H5FD_direct_t,file);
617
618 done:
619 FUNC_LEAVE_NOAPI(ret_value)
620 }
621
622
623 /*-------------------------------------------------------------------------
624 * Function: H5FD_direct_cmp
625 *
626 * Purpose: Compares two files belonging to this driver using an
627 * arbitrary (but consistent) ordering.
628 *
629 * Return: Success: A value like strcmp()
630 *
631 * Failure: never fails (arguments were checked by the
632 * caller).
633 *
634 * Programmer: Raymond Lu
635 * Thursday, 21 September 2006
636 *
637 * Modifications:
638 *
639 *-------------------------------------------------------------------------
640 */
641 static int
H5FD_direct_cmp(const H5FD_t * _f1,const H5FD_t * _f2)642 H5FD_direct_cmp(const H5FD_t *_f1, const H5FD_t *_f2)
643 {
644 const H5FD_direct_t *f1 = (const H5FD_direct_t*)_f1;
645 const H5FD_direct_t *f2 = (const H5FD_direct_t*)_f2;
646 int ret_value=0;
647
648 FUNC_ENTER_NOAPI_NOINIT_NOERR
649
650 #ifdef H5_HAVE_WIN32_API
651 if (f1->fileindexhi < f2->fileindexhi) HGOTO_DONE(-1)
652 if (f1->fileindexhi > f2->fileindexhi) HGOTO_DONE(1)
653
654 if (f1->fileindexlo < f2->fileindexlo) HGOTO_DONE(-1)
655 if (f1->fileindexlo > f2->fileindexlo) HGOTO_DONE(1)
656
657 #else
658 #ifdef H5_DEV_T_IS_SCALAR
659 if (f1->device < f2->device) HGOTO_DONE(-1)
660 if (f1->device > f2->device) HGOTO_DONE(1)
661 #else /* H5_DEV_T_IS_SCALAR */
662 /* If dev_t isn't a scalar value on this system, just use memcmp to
663 * determine if the values are the same or not. The actual return value
664 * shouldn't really matter...
665 */
666 if(HDmemcmp(&(f1->device),&(f2->device),sizeof(dev_t))<0) HGOTO_DONE(-1)
667 if(HDmemcmp(&(f1->device),&(f2->device),sizeof(dev_t))>0) HGOTO_DONE(1)
668 #endif /* H5_DEV_T_IS_SCALAR */
669
670 #ifndef H5_VMS
671 if (f1->inode < f2->inode) HGOTO_DONE(-1)
672 if (f1->inode > f2->inode) HGOTO_DONE(1)
673 #else
674 if(HDmemcmp(&(f1->inode),&(f2->inode),3*sizeof(ino_t))<0) HGOTO_DONE(-1)
675 if(HDmemcmp(&(f1->inode),&(f2->inode),3*sizeof(ino_t))>0) HGOTO_DONE(1)
676 #endif /*H5_VMS*/
677
678 #endif
679
680 done:
681 FUNC_LEAVE_NOAPI(ret_value)
682 }
683
684
685 /*-------------------------------------------------------------------------
686 * Function: H5FD_direct_query
687 *
688 * Purpose: Set the flags that this VFL driver is capable of supporting.
689 * (listed in H5FDpublic.h)
690 *
691 * Return: Success: non-negative
692 *
693 * Failure: negative
694 *
695 * Programmer: Raymond Lu
696 * Thursday, 21 September 2006
697 *
698 * Modifications:
699 *
700 *-------------------------------------------------------------------------
701 */
702 static herr_t
H5FD_direct_query(const H5FD_t UNUSED * _f,unsigned long * flags)703 H5FD_direct_query(const H5FD_t UNUSED * _f, unsigned long *flags /* out */)
704 {
705 FUNC_ENTER_NOAPI_NOINIT_NOERR
706
707 /* Set the VFL feature flags that this driver supports */
708 if(flags) {
709 *flags = 0;
710 *flags|=H5FD_FEAT_AGGREGATE_METADATA; /* OK to aggregate metadata allocations */
711 *flags|=H5FD_FEAT_ACCUMULATE_METADATA; /* OK to accumulate metadata for faster writes */
712 *flags|=H5FD_FEAT_DATA_SIEVE; /* OK to perform data sieving for faster raw data reads & writes */
713 *flags|=H5FD_FEAT_AGGREGATE_SMALLDATA; /* OK to aggregate "small" raw data allocations */
714 }
715
716 FUNC_LEAVE_NOAPI(SUCCEED)
717 }
718
719
720 /*-------------------------------------------------------------------------
721 * Function: H5FD_direct_get_eoa
722 *
723 * Purpose: Gets the end-of-address marker for the file. The EOA marker
724 * is the first address past the last byte allocated in the
725 * format address space.
726 *
727 * Return: Success: The end-of-address marker.
728 *
729 * Failure: HADDR_UNDEF
730 *
731 * Programmer: Raymond Lu
732 * Wednesday, 20 September 2006
733 *
734 * Modifications:
735 * Raymond Lu
736 * 21 Dec. 2006
737 * Added the parameter TYPE. It's only used for MULTI driver.
738 *
739 *-------------------------------------------------------------------------
740 */
741 static haddr_t
H5FD_direct_get_eoa(const H5FD_t * _file,H5FD_mem_t UNUSED type)742 H5FD_direct_get_eoa(const H5FD_t *_file, H5FD_mem_t UNUSED type)
743 {
744 const H5FD_direct_t *file = (const H5FD_direct_t*)_file;
745
746 FUNC_ENTER_NOAPI_NOINIT_NOERR
747
748 FUNC_LEAVE_NOAPI(file->eoa)
749 }
750
751
752 /*-------------------------------------------------------------------------
753 * Function: H5FD_direct_set_eoa
754 *
755 * Purpose: Set the end-of-address marker for the file. This function is
756 * called shortly after an existing HDF5 file is opened in order
757 * to tell the driver where the end of the HDF5 data is located.
758 *
759 * Return: Success: 0
760 *
761 * Failure: -1
762 *
763 * Programmer: Raymond Lu
764 * Wednesday, 20 September 2006
765 *
766 * Modifications:
767 * Raymond Lu
768 * 21 Dec. 2006
769 * Added the parameter TYPE. It's only used for MULTI driver.
770 *
771 *-------------------------------------------------------------------------
772 */
773 static herr_t
H5FD_direct_set_eoa(H5FD_t * _file,H5FD_mem_t UNUSED type,haddr_t addr)774 H5FD_direct_set_eoa(H5FD_t *_file, H5FD_mem_t UNUSED type, haddr_t addr)
775 {
776 H5FD_direct_t *file = (H5FD_direct_t*)_file;
777
778 FUNC_ENTER_NOAPI_NOINIT_NOERR
779
780 file->eoa = addr;
781
782 FUNC_LEAVE_NOAPI(SUCCEED)
783 }
784
785
786 /*-------------------------------------------------------------------------
787 * Function: H5FD_direct_get_eof
788 *
789 * Purpose: Returns the end-of-file marker, which is the greater of
790 * either the Unix end-of-file or the HDF5 end-of-address
791 * markers.
792 *
793 * Return: Success: End of file address, the first address past
794 * the end of the "file", either the Unix file
795 * or the HDF5 file.
796 *
797 * Failure: HADDR_UNDEF
798 *
799 * Programmer: Raymond Lu
800 * Wednesday, 20 September 2006
801 *
802 * Modifications:
803 *
804 *-------------------------------------------------------------------------
805 */
806 static haddr_t
H5FD_direct_get_eof(const H5FD_t * _file)807 H5FD_direct_get_eof(const H5FD_t *_file)
808 {
809 const H5FD_direct_t *file = (const H5FD_direct_t*)_file;
810
811 FUNC_ENTER_NOAPI_NOINIT
812
813 FUNC_LEAVE_NOAPI(MAX(file->eof, file->eoa))
814 }
815
816
817 /*-------------------------------------------------------------------------
818 * Function: H5FD_diect_get_handle
819 *
820 * Purpose: Returns the file handle of direct file driver.
821 *
822 * Returns: Non-negative if succeed or negative if fails.
823 *
824 * Programmer: Raymond Lu
825 * 21 September 2006
826 *
827 * Modifications:
828 *
829 *-------------------------------------------------------------------------
830 */
831 static herr_t
H5FD_direct_get_handle(H5FD_t * _file,hid_t UNUSED fapl,void ** file_handle)832 H5FD_direct_get_handle(H5FD_t *_file, hid_t UNUSED fapl, void** file_handle)
833 {
834 H5FD_direct_t *file = (H5FD_direct_t *)_file;
835 herr_t ret_value = SUCCEED;
836
837 FUNC_ENTER_NOAPI_NOINIT
838
839 if(!file_handle)
840 HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "file handle not valid")
841 *file_handle = &(file->fd);
842
843 done:
844 FUNC_LEAVE_NOAPI(ret_value)
845 }
846
847
848 /*-------------------------------------------------------------------------
849 * Function: H5FD_direct_read
850 *
851 * Purpose: Reads SIZE bytes of data from FILE beginning at address ADDR
852 * into buffer BUF according to data transfer properties in
853 * DXPL_ID.
854 *
855 * Return: Success: Zero. Result is stored in caller-supplied
856 * buffer BUF.
857 *
858 * Failure: -1, Contents of buffer BUF are undefined.
859 *
860 * Programmer: Raymond Lu
861 * Thursday, 21 September 2006
862 *
863 * Modifications:
864 *
865 *-------------------------------------------------------------------------
866 */
867 static herr_t
H5FD_direct_read(H5FD_t * _file,H5FD_mem_t UNUSED type,hid_t UNUSED dxpl_id,haddr_t addr,size_t size,void * buf)868 H5FD_direct_read(H5FD_t *_file, H5FD_mem_t UNUSED type, hid_t UNUSED dxpl_id, haddr_t addr,
869 size_t size, void *buf/*out*/)
870 {
871 H5FD_direct_t *file = (H5FD_direct_t*)_file;
872 ssize_t nbytes;
873 hbool_t _must_align = TRUE;
874 herr_t ret_value=SUCCEED; /* Return value */
875 size_t alloc_size;
876 void *copy_buf = NULL, *p2;
877 size_t _boundary;
878 size_t _fbsize;
879 size_t _cbsize;
880 haddr_t read_size; /* Size to read into copy buffer */
881 size_t copy_size = size; /* Size remaining to read when using copy buffer */
882 size_t copy_offset; /* Offset into copy buffer of the requested data */
883
884 FUNC_ENTER_NOAPI_NOINIT
885
886 HDassert(file && file->pub.cls);
887 HDassert(buf);
888
889 /* Check for overflow conditions */
890 if (HADDR_UNDEF==addr)
891 HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "addr undefined")
892 if (REGION_OVERFLOW(addr, size))
893 HGOTO_ERROR(H5E_ARGS, H5E_OVERFLOW, FAIL, "addr overflow")
894 if((addr + size) > file->eoa)
895 HGOTO_ERROR(H5E_ARGS, H5E_OVERFLOW, FAIL, "addr overflow")
896
897 /* If the system doesn't require data to be aligned, read the data in
898 * the same way as sec2 driver.
899 */
900 _must_align = file->fa.must_align;
901
902 /* Get the memory boundary for alignment, file system block size, and maximal
903 * copy buffer size.
904 */
905 _boundary = file->fa.mboundary;
906 _fbsize = file->fa.fbsize;
907 _cbsize = file->fa.cbsize;
908
909 /* if the data is aligned or the system doesn't require data to be aligned,
910 * read it directly from the file. If not, read a bigger
911 * and aligned data first, then copy the data into memory buffer.
912 */
913 if(!_must_align || ((addr%_fbsize==0) && (size%_fbsize==0) && ((size_t)buf%_boundary==0))) {
914 /* Seek to the correct location */
915 if ((addr!=file->pos || OP_READ!=file->op) &&
916 HDlseek(file->fd, (HDoff_t)addr, SEEK_SET)<0)
917 HSYS_GOTO_ERROR(H5E_IO, H5E_SEEKERROR, FAIL, "unable to seek to proper position")
918 /* Read the aligned data in file first, being careful of interrupted
919 * system calls and partial results. */
920 while (size>0) {
921 do {
922 nbytes = HDread(file->fd, buf, size);
923 } while (-1==nbytes && EINTR==errno);
924 if (-1==nbytes) /* error */
925 HSYS_GOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "file read failed")
926 if (0==nbytes) {
927 /* end of file but not end of format address space */
928 HDmemset(buf, 0, size);
929 break;
930 }
931 HDassert(nbytes>=0);
932 HDassert((size_t)nbytes<=size);
933 H5_CHECK_OVERFLOW(nbytes,ssize_t,size_t);
934 size -= (size_t)nbytes;
935 H5_CHECK_OVERFLOW(nbytes,ssize_t,haddr_t);
936 addr += (haddr_t)nbytes;
937 buf = (char*)buf + nbytes;
938 }
939 } else {
940 /* Calculate where we will begin copying from the copy buffer */
941 copy_offset = (size_t)(addr % _fbsize);
942
943 /* allocate memory needed for the Direct IO option up to the maximal
944 * copy buffer size. Make a bigger buffer for aligned I/O if size is
945 * smaller than maximal copy buffer. */
946 alloc_size = ((copy_offset + size - 1) / _fbsize + 1) * _fbsize;
947 if(alloc_size > _cbsize)
948 alloc_size = _cbsize;
949 HDassert(!(alloc_size % _fbsize));
950 if (HDposix_memalign(©_buf, _boundary, alloc_size) != 0)
951 HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, FAIL, "HDposix_memalign failed")
952
953 /* look for the aligned position for reading the data */
954 HDassert(!(((addr / _fbsize) * _fbsize) % _fbsize));
955 if(HDlseek(file->fd, (HDoff_t)((addr / _fbsize) * _fbsize),
956 SEEK_SET) < 0)
957 HSYS_GOTO_ERROR(H5E_IO, H5E_SEEKERROR, FAIL, "unable to seek to proper position")
958
959 /*
960 * Read the aligned data in file into aligned buffer first, then copy the data
961 * into the final buffer. If the data size is bigger than maximal copy buffer
962 * size, do the reading by segment (the outer while loop). If not, do one step
963 * reading.
964 */
965 do {
966 /* Read the aligned data in file first. Not able to handle interrupted
967 * system calls and partial results like sec2 driver does because the
968 * data may no longer be aligned. It's expecially true when the data in
969 * file is smaller than ALLOC_SIZE. */
970 HDmemset(copy_buf, 0, alloc_size);
971
972 /* Calculate how much data we have to read in this iteration
973 * (including unused parts of blocks) */
974 if((copy_size + copy_offset) < alloc_size)
975 read_size = ((copy_size + copy_offset - 1) / _fbsize + 1)
976 * _fbsize;
977 else
978 read_size = alloc_size;
979
980 HDassert(!(read_size % _fbsize));
981 do {
982 nbytes = HDread(file->fd, copy_buf, read_size);
983 } while(-1==nbytes && EINTR==errno);
984
985 if (-1==nbytes) /* error */
986 HSYS_GOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "file read failed")
987
988 /* Copy the needed data from the copy buffer to the output
989 * buffer, and update copy_size. If the copy buffer does not
990 * contain the rest of the data, just copy what's in the copy
991 * buffer and also update read_addr and copy_offset to read the
992 * next section of data. */
993 p2 = (unsigned char*)copy_buf + copy_offset;
994 if((copy_size + copy_offset) <= alloc_size) {
995 HDmemcpy(buf, p2, copy_size);
996 buf = (unsigned char *)buf + copy_size;
997 copy_size = 0;
998 } /* end if */
999 else {
1000 HDmemcpy(buf, p2, alloc_size - copy_offset);
1001 buf = (unsigned char*)buf + alloc_size - copy_offset;
1002 copy_size -= alloc_size - copy_offset;
1003 copy_offset = 0;
1004 } /* end else */
1005 } while (copy_size > 0);
1006
1007 /*Final step: update address*/
1008 addr = (haddr_t)(((addr + size - 1) / _fbsize + 1) * _fbsize);
1009
1010 if(copy_buf) {
1011 HDfree(copy_buf);
1012 copy_buf = NULL;
1013 } /* end if */
1014 }
1015
1016 /* Update current position */
1017 file->pos = addr;
1018 file->op = OP_READ;
1019
1020 done:
1021 if(ret_value<0) {
1022 if(copy_buf)
1023 HDfree(copy_buf);
1024
1025 /* Reset last file I/O information */
1026 file->pos = HADDR_UNDEF;
1027 file->op = OP_UNKNOWN;
1028 } /* end if */
1029
1030 FUNC_LEAVE_NOAPI(ret_value)
1031 }
1032
1033
1034 /*-------------------------------------------------------------------------
1035 * Function: H5FD_direct_write
1036 *
1037 * Purpose: Writes SIZE bytes of data to FILE beginning at address ADDR
1038 * from buffer BUF according to data transfer properties in
1039 * DXPL_ID.
1040 *
1041 * Return: Success: Zero
1042 *
1043 * Failure: -1
1044 *
1045 * Programmer: Raymond Lu
1046 * Thursday, 21 September 2006
1047 *
1048 * Modifications:
1049 *
1050 *-------------------------------------------------------------------------
1051 */
1052 static herr_t
H5FD_direct_write(H5FD_t * _file,H5FD_mem_t UNUSED type,hid_t UNUSED dxpl_id,haddr_t addr,size_t size,const void * buf)1053 H5FD_direct_write(H5FD_t *_file, H5FD_mem_t UNUSED type, hid_t UNUSED dxpl_id, haddr_t addr,
1054 size_t size, const void *buf)
1055 {
1056 H5FD_direct_t *file = (H5FD_direct_t*)_file;
1057 ssize_t nbytes;
1058 hbool_t _must_align = TRUE;
1059 herr_t ret_value=SUCCEED; /* Return value */
1060 size_t alloc_size;
1061 void *copy_buf = NULL, *p1;
1062 const void *p3;
1063 size_t _boundary;
1064 size_t _fbsize;
1065 size_t _cbsize;
1066 haddr_t write_addr; /* Address to write copy buffer */
1067 haddr_t write_size; /* Size to write from copy buffer */
1068 haddr_t read_size; /* Size to read into copy buffer */
1069 size_t copy_size = size; /* Size remaining to write when using copy buffer */
1070 size_t copy_offset; /* Offset into copy buffer of the data to write */
1071
1072 FUNC_ENTER_NOAPI_NOINIT
1073
1074 HDassert(file && file->pub.cls);
1075 HDassert(buf);
1076
1077 /* Check for overflow conditions */
1078 if (HADDR_UNDEF==addr)
1079 HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "addr undefined")
1080 if (REGION_OVERFLOW(addr, size))
1081 HGOTO_ERROR(H5E_ARGS, H5E_OVERFLOW, FAIL, "addr overflow")
1082 if (addr+size>file->eoa)
1083 HGOTO_ERROR(H5E_ARGS, H5E_OVERFLOW, FAIL, "addr overflow")
1084
1085 /* If the system doesn't require data to be aligned, read the data in
1086 * the same way as sec2 driver.
1087 */
1088 _must_align = file->fa.must_align;
1089
1090 /* Get the memory boundary for alignment, file system block size, and maximal
1091 * copy buffer size.
1092 */
1093 _boundary = file->fa.mboundary;
1094 _fbsize = file->fa.fbsize;
1095 _cbsize = file->fa.cbsize;
1096
1097 /* if the data is aligned or the system doesn't require data to be aligned,
1098 * write it directly to the file. If not, read a bigger and aligned data
1099 * first, update buffer with user data, then write the data out.
1100 */
1101 if(!_must_align || ((addr%_fbsize==0) && (size%_fbsize==0) && ((size_t)buf%_boundary==0))) {
1102 /* Seek to the correct location */
1103 if ((addr!=file->pos || OP_WRITE!=file->op) &&
1104 HDlseek(file->fd, (HDoff_t)addr, SEEK_SET)<0)
1105 HSYS_GOTO_ERROR(H5E_IO, H5E_SEEKERROR, FAIL, "unable to seek to proper position")
1106
1107 while (size>0) {
1108 do {
1109 nbytes = HDwrite(file->fd, buf, size);
1110 } while (-1==nbytes && EINTR==errno);
1111 if (-1==nbytes) /* error */
1112 HSYS_GOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "file write failed")
1113 HDassert(nbytes>0);
1114 HDassert((size_t)nbytes<=size);
1115 H5_CHECK_OVERFLOW(nbytes,ssize_t,size_t);
1116 size -= (size_t)nbytes;
1117 H5_CHECK_OVERFLOW(nbytes,ssize_t,haddr_t);
1118 addr += (haddr_t)nbytes;
1119 buf = (const char*)buf + nbytes;
1120 }
1121 } else {
1122 /* Calculate where we will begin reading from (on disk) and where we
1123 * will begin copying from the copy buffer */
1124 write_addr = (addr / _fbsize) * _fbsize;
1125 copy_offset = (size_t)(addr % _fbsize);
1126
1127 /* allocate memory needed for the Direct IO option up to the maximal
1128 * copy buffer size. Make a bigger buffer for aligned I/O if size is
1129 * smaller than maximal copy buffer.
1130 */
1131 alloc_size = ((copy_offset + size - 1) / _fbsize + 1) * _fbsize;
1132 if(alloc_size > _cbsize)
1133 alloc_size = _cbsize;
1134 HDassert(!(alloc_size % _fbsize));
1135
1136 if (HDposix_memalign(©_buf, _boundary, alloc_size) != 0)
1137 HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, FAIL, "HDposix_memalign failed")
1138
1139 /* look for the right position for reading or writing the data */
1140 if(HDlseek(file->fd, (HDoff_t)write_addr, SEEK_SET) < 0)
1141 HSYS_GOTO_ERROR(H5E_IO, H5E_SEEKERROR, FAIL, "unable to seek to proper position")
1142
1143 p3 = buf;
1144 do {
1145 /* Calculate how much data we have to write in this iteration
1146 * (including unused parts of blocks) */
1147 if((copy_size + copy_offset) < alloc_size)
1148 write_size = ((copy_size + copy_offset - 1) / _fbsize + 1)
1149 * _fbsize;
1150 else
1151 write_size = alloc_size;
1152
1153 /*
1154 * Read the aligned data first if the aligned region doesn't fall
1155 * entirely in the range to be writen. Not able to handle interrupted
1156 * system calls and partial results like sec2 driver does because the
1157 * data may no longer be aligned. It's expecially true when the data in
1158 * file is smaller than ALLOC_SIZE. Only read the entire section if
1159 * both ends are misaligned, otherwise only read the block on the
1160 * misaligned end.
1161 */
1162 HDmemset(copy_buf, 0, _fbsize);
1163
1164 if(copy_offset > 0) {
1165 if((write_addr + write_size) > (addr + size)) {
1166 HDassert((write_addr + write_size) - (addr + size) < _fbsize);
1167 read_size = write_size;
1168 p1 = copy_buf;
1169 } /* end if */
1170 else {
1171 read_size = _fbsize;
1172 p1 = copy_buf;
1173 } /* end else */
1174 } /* end if */
1175 else if((write_addr + write_size) > (addr + size)) {
1176 HDassert((write_addr + write_size) - (addr + size) < _fbsize);
1177 read_size = _fbsize;
1178 p1 = (unsigned char *)copy_buf + write_size - _fbsize;
1179
1180 /* Seek to the last block, for reading */
1181 HDassert(!((write_addr + write_size - _fbsize) % _fbsize));
1182 if(HDlseek(file->fd,
1183 (HDoff_t)(write_addr + write_size - _fbsize),
1184 SEEK_SET) < 0)
1185 HSYS_GOTO_ERROR(H5E_IO, H5E_SEEKERROR, FAIL, "unable to seek to proper position")
1186 } /* end if */
1187 else
1188 p1 = NULL;
1189
1190 if(p1) {
1191 HDassert(!(read_size % _fbsize));
1192 do {
1193 nbytes = HDread(file->fd, p1, read_size);
1194 } while (-1==nbytes && EINTR==errno);
1195
1196 if (-1==nbytes) /* error */
1197 HSYS_GOTO_ERROR(H5E_IO, H5E_READERROR, FAIL, "file read failed")
1198 } /* end if */
1199
1200 /* look for the right position and append or copy the data to be written to
1201 * the aligned buffer.
1202 * Consider all possible situations here: file address is not aligned on
1203 * file block size; the end of data address is not aligned; the end of data
1204 * address is aligned; data size is smaller or bigger than maximal copy size.
1205 */
1206 p1 = (unsigned char *)copy_buf + copy_offset;
1207 if((copy_size + copy_offset) <= alloc_size) {
1208 HDmemcpy(p1, p3, copy_size);
1209 copy_size = 0;
1210 } /* end if */
1211 else {
1212 HDmemcpy(p1, p3, alloc_size - copy_offset);
1213 p3 = (const unsigned char *)p3 + (alloc_size - copy_offset);
1214 copy_size -= alloc_size - copy_offset;
1215 copy_offset = 0;
1216 } /* end else */
1217
1218 /*look for the aligned position for writing the data*/
1219 HDassert(!(write_addr % _fbsize));
1220 if(HDlseek(file->fd, (HDoff_t)write_addr, SEEK_SET) < 0)
1221 HSYS_GOTO_ERROR(H5E_IO, H5E_SEEKERROR, FAIL, "unable to seek to proper position")
1222
1223 /*
1224 * Write the data. It doesn't truncate the extra data introduced by
1225 * alignment because that step is done in H5FD_direct_flush.
1226 */
1227 HDassert(!(write_size % _fbsize));
1228 do {
1229 nbytes = HDwrite(file->fd, copy_buf, write_size);
1230 } while (-1==nbytes && EINTR==errno);
1231
1232 if (-1==nbytes) /* error */
1233 HSYS_GOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "file write failed")
1234
1235 /* update the write address */
1236 write_addr += write_size;
1237 } while (copy_size > 0);
1238
1239 /*Update the address and size*/
1240 addr = write_addr;
1241 buf = (const char*)buf + size;
1242
1243 if(copy_buf) {
1244 HDfree(copy_buf);
1245 copy_buf = NULL;
1246 } /* end if */
1247 }
1248
1249 /* Update current position and eof */
1250 file->pos = addr;
1251 file->op = OP_WRITE;
1252 if (file->pos>file->eof)
1253 file->eof = file->pos;
1254
1255 done:
1256 if(ret_value<0) {
1257 if(copy_buf)
1258 HDfree(copy_buf);
1259
1260 /* Reset last file I/O information */
1261 file->pos = HADDR_UNDEF;
1262 file->op = OP_UNKNOWN;
1263 } /* end if */
1264
1265 FUNC_LEAVE_NOAPI(ret_value)
1266 }
1267
1268
1269 /*-------------------------------------------------------------------------
1270 * Function: H5FD_direct_truncate
1271 *
1272 * Purpose: Makes sure that the true file size is the same (or larger)
1273 * than the end-of-address.
1274 *
1275 * Return: Success: Non-negative
1276 *
1277 * Failure: Negative
1278 *
1279 * Programmer: Raymond Lu
1280 * Thursday, 21 September 2006
1281 *
1282 *-------------------------------------------------------------------------
1283 */
1284 static herr_t
H5FD_direct_truncate(H5FD_t * _file,hid_t UNUSED dxpl_id,hbool_t UNUSED closing)1285 H5FD_direct_truncate(H5FD_t *_file, hid_t UNUSED dxpl_id, hbool_t UNUSED closing)
1286 {
1287 H5FD_direct_t *file = (H5FD_direct_t*)_file;
1288 herr_t ret_value = SUCCEED; /* Return value */
1289
1290 FUNC_ENTER_NOAPI_NOINIT
1291
1292 HDassert(file);
1293
1294 /* Extend the file to make sure it's large enough */
1295 if (file->eoa!=file->eof) {
1296 #ifdef H5_HAVE_WIN32_API
1297 HFILE filehandle; /* Windows file handle */
1298 LARGE_INTEGER li; /* 64-bit integer for SetFilePointer() call */
1299
1300 /* Map the posix file handle to a Windows file handle */
1301 filehandle = _get_osfhandle(file->fd);
1302
1303 /* Translate 64-bit integers into form Windows wants */
1304 /* [This algorithm is from the Windows documentation for SetFilePointer()] */
1305 li.QuadPart = (LONGLONG)file->eoa;
1306 (void)SetFilePointer((HANDLE)filehandle,li.LowPart,&li.HighPart,FILE_BEGIN);
1307 if(SetEndOfFile((HANDLE)filehandle)==0)
1308 HGOTO_ERROR(H5E_IO, H5E_SEEKERROR, FAIL, "unable to extend file properly")
1309 #else /* H5_HAVE_WIN32_API */
1310 if (-1==HDftruncate(file->fd, (HDoff_t)file->eoa))
1311 HSYS_GOTO_ERROR(H5E_IO, H5E_SEEKERROR, FAIL, "unable to extend file properly")
1312 #endif /* H5_HAVE_WIN32_API */
1313
1314 /* Update the eof value */
1315 file->eof = file->eoa;
1316
1317 /* Reset last file I/O information */
1318 file->pos = HADDR_UNDEF;
1319 file->op = OP_UNKNOWN;
1320 }
1321 else if (file->fa.must_align){
1322 /*Even though eof is equal to eoa, file is still truncated because Direct I/O
1323 *write introduces some extra data for alignment.
1324 */
1325 if (-1==HDftruncate(file->fd, (HDoff_t)file->eof))
1326 HSYS_GOTO_ERROR(H5E_IO, H5E_SEEKERROR, FAIL, "unable to extend file properly")
1327 }
1328
1329 done:
1330 FUNC_LEAVE_NOAPI(ret_value)
1331 } /* end H5FD_direct_truncate() */
1332 #endif /* H5_HAVE_DIRECT */
1333
1334