/*-------------------------------------------------------------------------- NAME H5R__dereference PURPOSE Opens the HDF5 object referenced. USAGE hid_t H5R__dereference(ref, oapl_id, ref_type, ref) H5F_t *file; IN: File the object being dereferenced is within hid_t oapl_id; IN: Object access property list ID H5R_type_t ref_type; IN: Type of reference void *ref; IN: Reference to open. RETURNS Valid ID on success, Negative on failure DESCRIPTION Given a reference to some object, open that object and return an ID for that object. GLOBAL VARIABLES COMMENTS, BUGS, ASSUMPTIONS Currently only set up to work with references to datasets EXAMPLES REVISION LOG Raymond Lu 13 July 2011 I added the OAPL_ID parameter for the object being referenced. It only supports dataset access property list currently. M. Scot Breitenfeld 3 March 2015 Added a check for undefined reference pointer. --------------------------------------------------------------------------*/ hid_t H5R__dereference(H5F_t *file, hid_t oapl_id, H5R_type_t ref_type, const void *_ref) { H5O_loc_t oloc; /* Object location */ H5G_name_t path; /* Path of object */ H5G_loc_t loc; /* Group location */ unsigned rc; /* Reference count of object */ H5O_type_t obj_type; /* Type of object */ hid_t ret_value = H5I_INVALID_HID; /* Return value */ FUNC_ENTER_PACKAGE_VOL HDassert(_ref); HDassert(ref_type > H5R_BADTYPE && ref_type < H5R_MAXTYPE); HDassert(file); /* Initialize the object location */ H5O_loc_reset(&oloc); oloc.file = file; switch (ref_type) { case H5R_OBJECT: { oloc.addr = *(const hobj_ref_t *)_ref; /* Only object references currently supported */ if (!H5F_addr_defined(oloc.addr) || oloc.addr == 0) HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, H5I_INVALID_HID, "Undefined reference pointer") break; } case H5R_DATASET_REGION: { H5HG_t hobjid; /* Heap object ID */ uint8_t *buf; /* Buffer to store serialized selection in */ const uint8_t *p; /* Pointer to OID to store */ /* Get the heap ID for the dataset region */ p = (const uint8_t *)_ref; H5F_addr_decode(oloc.file, &p, &(hobjid.addr)); UINT32DECODE(p, hobjid.idx); if (!H5F_addr_defined(hobjid.addr) || hobjid.addr == 0) HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, H5I_INVALID_HID, "Undefined reference pointer") /* Get the dataset region from the heap (allocate inside routine) */ if(NULL == (buf = (uint8_t *)H5HG_read(oloc.file, &hobjid, NULL, NULL))) HGOTO_ERROR(H5E_REFERENCE, H5E_READERROR, H5I_INVALID_HID, "Unable to read dataset region information") /* Get the object oid for the dataset */ p = buf; H5F_addr_decode(oloc.file, &p, &(oloc.addr)); /* Free the buffer allocated in H5HG_read() */ H5MM_xfree(buf); break; } /* end case H5R_DATASET_REGION */ case H5R_BADTYPE: case H5R_MAXTYPE: default: HDassert("unknown reference type" && 0); HGOTO_ERROR(H5E_REFERENCE, H5E_UNSUPPORTED, H5I_INVALID_HID, "internal error (unknown reference type)") } /* end switch */ /* Get the # of links for object, and its type * (To check to make certain that this object hasn't been deleted * since the reference was created) */ if(H5O_get_rc_and_type(&oloc, &rc, &obj_type) < 0 || 0 == rc) HGOTO_ERROR(H5E_REFERENCE, H5E_LINKCOUNT, H5I_INVALID_HID, "dereferencing deleted object") /* Construct a group location for opening the object */ H5G_name_reset(&path); loc.oloc = &oloc; loc.path = &path; /* Open the object */ switch (obj_type) { case H5O_TYPE_GROUP: { H5G_t *group; /* Pointer to group to open */ if(NULL == (group = H5G_open(&loc))) HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, H5I_INVALID_HID, "not found") /* Create an atom for the group */ if((ret_value = H5I_register(H5I_GROUP, group, TRUE)) < 0) { H5G_close(group); HGOTO_ERROR(H5E_SYM, H5E_CANTREGISTER, H5I_INVALID_HID, "can't register group") } /* end if */ break; } case H5O_TYPE_NAMED_DATATYPE: { H5T_t *type; /* Pointer to datatype to open */ if(NULL == (type = H5T_open(&loc))) HGOTO_ERROR(H5E_DATATYPE, H5E_NOTFOUND, H5I_INVALID_HID, "not found") /* Create an atom for the datatype */ if((ret_value = H5I_register(H5I_DATATYPE, type, TRUE)) < 0) { H5T_close(type); HGOTO_ERROR(H5E_DATATYPE, H5E_CANTREGISTER, H5I_INVALID_HID, "can't register datatype") } /* end if */ break; }
/*------------------------------------------------------------------------- * Function: test_ooo_indices * * Purpose: Tests that indices can be stored out of order. This can * happen when the indices "wrap around" due to many * insertions and deletions (for example, from rewriting a * VL dataset). * * Return: Success: 0 * * Failure: number of errors * * Programmer: Neil Fortner * Monday, October 26, 2009 * * Modifications: * *------------------------------------------------------------------------- */ static int test_ooo_indices(hid_t fapl) { hid_t file = -1; H5F_t *f = NULL; unsigned i, j; H5HG_t *obj = NULL; herr_t status; int nerrors=0; char filename[1024]; TESTING("out of order indices"); if(NULL == (obj = (H5HG_t *)HDmalloc(2000 * sizeof(*obj)))) goto error; /* Open a clean file */ h5_fixname(FILENAME[4], fapl, filename, sizeof filename); if((file = H5Fcreate(filename, H5F_ACC_TRUNC, H5P_DEFAULT, fapl)) < 0) goto error; if(NULL == (f = (H5F_t *)H5I_object(file))) { H5_FAILED(); puts(" Unable to create file"); goto error; } /* end if */ /* Alternately insert 1000 entries and remove the previous group of 1000 * entries, until the indices wrap around */ for(i=0; i<66; i++) { /* Insert 1000 entries. The index into the obj array will alternate up * and down by 1000 so the previous set of insertions is preserved and * can be deleted. */ for(j=1000*((~i&1)); j<1000*((~i&1)+1); j++) { H5Eclear2(H5E_DEFAULT); status = H5HG_insert(f, H5P_DATASET_XFER_DEFAULT, sizeof(j), &j, &obj[j]); if (status<0) GHEAP_REPEATED_ERR(" Unable to insert object into global heap") /* Check that the index is as expected */ if(obj[j].idx != ((1000 * i) + j - (1000 * ((~i & 1)))) % ((1u << 16) - 1) + 1) GHEAP_REPEATED_ERR(" Unexpected global heap index"); } /* end for */ /* Remove the previous 1000 entries */ if(i>0) for(j=1000*(i&1); j<1000*((i&1)+1); j++) { H5Eclear2(H5E_DEFAULT); status = H5HG_remove(f, H5P_DATASET_XFER_DEFAULT, &obj[j]); if (status<0) GHEAP_REPEATED_ERR(" Unable to remove object from global heap"); } /* end for */ } /* end for */ /* The indices should have "wrapped around" on the last iteration */ HDassert(obj[534].idx == 65535); HDassert(obj[535].idx == 1); /* Reopen the file */ if (H5Fclose(file)<0) goto error; if((file = H5Fopen(filename, H5F_ACC_RDWR, fapl)) < 0) goto error; if(NULL == (f = (H5F_t *)H5I_object(file))) { H5_FAILED(); puts(" Unable to open file"); goto error; } /* end if */ /* Read the objects to make sure the heap is still readable */ for(i=0; i<1000; i++) { if(NULL == H5HG_read(f, H5P_DATASET_XFER_DEFAULT, &obj[i], &j, NULL)) goto error; if(i != j) { H5_FAILED(); puts(" Incorrect read value"); goto error; } /* end if */ } /* end for */ if (H5Fclose(file)<0) goto error; if (nerrors) goto error; HDfree(obj); obj = NULL; PASSED(); return 0; error: H5E_BEGIN_TRY { H5Fclose(file); } H5E_END_TRY; if(obj) HDfree(obj); return MAX(1, nerrors); } /* end test_ooo_indices */
/*------------------------------------------------------------------------- * Function: test_1 * * Purpose: Writes a sequence of objects to the global heap where each * object is larger than the one before. * * Return: Success: 0 * * Failure: number of errors * * Programmer: Robb Matzke * Tuesday, March 31, 1998 * * Modifications: * *------------------------------------------------------------------------- */ static int test_1 (hid_t fapl) { hid_t file = -1; H5F_t *f = NULL; H5HG_t obj[1024]; uint8_t out[1024]; uint8_t in[1024]; int i; size_t size; herr_t status; int nerrors = 0; char filename[1024]; TESTING("monotonically increasing lengths"); /* Open a clean file */ h5_fixname(FILENAME[0], fapl, filename, sizeof filename); if((file = H5Fcreate(filename, H5F_ACC_TRUNC, H5P_DEFAULT, fapl)) < 0) goto error; if(NULL == (f = (H5F_t *)H5I_object(file))) { H5_FAILED(); puts(" Unable to create file"); goto error; } /* * Write the objects, monotonically increasing in length. Since this is * a clean file, the addresses allocated for the collections should also * be monotonically increasing. */ for(i = 0; i < 1024; i++) { size = i + 1; HDmemset(out, 'A' + i % 26, size); H5Eclear2(H5E_DEFAULT); status = H5HG_insert(f, H5P_DATASET_XFER_DEFAULT, size, out, obj + i); if(status < 0) { H5_FAILED(); puts(" Unable to insert object into global heap"); nerrors++; } else if(i && H5F_addr_gt(obj[i - 1].addr, obj[i].addr)) { H5_FAILED(); puts(" Collection addresses are not monotonically increasing"); nerrors++; } } /* * Now try to read each object back. */ for(i = 0; i < 1024; i++) { size = i + 1; HDmemset(out, 'A' + i % 26, size); H5Eclear2(H5E_DEFAULT); if(NULL == H5HG_read(f, H5P_DATASET_XFER_DEFAULT, obj + i, in, NULL)) { H5_FAILED(); puts(" Unable to read object"); nerrors++; } else if(HDmemcmp(in, out, size)) { H5_FAILED(); puts(" Value read doesn't match value written"); nerrors++; } } if(H5Fclose(file) < 0) goto error; if(nerrors) goto error; PASSED(); return 0; error: H5E_BEGIN_TRY { H5Fclose(file); } H5E_END_TRY; return MAX(1, nerrors); }
/*------------------------------------------------------------------------- * Function: test_2 * * Purpose: Writes a sequence of objects to the global heap where each * object is smaller than the one before. * * Return: Success: 0 * * Failure: number of errors * * Programmer: Robb Matzke * Tuesday, March 31, 1998 * * Modifications: * *------------------------------------------------------------------------- */ static int test_2 (hid_t fapl) { hid_t file = -1; H5F_t *f = NULL; H5HG_t obj[1024]; uint8_t out[1024]; uint8_t in[1024]; int i; size_t size; int nerrors = 0; char filename[1024]; TESTING("monotonically decreasing lengths"); /* Open a clean file */ h5_fixname(FILENAME[1], fapl, filename, sizeof filename); if((file = H5Fcreate(filename, H5F_ACC_TRUNC, H5P_DEFAULT, fapl)) < 0) goto error; if(NULL == (f = (H5F_t *)H5I_object(file))) { H5_FAILED(); puts(" Unable to create file"); goto error; } /* * Write the objects, monotonically decreasing in length. */ for (i=0; i<1024; i++) { size = 1024-i; memset (out, 'A'+i%26, size); H5Eclear2(H5E_DEFAULT); if (H5HG_insert (f, H5P_DATASET_XFER_DEFAULT, size, out, obj+i)<0) { H5_FAILED(); puts(" Unable to insert object into global heap"); nerrors++; } } /* * Now try to read each object back. */ for (i=0; i<1024; i++) { size = 1024-i; memset (out, 'A'+i%26, size); H5Eclear2(H5E_DEFAULT); if (NULL==H5HG_read (f, H5P_DATASET_XFER_DEFAULT, obj+i, in, NULL)) { H5_FAILED(); puts(" Unable to read object"); nerrors++; } else if (memcmp (in, out, size)) { H5_FAILED(); puts(" Value read doesn't match value written"); nerrors++; } } if (H5Fclose(file)<0) goto error; if (nerrors) goto error; PASSED(); return 0; error: H5E_BEGIN_TRY { H5Fclose(file); } H5E_END_TRY; return MAX(1, nerrors); }