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