1 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
2  * Copyright by The HDF Group.                                               *
3  * All rights reserved.                                                      *
4  *                                                                           *
5  * This file is part of HDF5.  The full HDF5 copyright notice, including     *
6  * terms governing use, modification, and redistribution, is contained in    *
7  * the COPYING file, which can be found at the root of the source code       *
8  * distribution tree, or in https://www.hdfgroup.org/licenses.               *
9  * If you do not have access to either file, you may request a copy from     *
10  * help@hdfgroup.org.                                                        *
11  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
12 
13 /*
14  * Purpose:     File callbacks for the native VOL connector
15  *
16  */
17 
18 #define H5F_FRIEND /* Suppress error about including H5Fpkg    */
19 
20 #include "H5private.h"   /* Generic Functions                        */
21 #include "H5ACprivate.h" /* Metadata cache                           */
22 #include "H5Cprivate.h"  /* Cache                                    */
23 #include "H5Eprivate.h"  /* Error handling                           */
24 #include "H5Fpkg.h"      /* Files                                    */
25 #include "H5Gprivate.h"  /* Groups                                   */
26 #include "H5Iprivate.h"  /* IDs                                      */
27 #include "H5MFprivate.h" /* File memory management                   */
28 #include "H5Pprivate.h"  /* Property lists                           */
29 #include "H5PBprivate.h" /* Page buffering                           */
30 #include "H5VLprivate.h" /* Virtual Object Layer                     */
31 
32 #include "H5VLnative_private.h" /* Native VOL connector                     */
33 
34 /*-------------------------------------------------------------------------
35  * Function:    H5VL__native_file_create
36  *
37  * Purpose:     Handles the file create callback
38  *
39  * Return:      Success:    file pointer
40  *              Failure:    NULL
41  *
42  *-------------------------------------------------------------------------
43  */
44 void *
H5VL__native_file_create(const char * name,unsigned flags,hid_t fcpl_id,hid_t fapl_id,hid_t H5_ATTR_UNUSED dxpl_id,void H5_ATTR_UNUSED ** req)45 H5VL__native_file_create(const char *name, unsigned flags, hid_t fcpl_id, hid_t fapl_id,
46                          hid_t H5_ATTR_UNUSED dxpl_id, void H5_ATTR_UNUSED **req)
47 {
48     H5F_t *new_file  = NULL;
49     void * ret_value = NULL;
50 
51     FUNC_ENTER_PACKAGE
52 
53     /* Adjust bit flags by turning on the creation bit and making sure that
54      * the EXCL or TRUNC bit is set.  All newly-created files are opened for
55      * reading and writing.
56      */
57     if (0 == (flags & (H5F_ACC_EXCL | H5F_ACC_TRUNC)))
58         flags |= H5F_ACC_EXCL; /* default */
59     flags |= H5F_ACC_RDWR | H5F_ACC_CREAT;
60 
61     /* Create the file */
62     if (NULL == (new_file = H5F_open(name, flags, fcpl_id, fapl_id)))
63         HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, NULL, "unable to create file")
64     new_file->id_exists = TRUE;
65 
66     ret_value = (void *)new_file;
67 
68 done:
69     if (NULL == ret_value && new_file)
70         if (H5F__close(new_file) < 0)
71             HDONE_ERROR(H5E_FILE, H5E_CANTCLOSEFILE, NULL, "problems closing file")
72 
73     FUNC_LEAVE_NOAPI(ret_value)
74 } /* end H5VL__native_file_create() */
75 
76 /*-------------------------------------------------------------------------
77  * Function:    H5VL__native_file_open
78  *
79  * Purpose:     Handles the file open callback
80  *
81  * Return:      Success:    file pointer
82  *              Failure:    NULL
83  *
84  *-------------------------------------------------------------------------
85  */
86 void *
H5VL__native_file_open(const char * name,unsigned flags,hid_t fapl_id,hid_t H5_ATTR_UNUSED dxpl_id,void H5_ATTR_UNUSED ** req)87 H5VL__native_file_open(const char *name, unsigned flags, hid_t fapl_id, hid_t H5_ATTR_UNUSED dxpl_id,
88                        void H5_ATTR_UNUSED **req)
89 {
90     H5F_t *new_file  = NULL;
91     void * ret_value = NULL;
92 
93     FUNC_ENTER_PACKAGE
94 
95     /* Open the file */
96     if (NULL == (new_file = H5F_open(name, flags, H5P_FILE_CREATE_DEFAULT, fapl_id)))
97         HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, NULL, "unable to open file")
98     new_file->id_exists = TRUE;
99 
100     ret_value = (void *)new_file;
101 
102 done:
103     if (NULL == ret_value && new_file && H5F_try_close(new_file, NULL) < 0)
104         HDONE_ERROR(H5E_FILE, H5E_CANTCLOSEFILE, NULL, "problems closing file")
105 
106     FUNC_LEAVE_NOAPI(ret_value)
107 } /* end H5VL__native_file_open() */
108 
109 /*-------------------------------------------------------------------------
110  * Function:    H5VL__native_file_get
111  *
112  * Purpose:     Handles the file get callback
113  *
114  * Return:      SUCCEED/FAIL
115  *
116  *-------------------------------------------------------------------------
117  */
118 herr_t
H5VL__native_file_get(void * obj,H5VL_file_get_t get_type,hid_t H5_ATTR_UNUSED dxpl_id,void H5_ATTR_UNUSED ** req,va_list arguments)119 H5VL__native_file_get(void *obj, H5VL_file_get_t get_type, hid_t H5_ATTR_UNUSED dxpl_id,
120                       void H5_ATTR_UNUSED **req, va_list arguments)
121 {
122     H5F_t *f         = NULL;    /* File struct */
123     herr_t ret_value = SUCCEED; /* Return value */
124 
125     FUNC_ENTER_PACKAGE
126 
127     switch (get_type) {
128         /* "get container info" */
129         case H5VL_FILE_GET_CONT_INFO: {
130             H5VL_file_cont_info_t *info = HDva_arg(arguments, H5VL_file_cont_info_t *);
131 
132             /* Retrieve the file's container info */
133             if (H5F__get_cont_info((H5F_t *)obj, info) < 0)
134                 HGOTO_ERROR(H5E_FILE, H5E_CANTGET, FAIL, "can't get file container info")
135 
136             break;
137         }
138 
139         /* H5Fget_access_plist */
140         case H5VL_FILE_GET_FAPL: {
141             H5P_genplist_t *new_plist; /* New property list */
142             hid_t *         plist_id = HDva_arg(arguments, hid_t *);
143 
144             f = (H5F_t *)obj;
145 
146             /* Retrieve the file's access property list */
147             if ((*plist_id = H5F_get_access_plist(f, TRUE)) < 0)
148                 HGOTO_ERROR(H5E_FILE, H5E_CANTGET, FAIL, "can't get file access property list")
149 
150             if (NULL == (new_plist = (H5P_genplist_t *)H5I_object(*plist_id)))
151                 HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a property list")
152             break;
153         }
154 
155         /* H5Fget_create_plist */
156         case H5VL_FILE_GET_FCPL: {
157             H5P_genplist_t *plist; /* Property list */
158             hid_t *         plist_id = HDva_arg(arguments, hid_t *);
159 
160             f = (H5F_t *)obj;
161             if (NULL == (plist = (H5P_genplist_t *)H5I_object(f->shared->fcpl_id)))
162                 HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a property list")
163 
164             /* Create the property list object to return */
165             if ((*plist_id = H5P_copy_plist(plist, TRUE)) < 0)
166                 HGOTO_ERROR(H5E_PLIST, H5E_CANTINIT, FAIL, "unable to copy file creation properties")
167 
168             break;
169         }
170 
171         /* H5Fget_intent */
172         case H5VL_FILE_GET_INTENT: {
173             unsigned *intent_flags = HDva_arg(arguments, unsigned *);
174 
175             f = (H5F_t *)obj;
176 
177             /* HDF5 uses some flags internally that users don't know about.
178              * Simplify things for them so that they only get either H5F_ACC_RDWR
179              * or H5F_ACC_RDONLY and any SWMR flags.
180              */
181             if (H5F_INTENT(f) & H5F_ACC_RDWR) {
182                 *intent_flags = H5F_ACC_RDWR;
183 
184                 /* Check for SWMR write access on the file */
185                 if (H5F_INTENT(f) & H5F_ACC_SWMR_WRITE)
186                     *intent_flags |= H5F_ACC_SWMR_WRITE;
187             } /* end if */
188             else {
189                 *intent_flags = H5F_ACC_RDONLY;
190 
191                 /* Check for SWMR read access on the file */
192                 if (H5F_INTENT(f) & H5F_ACC_SWMR_READ)
193                     *intent_flags |= H5F_ACC_SWMR_READ;
194             } /* end else */
195 
196             break;
197         }
198 
199         /* H5Fget_fileno */
200         case H5VL_FILE_GET_FILENO: {
201             unsigned long *fno       = HDva_arg(arguments, unsigned long *);
202             unsigned long  my_fileno = 0;
203 
204             f = (H5F_t *)obj;
205             H5F_GET_FILENO(f, my_fileno);
206             *fno = my_fileno; /* sigh */
207 
208             break;
209         }
210 
211         /* H5Fget_name */
212         case H5VL_FILE_GET_NAME: {
213             H5I_type_t type = (H5I_type_t)HDva_arg(arguments, int); /* enum work-around */
214             size_t     size = HDva_arg(arguments, size_t);
215             char *     name = HDva_arg(arguments, char *);
216             ssize_t *  ret  = HDva_arg(arguments, ssize_t *);
217             size_t     len;
218 
219             if (H5VL_native_get_file_struct(obj, type, &f) < 0)
220                 HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file or file object")
221 
222             len = HDstrlen(H5F_OPEN_NAME(f));
223 
224             if (name) {
225                 HDstrncpy(name, H5F_OPEN_NAME(f), MIN(len + 1, size));
226                 if (len >= size)
227                     name[size - 1] = '\0';
228             } /* end if */
229 
230             /* Set the return value for the API call */
231             *ret = (ssize_t)len;
232             break;
233         }
234 
235         /* H5Fget_obj_count */
236         case H5VL_FILE_GET_OBJ_COUNT: {
237             unsigned types     = HDva_arg(arguments, unsigned);
238             ssize_t *ret       = HDva_arg(arguments, ssize_t *);
239             size_t   obj_count = 0; /* Number of opened objects */
240 
241             f = (H5F_t *)obj;
242             /* Perform the query */
243             if (H5F_get_obj_count(f, types, TRUE, &obj_count) < 0)
244                 HGOTO_ERROR(H5E_FILE, H5E_BADITER, FAIL, "H5F_get_obj_count failed")
245 
246             /* Set the return value */
247             *ret = (ssize_t)obj_count;
248             break;
249         }
250 
251         /* H5Fget_obj_ids */
252         case H5VL_FILE_GET_OBJ_IDS: {
253             unsigned types     = HDva_arg(arguments, unsigned);
254             size_t   max_objs  = HDva_arg(arguments, size_t);
255             hid_t *  oid_list  = HDva_arg(arguments, hid_t *);
256             ssize_t *ret       = HDva_arg(arguments, ssize_t *);
257             size_t   obj_count = 0; /* Number of opened objects */
258 
259             f = (H5F_t *)obj;
260             /* Perform the query */
261             if (H5F_get_obj_ids(f, types, max_objs, oid_list, TRUE, &obj_count) < 0)
262                 HGOTO_ERROR(H5E_FILE, H5E_BADITER, FAIL, "H5F_get_obj_ids failed")
263 
264             /* Set the return value */
265             *ret = (ssize_t)obj_count;
266             break;
267         }
268 
269         default:
270             HGOTO_ERROR(H5E_VOL, H5E_CANTGET, FAIL, "can't get this type of information")
271     } /* end switch */
272 
273 done:
274     FUNC_LEAVE_NOAPI(ret_value)
275 } /* end H5VL__native_file_get() */
276 
277 /*-------------------------------------------------------------------------
278  * Function:    H5VL__native_file_specific
279  *
280  * Purpose:     Handles the file specific callback
281  *
282  * Return:      SUCCEED/FAIL
283  *
284  *-------------------------------------------------------------------------
285  */
286 herr_t
H5VL__native_file_specific(void * obj,H5VL_file_specific_t specific_type,hid_t H5_ATTR_UNUSED dxpl_id,void H5_ATTR_UNUSED ** req,va_list arguments)287 H5VL__native_file_specific(void *obj, H5VL_file_specific_t specific_type, hid_t H5_ATTR_UNUSED dxpl_id,
288                            void H5_ATTR_UNUSED **req, va_list arguments)
289 {
290     herr_t ret_value = SUCCEED; /* Return value */
291 
292     FUNC_ENTER_PACKAGE
293 
294     switch (specific_type) {
295         /* H5Fflush */
296         case H5VL_FILE_FLUSH: {
297             H5I_type_t  type  = (H5I_type_t)HDva_arg(arguments, int);  /* enum work-around */
298             H5F_scope_t scope = (H5F_scope_t)HDva_arg(arguments, int); /* enum work-around */
299             H5F_t *     f     = NULL;                                  /* File to flush */
300 
301             /* Get the file for the object */
302             if (H5VL_native_get_file_struct(obj, type, &f) < 0)
303                 HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file or file object")
304 
305             /* Nothing to do if the file is read only. This determination is
306              * made at the shared open(2) flags level, implying that opening a
307              * file twice, once for read-only and once for read-write, and then
308              * calling H5Fflush() with the read-only handle, still causes data
309              * to be flushed.
310              */
311             if (H5F_ACC_RDWR & H5F_INTENT(f)) {
312                 /* Flush other files, depending on scope */
313                 if (H5F_SCOPE_GLOBAL == scope) {
314                     /* Call the flush routine for mounted file hierarchies */
315                     if (H5F_flush_mounts(f) < 0)
316                         HGOTO_ERROR(H5E_FILE, H5E_CANTFLUSH, FAIL, "unable to flush mounted file hierarchy")
317                 } /* end if */
318                 else {
319                     /* Call the flush routine, for this file */
320                     if (H5F__flush(f) < 0)
321                         HGOTO_ERROR(H5E_FILE, H5E_CANTFLUSH, FAIL,
322                                     "unable to flush file's cached information")
323                 } /* end else */
324             }     /* end if */
325             break;
326         }
327 
328         /* H5Freopen */
329         case H5VL_FILE_REOPEN: {
330             void **ret      = HDva_arg(arguments, void **);
331             H5F_t *new_file = NULL;
332 
333             /* Reopen the file through the VOL connector */
334             if (NULL == (new_file = H5F__reopen((H5F_t *)obj)))
335                 HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, FAIL, "unable to reopen file")
336             new_file->id_exists = TRUE;
337 
338             *ret = (void *)new_file;
339             break;
340         }
341 
342         /* H5Fmount */
343         case H5VL_FILE_MOUNT: {
344             H5I_type_t  type    = (H5I_type_t)HDva_arg(arguments, int); /* enum work-around */
345             const char *name    = HDva_arg(arguments, const char *);
346             H5F_t *     child   = HDva_arg(arguments, H5F_t *);
347             hid_t       fmpl_id = HDva_arg(arguments, hid_t);
348             H5G_loc_t   loc;
349 
350             if (H5G_loc_real(obj, type, &loc) < 0)
351                 HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file or file object")
352 
353             /* Do the mount */
354             if (H5F__mount(&loc, name, child, fmpl_id) < 0)
355                 HGOTO_ERROR(H5E_FILE, H5E_MOUNT, FAIL, "unable to mount file")
356 
357             break;
358         }
359 
360         /* H5Funmount */
361         case H5VL_FILE_UNMOUNT: {
362             H5I_type_t  type = (H5I_type_t)HDva_arg(arguments, int); /* enum work-around */
363             const char *name = HDva_arg(arguments, const char *);
364             H5G_loc_t   loc;
365 
366             if (H5G_loc_real(obj, type, &loc) < 0)
367                 HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file or file object")
368 
369             /* Unmount */
370             if (H5F__unmount(&loc, name) < 0)
371                 HGOTO_ERROR(H5E_FILE, H5E_MOUNT, FAIL, "unable to unmount file")
372 
373             break;
374         }
375 
376         /* H5Fis_accessible */
377         case H5VL_FILE_IS_ACCESSIBLE: {
378             hid_t       fapl_id = HDva_arg(arguments, hid_t);
379             const char *name    = HDva_arg(arguments, const char *);
380             htri_t *    result  = HDva_arg(arguments, htri_t *);
381 
382             /* Call private routine */
383             if ((*result = H5F__is_hdf5(name, fapl_id)) < 0)
384                 HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, FAIL, "error in HDF5 file check")
385             break;
386         }
387 
388         /* H5Fdelete */
389         case H5VL_FILE_DELETE: {
390             HGOTO_ERROR(H5E_FILE, H5E_UNSUPPORTED, FAIL,
391                         "H5Fdelete() is currently not supported in the native VOL connector")
392             break;
393         }
394 
395         /* Check if two files are the same */
396         case H5VL_FILE_IS_EQUAL: {
397             H5F_t *  file2    = (H5F_t *)HDva_arg(arguments, void *);
398             hbool_t *is_equal = HDva_arg(arguments, hbool_t *);
399 
400             if (!obj || !file2)
401                 *is_equal = FALSE;
402             else
403                 *is_equal = (((H5F_t *)obj)->shared == file2->shared);
404             break;
405         }
406 
407         default:
408             HGOTO_ERROR(H5E_VOL, H5E_UNSUPPORTED, FAIL, "invalid specific operation")
409     } /* end switch */
410 
411 done:
412     FUNC_LEAVE_NOAPI(ret_value)
413 } /* end H5VL__native_file_specific() */
414 
415 /*-------------------------------------------------------------------------
416  * Function:    H5VL__native_file_optional
417  *
418  * Purpose:     Handles the file optional callback
419  *
420  * Return:      SUCCEED/FAIL
421  *
422  *-------------------------------------------------------------------------
423  */
424 herr_t
H5VL__native_file_optional(void * obj,H5VL_file_optional_t optional_type,hid_t H5_ATTR_UNUSED dxpl_id,void H5_ATTR_UNUSED ** req,va_list arguments)425 H5VL__native_file_optional(void *obj, H5VL_file_optional_t optional_type, hid_t H5_ATTR_UNUSED dxpl_id,
426                            void H5_ATTR_UNUSED **req, va_list arguments)
427 {
428     H5F_t *f         = NULL;    /* File */
429     herr_t ret_value = SUCCEED; /* Return value */
430 
431     FUNC_ENTER_PACKAGE
432 
433     f = (H5F_t *)obj;
434     switch (optional_type) {
435         /* H5Fget_filesize */
436         case H5VL_NATIVE_FILE_GET_SIZE: {
437             haddr_t  max_eof_eoa; /* Maximum of the EOA & EOF */
438             haddr_t  base_addr;   /* Base address for the file */
439             hsize_t *size = HDva_arg(arguments, hsize_t *);
440 
441             /* Go get the actual file size */
442             if (H5F__get_max_eof_eoa(f, &max_eof_eoa) < 0)
443                 HGOTO_ERROR(H5E_FILE, H5E_CANTGET, FAIL, "file can't get max eof/eoa ")
444 
445             base_addr = H5FD_get_base_addr(f->shared->lf);
446 
447             if (size)
448                 *size = (hsize_t)(max_eof_eoa +
449                                   base_addr); /* Convert relative base address for file to absolute address */
450 
451             break;
452         }
453 
454         /* H5Fget_file_image */
455         case H5VL_NATIVE_FILE_GET_FILE_IMAGE: {
456             void *   buf_ptr = HDva_arg(arguments, void *);
457             ssize_t *ret     = HDva_arg(arguments, ssize_t *);
458             size_t   buf_len = HDva_arg(arguments, size_t);
459 
460             /* Do the actual work */
461             if ((*ret = H5F__get_file_image(f, buf_ptr, buf_len)) < 0)
462                 HGOTO_ERROR(H5E_FILE, H5E_CANTGET, FAIL, "get file image failed")
463             break;
464         }
465 
466         /* H5Fget_freespace */
467         case H5VL_NATIVE_FILE_GET_FREE_SPACE: {
468             hsize_t   tot_space; /* Amount of free space in the file */
469             hssize_t *ret = HDva_arg(arguments, hssize_t *);
470 
471             /* Go get the actual amount of free space in the file */
472             if (H5MF_get_freespace(f, &tot_space, NULL) < 0)
473                 HGOTO_ERROR(H5E_FILE, H5E_CANTGET, FAIL, "unable to check free space for file")
474             *ret = (hssize_t)tot_space;
475             break;
476         }
477 
478         /* H5Fget_free_sections */
479         case H5VL_NATIVE_FILE_GET_FREE_SECTIONS: {
480             H5F_sect_info_t *sect_info = HDva_arg(arguments, H5F_sect_info_t *);
481             ssize_t *        ret       = HDva_arg(arguments, ssize_t *);
482             H5F_mem_t        type      = (H5F_mem_t)HDva_arg(arguments, int); /* enum work-around */
483             size_t           nsects    = HDva_arg(arguments, size_t);
484 
485             /* Go get the free-space section information in the file */
486             if ((*ret = H5MF_get_free_sections(f, type, nsects, sect_info)) < 0)
487                 HGOTO_ERROR(H5E_FILE, H5E_CANTGET, FAIL, "unable to check free space for file")
488             break;
489         }
490 
491         /* H5Fget_info1/2 */
492         case H5VL_NATIVE_FILE_GET_INFO: {
493             H5I_type_t   type  = (H5I_type_t)HDva_arg(arguments, int); /* enum work-around */
494             H5F_info2_t *finfo = HDva_arg(arguments, H5F_info2_t *);
495 
496             /* Get the file struct. This call is careful to not return the file pointer
497              * for the top file in a mount hierarchy.
498              */
499             if (H5VL_native_get_file_struct(obj, type, &f) < 0)
500                 HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "could not get a file struct")
501 
502             /* Get the file info */
503             if (H5F__get_info(f, finfo) < 0)
504                 HGOTO_ERROR(H5E_FILE, H5E_CANTGET, FAIL, "unable to retrieve file info")
505 
506             break;
507         }
508 
509         /* H5Fget_mdc_config */
510         case H5VL_NATIVE_FILE_GET_MDC_CONF: {
511             H5AC_cache_config_t *config_ptr = HDva_arg(arguments, H5AC_cache_config_t *);
512 
513             /* Go get the resize configuration */
514             if (H5AC_get_cache_auto_resize_config(f->shared->cache, config_ptr) < 0)
515                 HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "H5AC_get_cache_auto_resize_config() failed.")
516             break;
517         }
518 
519         /* H5Fget_mdc_hit_rate */
520         case H5VL_NATIVE_FILE_GET_MDC_HR: {
521             double *hit_rate_ptr = HDva_arg(arguments, double *);
522 
523             /* Go get the current hit rate */
524             if (H5AC_get_cache_hit_rate(f->shared->cache, hit_rate_ptr) < 0)
525                 HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "H5AC_get_cache_hit_rate() failed.")
526             break;
527         }
528 
529         /* H5Fget_mdc_size */
530         case H5VL_NATIVE_FILE_GET_MDC_SIZE: {
531             size_t * max_size_ptr        = HDva_arg(arguments, size_t *);
532             size_t * min_clean_size_ptr  = HDva_arg(arguments, size_t *);
533             size_t * cur_size_ptr        = HDva_arg(arguments, size_t *);
534             int *    cur_num_entries_ptr = HDva_arg(arguments, int *);
535             uint32_t cur_num_entries;
536 
537             /* Go get the size data */
538             if (H5AC_get_cache_size(f->shared->cache, max_size_ptr, min_clean_size_ptr, cur_size_ptr,
539                                     &cur_num_entries) < 0)
540                 HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "H5AC_get_cache_size() failed.")
541 
542             if (cur_num_entries_ptr != NULL)
543                 *cur_num_entries_ptr = (int)cur_num_entries;
544             break;
545         }
546 
547         /* H5Fget_vfd_handle */
548         case H5VL_NATIVE_FILE_GET_VFD_HANDLE: {
549             void **file_handle = HDva_arg(arguments, void **);
550             hid_t  fapl_id     = HDva_arg(arguments, hid_t);
551 
552             /* Retrieve the VFD handle for the file */
553             if (H5F_get_vfd_handle(f, fapl_id, file_handle) < 0)
554                 HGOTO_ERROR(H5E_FILE, H5E_CANTGET, FAIL, "can't retrieve VFD handle")
555             break;
556         }
557 
558         /* H5Fclear_elink_file_cache */
559         case H5VL_NATIVE_FILE_CLEAR_ELINK_CACHE: {
560             /* Release the EFC */
561             if (f->shared->efc)
562                 if (H5F__efc_release(f->shared->efc) < 0)
563                     HGOTO_ERROR(H5E_FILE, H5E_CANTRELEASE, FAIL, "can't release external file cache")
564             break;
565         }
566 
567         /* H5Freset_mdc_hit_rate_stats */
568         case H5VL_NATIVE_FILE_RESET_MDC_HIT_RATE: {
569             /* Reset the hit rate statistic */
570             if (H5AC_reset_cache_hit_rate_stats(f->shared->cache) < 0)
571                 HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "can't reset cache hit rate")
572             break;
573         }
574 
575         /* H5Fset_mdc_config */
576         case H5VL_NATIVE_FILE_SET_MDC_CONFIG: {
577             H5AC_cache_config_t *config_ptr = HDva_arg(arguments, H5AC_cache_config_t *);
578 
579             /* set the resize configuration  */
580             if (H5AC_set_cache_auto_resize_config(f->shared->cache, config_ptr) < 0)
581                 HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "H5AC_set_cache_auto_resize_config() failed")
582             break;
583         }
584 
585         /* H5Fget_metadata_read_retry_info */
586         case H5VL_NATIVE_FILE_GET_METADATA_READ_RETRY_INFO: {
587             H5F_retry_info_t *info = HDva_arg(arguments, H5F_retry_info_t *);
588 
589             if (H5F_get_metadata_read_retry_info(f, info) < 0)
590                 HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "can't get metadata read retry info")
591 
592             break;
593         }
594 
595         /* H5Fstart_swmr_write */
596         case H5VL_NATIVE_FILE_START_SWMR_WRITE: {
597             if (H5F__start_swmr_write(f) < 0)
598                 HGOTO_ERROR(H5E_CACHE, H5E_SYSTEM, FAIL, "can't start SWMR write")
599 
600             break;
601         }
602 
603         /* H5Fstart_mdc_logging */
604         case H5VL_NATIVE_FILE_START_MDC_LOGGING: {
605             /* Call mdc logging function */
606             if (H5C_start_logging(f->shared->cache) < 0)
607                 HGOTO_ERROR(H5E_FILE, H5E_LOGGING, FAIL, "unable to start mdc logging")
608 
609             break;
610         }
611 
612         /* H5Fstop_mdc_logging */
613         case H5VL_NATIVE_FILE_STOP_MDC_LOGGING: {
614             /* Call mdc logging function */
615             if (H5C_stop_logging(f->shared->cache) < 0)
616                 HGOTO_ERROR(H5E_FILE, H5E_LOGGING, FAIL, "unable to stop mdc logging")
617 
618             break;
619         }
620 
621         /* H5Fget_mdc_logging_status */
622         case H5VL_NATIVE_FILE_GET_MDC_LOGGING_STATUS: {
623             hbool_t *is_enabled           = HDva_arg(arguments, hbool_t *);
624             hbool_t *is_currently_logging = HDva_arg(arguments, hbool_t *);
625 
626             /* Call mdc logging function */
627             if (H5C_get_logging_status(f->shared->cache, is_enabled, is_currently_logging) < 0)
628                 HGOTO_ERROR(H5E_FILE, H5E_LOGGING, FAIL, "unable to get logging status")
629 
630             break;
631         }
632 
633         /* H5Fformat_convert */
634         case H5VL_NATIVE_FILE_FORMAT_CONVERT: {
635             /* Convert the format */
636             if (H5F__format_convert(f) < 0)
637                 HGOTO_ERROR(H5E_FILE, H5E_CANTCONVERT, FAIL, "can't convert file format")
638 
639             break;
640         }
641 
642         /* H5Freset_page_buffering_stats */
643         case H5VL_NATIVE_FILE_RESET_PAGE_BUFFERING_STATS: {
644             /* Sanity check */
645             if (NULL == f->shared->page_buf)
646                 HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "page buffering not enabled on file")
647 
648             /* Reset the statistics */
649             if (H5PB_reset_stats(f->shared->page_buf) < 0)
650                 HGOTO_ERROR(H5E_FILE, H5E_CANTGET, FAIL, "can't reset stats for page buffering")
651 
652             break;
653         }
654 
655         /* H5Fget_page_buffering_stats */
656         case H5VL_NATIVE_FILE_GET_PAGE_BUFFERING_STATS: {
657             unsigned *accesses  = HDva_arg(arguments, unsigned *);
658             unsigned *hits      = HDva_arg(arguments, unsigned *);
659             unsigned *misses    = HDva_arg(arguments, unsigned *);
660             unsigned *evictions = HDva_arg(arguments, unsigned *);
661             unsigned *bypasses  = HDva_arg(arguments, unsigned *);
662 
663             /* Sanity check */
664             if (NULL == f->shared->page_buf)
665                 HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "page buffering not enabled on file")
666 
667             /* Get the statistics */
668             if (H5PB_get_stats(f->shared->page_buf, accesses, hits, misses, evictions, bypasses) < 0)
669                 HGOTO_ERROR(H5E_FILE, H5E_CANTGET, FAIL, "can't retrieve stats for page buffering")
670 
671             break;
672         }
673 
674         /* H5Fget_mdc_image_info */
675         case H5VL_NATIVE_FILE_GET_MDC_IMAGE_INFO: {
676             haddr_t *image_addr = HDva_arg(arguments, haddr_t *);
677             hsize_t *image_len  = HDva_arg(arguments, hsize_t *);
678 
679             /* Go get the address and size of the cache image */
680             if (H5AC_get_mdc_image_info(f->shared->cache, image_addr, image_len) < 0)
681                 HGOTO_ERROR(H5E_FILE, H5E_CANTGET, FAIL, "can't retrieve cache image info")
682 
683             break;
684         }
685 
686         /* H5Fget_eoa */
687         case H5VL_NATIVE_FILE_GET_EOA: {
688             haddr_t *eoa = HDva_arg(arguments, haddr_t *);
689             haddr_t  rel_eoa; /* Relative address of EOA */
690 
691             /* Sanity check */
692             HDassert(eoa);
693 
694             /* This routine will work only for drivers with this feature enabled.*/
695             /* We might introduce a new feature flag in the future */
696             if (!H5F_HAS_FEATURE(f, H5FD_FEAT_SUPPORTS_SWMR_IO))
697                 HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, FAIL,
698                             "must use a SWMR-compatible VFD for this public routine")
699 
700             /* The real work */
701             if (HADDR_UNDEF == (rel_eoa = H5F_get_eoa(f, H5FD_MEM_DEFAULT)))
702                 HGOTO_ERROR(H5E_FILE, H5E_CANTGET, FAIL, "get_eoa request failed")
703 
704             /* Set return value */
705             /* (Note compensating for base address subtraction in internal routine) */
706             *eoa = rel_eoa + H5F_get_base_addr(f);
707 
708             break;
709         }
710 
711         /* H5Fincrement_filesize */
712         case H5VL_NATIVE_FILE_INCR_FILESIZE: {
713             hsize_t increment = HDva_arg(arguments, hsize_t);
714             haddr_t max_eof_eoa; /* Maximum of the relative EOA & EOF */
715 
716             /* This public routine will work only for drivers with this feature enabled.*/
717             /* We might introduce a new feature flag in the future */
718             if (!H5F_HAS_FEATURE(f, H5FD_FEAT_SUPPORTS_SWMR_IO))
719                 HGOTO_ERROR(H5E_FILE, H5E_BADVALUE, FAIL,
720                             "must use a SWMR-compatible VFD for this public routine")
721 
722             /* Get the maximum of EOA and EOF */
723             if (H5F__get_max_eof_eoa(f, &max_eof_eoa) < 0)
724                 HGOTO_ERROR(H5E_FILE, H5E_CANTGET, FAIL, "file can't get max eof/eoa ")
725 
726             /* Set EOA to the maximum value + increment */
727             if (H5F__set_eoa(f, H5FD_MEM_DEFAULT, max_eof_eoa + increment) < 0)
728                 HGOTO_ERROR(H5E_FILE, H5E_CANTSET, FAIL, "driver set_eoa request failed")
729 
730             break;
731         }
732 
733         /* H5Fset_latest_format, H5Fset_libver_bounds */
734         case H5VL_NATIVE_FILE_SET_LIBVER_BOUNDS: {
735             H5F_libver_t low  = (H5F_libver_t)HDva_arg(arguments, int); /* enum work-around */
736             H5F_libver_t high = (H5F_libver_t)HDva_arg(arguments, int); /* enum work-around */
737 
738             /* Call internal set_libver_bounds function */
739             if (H5F__set_libver_bounds(f, low, high) < 0)
740                 HGOTO_ERROR(H5E_FILE, H5E_CANTSET, FAIL, "cannot set low/high bounds")
741 
742             break;
743         }
744 
745         /* H5Fget_dset_no_attrs_hint */
746         case H5VL_NATIVE_FILE_GET_MIN_DSET_OHDR_FLAG: {
747             hbool_t *minimize = HDva_arg(arguments, hbool_t *);
748             *minimize         = H5F_GET_MIN_DSET_OHDR(f);
749             break;
750         }
751 
752         /* H5Fset_dset_no_attrs_hint */
753         case H5VL_NATIVE_FILE_SET_MIN_DSET_OHDR_FLAG: {
754             int minimize = HDva_arg(arguments, int);
755             if (H5F_set_min_dset_ohdr(f, (hbool_t)minimize) < 0)
756                 HGOTO_ERROR(H5E_FILE, H5E_CANTSET, FAIL,
757                             "cannot set file's dataset object header minimization flag")
758             break;
759         }
760 
761 #ifdef H5_HAVE_PARALLEL
762         /* H5Fget_mpi_atomicity */
763         case H5VL_NATIVE_FILE_GET_MPI_ATOMICITY: {
764             hbool_t *flag = (hbool_t *)HDva_arg(arguments, hbool_t *);
765             if (H5F_get_mpi_atomicity(f, flag) < 0)
766                 HGOTO_ERROR(H5E_FILE, H5E_CANTGET, FAIL, "cannot get MPI atomicity");
767             break;
768         }
769 
770         /* H5Fset_mpi_atomicity */
771         case H5VL_NATIVE_FILE_SET_MPI_ATOMICITY: {
772             hbool_t flag = (hbool_t)HDva_arg(arguments, int);
773             if (H5F_set_mpi_atomicity(f, flag) < 0)
774                 HGOTO_ERROR(H5E_FILE, H5E_CANTSET, FAIL, "cannot set MPI atomicity");
775             break;
776         }
777 #endif /* H5_HAVE_PARALLEL */
778 
779         /* Finalize H5Fopen */
780         case H5VL_NATIVE_FILE_POST_OPEN: {
781             /* Call package routine */
782             if (H5F__post_open((H5F_t *)obj) < 0)
783                 HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, FAIL, "can't finish opening file")
784             break;
785         }
786 
787         default:
788             HGOTO_ERROR(H5E_VOL, H5E_UNSUPPORTED, FAIL, "invalid optional operation")
789     } /* end switch */
790 
791 done:
792     FUNC_LEAVE_NOAPI(ret_value)
793 } /* end H5VL__native_file_optional() */
794 
795 /*-------------------------------------------------------------------------
796  * Function:    H5VL__native_file_close
797  *
798  * Purpose:     Handles the file close callback
799  *
800  * Return:      Success:    SUCCEED
801  *              Failure:    FAIL (file will not be closed)
802  *
803  *-------------------------------------------------------------------------
804  */
805 herr_t
H5VL__native_file_close(void * file,hid_t H5_ATTR_UNUSED dxpl_id,void H5_ATTR_UNUSED ** req)806 H5VL__native_file_close(void *file, hid_t H5_ATTR_UNUSED dxpl_id, void H5_ATTR_UNUSED **req)
807 {
808     int    nref;
809     H5F_t *f         = (H5F_t *)file;
810     hid_t  file_id   = H5I_INVALID_HID;
811     herr_t ret_value = SUCCEED; /* Return value */
812 
813     FUNC_ENTER_PACKAGE
814 
815     /* This routine should only be called when a file ID's ref count drops to zero */
816     HDassert(H5F_ID_EXISTS(f));
817 
818     /* Flush file if this is the last reference to this id and we have write
819      * intent, unless it will be flushed by the "shared" file being closed.
820      * This is only necessary to replicate previous behaviour, and could be
821      * disabled by an option/property to improve performance.
822      */
823     if ((H5F_NREFS(f) > 1) && (H5F_INTENT(f) & H5F_ACC_RDWR)) {
824         /* Get the file ID corresponding to the H5F_t struct */
825         if (H5I_find_id(f, H5I_FILE, &file_id) < 0 || H5I_INVALID_HID == file_id)
826             HGOTO_ERROR(H5E_ATOM, H5E_CANTGET, FAIL, "invalid atom")
827 
828         /* Get the number of references outstanding for this file ID */
829         if ((nref = H5I_get_ref(file_id, FALSE)) < 0)
830             HGOTO_ERROR(H5E_ATOM, H5E_CANTGET, FAIL, "can't get ID ref count")
831         if (nref == 1)
832             if (H5F__flush(f) < 0)
833                 HGOTO_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "unable to flush cache")
834     } /* end if */
835 
836     /* Close the file */
837     if (H5F__close(f) < 0)
838         HGOTO_ERROR(H5E_FILE, H5E_CANTDEC, FAIL, "can't close file")
839 
840 done:
841     FUNC_LEAVE_NOAPI(ret_value)
842 } /* end H5VL__native_file_close() */
843