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