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 Info: This module contains the functionality for committing datatypes
16  *      to a file for the H5T interface.
17  */
18 
19 /****************/
20 /* Module Setup */
21 /****************/
22 
23 #include "H5Tmodule.h"          /* This source code file is part of the H5T module */
24 
25 
26 /***********/
27 /* Headers */
28 /***********/
29 #include "H5private.h"		/* Generic Functions			*/
30 #include "H5ACprivate.h"        /* Metadata cache                       */
31 #include "H5Eprivate.h"		/* Error handling			*/
32 #include "H5FOprivate.h"	/* File objects				*/
33 #include "H5Iprivate.h"		/* IDs					*/
34 #include "H5Lprivate.h"		/* Links				*/
35 #include "H5Pprivate.h"         /* Property lists                       */
36 #include "H5Tpkg.h"		/* Datatypes				*/
37 
38 
39 /****************/
40 /* Local Macros */
41 /****************/
42 
43 
44 /******************/
45 /* Local Typedefs */
46 /******************/
47 
48 
49 /********************/
50 /* Package Typedefs */
51 /********************/
52 
53 
54 /********************/
55 /* Local Prototypes */
56 /********************/
57 static H5T_t *H5T_open_oid(const H5G_loc_t *loc, hid_t dxpl_id);
58 
59 
60 /*********************/
61 /* Public Variables */
62 /*********************/
63 
64 
65 /*********************/
66 /* Package Variables */
67 /*********************/
68 
69 
70 /*****************************/
71 /* Library Private Variables */
72 /*****************************/
73 
74 
75 /*******************/
76 /* Local Variables */
77 /*******************/
78 
79 
80 
81 /*-------------------------------------------------------------------------
82  * Function:	H5Tcommit2
83  *
84  * Purpose:	Save a transient datatype to a file and turn the type handle
85  *		into a "named", immutable type.
86  *
87  * Return:	Non-negative on success/Negative on failure
88  *
89  * Programmer:  Quincey Koziol
90  *              April 5, 2007
91  *
92  *-------------------------------------------------------------------------
93  */
94 herr_t
H5Tcommit2(hid_t loc_id,const char * name,hid_t type_id,hid_t lcpl_id,hid_t tcpl_id,hid_t tapl_id)95 H5Tcommit2(hid_t loc_id, const char *name, hid_t type_id, hid_t lcpl_id,
96     hid_t tcpl_id, hid_t tapl_id)
97 {
98     H5G_loc_t	loc;                    /* Location to create datatype */
99     H5T_t	*type;                  /* Datatype for ID */
100     hid_t       dxpl_id = H5AC_ind_read_dxpl_id; /* dxpl used by library */
101     herr_t      ret_value = SUCCEED;    /* Return value */
102 
103     FUNC_ENTER_API(FAIL)
104     H5TRACE6("e", "i*siiii", loc_id, name, type_id, lcpl_id, tcpl_id, tapl_id);
105 
106     /* Check arguments */
107     if(H5G_loc(loc_id, &loc) < 0)
108 	HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a location")
109     if(!name || !*name)
110 	HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no name")
111     if(NULL == (type = (H5T_t *)H5I_object_verify(type_id, H5I_DATATYPE)))
112 	HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype")
113 
114     /* Get correct property list */
115     if(H5P_DEFAULT == lcpl_id)
116         lcpl_id = H5P_LINK_CREATE_DEFAULT;
117     else
118         if(TRUE != H5P_isa_class(lcpl_id, H5P_LINK_CREATE))
119             HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not link creation property list")
120 
121     /* Get correct property list */
122     if(H5P_DEFAULT == tcpl_id)
123         tcpl_id = H5P_DATATYPE_CREATE_DEFAULT;
124     else
125         if(TRUE != H5P_isa_class(tcpl_id, H5P_DATATYPE_CREATE))
126             HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not datatype creation property list")
127 
128     /* Verify access property list and get correct dxpl */
129     if(H5P_verify_apl_and_dxpl(&tapl_id, H5P_CLS_TACC, &dxpl_id, loc_id, TRUE) < 0)
130         HGOTO_ERROR(H5E_DATATYPE, H5E_CANTSET, FAIL, "can't set access and transfer property lists")
131 
132     /* Commit the type */
133     if(H5T__commit_named(&loc, name, type, lcpl_id, tcpl_id, tapl_id, dxpl_id) < 0)
134 	HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to commit datatype")
135 
136 done:
137     FUNC_LEAVE_API(ret_value)
138 } /* end H5Tcommit2() */
139 
140 
141 /*-------------------------------------------------------------------------
142  * Function:	H5T__commit_named
143  *
144  * Purpose:	Internal routine to save a transient datatype to a file and
145  *              turn the type ID into a "named", immutable type.
146  *
147  * Return:	Non-negative on success/Negative on failure
148  *
149  * Programmer:  Quincey Koziol
150  *              April 5, 2007
151  *
152  *-------------------------------------------------------------------------
153  */
154 herr_t
H5T__commit_named(const H5G_loc_t * loc,const char * name,H5T_t * dt,hid_t lcpl_id,hid_t tcpl_id,hid_t tapl_id,hid_t dxpl_id)155 H5T__commit_named(const H5G_loc_t *loc, const char *name, H5T_t *dt,
156     hid_t lcpl_id, hid_t tcpl_id, hid_t tapl_id, hid_t dxpl_id)
157 {
158     H5O_obj_create_t ocrt_info;         /* Information for object creation */
159     H5T_obj_create_t tcrt_info;         /* Information for named datatype creation */
160     H5T_state_t old_state;              /* The state of the datatype before H5T__commit. */
161     herr_t      ret_value = SUCCEED;    /* Return value */
162 
163     FUNC_ENTER_PACKAGE
164 
165     /* Sanity checks */
166     HDassert(loc);
167     HDassert(name && *name);
168     HDassert(dt);
169     HDassert(lcpl_id != H5P_DEFAULT);
170     HDassert(tcpl_id != H5P_DEFAULT);
171     HDassert(tapl_id != H5P_DEFAULT);
172     HDassert(dxpl_id != H5P_DEFAULT);
173 
174     /* Record the type's state so that we can revert to it if linking fails */
175     old_state = dt->shared->state;
176 
177     /* Set up named datatype creation info */
178     tcrt_info.dt = dt;
179     tcrt_info.tcpl_id = tcpl_id;
180 
181     /* Set up object creation information */
182     ocrt_info.obj_type = H5O_TYPE_NAMED_DATATYPE;
183     ocrt_info.crt_info = &tcrt_info;
184     ocrt_info.new_obj = NULL;
185 
186     /* Create the new named datatype and link it to its parent group */
187     if(H5L_link_object(loc, name, &ocrt_info, lcpl_id, tapl_id, dxpl_id) < 0)
188         HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to create and link to named datatype")
189     HDassert(ocrt_info.new_obj);
190 
191 done:
192     /* If the datatype was committed but something failed after that, we need
193      * to return it to the state it was in before it was committed.
194      */
195     if(ret_value < 0 && (NULL != ocrt_info.new_obj)) {
196 	if(dt->shared->state == H5T_STATE_OPEN && dt->sh_loc.type == H5O_SHARE_TYPE_COMMITTED) {
197             /* Remove the datatype from the list of opened objects in the file */
198             if(H5FO_top_decr(dt->sh_loc.file, dt->sh_loc.u.loc.oh_addr) < 0)
199                 HDONE_ERROR(H5E_DATASET, H5E_CANTRELEASE, FAIL, "can't decrement count for object")
200             if(H5FO_delete(dt->sh_loc.file, dxpl_id, dt->sh_loc.u.loc.oh_addr) < 0)
201                 HDONE_ERROR(H5E_DATASET, H5E_CANTRELEASE, FAIL, "can't remove dataset from list of open objects")
202 
203             /* Close the datatype object */
204 	    if(H5O_close(&(dt->oloc), NULL) < 0)
205                 HDONE_ERROR(H5E_DATATYPE, H5E_CLOSEERROR, FAIL, "unable to release object header")
206 
207             /* Remove the datatype's object header from the file */
208             if(H5O_delete(dt->sh_loc.file, dxpl_id, dt->sh_loc.u.loc.oh_addr) < 0)
209                 HDONE_ERROR(H5E_DATATYPE, H5E_CANTDELETE, FAIL, "unable to delete object header")
210 
211             /* Mark datatype as being back in memory */
212             if(H5T_set_loc(dt, dt->sh_loc.file, H5T_LOC_MEMORY))
213                 HDONE_ERROR(H5E_DATATYPE, H5E_CANTDELETE, FAIL, "unable to return datatype to memory")
214 	    dt->sh_loc.type = H5O_SHARE_TYPE_UNSHARED;
215             dt->shared->state = old_state;
216 	} /* end if */
217     } /* end if */
218 
219     FUNC_LEAVE_NOAPI(ret_value)
220 } /* end H5T__commit_named() */
221 
222 
223 /*-------------------------------------------------------------------------
224  * Function:	H5Tcommit_anon
225  *
226  * Purpose:	Save a transient datatype to a file and turn the type handle
227  *		into a "named", immutable type.
228  *
229  *              The resulting ID should be linked into the file with
230  *              H5Olink or it will be deleted when closed.
231  *
232  * Note:	Datatype access property list is unused currently, but is
233  *		checked for sanity anyway.
234  *
235  * Return:	Non-negative on success/Negative on failure
236  *
237  * Programmer:  Peter Cao
238  *              May 17, 2005
239  *
240  *-------------------------------------------------------------------------
241  */
242 herr_t
H5Tcommit_anon(hid_t loc_id,hid_t type_id,hid_t tcpl_id,hid_t tapl_id)243 H5Tcommit_anon(hid_t loc_id, hid_t type_id, hid_t tcpl_id, hid_t tapl_id)
244 {
245     H5G_loc_t	loc;                    /* Group location for location */
246     H5T_t	*type = NULL;           /* Datatype created */
247     hid_t       dxpl_id = H5AC_ind_read_dxpl_id; /* dxpl used by library */
248     herr_t      ret_value = SUCCEED;    /* Return value */
249 
250     FUNC_ENTER_API(FAIL)
251     H5TRACE4("e", "iiii", loc_id, type_id, tcpl_id, tapl_id);
252 
253     /* Check arguments */
254     if(H5G_loc(loc_id, &loc) < 0)
255 	HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a location")
256     if(NULL == (type = (H5T_t *)H5I_object_verify(type_id, H5I_DATATYPE)))
257 	HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype")
258 
259     /* Get correct property list */
260     if(H5P_DEFAULT == tcpl_id)
261         tcpl_id = H5P_DATATYPE_CREATE_DEFAULT;
262     else
263         if(TRUE != H5P_isa_class(tcpl_id, H5P_DATATYPE_CREATE))
264             HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not datatype creation property list")
265 
266     /* Verify access property list and get correct dxpl */
267     if(H5P_verify_apl_and_dxpl(&tapl_id, H5P_CLS_TACC, &dxpl_id, loc_id, TRUE) < 0)
268         HGOTO_ERROR(H5E_DATATYPE, H5E_CANTSET, FAIL, "can't set access and transfer property lists")
269 
270     /* Commit the type */
271     if(H5T__commit(loc.oloc->file, type, tcpl_id, dxpl_id) < 0)
272 	HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to commit datatype")
273 
274     /* Release the datatype's object header */
275     {
276         H5O_loc_t *oloc;         /* Object location for datatype */
277 
278         /* Get the new committed datatype's object location */
279         if(NULL == (oloc = H5T_oloc(type)))
280             HGOTO_ERROR(H5E_DATATYPE, H5E_CANTGET, FAIL, "unable to get object location of committed datatype")
281 
282         /* Decrement refcount on committed datatype's object header in memory */
283         if(H5O_dec_rc_by_loc(oloc, dxpl_id) < 0)
284            HGOTO_ERROR(H5E_DATATYPE, H5E_CANTDEC, FAIL, "unable to decrement refcount on newly created object")
285     } /* end if */
286 
287 done:
288     FUNC_LEAVE_API(ret_value)
289 } /* end H5Tcommit_anon() */
290 
291 
292 /*-------------------------------------------------------------------------
293  * Function:	H5T__commit
294  *
295  * Purpose:	Commit a type, giving it a name and causing it to become
296  *		immutable.
297  *
298  * Return:	Non-negative on success/Negative on failure
299  *
300  * Programmer:	Robb Matzke
301  *              Monday, June  1, 1998
302  *
303  *-------------------------------------------------------------------------
304  */
305 herr_t
H5T__commit(H5F_t * file,H5T_t * type,hid_t tcpl_id,hid_t dxpl_id)306 H5T__commit(H5F_t *file, H5T_t *type, hid_t tcpl_id, hid_t dxpl_id)
307 {
308     H5O_loc_t   temp_oloc;              /* Temporary object header location */
309     H5G_name_t  temp_path;              /* Temporary path */
310     hbool_t     loc_init = FALSE;       /* Have temp_oloc and temp_path been initialized? */
311     size_t      dtype_size;             /* Size of the datatype message */
312     herr_t      ret_value = SUCCEED;    /* Return value */
313 
314     FUNC_ENTER_PACKAGE
315 
316     HDassert(file);
317     HDassert(type);
318     HDassert(tcpl_id != H5P_DEFAULT);
319 
320     /* Check if we are allowed to write to this file */
321     if(0 == (H5F_INTENT(file) & H5F_ACC_RDWR))
322         HGOTO_ERROR(H5E_DATATYPE, H5E_WRITEERROR, FAIL, "no write intent on file")
323 
324     /*
325      * Check arguments.  We cannot commit an immutable type because H5Tclose()
326      * normally fails on such types (try H5Tclose(H5T_NATIVE_INT)) but closing
327      * a named type should always succeed.
328      */
329     if(H5T_STATE_NAMED == type->shared->state || H5T_STATE_OPEN == type->shared->state)
330 	HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "datatype is already committed")
331     if(H5T_STATE_IMMUTABLE == type->shared->state)
332 	HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "datatype is immutable")
333 
334     /* Check for a "sensible" datatype to store on disk */
335     if(H5T_is_sensible(type) <= 0)
336         HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "datatype is not sensible")
337 
338     /* Mark datatype as being on disk now.  This step changes the size of
339      *  datatype as stored on disk.
340      */
341     if(H5T_set_loc(type, file, H5T_LOC_DISK) < 0)
342         HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "cannot mark datatype on disk")
343 
344     /* Reset datatype location and path */
345     if(H5O_loc_reset(&temp_oloc) < 0)
346 	HGOTO_ERROR(H5E_SYM, H5E_CANTRESET, FAIL, "unable to initialize location")
347     if(H5G_name_reset(&temp_path) < 0)
348 	HGOTO_ERROR(H5E_SYM, H5E_CANTRESET, FAIL, "unable to initialize path")
349     loc_init = TRUE;
350 
351     /* Set the latest format, if requested */
352     if(H5F_USE_LATEST_FLAGS(file, H5F_LATEST_DATATYPE))
353         if(H5T_set_latest_version(type) < 0)
354             HGOTO_ERROR(H5E_DATASET, H5E_CANTSET, FAIL, "can't set latest version of datatype")
355 
356     /* Calculate message size infomation, for creating object header */
357     dtype_size = H5O_msg_size_f(file, tcpl_id, H5O_DTYPE_ID, type, (size_t)0);
358     HDassert(dtype_size);
359 
360     /*
361      * Create the object header and open it for write access. Insert the data
362      * type message and then give the object header a name.
363      */
364     if(H5O_create(file, dxpl_id, dtype_size, (size_t)1, tcpl_id, &temp_oloc) < 0)
365 	HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to create datatype object header")
366     if(H5O_msg_create(&temp_oloc, H5O_DTYPE_ID, H5O_MSG_FLAG_CONSTANT | H5O_MSG_FLAG_DONTSHARE, H5O_UPDATE_TIME, type, dxpl_id) < 0)
367 	HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to update type header message")
368 
369     /* Copy the new object header's location into the datatype, taking ownership of it */
370     if(H5O_loc_copy(&(type->oloc), &temp_oloc, H5_COPY_SHALLOW) < 0)
371 	HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to copy datatype location")
372     if(H5G_name_copy(&(type->path), &temp_path, H5_COPY_SHALLOW) < 0)
373 	HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to copy datatype location")
374     loc_init = FALSE;
375 
376     /* Set the shared info fields */
377     H5T_update_shared(type);
378     type->shared->state = H5T_STATE_OPEN;
379     type->shared->fo_count = 1;
380 
381     /* Add datatype to the list of open objects in the file */
382     if(H5FO_top_incr(type->sh_loc.file, type->sh_loc.u.loc.oh_addr) < 0)
383         HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINC, FAIL, "can't incr object ref. count")
384     if(H5FO_insert(type->sh_loc.file, type->sh_loc.u.loc.oh_addr, type->shared, TRUE) < 0)
385         HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINSERT, FAIL, "can't insert datatype into list of open objects")
386 
387     /* Mark datatype as being on memory again.  Since this datatype may still be
388      *  used in memory after committed to disk, change its size back as in memory.
389      */
390     if(H5T_set_loc(type, NULL, H5T_LOC_MEMORY) < 0)
391         HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "cannot mark datatype in memory")
392 
393 done:
394     if(ret_value < 0) {
395         if(loc_init) {
396             H5O_loc_free(&temp_oloc);
397             H5G_name_free(&temp_path);
398         } /* end if */
399         if((type->shared->state == H5T_STATE_TRANSIENT || type->shared->state == H5T_STATE_RDONLY) && (type->sh_loc.type == H5O_SHARE_TYPE_COMMITTED)) {
400             if(H5O_dec_rc_by_loc(&(type->oloc), dxpl_id) < 0)
401                 HDONE_ERROR(H5E_DATATYPE, H5E_CANTDEC, FAIL, "unable to decrement refcount on newly created object")
402 	    if(H5O_close(&(type->oloc), NULL) < 0)
403                 HDONE_ERROR(H5E_DATATYPE, H5E_CLOSEERROR, FAIL, "unable to release object header")
404             if(H5O_delete(file, dxpl_id, type->sh_loc.u.loc.oh_addr) < 0)
405                 HDONE_ERROR(H5E_DATATYPE, H5E_CANTDELETE, FAIL, "unable to delete object header")
406 	    type->sh_loc.type = H5O_SHARE_TYPE_UNSHARED;
407 	} /* end if */
408     } /* end if */
409 
410     FUNC_LEAVE_NOAPI(ret_value)
411 } /* H5T__commit() */
412 
413 
414 /*-------------------------------------------------------------------------
415  * Function:	H5Tcommitted
416  *
417  * Purpose:	Determines if a datatype is committed or not.
418  *
419  * Return:	Success:	TRUE if committed, FALSE otherwise.
420  *
421  *		Failure:	Negative
422  *
423  * Programmer:	Robb Matzke
424  *              Thursday, June  4, 1998
425  *
426  *-------------------------------------------------------------------------
427  */
428 htri_t
H5Tcommitted(hid_t type_id)429 H5Tcommitted(hid_t type_id)
430 {
431     H5T_t	*type;          /* Datatype to query */
432     htri_t      ret_value;      /* Return value */
433 
434     FUNC_ENTER_API(FAIL)
435     H5TRACE1("t", "i", type_id);
436 
437     /* Check arguments */
438     if(NULL == (type = (H5T_t *)H5I_object_verify(type_id, H5I_DATATYPE)))
439 	HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype")
440 
441     /* Set return value */
442     ret_value = H5T_committed(type);
443 
444 done:
445     FUNC_LEAVE_API(ret_value)
446 } /* end H5Tcommitted() */
447 
448 
449 /*-------------------------------------------------------------------------
450  * Function:	H5T_committed
451  *
452  * Purpose:	Determines if a datatype is committed or not.
453  *
454  * Return:	Success:	TRUE if committed, FALSE otherwise.
455  *
456  * Programmer:	Quincey Koziol
457  *              Wednesday, September 24, 2003
458  *
459  *-------------------------------------------------------------------------
460  */
461 htri_t
H5T_committed(const H5T_t * type)462 H5T_committed(const H5T_t *type)
463 {
464     /* Use no-init for efficiency */
465     FUNC_ENTER_NOAPI_NOINIT_NOERR
466 
467     HDassert(type);
468 
469     FUNC_LEAVE_NOAPI(H5T_STATE_OPEN == type->shared->state || H5T_STATE_NAMED == type->shared->state)
470 } /* end H5T_committed() */
471 
472 
473 /*-------------------------------------------------------------------------
474  * Function:	H5T_link
475  *
476  * Purpose:	Adjust the link count for an object header by adding
477  *		ADJUST to the link count.
478  *
479  * Return:	Success:	New link count
480  *		Failure:	Negative
481  *
482  * Programmer:	Quincey Koziol
483  *              Friday, September 26, 2003
484  *
485  *-------------------------------------------------------------------------
486  */
487 int
H5T_link(const H5T_t * type,int adjust,hid_t dxpl_id)488 H5T_link(const H5T_t *type, int adjust, hid_t dxpl_id)
489 {
490     int ret_value = -1;         /* Return value */
491 
492     FUNC_ENTER_NOAPI(FAIL)
493 
494     HDassert(type);
495     HDassert(type->sh_loc.type == H5O_SHARE_TYPE_COMMITTED);
496 
497     /* Adjust the link count on the named datatype */
498     if((ret_value = H5O_link(&type->oloc, adjust, dxpl_id)) < 0)
499         HGOTO_ERROR(H5E_DATATYPE, H5E_LINKCOUNT, FAIL, "unable to adjust named datatype link count")
500 
501 done:
502     FUNC_LEAVE_NOAPI(ret_value)
503 } /* end H5T_link() */
504 
505 
506 /*-------------------------------------------------------------------------
507  * Function:	H5Topen2
508  *
509  * Purpose:	Opens a named datatype using a Datatype Access Property
510  *              List.
511  *
512  * Return:	Success:	Object ID of the named datatype.
513  *		Failure:	Negative
514  *
515  * Programmer:	James Laird
516  *              Thursday July 27, 2006
517  *
518  *-------------------------------------------------------------------------
519  */
520 hid_t
H5Topen2(hid_t loc_id,const char * name,hid_t tapl_id)521 H5Topen2(hid_t loc_id, const char *name, hid_t tapl_id)
522 {
523     H5T_t      *type = NULL;           /* Datatype opened in file */
524     H5G_loc_t	 loc;                   /* Group location of object to open */
525     H5G_name_t   path;            	/* Datatype group hier. path */
526     H5O_loc_t    oloc;            	/* Datatype object location */
527     H5O_type_t   obj_type;              /* Type of object at location */
528     H5G_loc_t    type_loc;              /* Group object for datatype */
529     hbool_t      obj_found = FALSE;     /* Object at 'name' found */
530     hid_t        dxpl_id = H5AC_ind_read_dxpl_id; /* dxpl to use to open datatype */
531     hid_t        ret_value = FAIL;      /* Return value */
532 
533     FUNC_ENTER_API(FAIL)
534     H5TRACE3("i", "i*si", loc_id, name, tapl_id);
535 
536     /* Check args */
537     if(H5G_loc(loc_id, &loc) < 0)
538         HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a location")
539     if(!name || !*name)
540         HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no name")
541 
542     /* Verify access property list and get correct dxpl */
543     if(H5P_verify_apl_and_dxpl(&tapl_id, H5P_CLS_TACC, &dxpl_id, loc_id, FALSE) < 0)
544         HGOTO_ERROR(H5E_DATATYPE, H5E_CANTSET, FAIL, "can't set access and transfer property lists")
545 
546     /* Set up datatype location to fill in */
547     type_loc.oloc = &oloc;
548     type_loc.path = &path;
549     H5G_loc_reset(&type_loc);
550 
551     /*
552      * Find the named datatype object header and read the datatype message
553      * from it.
554      */
555     if(H5G_loc_find(&loc, name, &type_loc/*out*/, tapl_id, dxpl_id) < 0)
556         HGOTO_ERROR(H5E_DATATYPE, H5E_NOTFOUND, FAIL, "not found")
557     obj_found = TRUE;
558 
559     /* Check that the object found is the correct type */
560     if(H5O_obj_type(&oloc, &obj_type, dxpl_id) < 0)
561         HGOTO_ERROR(H5E_DATATYPE, H5E_CANTGET, FAIL, "can't get object type")
562     if(obj_type != H5O_TYPE_NAMED_DATATYPE)
563         HGOTO_ERROR(H5E_DATATYPE, H5E_BADTYPE, FAIL, "not a named datatype")
564 
565     /* Open it */
566     if(NULL == (type = H5T_open(&type_loc, dxpl_id)))
567         HGOTO_ERROR(H5E_DATATYPE, H5E_CANTOPENOBJ, FAIL, "unable to open named datatype")
568 
569     /* Register the type and return the ID */
570     if((ret_value = H5I_register(H5I_DATATYPE, type, TRUE)) < 0)
571         HGOTO_ERROR(H5E_DATATYPE, H5E_CANTREGISTER, FAIL, "unable to register named datatype")
572 
573 done:
574     if(ret_value < 0) {
575         if(type != NULL)
576             H5T_close(type);
577         else {
578             if(obj_found && H5F_addr_defined(type_loc.oloc->addr))
579                 H5G_loc_free(&type_loc);
580         } /* end else */
581     } /* end if */
582 
583     FUNC_LEAVE_API(ret_value)
584 } /* end H5Topen2() */
585 
586 
587 /*-------------------------------------------------------------------------
588  * Function:	H5Tget_create_plist
589  *
590  * Purpose:	Returns a copy of the datatype creation property list.
591  *
592  * Return:	Success:	ID for a copy of the datatype creation
593  *				property list.  The property list ID should be
594  *				released by calling H5Pclose().
595  *
596  *		Failure:	FAIL
597  *
598  * Programmer:	Quincey Koziol
599  *		Tuesday, November 28, 2006
600  *
601  *-------------------------------------------------------------------------
602  */
603 hid_t
H5Tget_create_plist(hid_t dtype_id)604 H5Tget_create_plist(hid_t dtype_id)
605 {
606     H5T_t	        *type;          /* Datatype object for ID */
607     H5P_genplist_t      *tcpl_plist;    /* Existing datatype creation propertty list */
608     hid_t		new_tcpl_id = FAIL;     /* New datatype creation property list */
609     herr_t              status;         /* Generic status value */
610     hid_t		ret_value;      /* Return value */
611 
612     FUNC_ENTER_API(FAIL)
613     H5TRACE1("i", "i", dtype_id);
614 
615     /* Check arguments */
616     if(NULL == (type = (H5T_t *)H5I_object_verify(dtype_id, H5I_DATATYPE)))
617 	HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype")
618 
619     /* Copy the default datatype creation property list */
620     if(NULL == (tcpl_plist = (H5P_genplist_t *)H5I_object(H5P_LST_DATATYPE_CREATE_ID_g)))
621          HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "can't get default creation property list")
622     if((new_tcpl_id = H5P_copy_plist(tcpl_plist, TRUE)) < 0)
623         HGOTO_ERROR(H5E_DATATYPE, H5E_CANTGET, FAIL, "unable to copy the creation property list")
624 
625     /* Check if the datatype is committed */
626     if((status = H5T_committed(type)) < 0)
627         HGOTO_ERROR(H5E_DATATYPE, H5E_CANTGET, FAIL, "can't check whether datatype is committed")
628 
629     /* Retrieve further information, if the datatype is committed */
630     if(status > 0) {
631         H5P_genplist_t  *new_plist;     /* New datatype creation property list */
632 
633         /* Get property list object for new TCPL */
634         if(NULL == (new_plist = (H5P_genplist_t *)H5I_object(new_tcpl_id)))
635             HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "can't get property list")
636 
637         /* Retrieve any object creation properties */
638         if(H5O_get_create_plist(&type->oloc, H5AC_ind_read_dxpl_id, new_plist) < 0)
639             HGOTO_ERROR(H5E_DATATYPE, H5E_CANTGET, FAIL, "can't get object creation info")
640     } /* end if */
641 
642     /* Set the return value */
643     ret_value = new_tcpl_id;
644 
645 done:
646     if(ret_value < 0)
647         if(new_tcpl_id > 0)
648             if(H5I_dec_app_ref(new_tcpl_id) < 0)
649                 HDONE_ERROR(H5E_DATATYPE, H5E_CANTDEC, FAIL, "unable to close temporary object")
650 
651     FUNC_LEAVE_API(ret_value)
652 } /* end H5Tget_create_plist() */
653 
654 
655 /*-------------------------------------------------------------------------
656  * Function:	H5T_open
657  *
658  * Purpose:	Open a named datatype.
659  *
660  * Return:	Success:	Ptr to a new datatype.
661  *
662  *		Failure:	NULL
663  *
664  * Programmer:	Robb Matzke
665  *              Monday, June  1, 1998
666  *
667  *-------------------------------------------------------------------------
668  */
669 H5T_t *
H5T_open(const H5G_loc_t * loc,hid_t dxpl_id)670 H5T_open(const H5G_loc_t *loc, hid_t dxpl_id)
671 {
672     H5T_shared_t   *shared_fo = NULL;
673     H5T_t          *dt = NULL;
674     H5T_t          *ret_value = NULL;   /* Return value */
675 
676     FUNC_ENTER_NOAPI(NULL)
677 
678     HDassert(loc);
679 
680     /* Check if datatype was already open */
681     if(NULL == (shared_fo = (H5T_shared_t *)H5FO_opened(loc->oloc->file, loc->oloc->addr))) {
682         /* Clear any errors from H5FO_opened() */
683         H5E_clear_stack(NULL);
684 
685         /* Open the datatype object */
686         if(NULL == (dt = H5T_open_oid(loc, dxpl_id)))
687             HGOTO_ERROR(H5E_DATATYPE, H5E_NOTFOUND, NULL, "not found")
688 
689         /* Add the datatype to the list of opened objects in the file */
690         if(H5FO_insert(dt->sh_loc.file, dt->sh_loc.u.loc.oh_addr, dt->shared, FALSE) < 0)
691             HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINSERT, NULL, "can't insert datatype into list of open objects")
692 
693         /* Increment object count for the object in the top file */
694         if(H5FO_top_incr(dt->sh_loc.file, dt->sh_loc.u.loc.oh_addr) < 0)
695             HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINC, NULL, "can't increment object count")
696 
697         /* Mark any datatypes as being in memory now */
698         if(H5T_set_loc(dt, NULL, H5T_LOC_MEMORY) < 0)
699             HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, NULL, "invalid datatype location")
700 
701         dt->shared->fo_count = 1;
702     } /* end if */
703     else {
704         if(NULL == (dt = H5FL_MALLOC(H5T_t)))
705             HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "can't allocate space for datatype")
706 
707 #if defined(H5_USING_MEMCHECKER) || !defined(NDEBUG)
708         /* Clear object location */
709         if(H5O_loc_reset(&(dt->oloc)) < 0)
710             HGOTO_ERROR(H5E_DATATYPE, H5E_CANTOPENOBJ, NULL, "unable to reset location")
711 
712         /* Clear path name */
713         if(H5G_name_reset(&(dt->path)) < 0)
714             HGOTO_ERROR(H5E_DATATYPE, H5E_CANTOPENOBJ, NULL, "unable to reset path")
715 #endif /* H5_USING_MEMCHECKER */
716 
717         /* Shallow copy (take ownership) of the object location object */
718         if(H5O_loc_copy(&dt->oloc, loc->oloc, H5_COPY_SHALLOW) < 0)
719             HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCOPY, NULL, "can't copy object location")
720 
721         /* Shallow copy (take ownership) of the group hier. path */
722         if(H5G_name_copy(&(dt->path), loc->path, H5_COPY_SHALLOW) < 0)
723             HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCOPY, NULL, "can't copy path")
724 
725         /* Set the shared component info */
726         H5T_update_shared(dt);
727 
728         /* Point to shared datatype info */
729         dt->shared = shared_fo;
730 
731         /* Mark any datatypes as being in memory now */
732         if(H5T_set_loc(dt, NULL, H5T_LOC_MEMORY) < 0)
733             HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, NULL, "invalid datatype location")
734 
735         /* Increment ref. count on shared info */
736         shared_fo->fo_count++;
737 
738         /* Check if the object has been opened through the top file yet */
739         if(H5FO_top_count(dt->sh_loc.file, dt->sh_loc.u.loc.oh_addr) == 0) {
740             /* Open the object through this top file */
741             if(H5O_open(&(dt->oloc)) < 0)
742                 HGOTO_ERROR(H5E_DATATYPE, H5E_CANTOPENOBJ, NULL, "unable to open object header")
743         } /* end if */
744 
745         /* Increment object count for the object in the top file */
746         if(H5FO_top_incr(dt->sh_loc.file, dt->sh_loc.u.loc.oh_addr) < 0)
747             HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINC, NULL, "can't increment object count")
748     } /* end else */
749 
750     ret_value = dt;
751 
752 done:
753     if(ret_value == NULL) {
754         if(dt) {
755             if(shared_fo == NULL)   /* Need to free shared fo */
756                 dt->shared = H5FL_FREE(H5T_shared_t, dt->shared);
757 
758             H5O_loc_free(&(dt->oloc));
759             H5G_name_free(&(dt->path));
760 
761             dt = H5FL_FREE(H5T_t, dt);
762         } /* end if */
763 
764         if(shared_fo)
765             shared_fo->fo_count--;
766     } /* end if */
767 
768     FUNC_LEAVE_NOAPI(ret_value)
769 } /* end H5T_open() */
770 
771 
772 /*-------------------------------------------------------------------------
773  * Function:	H5T_open_oid
774  *
775  * Purpose:	Open a named datatype.
776  *
777  * Return:	Success:	Ptr to a new datatype.
778  *
779  *		Failure:	NULL
780  *
781  * Programmer:	Quincey Koziol
782  *              Wednesday, March 17, 1999
783  *
784  *-------------------------------------------------------------------------
785  */
786 static H5T_t *
H5T_open_oid(const H5G_loc_t * loc,hid_t dxpl_id)787 H5T_open_oid(const H5G_loc_t *loc, hid_t dxpl_id)
788 {
789     H5T_t *dt = NULL;          /* Datatype from the file */
790     H5T_t *ret_value = NULL;   /* Return value */
791 
792     FUNC_ENTER_NOAPI_NOINIT
793 
794     HDassert(loc);
795 
796     /* Open named datatype object in file */
797     if(H5O_open(loc->oloc) < 0)
798 	HGOTO_ERROR(H5E_DATATYPE, H5E_CANTOPENOBJ, NULL, "unable to open named datatype")
799 
800     /* Deserialize the datatype message into a datatype in memory */
801     if(NULL == (dt = (H5T_t *)H5O_msg_read(loc->oloc, H5O_DTYPE_ID, NULL, dxpl_id)))
802 	HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, NULL, "unable to load type message from object header")
803 
804     /* Mark the type as named and open */
805     dt->shared->state = H5T_STATE_OPEN;
806 
807     /* Shallow copy (take ownership) of the object location object */
808     if(H5O_loc_copy(&dt->oloc, loc->oloc, H5_COPY_SHALLOW) < 0)
809         HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCOPY, NULL, "can't copy object location")
810 
811     /* Shallow copy (take ownership) of the group hier. path */
812     if(H5G_name_copy(&(dt->path), loc->path, H5_COPY_SHALLOW) < 0)
813         HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCOPY, NULL, "can't copy path")
814 
815     /* Set the shared component info */
816     H5T_update_shared(dt);
817 
818     /* Set return value */
819     ret_value = dt;
820 
821 done:
822     if(ret_value == NULL)
823         if(dt == NULL)
824             H5O_close(loc->oloc, NULL);
825 
826     FUNC_LEAVE_NOAPI(ret_value)
827 } /* end H5T_open_oid() */
828 
829 
830 /*-------------------------------------------------------------------------
831  * Function:	H5T_update_shared
832  *
833  * Purpose:	Update the shared location information from the object location
834  *
835  * Return:	Non-negative on success/Negative on failure
836  *
837  * Programmer:	Quincey Koziol
838  *              Friday, April 13, 2007
839  *
840  *-------------------------------------------------------------------------
841  */
842 herr_t
H5T_update_shared(H5T_t * dt)843 H5T_update_shared(H5T_t *dt)
844 {
845     FUNC_ENTER_NOAPI_NOINIT_NOERR
846 
847     HDassert(dt);
848 
849     /* Set the shared location fields from the named datatype info */
850     H5O_UPDATE_SHARED(&(dt->sh_loc), H5O_SHARE_TYPE_COMMITTED, dt->oloc.file, H5O_DTYPE_ID, 0, dt->oloc.addr)
851 
852     FUNC_LEAVE_NOAPI(SUCCEED)
853 } /* H5T_update_shared() */
854 
855