Hi to all,

I am trying to establish a sandbox application that stores an object inside a file "red/SDS.h5" and creates a link to it in an index file under extlink_prefix_source.h5 in the current directory. Creating the link is no problem. But I have the feeling that the prefix ("red") is not stored alright. Because if I try to read the object through the link, I get a hdf5 stack trace indicating that the target file (here: "red/SDS.h5") is not present.

I attached a sample program that is based on h5_extlink.c from the official tutorial. I'd be grateful, if someone could give me a hand on this one. This is single threaded for now.

Best,
Peter

PS. using gcc 4.9.2 and hdf5 1.8.13. (fc21)

--
Peter Steinbach, Dr. rer. nat.
HPC Developer

Scionics Computer Innovation GmbH
Löscherstr. 16
01309 Dresden
fon: +49 351 210 2882
fax: +49 351 210 1689
http://www.scionics.de

Sitz der Gesellschaft:  Dresden (Main office)
Amtsgericht - Registergericht:  Dresden HRB 20337 (Commercial Registry)
Ust-IdNr.:  DE813263791 (VAT ID Number)
Geschäftsführer:  John Duperon, Jeff Oegema (Managing Directors)
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 * Copyright by The HDF Group.                                               *
 * Copyright by the Board of Trustees of the University of Illinois.         *
 * All rights reserved.                                                      *
 *                                                                           *
 * This file is part of HDF5.  The full HDF5 copyright notice, including     *
 * terms governing use, modification, and redistribution, is contained in    *
 * the files COPYING and Copyright.html.  COPYING can be found at the root   *
 * of the source code distribution tree; Copyright.html can be found at the  *
 * root level of an installed copy of the electronic HDF5 document set and   *
 * is linked from the top-level documents page.  It can also be found at     *
 * http://hdfgroup.org/HDF5/doc/Copyright.html.  If you do not have          *
 * access to either file, you may request a copy from [email protected].     *
 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */

/* This program demonstrates how to create and use "external links" in
 * HDF5.
 *
 * External links point from one HDF5 file to an object (Group, Dataset, or
 * committed Datatype) in another file.
 */

#include "hdf5.h"
#include <string.h>

#define SOURCE_FILE "extlink_source.h5"
#define TARGET_FILE "SDS.h5"
#define TARGET_PATH "red/"

#define PREFIX_SOURCE_FILE "extlink_prefix_source.h5"

#define SOFT_LINK_FILE "soft_link.h5"
#define SOFT_LINK_NAME "soft_link_to_group"
#define UD_SOFT_LINK_NAME "ud_soft_link"
#define TARGET_GROUP "target_group"

#define UD_SOFT_CLASS 65

#define HARD_LINK_FILE "hard_link.h5"
#define HARD_LINK_NAME "hard_link_to_group"
#define UD_HARD_LINK_NAME "ud_hard_link"

#define UD_HARD_CLASS 66

#define PLIST_LINK_PROP "plist_link_prop"
#define UD_PLIST_CLASS 66

#define H5FILE_NAME        "red/SDS.h5"
#define DATASETNAME "IntArray"
#define DATASETNAME_IN_GROUP "new/IntArray"
#define NX     5                      /* dataset dimensions */
#define NY     6
#define RANK   2
#define NX_SUB  3           /* hyperslab dimensions */
#define NY_SUB  4
#define READ_NX 7           /* output buffer dimensions */
#define READ_NY 7
#define READ_NZ  3
#define RANK         2
#define RANK_OUT     3


/* External link prefix example
 *
 * Uses a group access property list to set a "prefix" for the filenames
 * accessed through an external link.
 *
 * Group access property lists inherit from link access property lists;
 * the external link prefix property is actually a property of LAPLs.
 *
 * This example requires a "red" directory and a "blue" directory to exist
 * where it is run (so to run this example on Unix, first mkdir red and mkdir
 * blue).
 */
static void extlink_prefix_example()
{
    hid_t source_file_id, red_file_id, blue_file_id;
    hid_t group_id, group2_id;
    hid_t gapl_id;

    /* Create three files, a source and two targets.  The targets will have
     * the same name, but one will be located in the red directory and one will
     * be located in the blue directory */
    source_file_id = H5Fcreate(PREFIX_SOURCE_FILE, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT);
    red_file_id = H5Fcreate("red/useful.h5", H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT);
    blue_file_id = H5Fcreate("blue/prefix_target.h5", H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT);

    /* This test needs a red and a blue directory in the filesystem. If they're not present,
     * trying to create the files above will fail.
     */
    if(red_file_id < 0 || blue_file_id < 0)
      printf("This test requires directories named 'red' and 'blue' to exist. Did you forget to create them?\n");

    /* Create an external link in the source file pointing to the root group of
     * a file named prefix_target.h5.  This file doesn't exist in the current
     * directory, but the files in the red and blue directories both have this
     * name.
     */
    H5Lcreate_external("useful.h5", "/IntArray", source_file_id, "ext_link", H5P_DEFAULT, H5P_DEFAULT);

    /* If we tried to traverse the external link now, we would fail (since the
     * file it points to doesn't exist).  Instead, we'll create a group access
     * property list that will provide a prefix path to the external link.
     * Group access property lists inherit the properties of link access
     * property lists.
     */
    gapl_id = H5Pcreate(H5P_GROUP_ACCESS);
    H5Pset_elink_prefix(gapl_id, "red/");

    /* Now if we traverse the external link, HDF5 will look for an external
     * file named red/prefix_target.h5, which exists.
     * To pass the group access property list, we need to use H5Gopen2.
     */
    group_id = H5Gopen2(source_file_id, "ext_link", gapl_id);

    /* Now we can use the open group ID to create a new group inside the
     * "red" file.
     */
    group2_id = H5Gcreate2(group_id, "pink", H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);

    /* Close both groups. */
    H5Gclose(group2_id);
    H5Gclose(group_id);

    /* /\* If we change the prefix, the same external link can find a file in the blue */
    /*  * directory. */
    /*  *\/ */
    /* H5Pset_elink_prefix(gapl_id, "blue/"); */
    /* group_id = H5Gopen2(source_file_id, "ext_link", gapl_id); */
    /* group2_id = H5Gcreate2(group_id, "sky blue", H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT); */

    /* /\* Close both groups. *\/ */
    /* H5Gclose(group2_id); */
    /* H5Gclose(group_id); */

    /* /\* Each file has had a group created inside it using the same external link. *\/ */
    /* group_id = H5Gopen2(red_file_id, "pink", H5P_DEFAULT); */
    /* group2_id = H5Gopen2(blue_file_id, "sky blue", H5P_DEFAULT); */

    /* /\* Clean up our open IDs *\/ */
    /* H5Gclose(group2_id); */
    /* H5Gclose(group_id); */
    H5Pclose(gapl_id);
    H5Fclose(blue_file_id);
    H5Fclose(red_file_id);
    H5Fclose(source_file_id);

    /* User-defined links can expand on the ability to pass in parameters
     * using an access property list; for instance, a user-defined link
     * might function like an external link but allow the full filename to be
     * passed in through the access property list.
     */
}

static void my_extlink_prefix_example(const char* _tgt_filename, const char* _tgt_obj)
{
    hid_t source_file_id, red_file_id;
    hid_t group_id, group2_id;
    hid_t gapl_id;

    /* Create three files, a source and two targets.  The targets will have
     * the same name, but one will be located in the red directory and one will
     * be located in the blue directory */
    source_file_id = H5Fcreate(PREFIX_SOURCE_FILE, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT);

    printf("opening %s\n",_tgt_filename);
    //    red_file_id = H5Fcreate(_tgt_filename, H5F_ACC_RDONLY, H5P_DEFAULT, H5P_DEFAULT);
    red_file_id = H5Fopen(_tgt_filename, H5F_ACC_RDONLY, H5P_DEFAULT);

    /* This test needs a red and a blue directory in the filesystem. If they're not present,
     * trying to create the files above will fail.
     */
    if(red_file_id < 0)
      printf("This test requires directories named 'red' to exist. Did you forget to create %s?\n",_tgt_filename);

    /* Create an external link in the source file pointing to the root group of
     * a file named prefix_target.h5.  This file doesn't exist in the current
     * directory, but the files in the red and blue directories both have this
     * name.
     */
    H5Lcreate_external(TARGET_FILE,
		       DATASETNAME_IN_GROUP,
		       //DATASETNAME
		       source_file_id, "ext_link", H5P_DEFAULT, H5P_DEFAULT);

    printf("%s:%s --> %s:%s\n",PREFIX_SOURCE_FILE,"ext_link",_tgt_filename,_tgt_obj);
    /* If we tried to traverse the external link now, we would fail (since the
     * file it points to doesn't exist).  Instead, we'll create a group access
     * property list that will provide a prefix path to the external link.
     * Group access property lists inherit the properties of link access
     * property lists.
     */
    gapl_id = H5Pcreate(H5P_GROUP_ACCESS);
    H5Pset_elink_prefix(gapl_id, TARGET_PATH);

    /* /\* Now if we traverse the external link, HDF5 will look for an external */
    /*  * file named red/prefix_target.h5, which exists. */
    /*  * To pass the group access property list, we need to use H5Gopen2. */
    /*  *\/ */
    /* group_id = H5Gopen2(source_file_id, "ext_link", gapl_id); */


    /* /\* Close both groups. *\/ */
    /* H5Gclose(group2_id); */
    /* H5Gclose(group_id); */

    /* /\* If we change the prefix, the same external link can find a file in the blue */
    /*  * directory. */
    /*  *\/ */
    /* H5Pset_elink_prefix(gapl_id, "blue/"); */
    /* group_id = H5Gopen2(source_file_id, "ext_link", gapl_id); */
    /* group2_id = H5Gcreate2(group_id, "sky blue", H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT); */

    /* /\* Close both groups. *\/ */
    /* H5Gclose(group2_id); */
    /* H5Gclose(group_id); */

    /* /\* Each file has had a group created inside it using the same external link. *\/ */
    /* group_id = H5Gopen2(red_file_id, "pink", H5P_DEFAULT); */
    /* group2_id = H5Gopen2(blue_file_id, "sky blue", H5P_DEFAULT); */

    /* /\* Clean up our open IDs *\/ */
    /* H5Gclose(group2_id); */
    /* H5Gclose(group_id); */
    H5Pclose(gapl_id);
    H5Fclose(red_file_id);
    H5Fclose(source_file_id);

    /* User-defined links can expand on the ability to pass in parameters
     * using an access property list; for instance, a user-defined link
     * might function like an external link but allow the full filename to be
     * passed in through the access property list.
     */
}


int write_long (const char* _fname, const char* _dname)
{
  hid_t       file, dataset,group_id;         /* file and dataset handles */
  hid_t       datatype, dataspace;   /* handles */
  hsize_t     dimsf[2];              /* dataset dimensions */
  herr_t      status;
  int         data[NX][NY];          /* data to write */
  int         i, j;

  printf("write_long ... %s:%s\n",H5FILE_NAME,DATASETNAME);
  /*
   * Data  and output buffer initialization.
   */
  for(j = 0; j < NX; j++)
    for(i = 0; i < NY; i++)
      data[j][i] = i + j;
  /*
   * 0 1 2 3 4 5
   * 1 2 3 4 5 6
   * 2 3 4 5 6 7
   * 3 4 5 6 7 8
   * 4 5 6 7 8 9
   */

  /*
   * Create a new file using H5F_ACC_TRUNC access,
   * default file creation properties, and default file
   * access properties.
   */
    
  /* file = H5Fcreate(H5FILE_NAME, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT); */
  file = H5Fcreate(_fname, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT);
  
  /*
   * Describe the size of the array and create the data space for fixed
   * size dataset.
   */
  dimsf[0] = NX;
  dimsf[1] = NY;
  dataspace = H5Screate_simple(RANK, dimsf, NULL);

  /*
   * Define datatype for the data in the file.
   * We will store little endian INT numbers.
   */
  datatype = H5Tcopy(H5T_NATIVE_INT);
  status = H5Tset_order(datatype, H5T_ORDER_LE);

  /*
   * Create a new dataset within the file using defined dataspace and
   * datatype and default dataset creation properties.
   */
  group_id = H5Gcreate2(file, "new/", H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
  
  dataset = H5Dcreate2(group_id, _dname, datatype, dataspace,
		       H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);

  /*
   * Write the data to the dataset using default transfer properties.
   */
  status = H5Dwrite(dataset, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, H5P_DEFAULT, data);

  /*
   * Close/release resources.
   */
  H5Sclose(dataspace);
  H5Tclose(datatype);
  H5Dclose(dataset);
  H5Gclose(group_id);
  H5Fclose(file);

  return 0;

  
}

int read_long(const char* _fname, const char* _dname)
{
    hid_t       file, dataset;         /* handles */
    hid_t       datatype, dataspace;
    hid_t       memspace;
    H5T_class_t t_class;                 /* data type class */
    H5T_order_t order;                 /* data order */
    size_t      size;                  /*
				        * size of the data element
				        * stored in file
				        */
    hsize_t     dimsm[3];              /* memory space dimensions */
    hsize_t     dims_out[2];           /* dataset dimensions */
    herr_t      status;

    int         data_out[READ_NX][READ_NY][READ_NZ ]; /* output buffer */

    hsize_t      count[2];              /* size of the hyperslab in the file */
    hsize_t      offset[2];             /* hyperslab offset in the file */
    hsize_t      count_out[3];          /* size of the hyperslab in memory */
    hsize_t      offset_out[3];         /* hyperslab offset in memory */
    int          i, j, k, status_n, rank;

    for (j = 0; j < READ_NX; j++) {
	for (i = 0; i < READ_NY; i++) {
	    for (k = 0; k < READ_NZ ; k++)
		data_out[j][i][k] = 0;
	}
    }

    /*
     * Open the file and the dataset.
     */
    file = H5Fopen(_fname, H5F_ACC_RDONLY, H5P_DEFAULT);
    dataset = H5Dopen2(file, _dname, H5P_DEFAULT);

    /*
     * Get datatype and dataspace handles and then query
     * dataset class, order, size, rank and dimensions.
     */
    datatype  = H5Dget_type(dataset);     /* datatype handle */
    t_class     = H5Tget_class(datatype);
    if (t_class == H5T_INTEGER) printf("Data set has INTEGER type \n");
    order     = H5Tget_order(datatype);
    if (order == H5T_ORDER_LE) printf("Little endian order \n");

    size  = H5Tget_size(datatype);
    printf(" Data size is %d \n", (int)size);

    dataspace = H5Dget_space(dataset);    /* dataspace handle */
    rank      = H5Sget_simple_extent_ndims(dataspace);
    status_n  = H5Sget_simple_extent_dims(dataspace, dims_out, NULL);
    printf("rank %d, dimensions %lu x %lu \n", rank,
	   (unsigned long)(dims_out[0]), (unsigned long)(dims_out[1]));

    /*
     * Define hyperslab in the dataset.
     */
    offset[0] = 1;
    offset[1] = 2;
    count[0]  = NX_SUB;
    count[1]  = NY_SUB;
    status = H5Sselect_hyperslab(dataspace, H5S_SELECT_SET, offset, NULL,
				 count, NULL);

    /*
     * Define the memory dataspace.
     */
    dimsm[0] = READ_NX;
    dimsm[1] = READ_NY;
    dimsm[2] = READ_NZ ;
    memspace = H5Screate_simple(RANK_OUT,dimsm,NULL);

    /*
     * Define memory hyperslab.
     */
    offset_out[0] = 3;
    offset_out[1] = 0;
    offset_out[2] = 0;
    count_out[0]  = NX_SUB;
    count_out[1]  = NY_SUB;
    count_out[2]  = 1;
    status = H5Sselect_hyperslab(memspace, H5S_SELECT_SET, offset_out, NULL,
				 count_out, NULL);

    /*
     * Read data from hyperslab in the file into the hyperslab in
     * memory and display.
     */
    status = H5Dread(dataset, H5T_NATIVE_INT, memspace, dataspace,
		     H5P_DEFAULT, data_out);
    for (j = 0; j < READ_NX; j++) {
	for (i = 0; i < READ_NY; i++)
	  printf("%d ", data_out[j][i][0]);
	printf("\n");
    }
    /*
     * 0 0 0 0 0 0 0
     * 0 0 0 0 0 0 0
     * 0 0 0 0 0 0 0
     * 3 4 5 6 0 0 0
     * 4 5 6 7 0 0 0
     * 5 6 7 8 0 0 0
     * 0 0 0 0 0 0 0
     */

    /*
     * Close/release resources.
     */
    H5Tclose(datatype);
    H5Dclose(dataset);
    H5Sclose(dataspace);
    H5Sclose(memspace);
    H5Fclose(file);

    return 0;
}

/* Main function
 *
 * Invokes the example functions.
 */
 int main(void)
{

  write_long(H5FILE_NAME,DATASETNAME);

  printf("Testing external link prefixes.\n");
  my_extlink_prefix_example(H5FILE_NAME,DATASETNAME_IN_GROUP);

  printf("\n\nnative read.\n");
  read_long(H5FILE_NAME,DATASETNAME_IN_GROUP); 

  printf("\n\nread through link.\n");
  read_long(PREFIX_SOURCE_FILE,"ext_link"); 
  return 0;
}


_______________________________________________
Hdf-forum is for HDF software users discussion.
[email protected]
http://lists.hdfgroup.org/mailman/listinfo/hdf-forum_lists.hdfgroup.org
Twitter: https://twitter.com/hdf5

Reply via email to