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:     The native VOL connector where access is to a single HDF5 file
15  *              using HDF5 VFDs.
16  */
17 
18 /****************/
19 /* Module Setup */
20 /****************/
21 
22 #define H5VL_FRIEND /* Suppress error about including H5VLpkg   */
23 
24 /***********/
25 /* Headers */
26 /***********/
27 
28 #include "H5private.h"  /* Generic Functions                        */
29 #include "H5Aprivate.h" /* Attributes                               */
30 #include "H5Dprivate.h" /* Datasets                                 */
31 #include "H5Eprivate.h" /* Error handling                           */
32 #include "H5Fprivate.h" /* Files                                    */
33 #include "H5Gprivate.h" /* Groups                                   */
34 #include "H5Iprivate.h" /* IDs                                      */
35 #include "H5Oprivate.h" /* Object headers                           */
36 #include "H5Pprivate.h" /* Property lists                           */
37 #include "H5Tprivate.h" /* Datatypes                                */
38 #include "H5VLpkg.h"    /* Virtual Object Layer                     */
39 
40 #include "H5VLnative_private.h" /* Native VOL connector                     */
41 
42 /* The VOL connector identification number */
43 static hid_t H5VL_NATIVE_ID_g = H5I_INVALID_HID;
44 
45 /* Prototypes */
46 static herr_t H5VL__native_term(void);
47 
48 /* Native VOL connector class struct */
49 static const H5VL_class_t H5VL_native_cls_g = {
50     H5VL_VERSION,      /* VOL class struct version */
51     H5VL_NATIVE_VALUE, /* value        */
52     H5VL_NATIVE_NAME,  /* name         */
53     0,                 /* capability flags */
54     NULL,              /* initialize   */
55     H5VL__native_term, /* terminate    */
56     {
57         /* info_cls */
58         (size_t)0, /* info size    */
59         NULL,      /* info copy    */
60         NULL,      /* info compare */
61         NULL,      /* info free    */
62         NULL,      /* info to str  */
63         NULL       /* str to info  */
64     },
65     {
66         /* wrap_cls */
67         NULL, /* get_object   */
68         NULL, /* get_wrap_ctx */
69         NULL, /* wrap_object  */
70         NULL, /* unwrap_object */
71         NULL  /* free_wrap_ctx */
72     },
73     {
74         /* attribute_cls */
75         H5VL__native_attr_create,   /* create       */
76         H5VL__native_attr_open,     /* open         */
77         H5VL__native_attr_read,     /* read         */
78         H5VL__native_attr_write,    /* write        */
79         H5VL__native_attr_get,      /* get          */
80         H5VL__native_attr_specific, /* specific     */
81         H5VL__native_attr_optional, /* optional     */
82         H5VL__native_attr_close     /* close        */
83     },
84     {
85         /* dataset_cls */
86         H5VL__native_dataset_create,   /* create       */
87         H5VL__native_dataset_open,     /* open         */
88         H5VL__native_dataset_read,     /* read         */
89         H5VL__native_dataset_write,    /* write        */
90         H5VL__native_dataset_get,      /* get          */
91         H5VL__native_dataset_specific, /* specific     */
92         H5VL__native_dataset_optional, /* optional     */
93         H5VL__native_dataset_close     /* close        */
94     },
95     {
96         /* datatype_cls */
97         H5VL__native_datatype_commit,   /* commit       */
98         H5VL__native_datatype_open,     /* open         */
99         H5VL__native_datatype_get,      /* get          */
100         H5VL__native_datatype_specific, /* specific     */
101         NULL,                           /* optional     */
102         H5VL__native_datatype_close     /* close        */
103     },
104     {
105         /* file_cls */
106         H5VL__native_file_create,   /* create       */
107         H5VL__native_file_open,     /* open         */
108         H5VL__native_file_get,      /* get          */
109         H5VL__native_file_specific, /* specific     */
110         H5VL__native_file_optional, /* optional     */
111         H5VL__native_file_close     /* close        */
112     },
113     {
114         /* group_cls */
115         H5VL__native_group_create,   /* create       */
116         H5VL__native_group_open,     /* open         */
117         H5VL__native_group_get,      /* get          */
118         H5VL__native_group_specific, /* specific     */
119         H5VL__native_group_optional, /* optional     */
120         H5VL__native_group_close     /* close        */
121     },
122     {
123         /* link_cls */
124         H5VL__native_link_create,   /* create       */
125         H5VL__native_link_copy,     /* copy         */
126         H5VL__native_link_move,     /* move         */
127         H5VL__native_link_get,      /* get          */
128         H5VL__native_link_specific, /* specific     */
129         NULL                        /* optional     */
130     },
131     {
132         /* object_cls */
133         H5VL__native_object_open,     /* open         */
134         H5VL__native_object_copy,     /* copy         */
135         H5VL__native_object_get,      /* get          */
136         H5VL__native_object_specific, /* specific     */
137         H5VL__native_object_optional  /* optional     */
138     },
139     {
140         /* introspect_cls */
141         H5VL__native_introspect_get_conn_cls, /* get_conn_cls */
142         H5VL__native_introspect_opt_query,    /* opt_query    */
143     },
144     {
145         /* request_cls */
146         NULL, /* wait         */
147         NULL, /* notify       */
148         NULL, /* cancel       */
149         NULL, /* specific     */
150         NULL, /* optional     */
151         NULL  /* free         */
152     },
153     {
154         /* blob_cls */
155         H5VL__native_blob_put,      /* put */
156         H5VL__native_blob_get,      /* get */
157         H5VL__native_blob_specific, /* specific */
158         NULL                        /* optional */
159     },
160     {
161         /* token_cls */
162         H5VL__native_token_cmp,    /* cmp            */
163         H5VL__native_token_to_str, /* to_str         */
164         H5VL__native_str_to_token  /* from_str       */
165     },
166     NULL /* optional     */
167 };
168 
169 /*-------------------------------------------------------------------------
170  * Function:    H5VL_native_register
171  *
172  * Purpose:     Register the native VOL connector and retrieve an ID for it.
173  *
174  * Return:      Success:    The ID for the native connector
175  *              Failure:    H5I_INVALID_HID
176  *
177  *-------------------------------------------------------------------------
178  */
179 hid_t
H5VL_native_register(void)180 H5VL_native_register(void)
181 {
182     hid_t ret_value = H5I_INVALID_HID; /* Return value */
183 
184     FUNC_ENTER_NOAPI(H5I_INVALID_HID)
185 
186     /* Register the native VOL connector, if it isn't already */
187     if (H5I_INVALID_HID == H5VL_NATIVE_ID_g)
188         if ((H5VL_NATIVE_ID_g =
189                  H5VL__register_connector(&H5VL_native_cls_g, TRUE, H5P_VOL_INITIALIZE_DEFAULT)) < 0)
190             HGOTO_ERROR(H5E_VOL, H5E_CANTINSERT, H5I_INVALID_HID, "can't create ID for native VOL connector")
191 
192     /* Set return value */
193     ret_value = H5VL_NATIVE_ID_g;
194 
195 done:
196     FUNC_LEAVE_NOAPI(ret_value)
197 } /* end H5VL_native_register() */
198 
199 /*---------------------------------------------------------------------------
200  * Function:    H5VL__native_term
201  *
202  * Purpose:     Shut down the native VOL
203  *
204  * Returns:     SUCCEED (Can't fail)
205  *
206  *---------------------------------------------------------------------------
207  */
208 static herr_t
H5VL__native_term(void)209 H5VL__native_term(void)
210 {
211     FUNC_ENTER_STATIC_NOERR
212 
213     /* Reset VOL ID */
214     H5VL_NATIVE_ID_g = H5I_INVALID_HID;
215 
216     FUNC_LEAVE_NOAPI(SUCCEED)
217 } /* end H5VL__native_term() */
218 
219 /*---------------------------------------------------------------------------
220  * Function:    H5VL__native_introspect_get_conn_cls
221  *
222  * Purpose:     Query the connector class.
223  *
224  * Note:        This routine is in this file so that it can return the address
225  *              of the staticly declared class struct.
226  *
227  * Returns:     SUCCEED (Can't fail)
228  *
229  *---------------------------------------------------------------------------
230  */
231 herr_t
H5VL__native_introspect_get_conn_cls(void H5_ATTR_UNUSED * obj,H5VL_get_conn_lvl_t H5_ATTR_UNUSED lvl,const H5VL_class_t ** conn_cls)232 H5VL__native_introspect_get_conn_cls(void H5_ATTR_UNUSED *obj, H5VL_get_conn_lvl_t H5_ATTR_UNUSED lvl,
233                                      const H5VL_class_t **conn_cls)
234 {
235     FUNC_ENTER_PACKAGE_NOERR
236 
237     /* Sanity check */
238     HDassert(conn_cls);
239 
240     /* Retrieve the native VOL connector class */
241     *conn_cls = &H5VL_native_cls_g;
242 
243     FUNC_LEAVE_NOAPI(SUCCEED)
244 } /* end H5VL__native_introspect_get_conn_cls() */
245 
246 /*-------------------------------------------------------------------------
247  * Function:    H5VL_native_get_file_addr_len
248  *
249  * Purpose:     Convenience function to get a file's address length from a
250  *              location ID. Useful when you have to encode/decode addresses
251  *              to/from tokens.
252  *
253  * Return:      SUCCEED/FAIL
254  *
255  *-------------------------------------------------------------------------
256  */
257 herr_t
H5VL_native_get_file_addr_len(hid_t loc_id,size_t * addr_len)258 H5VL_native_get_file_addr_len(hid_t loc_id, size_t *addr_len)
259 {
260     H5I_type_t vol_obj_type = H5I_BADID; /* Object type of loc_id */
261     void *     vol_obj      = NULL;      /* VOL Object of loc_id */
262     herr_t     ret_value    = SUCCEED;   /* Return value */
263 
264     FUNC_ENTER_NOAPI(FAIL)
265 
266     /* check arguments */
267     HDassert(addr_len);
268 
269     /* Get object type */
270     if ((vol_obj_type = H5I_get_type(loc_id)) < 0)
271         HGOTO_ERROR(H5E_VOL, H5E_BADTYPE, FAIL, "invalid location identifier")
272 
273     /* Retrieve underlying VOL object */
274     if (NULL == (vol_obj = H5VL_object(loc_id)))
275         HGOTO_ERROR(H5E_VOL, H5E_BADTYPE, FAIL, "invalid location identifier")
276 
277     /* Retrieve file address length */
278     if (H5VL__native_get_file_addr_len(vol_obj, vol_obj_type, addr_len) < 0)
279         HGOTO_ERROR(H5E_VOL, H5E_CANTGET, FAIL, "can't get file address length")
280 
281 done:
282     FUNC_LEAVE_NOAPI(ret_value)
283 } /* end H5VL_native_get_file_addr_len() */
284 
285 /*-------------------------------------------------------------------------
286  * Function:    H5VL__native_get_file_addr_len
287  *
288  * Purpose:     Convenience function to get a file's address length from a
289  *              VOL object. Useful when you have to encode/decode addresses
290  *              to/from tokens.
291  *
292  * Return:      SUCCEED/FAIL
293  *
294  *-------------------------------------------------------------------------
295  */
296 herr_t
H5VL__native_get_file_addr_len(void * obj,H5I_type_t obj_type,size_t * addr_len)297 H5VL__native_get_file_addr_len(void *obj, H5I_type_t obj_type, size_t *addr_len)
298 {
299     H5F_t *file      = NULL; /* File stuct pointer */
300     herr_t ret_value = SUCCEED;
301 
302     FUNC_ENTER_NOAPI(FAIL)
303 
304     /* check arguments */
305     HDassert(obj);
306     HDassert(addr_len);
307 
308     /* Retrieve file from the VOL object */
309     if (H5VL_native_get_file_struct(obj, obj_type, &file) < 0)
310         HGOTO_ERROR(H5E_VOL, H5E_CANTGET, FAIL, "couldn't get file from VOL object")
311 
312     /* Get the length of an address in this file */
313     *addr_len = H5F_SIZEOF_ADDR(file);
314 
315 done:
316     FUNC_LEAVE_NOAPI(ret_value)
317 } /* end H5VL__native_get_file_addr_len() */
318 
319 /*-------------------------------------------------------------------------
320  * Function:    H5VLnative_addr_to_token
321  *
322  * Purpose:     Converts a native VOL haddr_t address to an abstract VOL token.
323  *
324  * Return:      SUCCEED/FAIL
325  *
326  *-------------------------------------------------------------------------
327  */
328 herr_t
H5VLnative_addr_to_token(hid_t loc_id,haddr_t addr,H5O_token_t * token)329 H5VLnative_addr_to_token(hid_t loc_id, haddr_t addr, H5O_token_t *token)
330 {
331     H5I_type_t vol_obj_type = H5I_BADID; /* Object type of loc_id */
332     void *     vol_obj      = NULL;      /* VOL Object of loc_id */
333     herr_t     ret_value    = SUCCEED;   /* Return value         */
334 
335     FUNC_ENTER_API(FAIL)
336     H5TRACE3("e", "ia*k", loc_id, addr, token);
337 
338     /* Check args */
339     if (NULL == token)
340         HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "token pointer can't be NULL")
341 
342     /* Get object type */
343     if ((vol_obj_type = H5I_get_type(loc_id)) < 0)
344         HGOTO_ERROR(H5E_VOL, H5E_BADTYPE, FAIL, "invalid location identifier")
345 
346     /* Retrieve underlying VOL object */
347     if (NULL == (vol_obj = H5VL_object(loc_id)))
348         HGOTO_ERROR(H5E_VOL, H5E_CANTGET, FAIL, "can't get underlying VOL object")
349 
350 #ifndef NDEBUG
351     {
352         H5VL_object_t *vol_obj_container;
353         hbool_t        is_native_vol_obj;
354 
355         /* Get the location object */
356         if (NULL == (vol_obj_container = (H5VL_object_t *)H5I_object(loc_id)))
357             HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid location identifier")
358 
359         /* Make sure that the VOL object is a native connector object */
360         if (H5VL_object_is_native(vol_obj_container, &is_native_vol_obj) < 0)
361             HGOTO_ERROR(H5E_VOL, H5E_CANTGET, FAIL,
362                         "can't determine if VOL object is native connector object")
363 
364         HDassert(is_native_vol_obj && "not a native VOL connector object");
365     }
366 #endif
367 
368     /* Convert the haddr_t to an object token */
369     if (H5VL_native_addr_to_token(vol_obj, vol_obj_type, addr, token) < 0)
370         HGOTO_ERROR(H5E_VOL, H5E_CANTSERIALIZE, FAIL, "couldn't serialize haddr_t into object token")
371 
372 done:
373     FUNC_LEAVE_API(ret_value)
374 } /* end H5VLnative_addr_to_token() */
375 
376 /*-------------------------------------------------------------------------
377  * Function:    H5VL_native_addr_to_token
378  *
379  * Purpose:     Converts a native VOL haddr_t address to an abstract VOL token.
380  *
381  * Return:      SUCCEED/FAIL
382  *
383  *-------------------------------------------------------------------------
384  */
385 herr_t
H5VL_native_addr_to_token(void * obj,H5I_type_t obj_type,haddr_t addr,H5O_token_t * token)386 H5VL_native_addr_to_token(void *obj, H5I_type_t obj_type, haddr_t addr, H5O_token_t *token)
387 {
388     uint8_t *p;
389     size_t   addr_len  = 0; /* Size of haddr_t      */
390     herr_t   ret_value = SUCCEED;
391 
392     FUNC_ENTER_NOAPI(FAIL)
393 
394     /* Check args */
395     HDassert(obj);
396     HDassert(token);
397 
398     /* Get the length of an haddr_t in the file */
399     if (H5VL__native_get_file_addr_len(obj, obj_type, &addr_len) < 0)
400         HGOTO_ERROR(H5E_VOL, H5E_CANTGET, FAIL, "couldn't get length of haddr_t from VOL object")
401 
402     /* Ensure that token is initialized */
403     HDmemset(token, 0, sizeof(H5O_token_t));
404 
405     /* Encode token */
406     p = (uint8_t *)token;
407     H5F_addr_encode_len(addr_len, &p, addr);
408 
409 done:
410     FUNC_LEAVE_NOAPI(ret_value)
411 } /* end H5VL_native_addr_to_token() */
412 
413 /*-------------------------------------------------------------------------
414  * Function:    H5VLnative_token_to_addr
415  *
416  * Purpose:     Converts an abstract VOL token to a native VOL haddr_t address.
417  *
418  * Return:      SUCCEED/FAIL
419  *
420  *-------------------------------------------------------------------------
421  */
422 herr_t
H5VLnative_token_to_addr(hid_t loc_id,H5O_token_t token,haddr_t * addr)423 H5VLnative_token_to_addr(hid_t loc_id, H5O_token_t token, haddr_t *addr)
424 {
425     H5I_type_t vol_obj_type = H5I_BADID; /* Object type of loc_id */
426     void *     vol_obj      = NULL;      /* VOL Object of loc_id */
427     herr_t     ret_value    = SUCCEED;   /* Return value         */
428 
429     FUNC_ENTER_API(FAIL)
430     H5TRACE3("e", "ik*a", loc_id, token, addr);
431 
432     /* Check args */
433     if (NULL == addr)
434         HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "addr pointer can't be NULL")
435 
436     /* Get object type */
437     if ((vol_obj_type = H5I_get_type(loc_id)) < 0)
438         HGOTO_ERROR(H5E_VOL, H5E_BADTYPE, FAIL, "invalid location identifier")
439 
440     /* Retrieve underlying VOL object */
441     if (NULL == (vol_obj = H5VL_object(loc_id)))
442         HGOTO_ERROR(H5E_VOL, H5E_CANTGET, FAIL, "can't get underlying VOL object")
443 
444 #ifndef NDEBUG
445     {
446         H5VL_object_t *vol_obj_container;
447         hbool_t        is_native_vol_obj;
448 
449         /* Get the location object */
450         if (NULL == (vol_obj_container = (H5VL_object_t *)H5I_object(loc_id)))
451             HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid location identifier")
452 
453         /* Make sure that the VOL object is a native connector object */
454         if (H5VL_object_is_native(vol_obj_container, &is_native_vol_obj) < 0)
455             HGOTO_ERROR(H5E_VOL, H5E_CANTGET, FAIL,
456                         "can't determine if VOL object is native connector object")
457 
458         HDassert(is_native_vol_obj && "not a native VOL connector object");
459     }
460 #endif
461 
462     /* Convert the object token to an haddr_t */
463     if (H5VL_native_token_to_addr(vol_obj, vol_obj_type, token, addr) < 0)
464         HGOTO_ERROR(H5E_VOL, H5E_CANTUNSERIALIZE, FAIL, "couldn't deserialize object token into haddr_t")
465 
466 done:
467     FUNC_LEAVE_API(ret_value)
468 } /* end H5VLnative_token_to_addr() */
469 
470 /*-------------------------------------------------------------------------
471  * Function:    H5VL_native_token_to_addr
472  *
473  * Purpose:     Converts an abstract VOL token to a native VOL haddr_t address.
474  *
475  * Return:      SUCCEED/FAIL
476  *
477  *-------------------------------------------------------------------------
478  */
479 herr_t
H5VL_native_token_to_addr(void * obj,H5I_type_t obj_type,H5O_token_t token,haddr_t * addr)480 H5VL_native_token_to_addr(void *obj, H5I_type_t obj_type, H5O_token_t token, haddr_t *addr)
481 {
482     const uint8_t *p;
483     size_t         addr_len  = 0; /* Size of haddr_t      */
484     herr_t         ret_value = SUCCEED;
485 
486     FUNC_ENTER_NOAPI(FAIL)
487 
488     /* Check args */
489     HDassert(obj);
490     HDassert(addr);
491 
492     /* Get the length of an haddr_t in the file */
493     if (H5VL__native_get_file_addr_len(obj, obj_type, &addr_len) < 0)
494         HGOTO_ERROR(H5E_VOL, H5E_CANTGET, FAIL, "couldn't get length of haddr_t from VOL object")
495 
496     /* Decode token */
497     p = (const uint8_t *)&token;
498     H5F_addr_decode_len(addr_len, &p, addr);
499 
500 done:
501     FUNC_LEAVE_NOAPI(ret_value)
502 } /* end H5VL_native_token_to_addr() */
503 
504 /*---------------------------------------------------------------------------
505  * Function:    H5VL_native_get_file_struct
506  *
507  * Purpose:     Utility routine to get file struct for an object
508  *
509  * Returns:     SUCCEED/FAIL
510  *
511  *---------------------------------------------------------------------------
512  */
513 herr_t
H5VL_native_get_file_struct(void * obj,H5I_type_t type,H5F_t ** file)514 H5VL_native_get_file_struct(void *obj, H5I_type_t type, H5F_t **file)
515 {
516     H5O_loc_t *oloc      = NULL;    /* Object location for ID   */
517     herr_t     ret_value = SUCCEED; /* Return value             */
518 
519     FUNC_ENTER_NOAPI(FAIL);
520 
521     *file = NULL;
522 
523     switch (type) {
524         case H5I_FILE:
525             *file = (H5F_t *)obj;
526             break;
527 
528         case H5I_GROUP:
529             oloc = H5G_oloc((H5G_t *)obj);
530             break;
531 
532         case H5I_DATATYPE:
533             oloc = H5T_oloc((H5T_t *)obj);
534             break;
535 
536         case H5I_DATASET:
537             oloc = H5D_oloc((H5D_t *)obj);
538             break;
539 
540         case H5I_ATTR:
541             oloc = H5A_oloc((H5A_t *)obj);
542             break;
543 
544         case H5I_MAP:
545             HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "maps not supported in native VOL connector")
546 
547         case H5I_UNINIT:
548         case H5I_BADID:
549         case H5I_DATASPACE:
550         case H5I_VFL:
551         case H5I_VOL:
552         case H5I_GENPROP_CLS:
553         case H5I_GENPROP_LST:
554         case H5I_ERROR_CLASS:
555         case H5I_ERROR_MSG:
556         case H5I_ERROR_STACK:
557         case H5I_SPACE_SEL_ITER:
558         case H5I_NTYPES:
559         default:
560             HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file or file object")
561     } /* end switch */
562 
563     /* Set return value for objects (not files) */
564     if (oloc)
565         *file = oloc->file;
566 
567     /* Couldn't find a file struct */
568     if (!*file)
569         HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "object is not associated with a file")
570 
571 done:
572     FUNC_LEAVE_NOAPI(ret_value)
573 } /* H5VL_native_get_file_struct */
574