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 COPYING file, which can be found at the root of the source code *
9 * distribution tree, or in https://support.hdfgroup.org/ftp/HDF5/releases. *
10 * If you do not have access to either file, you may request a copy from *
11 * help@hdfgroup.org. *
12 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
13
14 /****************/
15 /* Module Setup */
16 /****************/
17
18 #define H5D_PACKAGE /*suppress error about including H5Dpkg */
19 #define H5O_PACKAGE /*suppress error about including H5Opkg */
20
21
22 /***********/
23 /* Headers */
24 /***********/
25 #include "H5private.h" /* Generic Functions */
26 #include "H5Dpkg.h" /* Datasets */
27 #include "H5Eprivate.h" /* Error handling */
28 #include "H5FLprivate.h" /* Free lists */
29 #include "H5Iprivate.h" /* IDs */
30 #include "H5Opkg.h" /* Object headers */
31
32
33 /****************/
34 /* Local Macros */
35 /****************/
36
37
38 /******************/
39 /* Local Typedefs */
40 /******************/
41
42
43 /********************/
44 /* Local Prototypes */
45 /********************/
46 static void *H5O__dset_get_copy_file_udata(void);
47 static void H5O__dset_free_copy_file_udata(void *);
48 static htri_t H5O__dset_isa(H5O_t *loc);
49 static hid_t H5O__dset_open(const H5G_loc_t *obj_loc, hid_t lapl_id,
50 hid_t dxpl_id, hbool_t app_ref);
51 static void *H5O__dset_create(H5F_t *f, void *_crt_info, H5G_loc_t *obj_loc,
52 hid_t dxpl_id);
53 static H5O_loc_t *H5O__dset_get_oloc(hid_t obj_id);
54 static herr_t H5O__dset_bh_info(H5F_t *f, hid_t dxpl_id, H5O_t *oh,
55 H5_ih_info_t *bh_info);
56 static herr_t H5O__dset_flush(H5G_loc_t *obj_loc, hid_t dxpl_id);
57
58
59 /*********************/
60 /* Package Variables */
61 /*********************/
62
63
64 /*****************************/
65 /* Library Private Variables */
66 /*****************************/
67
68
69 /*******************/
70 /* Local Variables */
71 /*******************/
72
73 /* This message derives from H5O object class */
74 const H5O_obj_class_t H5O_OBJ_DATASET[1] = {{
75 H5O_TYPE_DATASET, /* object type */
76 "dataset", /* object name, for debugging */
77 H5O__dset_get_copy_file_udata, /* get 'copy file' user data */
78 H5O__dset_free_copy_file_udata, /* free 'copy file' user data */
79 H5O__dset_isa, /* "isa" message */
80 H5O__dset_open, /* open an object of this class */
81 H5O__dset_create, /* create an object of this class */
82 H5O__dset_get_oloc, /* get an object header location for an object */
83 H5O__dset_bh_info, /* get the index & heap info for an object */
84 H5O__dset_flush /* flush an opened object of this class */
85 }};
86
87 /* Declare a free list to manage the H5D_copy_file_ud_t struct */
88 H5FL_DEFINE(H5D_copy_file_ud_t);
89
90
91 /*-------------------------------------------------------------------------
92 * Function: H5O__dset_get_copy_file_udata
93 *
94 * Purpose: Allocates the user data needed for copying a dataset's
95 * object header from file to file.
96 *
97 * Return: Success: Non-NULL pointer to user data
98 *
99 * Failure: NULL
100 *
101 * Programmer: Quincey Koziol
102 * Monday, November 21, 2005
103 *
104 *-------------------------------------------------------------------------
105 */
106 static void *
H5O__dset_get_copy_file_udata(void)107 H5O__dset_get_copy_file_udata(void)
108 {
109 void *ret_value; /* Return value */
110
111 FUNC_ENTER_STATIC
112
113 /* Allocate space for the 'copy file' user data for copying datasets */
114 if(NULL == (ret_value = H5FL_CALLOC(H5D_copy_file_ud_t)))
115 HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
116
117 done:
118 FUNC_LEAVE_NOAPI(ret_value)
119 } /* end H5O__dset_get_copy_file_udata() */
120
121
122 /*-------------------------------------------------------------------------
123 * Function: H5O__dset_free_copy_file_udata
124 *
125 * Purpose: Release the user data needed for copying a dataset's
126 * object header from file to file.
127 *
128 * Return: <none>
129 *
130 * Programmer: Quincey Koziol
131 * Monday, November 21, 2005
132 *
133 *-------------------------------------------------------------------------
134 */
135 static void
H5O__dset_free_copy_file_udata(void * _udata)136 H5O__dset_free_copy_file_udata(void *_udata)
137 {
138 H5D_copy_file_ud_t *udata = (H5D_copy_file_ud_t *)_udata;
139
140 FUNC_ENTER_STATIC_NOERR
141
142 /* Sanity check */
143 HDassert(udata);
144
145 /* Release copy of dataset's dataspace extent, if it was set */
146 if(udata->src_space_extent)
147 H5O_msg_free(H5O_SDSPACE_ID, udata->src_space_extent);
148
149 /* Release copy of dataset's datatype, if it was set */
150 if(udata->src_dtype)
151 H5T_close(udata->src_dtype);
152
153 /* Release copy of dataset's filter pipeline, if it was set */
154 if(udata->common.src_pline)
155 H5O_msg_free(H5O_PLINE_ID, udata->common.src_pline);
156
157 /* Release space for 'copy file' user data */
158 udata = H5FL_FREE(H5D_copy_file_ud_t, udata);
159
160 FUNC_LEAVE_NOAPI_VOID
161 } /* end H5O__dset_free_copy_file_udata() */
162
163
164 /*-------------------------------------------------------------------------
165 * Function: H5O__dset_isa
166 *
167 * Purpose: Determines if an object has the requisite messages for being
168 * a dataset.
169 *
170 * Return: Success: TRUE if the required dataset messages are
171 * present; FALSE otherwise.
172 *
173 * Failure: FAIL if the existence of certain messages
174 * cannot be determined.
175 *
176 * Programmer: Robb Matzke
177 * Monday, November 2, 1998
178 *
179 *-------------------------------------------------------------------------
180 */
181 static htri_t
H5O__dset_isa(H5O_t * oh)182 H5O__dset_isa(H5O_t *oh)
183 {
184 htri_t exists; /* Flag if header message of interest exists */
185 htri_t ret_value = TRUE; /* Return value */
186
187 FUNC_ENTER_STATIC
188
189 HDassert(oh);
190
191 /* Datatype */
192 if((exists = H5O_msg_exists_oh(oh, H5O_DTYPE_ID)) < 0)
193 HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to read object header")
194 else if(!exists)
195 HGOTO_DONE(FALSE)
196
197 /* Layout */
198 if((exists = H5O_msg_exists_oh(oh, H5O_SDSPACE_ID)) < 0)
199 HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to read object header")
200 else if(!exists)
201 HGOTO_DONE(FALSE)
202
203 done:
204 FUNC_LEAVE_NOAPI(ret_value)
205 } /* end H5O__dset_isa() */
206
207
208 /*-------------------------------------------------------------------------
209 * Function: H5O__dset_open
210 *
211 * Purpose: Open a dataset at a particular location
212 *
213 * Return: Success: Open object identifier
214 * Failure: Negative
215 *
216 * Programmer: Quincey Koziol
217 * Monday, November 6, 2006
218 *
219 *-------------------------------------------------------------------------
220 */
221 static hid_t
H5O__dset_open(const H5G_loc_t * obj_loc,hid_t lapl_id,hid_t dxpl_id,hbool_t app_ref)222 H5O__dset_open(const H5G_loc_t *obj_loc, hid_t lapl_id, hid_t dxpl_id, hbool_t app_ref)
223 {
224 H5D_t *dset = NULL; /* Dataset opened */
225 htri_t isdapl; /* lapl_id is a dapl */
226 hid_t dapl_id; /* dapl to use to open this dataset */
227 hid_t ret_value; /* Return value */
228
229 FUNC_ENTER_STATIC
230
231 HDassert(obj_loc);
232
233 /* If the lapl passed in is a dapl, use it. Otherwise, use the default dapl */
234 if(lapl_id == H5P_DEFAULT)
235 isdapl = FALSE;
236 else
237 if((isdapl = H5P_isa_class(lapl_id, H5P_DATASET_ACCESS)) < 0)
238 HGOTO_ERROR(H5E_PLIST, H5E_CANTCOMPARE, FAIL, "unable to compare property list classes")
239
240 if(isdapl)
241 dapl_id = lapl_id;
242 else
243 dapl_id = H5P_DATASET_ACCESS_DEFAULT;
244
245 /* Open the dataset */
246 if(NULL == (dset = H5D_open(obj_loc, dapl_id, dxpl_id)))
247 HGOTO_ERROR(H5E_DATASET, H5E_CANTOPENOBJ, FAIL, "unable to open dataset")
248
249 /* Register an ID for the dataset */
250 if((ret_value = H5I_register(H5I_DATASET, dset, app_ref)) < 0)
251 HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, FAIL, "unable to register dataset")
252
253 done:
254 if(ret_value < 0)
255 if(dset && H5D_close(dset) < 0)
256 HDONE_ERROR(H5E_DATASET, H5E_CLOSEERROR, FAIL, "unable to release dataset")
257
258 FUNC_LEAVE_NOAPI(ret_value)
259 } /* end H5O__dset_open() */
260
261
262 /*-------------------------------------------------------------------------
263 * Function: H5O__dset_create
264 *
265 * Purpose: Create a dataset in a file
266 *
267 * Return: Success: Pointer to the dataset data structure
268 * Failure: NULL
269 *
270 * Programmer: Quincey Koziol
271 * Wednesday, April 11, 2007
272 *
273 *-------------------------------------------------------------------------
274 */
275 static void *
H5O__dset_create(H5F_t * f,void * _crt_info,H5G_loc_t * obj_loc,hid_t dxpl_id)276 H5O__dset_create(H5F_t *f, void *_crt_info, H5G_loc_t *obj_loc, hid_t dxpl_id)
277 {
278 H5D_obj_create_t *crt_info = (H5D_obj_create_t *)_crt_info; /* Dataset creation parameters */
279 H5D_t *dset = NULL; /* New dataset created */
280 void *ret_value; /* Return value */
281
282 FUNC_ENTER_STATIC
283
284 /* Sanity checks */
285 HDassert(f);
286 HDassert(crt_info);
287 HDassert(obj_loc);
288
289 /* Create the the dataset */
290 if(NULL == (dset = H5D__create(f, crt_info->type_id, crt_info->space, crt_info->dcpl_id, crt_info->dapl_id, dxpl_id)))
291 HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, NULL, "unable to create dataset")
292
293 /* Set up the new dataset's location */
294 if(NULL == (obj_loc->oloc = H5D_oloc(dset)))
295 HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, NULL, "unable to get object location of dataset")
296 if(NULL == (obj_loc->path = H5D_nameof(dset)))
297 HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, NULL, "unable to get path of dataset")
298
299 /* Set the return value */
300 ret_value = dset;
301
302 done:
303 if(ret_value == NULL)
304 if(dset && H5D_close(dset) < 0)
305 HDONE_ERROR(H5E_DATASET, H5E_CLOSEERROR, NULL, "unable to release dataset")
306
307 FUNC_LEAVE_NOAPI(ret_value)
308 } /* end H5O__dset_create() */
309
310
311 /*-------------------------------------------------------------------------
312 * Function: H5O__dset_get_oloc
313 *
314 * Purpose: Retrieve the object header location for an open object
315 *
316 * Return: Success: Pointer to object header location
317 * Failure: NULL
318 *
319 * Programmer: Quincey Koziol
320 * Monday, November 6, 2006
321 *
322 *-------------------------------------------------------------------------
323 */
324 static H5O_loc_t *
H5O__dset_get_oloc(hid_t obj_id)325 H5O__dset_get_oloc(hid_t obj_id)
326 {
327 H5D_t *dset; /* Dataset opened */
328 H5O_loc_t *ret_value; /* Return value */
329
330 FUNC_ENTER_STATIC
331
332 /* Get the dataset */
333 if(NULL == (dset = (H5D_t *)H5I_object(obj_id)))
334 HGOTO_ERROR(H5E_OHDR, H5E_BADATOM, NULL, "couldn't get object from ID")
335
336 /* Get the dataset's object header location */
337 if(NULL == (ret_value = H5D_oloc(dset)))
338 HGOTO_ERROR(H5E_OHDR, H5E_CANTGET, NULL, "unable to get object location from object")
339
340 done:
341 FUNC_LEAVE_NOAPI(ret_value)
342 } /* end H5O__dset_get_oloc() */
343
344
345 /*-------------------------------------------------------------------------
346 * Function: H5O__dset_bh_info
347 *
348 * Purpose: Returns the amount of btree storage that is used for chunked
349 * dataset.
350 *
351 * Return: Success: non-negative
352 * Failure: negative
353 *
354 * Programmer: Vailin Choi
355 * July 11, 2007
356 *
357 * Modification:Raymond Lu
358 * 5 February, 2010
359 * I added the call to H5O_msg_reset after H5D_chunk_bh_info
360 * to free the PLINE.
361 *-------------------------------------------------------------------------
362 */
363 static herr_t
H5O__dset_bh_info(H5F_t * f,hid_t dxpl_id,H5O_t * oh,H5_ih_info_t * bh_info)364 H5O__dset_bh_info(H5F_t *f, hid_t dxpl_id, H5O_t *oh, H5_ih_info_t *bh_info)
365 {
366 H5O_layout_t layout; /* Data storage layout message */
367 H5O_pline_t pline; /* I/O pipeline message */
368 H5O_efl_t efl; /* External File List message */
369 hbool_t layout_read = FALSE; /* Whether the layout message was read */
370 hbool_t pline_read = FALSE; /* Whether the I/O pipeline message was read */
371 hbool_t efl_read = FALSE; /* Whether the external file list message was read */
372 htri_t exists; /* Flag if header message of interest exists */
373 herr_t ret_value = SUCCEED; /* Return value */
374
375 FUNC_ENTER_STATIC
376
377 /* Sanity check */
378 HDassert(f);
379 HDassert(oh);
380 HDassert(bh_info);
381
382 /* Get the layout message from the object header */
383 if(NULL == H5O_msg_read_oh(f, dxpl_id, oh, H5O_LAYOUT_ID, &layout))
384 HGOTO_ERROR(H5E_OHDR, H5E_CANTGET, FAIL, "can't find layout message")
385 layout_read = TRUE;
386
387 /* Check for chunked dataset storage */
388 if(layout.type == H5D_CHUNKED && H5D__chunk_is_space_alloc(&layout.storage)) {
389 /* Check for I/O pipeline message */
390 if((exists = H5O_msg_exists_oh(oh, H5O_PLINE_ID)) < 0)
391 HGOTO_ERROR(H5E_DATASET, H5E_CANTINIT, FAIL, "unable to read object header")
392 else if(exists) {
393 if(NULL == H5O_msg_read_oh(f, dxpl_id, oh, H5O_PLINE_ID, &pline))
394 HGOTO_ERROR(H5E_OHDR, H5E_CANTGET, FAIL, "can't find I/O pipeline message")
395 pline_read = TRUE;
396 } /* end else if */
397 else
398 HDmemset(&pline, 0, sizeof(pline));
399
400 if(H5D__chunk_bh_info(f, dxpl_id, &layout, &pline, &(bh_info->index_size)) < 0)
401 HGOTO_ERROR(H5E_OHDR, H5E_CANTGET, FAIL, "can't determine chunked dataset btree info")
402 } /* end if */
403
404 /* Check for External File List message in the object header */
405 if((exists = H5O_msg_exists_oh(oh, H5O_EFL_ID)) < 0)
406 HGOTO_ERROR(H5E_OHDR, H5E_NOTFOUND, FAIL, "unable to check for EFL message")
407
408 if(exists && H5D__efl_is_space_alloc(&layout.storage)) {
409 /* Start with clean EFL info */
410 HDmemset(&efl, 0, sizeof(efl));
411
412 /* Get External File List message from the object header */
413 if(NULL == H5O_msg_read_oh(f, dxpl_id, oh, H5O_EFL_ID, &efl))
414 HGOTO_ERROR(H5E_OHDR, H5E_CANTGET, FAIL, "can't find EFL message")
415 efl_read = TRUE;
416
417 /* Get size of local heap for EFL message's file list */
418 if(H5D__efl_bh_info(f, dxpl_id, &efl, &(bh_info->heap_size)) < 0)
419 HGOTO_ERROR(H5E_OHDR, H5E_CANTGET, FAIL, "can't determine EFL heap info")
420 } /* end if */
421
422 done:
423 /* Free messages, if they've been read in */
424 if(layout_read && H5O_msg_reset(H5O_LAYOUT_ID, &layout) < 0)
425 HDONE_ERROR(H5E_DATASET, H5E_CANTRESET, FAIL, "unable to reset data storage layout message")
426 if(pline_read && H5O_msg_reset(H5O_PLINE_ID, &pline) < 0)
427 HDONE_ERROR(H5E_DATASET, H5E_CANTRESET, FAIL, "unable to reset I/O pipeline message")
428 if(efl_read && H5O_msg_reset(H5O_EFL_ID, &efl) < 0)
429 HDONE_ERROR(H5E_DATASET, H5E_CANTRESET, FAIL, "unable to reset external file list message")
430
431 FUNC_LEAVE_NOAPI(ret_value)
432 } /* end H5O__dset_bh_info() */
433
434
435 /*-------------------------------------------------------------------------
436 * Function: H5O__dset_flush
437 *
438 * Purpose: To flush any dataset information cached in memory
439 *
440 * Return: Success: non-negative
441 * Failure: negative
442 *
443 * Programmer: Vailin Choi
444 * February 2012
445 *
446 *-------------------------------------------------------------------------
447 */
448 static herr_t
H5O__dset_flush(H5G_loc_t * obj_loc,hid_t dxpl_id)449 H5O__dset_flush(H5G_loc_t *obj_loc, hid_t dxpl_id)
450 {
451 H5D_t *dset = NULL; /* Dataset opened */
452 H5O_type_t obj_type; /* Type of object at location */
453 herr_t ret_value = SUCCEED; /* Return value */
454
455 FUNC_ENTER_STATIC
456
457 HDassert(obj_loc);
458 HDassert(obj_loc->oloc);
459
460 /* Check that the object found is the correct type */
461 if(H5O_obj_type(obj_loc->oloc, &obj_type, dxpl_id) < 0)
462 HGOTO_ERROR(H5E_DATASET, H5E_CANTGET, FAIL, "can't get object type")
463
464 if(obj_type != H5O_TYPE_DATASET)
465 HGOTO_ERROR(H5E_DATASET, H5E_BADTYPE, FAIL, "not a dataset")
466
467 /* Open the dataset */
468 if(NULL == (dset = H5D_open(obj_loc, H5P_DATASET_ACCESS_DEFAULT, dxpl_id)))
469 HGOTO_ERROR(H5E_DATASET, H5E_CANTOPENOBJ, FAIL, "unable to open dataset")
470
471 if(H5D__flush_real(dset, dxpl_id) < 0)
472 HDONE_ERROR(H5E_DATASET, H5E_WRITEERROR, FAIL, "unable to flush cached dataset info")
473
474 done:
475 if(dset && H5D_close(dset) < 0)
476 HDONE_ERROR(H5E_DATASET, H5E_CLOSEERROR, FAIL, "unable to release dataset")
477 FUNC_LEAVE_NOAPI(ret_value)
478 } /* end H5O__dset_flush() */
479
480