MOAB: Mesh Oriented datABase  (version 5.2.1)
file.c
Go to the documentation of this file.
00001 /**
00002  * MOAB, a Mesh-Oriented datABase, is a software component for creating,
00003  * storing and accessing finite element mesh data.
00004  *
00005  * Copyright 2004 Sandia Corporation.  Under the terms of Contract
00006  * DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government
00007  * retains certain rights in this software.
00008  *
00009  * This library is free software; you can redistribute it and/or
00010  * modify it under the terms of the GNU Lesser General Public
00011  * License as published by the Free Software Foundation; either
00012  * version 2.1 of the License, or (at your option) any later version.
00013  *
00014  */
00015 
00016 #include <stdlib.h>
00017 #include <string.h>
00018 #include <assert.h>
00019 #include <H5Fpublic.h>
00020 #include <H5Ppublic.h>
00021 #include <H5Gpublic.h>
00022 #include <H5Spublic.h>
00023 #include <H5Tpublic.h>
00024 #include <H5Apublic.h>
00025 #ifdef MOAB_HAVE_HDF5_PARALLEL
00026 #include <H5FDmpi.h>
00027 #include <H5FDmpio.h>
00028 #endif
00029 #include "mhdf.h"
00030 #include "status.h"
00031 #include "names-and-paths.h"
00032 #include "util.h"
00033 #include "file-handle.h"
00034 
00035 static int make_hdf_group( const char* path, hid_t file, size_t size, mhdf_Status* status );
00036 
00037 mhdf_FileHandle mhdf_createFile( const char* filename, int overwrite, const char** elem_type_list, size_t elem_list_len,
00038                                  hid_t id_type, mhdf_Status* status )
00039 {
00040     FileHandle*   file_ptr;
00041     unsigned int  flags;
00042     unsigned char idx;
00043     size_t        i;
00044     hid_t         enum_id, group_id;
00045     int           rval;
00046     API_BEGIN;
00047 
00048     if( elem_list_len > 255 )
00049     {
00050         mhdf_setFail( status, "Element type list too long." );
00051         return NULL;
00052     }
00053     mhdf_setOkay( status );
00054 
00055     /* Create struct to hold working data */
00056     file_ptr = mhdf_alloc_FileHandle( 0, id_type, status );
00057     if( !file_ptr ) return NULL;
00058 
00059     /* Create the file */
00060     flags = overwrite ? H5F_ACC_TRUNC : H5F_ACC_EXCL;
00061     file_ptr->hdf_handle = H5Fcreate( filename, flags, H5P_DEFAULT, H5P_DEFAULT );
00062     if( file_ptr->hdf_handle < 0 )
00063     {
00064         mhdf_setFail( status, "Failed to create file \"%s\"", filename );
00065         free( file_ptr );
00066         return NULL;
00067     }
00068 
00069     /* Create file structure */
00070     if( !make_hdf_group( ROOT_GROUP, file_ptr->hdf_handle, 6, status ) ||
00071         !make_hdf_group( TAG_GROUP, file_ptr->hdf_handle, 0, status ) ||
00072         !make_hdf_group( ELEMENT_GROUP, file_ptr->hdf_handle, 8, status ) ||
00073         !make_hdf_group( NODE_GROUP, file_ptr->hdf_handle, 3, status ) ||
00074         !make_hdf_group( SET_GROUP, file_ptr->hdf_handle, 5, status ) ||
00075         !make_hdf_group( NODE_TAG_GROUP, file_ptr->hdf_handle, 0, status ) ||
00076         !make_hdf_group( SET_TAG_GROUP, file_ptr->hdf_handle, 0, status ) )
00077     {
00078         H5Fclose( file_ptr->hdf_handle );
00079         free( file_ptr );
00080         return NULL;
00081     }
00082 
00083     /* Store the max ID as an attribite on the /tstt/ group */
00084 #if defined( H5Gopen_vers ) && H5Gopen_vers > 1
00085     group_id = H5Gopen2( file_ptr->hdf_handle, ROOT_GROUP, H5P_DEFAULT );
00086 #else
00087     group_id = H5Gopen( file_ptr->hdf_handle, ROOT_GROUP );
00088 #endif
00089     rval = mhdf_create_scalar_attrib( group_id, MAX_ID_ATTRIB, H5T_NATIVE_ULONG, &file_ptr->max_id, status );
00090     H5Gclose( group_id );
00091     if( !rval )
00092     {
00093         H5Fclose( file_ptr->hdf_handle );
00094         free( file_ptr );
00095         return NULL;
00096     }
00097 
00098     /* Create the type name list in file */
00099     enum_id = H5Tenum_create( H5T_NATIVE_UCHAR );
00100     if( enum_id < 0 )
00101     {
00102         mhdf_setFail( status, "Failed to store elem type list." );
00103         H5Fclose( file_ptr->hdf_handle );
00104         free( file_ptr );
00105         return NULL;
00106     }
00107     for( i = 0; i < elem_list_len; ++i )
00108     {
00109         if( !elem_type_list[ i ] || !*elem_type_list[ i ] ) continue;
00110 
00111         idx = (unsigned char)i;
00112         if( H5Tenum_insert( enum_id, elem_type_list[ i ], &idx ) < 0 )
00113         {
00114             mhdf_setFail( status, "Failed to store elem type list." );
00115             H5Fclose( file_ptr->hdf_handle );
00116             free( file_ptr );
00117             return NULL;
00118         }
00119     }
00120 #if defined( H5Tcommit_vers ) && H5Tcommit_vers > 1
00121     if( H5Tcommit2( file_ptr->hdf_handle, TYPE_ENUM_PATH, enum_id, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT ) < 0 )
00122 #else
00123     if( H5Tcommit( file_ptr->hdf_handle, TYPE_ENUM_PATH, enum_id ) < 0 )
00124 #endif
00125     {
00126         mhdf_setFail( status, "Failed to store elem type list." );
00127         H5Fclose( file_ptr->hdf_handle );
00128         free( file_ptr );
00129         return NULL;
00130     }
00131     H5Tclose( enum_id );
00132 
00133     API_END_H( 1 );
00134     return file_ptr;
00135 }
00136 
00137 mhdf_FileHandle mhdf_openFile( const char* filename, int writeable, unsigned long* max_id_out, hid_t id_type,
00138                                mhdf_Status* status )
00139 {
00140     return mhdf_openFileWithOpt( filename, writeable, max_id_out, id_type, H5P_DEFAULT, status );
00141 }
00142 
00143 int mhdf_countOpenHandles( mhdf_FileHandle file_handle )
00144 {
00145     return H5Fget_obj_count( ( (FileHandle*)file_handle )->hdf_handle, H5F_OBJ_ALL );
00146 }
00147 
00148 static herr_t get_max_id( hid_t group_id, const char* subgroup, const char* datatable, unsigned long* data )
00149 {
00150     unsigned long id;
00151     hid_t         elem_id, conn_id, attr_id, space_id;
00152     herr_t        rval;
00153     int           rank;
00154     hsize_t       dims[ 2 ];
00155 
00156 #if defined( H5Gopen_vers ) && H5Gopen_vers > 1
00157     elem_id = H5Gopen2( group_id, subgroup, H5P_DEFAULT );
00158 #else
00159     elem_id = H5Gopen( group_id, subgroup );
00160 #endif
00161     if( elem_id < 0 ) return (herr_t)-1;
00162 
00163 #if defined( H5Dopen_vers ) && H5Dopen_vers > 1
00164     conn_id = H5Dopen2( elem_id, datatable, H5P_DEFAULT );
00165 #else
00166     conn_id = H5Dopen( elem_id, datatable );
00167 #endif
00168     H5Gclose( elem_id );
00169     if( conn_id < 0 ) return (herr_t)-1;
00170 
00171     space_id = H5Dget_space( conn_id );
00172     if( space_id < 0 )
00173     {
00174         H5Dclose( conn_id );
00175         return -1;
00176     }
00177 
00178     rank = H5Sget_simple_extent_ndims( space_id );
00179     if( rank <= 0 || rank > 2 )
00180     {
00181         H5Dclose( conn_id );
00182         H5Sclose( space_id );
00183         return -1;
00184     }
00185 
00186     rval = H5Sget_simple_extent_dims( space_id, dims, NULL );
00187     H5Sclose( space_id );
00188     if( rval < 0 )
00189     {
00190         H5Dclose( conn_id );
00191         return -1;
00192     }
00193 
00194     attr_id = H5Aopen_name( conn_id, START_ID_ATTRIB );
00195     H5Dclose( conn_id );
00196     if( attr_id < 0 ) return (herr_t)-1;
00197 
00198     rval = H5Aread( attr_id, H5T_NATIVE_ULONG, &id );
00199     H5Aclose( attr_id );
00200     if( rval < 0 ) return rval;
00201 
00202     id += dims[ 0 ];
00203     if( id > *data ) *data = id;
00204     return 0;
00205 }
00206 
00207 static herr_t max_id_iter( hid_t group_id, const char* name, void* data )
00208 {
00209     return get_max_id( group_id, name, CONNECTIVITY_NAME, (unsigned long*)data );
00210 }
00211 
00212 static int scan_for_max_id( FileHandle* file_ptr, mhdf_Status* status )
00213 {
00214     hid_t  group_id;
00215     herr_t rval;
00216 
00217     /* Check for new format, with max_id as attrib of root group */
00218 #if defined( H5Gopen_vers ) && H5Gopen_vers > 1
00219     group_id = H5Gopen2( file_ptr->hdf_handle, ROOT_GROUP, H5P_DEFAULT );
00220 #else
00221     group_id = H5Gopen( file_ptr->hdf_handle, ROOT_GROUP );
00222 #endif
00223     if( group_id < 0 )
00224     {
00225         mhdf_setFail( status, "Internal error - invalid file." );
00226         return 0;
00227     }
00228     if( mhdf_read_scalar_attrib( group_id, MAX_ID_ATTRIB, H5T_NATIVE_ULONG, &file_ptr->max_id, status ) )
00229     {
00230         H5Gclose( group_id );
00231         return 1;
00232     }
00233 
00234     /* Didn't find it, scan the elements group */
00235     rval = H5Giterate( group_id, ELEMENT_GROUP_NAME, 0, &max_id_iter, &file_ptr->max_id );
00236     if( rval )
00237     {
00238         H5Gclose( group_id );
00239         mhdf_setFail( status, "Internal error -- invalid file." );
00240         return 0;
00241     }
00242 
00243     /* Check node table too */
00244     rval = get_max_id( group_id, NODE_GROUP_NAME, "coordinates", (unsigned long*)( &file_ptr->max_id ) );
00245     if( rval )
00246     {
00247         H5Gclose( group_id );
00248         mhdf_setFail( status, "Internal error -- invalid file." );
00249         return 0;
00250     }
00251 
00252     /* Check set table, if it exists */
00253     rval = mhdf_is_in_group( group_id, SET_GROUP_NAME, status );
00254     if( rval < 1 )
00255     {
00256         H5Gclose( group_id );
00257         return !rval;
00258     }
00259     rval = get_max_id( group_id, SET_GROUP_NAME, SET_META_NAME, (unsigned long*)( &file_ptr->max_id ) );
00260     H5Gclose( group_id );
00261     if( rval )
00262     {
00263         mhdf_setFail( status, "Internal error -- invalid file." );
00264         return 0;
00265     }
00266 
00267     return 1;
00268 }
00269 
00270 mhdf_FileHandle mhdf_openFileWithOpt( const char* filename, int writable, unsigned long* max_id_out, hid_t id_type,
00271                                       hid_t access_prop, mhdf_Status* status )
00272 {
00273     FileHandle*  file_ptr;
00274     unsigned int flags;
00275     hid_t        group_id;
00276     int          check_is_hdf5 = 1;
00277 #ifdef MOAB_HAVE_HDF5_PARALLEL
00278     herr_t   err;
00279     MPI_Comm comm;
00280     MPI_Info info;
00281 #endif
00282     API_BEGIN;
00283 
00284     /* Check if file is HDF5 */
00285     /* Don't do this because it can't handle MPI-IO driver code that
00286        passes options via prefixes on the file name. */
00287 #ifdef MOAB_HAVE_HDF5_PARALLEL
00288     if( access_prop != H5P_DEFAULT )
00289     {
00290         err = H5Pget_fapl_mpio( access_prop, &comm, &info );
00291         if( err >= 0 )
00292         {
00293             check_is_hdf5 = 0;
00294             /* MPI Documentation is inconsistent with regards to whether
00295                or not the above call dup's these, but my testing with 1.8.3
00296                indicates that at least for that version they are not.
00297             MPI_Comm_free(&comm);
00298             MPI_Info_free(&info); */
00299         }
00300     }
00301 #endif
00302     if( check_is_hdf5 && H5Fis_hdf5( filename ) <= 0 )
00303     {
00304         mhdf_setFail( status, "%s: File is not HDF5", filename );
00305         return NULL;
00306     }
00307 
00308     /* Create struct to hold working data */
00309     file_ptr = mhdf_alloc_FileHandle( 0, id_type, status );
00310     if( !file_ptr )
00311     {
00312         mhdf_setFail( status, "Memory allocation failed" );
00313         return NULL;
00314     }
00315 
00316     /* Create the file */
00317     flags = writable ? H5F_ACC_RDWR : H5F_ACC_RDONLY;
00318     file_ptr->hdf_handle = H5Fopen( filename, flags, access_prop );
00319     if( file_ptr->hdf_handle < 0 )
00320     {
00321         mhdf_setFail( status, "Failed to open file \"%s\"", filename );
00322         free( file_ptr );
00323         return NULL;
00324     }
00325 
00326     /* Check for TSTT data in file */
00327 #if defined( H5Gopen_vers ) && H5Gopen_vers > 1
00328     group_id = H5Gopen2( file_ptr->hdf_handle, ROOT_GROUP, H5P_DEFAULT );
00329 #else
00330     group_id = H5Gopen( file_ptr->hdf_handle, ROOT_GROUP );
00331 #endif
00332     if( group_id < 0 )
00333     {
00334         mhdf_setFail( status, "Invalid file \"%s\"\n", filename );
00335         H5Fclose( file_ptr->hdf_handle );
00336         free( file_ptr );
00337         return NULL;
00338     }
00339     H5Gclose( group_id );
00340 
00341     /* Get max id */
00342     if( !scan_for_max_id( file_ptr, status ) )
00343     {
00344         H5Fclose( file_ptr->hdf_handle );
00345         mhdf_setFail( status, "Internal error reading file" );
00346         free( file_ptr );
00347         return NULL;
00348     }
00349 
00350     if( max_id_out ) *max_id_out = file_ptr->max_id;
00351 
00352     mhdf_setOkay( status );
00353     API_END_H( 1 );
00354     return file_ptr;
00355 }
00356 
00357 void mhdf_getElemName( mhdf_FileHandle file_handle, unsigned int type_index, char* buffer, size_t buf_size,
00358                        mhdf_Status* status )
00359 {
00360     FileHandle* file_ptr;
00361     herr_t      rval;
00362     hid_t       enum_id;
00363     API_BEGIN;
00364 
00365     if( type_index > 255 )
00366     {
00367         mhdf_setFail( status, "Type index out of bounds." );
00368         return;
00369     }
00370 
00371     file_ptr = (FileHandle*)( file_handle );
00372     if( !mhdf_check_valid_file( file_ptr, status ) ) return;
00373 
00374     enum_id = get_elem_type_enum( file_ptr, status );
00375     if( enum_id < 0 ) return;
00376 
00377     rval = H5Tconvert( H5T_NATIVE_UINT, H5Tget_super( enum_id ), 1, &type_index, NULL, H5P_DEFAULT );
00378     if( rval < 0 )
00379     {
00380         H5Tclose( enum_id );
00381         mhdf_setFail( status, "Internal error converting to enum type." );
00382         return;
00383     }
00384 
00385     rval = H5Tenum_nameof( enum_id, &type_index, buffer, buf_size );
00386     H5Tclose( enum_id );
00387     if( rval < 0 )
00388         mhdf_setFail( status, "H5Tenum_nameof failed.  Invalid type index?" );
00389     else
00390         mhdf_setOkay( status );
00391 
00392     API_END;
00393 }
00394 
00395 int mhdf_checkOpenHandles( mhdf_FileHandle handle, mhdf_Status* status )
00396 {
00397     FileHandle* file_ptr;
00398     int         result;
00399     API_BEGIN;
00400 
00401     file_ptr = (FileHandle*)( handle );
00402     if( !mhdf_check_valid_file( file_ptr, status ) ) return -1;
00403 
00404     /* Check for open handles.  HDF5 will not actually close the
00405        file until all handles are closed. */
00406     result = H5Fget_obj_count( file_ptr->hdf_handle, H5F_OBJ_ALL );
00407     if( result != 1 )
00408     {
00409         mhdf_setFail( status,
00410                       "Cannot close file with open handles: "
00411                       "%d file, %d data, %d group, %d type, %d attr\n",
00412                       H5Fget_obj_count( file_ptr->hdf_handle, H5F_OBJ_FILE ) - 1,
00413                       H5Fget_obj_count( file_ptr->hdf_handle, H5F_OBJ_DATASET ),
00414                       H5Fget_obj_count( file_ptr->hdf_handle, H5F_OBJ_GROUP ),
00415                       H5Fget_obj_count( file_ptr->hdf_handle, H5F_OBJ_DATATYPE ),
00416                       H5Fget_obj_count( file_ptr->hdf_handle, H5F_OBJ_ATTR ) );
00417         return result - 1;
00418     }
00419 
00420     API_END_H( 0 );
00421     return 0;
00422 }
00423 
00424 void mhdf_closeFile( mhdf_FileHandle handle, mhdf_Status* status )
00425 {
00426     FileHandle* file_ptr;
00427     API_BEGIN;
00428 
00429     file_ptr = (FileHandle*)( handle );
00430     if( !mhdf_check_valid_file( file_ptr, status ) ) return;
00431     /*
00432       if (file_ptr->open_handle_count)
00433       {
00434         mhdf_setError( status, "Cannot close file with %d open data handles.",
00435           file_ptr->open_handle_count );
00436         return;
00437       }
00438     */
00439 
00440     /* Check for open handles.  HDF5 will not actually close the
00441        file until all handles are closed. */
00442     if( mhdf_checkOpenHandles( handle, status ) ) return;
00443 
00444     if( 0 > H5Fclose( file_ptr->hdf_handle ) )
00445     {
00446         mhdf_setFail( status, "H5FClose failed.  Invalid handle?" );
00447         return;
00448     }
00449 
00450     memset( file_ptr, 0, sizeof( FileHandle ) );
00451     free( file_ptr );
00452     mhdf_setOkay( status );
00453     API_END_H( -1 );
00454 }
00455 
00456 void mhdf_closeData( mhdf_FileHandle file, hid_t handle, mhdf_Status* status )
00457 {
00458     FileHandle* file_ptr;
00459     herr_t      rval = -1;
00460 
00461     file_ptr = (FileHandle*)( file );
00462     if( !mhdf_check_valid_file( file_ptr, status ) ) return;
00463 
00464     switch( H5Iget_type( handle ) )
00465     {
00466         case H5I_GROUP:
00467             rval = H5Gclose( handle );
00468             break;
00469         case H5I_DATATYPE:
00470             rval = H5Tclose( handle );
00471             break;
00472         case H5I_DATASPACE:
00473             rval = H5Sclose( handle );
00474             break;
00475         case H5I_DATASET:
00476             rval = H5Dclose( handle );
00477             break;
00478         default:
00479             rval = -1;
00480     }
00481 
00482     if( rval < 0 ) { mhdf_setFail( status, "H5Xclose failed.  Invalid handle?\n" ); }
00483     else
00484     {
00485         file_ptr->open_handle_count--;
00486         mhdf_setOkay( status );
00487     }
00488 }
00489 
00490 void mhdf_addElement( mhdf_FileHandle file_handle, const char* name, unsigned int elem_type, mhdf_Status* status )
00491 {
00492     FileHandle* file_ptr = (FileHandle*)file_handle;
00493     hid_t       group_id, tag_id, enum_id;
00494     char *      path, *ptr;
00495     size_t      name_len;
00496     herr_t      rval;
00497     API_BEGIN;
00498 
00499     if( !mhdf_check_valid_file( file_ptr, status ) ) return;
00500 
00501     name_len = mhdf_name_to_path( name, NULL, 0 );
00502     name_len += strlen( ELEMENT_GROUP ) + 1;
00503     path = (char*)mhdf_malloc( name_len, status );
00504     if( !path ) return;
00505 
00506     strcpy( path, ELEMENT_GROUP );
00507     ptr = path + strlen( ELEMENT_GROUP );
00508     if( !mhdf_path_to_name( name, ptr ) )
00509     {
00510         mhdf_setFail( status, "Invalid character string in internal file path: \"%s\"\n", name );
00511         return;
00512     }
00513 
00514 #if defined( H5Gcreate_vers ) && H5Gcreate_vers > 1
00515     group_id = H5Gcreate2( file_ptr->hdf_handle, path, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT );
00516 #else
00517     group_id = H5Gcreate( file_ptr->hdf_handle, path, 3 );
00518 #endif
00519     if( group_id < 0 )
00520     {
00521         mhdf_setFail( status, "Creation of \"%s\" group failed.\n", path );
00522         free( path );
00523         return;
00524     }
00525     free( path );
00526 
00527 #if defined( H5Gcreate_vers ) && H5Gcreate_vers > 1
00528     tag_id = H5Gcreate2( group_id, DENSE_TAG_SUBGROUP, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT );
00529 #else
00530     tag_id = H5Gcreate( group_id, DENSE_TAG_SUBGROUP, 0 );
00531 #endif
00532     if( tag_id < 0 )
00533     {
00534         H5Gclose( group_id );
00535         mhdf_setFail( status, "Creation of tag subgroup failed.\n" );
00536         return;
00537     }
00538     H5Gclose( tag_id );
00539 
00540     enum_id = get_elem_type_enum( file_ptr, status );
00541     if( enum_id < 0 )
00542     {
00543         H5Gclose( group_id );
00544         return;
00545     }
00546 
00547     rval = H5Tconvert( H5T_NATIVE_UINT, H5Tget_super( enum_id ), 1, &elem_type, NULL, H5P_DEFAULT );
00548     if( rval < 0 )
00549     {
00550         H5Gclose( group_id );
00551         H5Tclose( enum_id );
00552         mhdf_setFail( status, "Internal error converting to enum type." );
00553         return;
00554     }
00555 
00556     rval = mhdf_create_scalar_attrib( group_id, ELEM_TYPE_ATTRIB, enum_id, &elem_type, status );
00557     H5Tclose( enum_id );
00558     if( rval < 0 )
00559     {
00560         H5Gclose( group_id );
00561         return;
00562     }
00563 
00564     H5Gclose( group_id );
00565     mhdf_setOkay( status );
00566     API_END;
00567 }
00568 
00569 char** mhdf_getElemHandles( mhdf_FileHandle file_handle, unsigned int* count_out, mhdf_Status* status )
00570 {
00571     hsize_t     count, length, i;
00572     char**      buffer;
00573     char*       current;
00574     hid_t       group_id;
00575     herr_t      rval;
00576     ssize_t     rlen = 0;
00577     size_t      remaining;
00578     FileHandle* file_ptr = (FileHandle*)file_handle;
00579     if( !mhdf_check_valid_file( file_ptr, status ) ) return NULL;
00580 
00581 #if defined( H5Gopen_vers ) && H5Gopen_vers > 1
00582     group_id = H5Gopen2( file_ptr->hdf_handle, ELEMENT_GROUP, H5P_DEFAULT );
00583 #else
00584     group_id = H5Gopen( file_ptr->hdf_handle, ELEMENT_GROUP );
00585 #endif
00586     if( group_id < 0 )
00587     {
00588         mhdf_setFail( status, "Invalid file -- element group does not exist." );
00589         return NULL;
00590     }
00591 
00592     rval = H5Gget_num_objs( group_id, &count );
00593     if( rval < 0 )
00594     {
00595         H5Gclose( group_id );
00596         mhdf_setFail( status, "Internal error calling H5Gget_num_objs." );
00597         return NULL;
00598     }
00599     *count_out = count;
00600 
00601     for( i = 0; i < count; ++i )
00602     {
00603         rlen += H5Gget_objname_by_idx( group_id, i, NULL, 0 ) + 1;
00604     }
00605 
00606     length = count * sizeof( char* ) + rlen;
00607     buffer = (char**)mhdf_malloc( length, status );
00608     if( !buffer )
00609     {
00610         H5Gclose( group_id );
00611         return NULL;
00612     }
00613     current = (char*)( buffer + count );
00614     remaining = rlen;
00615 
00616     for( i = 0; i < count; ++i )
00617     {
00618         buffer[ i ] = current;
00619         rlen = H5Gget_objname_by_idx( group_id, i, current, remaining ) + 1;
00620         if( rlen < 0 )
00621         {
00622             H5Gclose( group_id );
00623             free( buffer );
00624             mhdf_setFail( status, "Internal error calling H5Gget_objname_by_idx." );
00625             return NULL;
00626         }
00627 
00628         mhdf_path_to_name( current, current );
00629         remaining -= rlen;
00630         current += rlen;
00631     }
00632 
00633     H5Gclose( group_id );
00634     mhdf_setOkay( status );
00635     return buffer;
00636 }
00637 
00638 void mhdf_getElemTypeName( mhdf_FileHandle file_handle, const char* elem_handle, char* buffer, size_t buf_len,
00639                            mhdf_Status* status )
00640 {
00641     FileHandle* file_ptr;
00642     hid_t       elem_id, type_id, attr_id;
00643     char        bytes[ 16 ];
00644     herr_t      rval;
00645     API_BEGIN;
00646 
00647     if( NULL == buffer || buf_len < 2 )
00648     {
00649         mhdf_setFail( status, "invalid input" );
00650         return;
00651     }
00652     buffer[ 0 ] = '\0';
00653 
00654     file_ptr = (FileHandle*)( file_handle );
00655     if( !mhdf_check_valid_file( file_ptr, status ) ) return;
00656 
00657     elem_id = mhdf_elem_group_from_handle( file_ptr, elem_handle, status );
00658     if( elem_id < 0 ) return;
00659 
00660     attr_id = H5Aopen_name( elem_id, ELEM_TYPE_ATTRIB );
00661     H5Gclose( elem_id );
00662     if( attr_id < 0 )
00663     {
00664         mhdf_setFail( status, "Missing element type attribute.  Invalid file." );
00665         return;
00666     }
00667 
00668     type_id = H5Aget_type( attr_id );
00669     assert( type_id > 0 );
00670 
00671     rval = H5Aread( attr_id, type_id, bytes );
00672     H5Aclose( attr_id );
00673     if( rval < 0 )
00674     {
00675         H5Tclose( type_id );
00676         mhdf_setFail( status, "Failed to read element type attribute.  Invalid file." );
00677         return;
00678     }
00679 
00680     rval = H5Tenum_nameof( type_id, bytes, buffer, buf_len );
00681     H5Tclose( type_id );
00682     if( rval < 0 )
00683     {
00684         mhdf_setFail( status, "Invalid datatype for element type attribute.  Invalid file." );
00685         return;
00686     }
00687 
00688     mhdf_setOkay( status );
00689     API_END;
00690     return;
00691 }
00692 
00693 static int make_hdf_group( const char* path, hid_t file, size_t sz, mhdf_Status* status )
00694 {
00695 #if defined( H5Gcreate_vers ) && H5Gcreate_vers > 1
00696     hid_t handle = H5Gcreate2( file, path, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT );
00697     /* empty statement to avoid compiler warning */
00698     if( sz ) {}
00699 #else
00700     hid_t handle = H5Gcreate( file, path, sz );
00701 #endif
00702     if( handle < 0 )
00703     {
00704         mhdf_setFail( status, "Failed to create \"%s\" group.", path );
00705         return 0;
00706     }
00707     else
00708     {
00709         H5Gclose( handle );
00710         return 1;
00711     }
00712 }
00713 
00714 const char* mhdf_node_type_handle( void )
00715 {
00716     static const char rval[] = "nodes";
00717     return rval;
00718 }
00719 
00720 const char* mhdf_set_type_handle( void )
00721 {
00722     static const char rval[] = "sets";
00723     return rval;
00724 }
00725 
00726 int mhdf_isPolyElement( mhdf_FileHandle file_handle, const char* elem_handle, mhdf_Status* status )
00727 {
00728     FileHandle* file_ptr;
00729     hid_t       elem_id;
00730     int         rval;
00731     API_BEGIN;
00732 
00733     file_ptr = (FileHandle*)( file_handle );
00734     if( !mhdf_check_valid_file( file_ptr, status ) ) return -1;
00735 
00736     elem_id = mhdf_elem_group_from_handle( file_ptr, elem_handle, status );
00737     if( elem_id < 0 ) return -1;
00738 
00739     mhdf_setOkay( status );
00740     rval = mhdf_is_in_group( elem_id, POLY_INDEX_NAME, status );
00741     H5Gclose( elem_id );
00742     API_END;
00743     return rval;
00744 }
00745 
00746 void mhdf_writeHistory( mhdf_FileHandle file_handle, const char** strings, int num_strings, mhdf_Status* status )
00747 {
00748     FileHandle* file_ptr;
00749     hid_t       data_id, type_id, space_id;
00750     hsize_t     dim = (hsize_t)num_strings;
00751     herr_t      rval;
00752     API_BEGIN;
00753 
00754     file_ptr = (FileHandle*)( file_handle );
00755     if( !mhdf_check_valid_file( file_ptr, status ) ) return;
00756 
00757     type_id = H5Tcopy( H5T_C_S1 );
00758     if( type_id < 0 || H5Tset_size( type_id, H5T_VARIABLE ) < 0 )
00759     {
00760         if( type_id >= 0 ) H5Tclose( type_id );
00761         mhdf_setFail( status, "Could not create variable length string type." );
00762         return;
00763     }
00764 
00765     space_id = H5Screate_simple( 1, &dim, NULL );
00766     if( space_id < 0 )
00767     {
00768         H5Tclose( type_id );
00769         mhdf_setFail( status, "H5Screate_simple failed." );
00770         return;
00771     }
00772 
00773 #if defined( H5Dcreate_vers ) && H5Dcreate_vers > 1
00774     data_id =
00775         H5Dcreate2( file_ptr->hdf_handle, HISTORY_PATH, type_id, space_id, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT );
00776 #else
00777     data_id = H5Dcreate( file_ptr->hdf_handle, HISTORY_PATH, type_id, space_id, H5P_DEFAULT );
00778 #endif
00779     H5Sclose( space_id );
00780     if( data_id < 0 )
00781     {
00782         H5Tclose( type_id );
00783         mhdf_setFail( status, "Failed to create \"%s\".", HISTORY_PATH );
00784         return;
00785     }
00786 
00787     rval = H5Dwrite( data_id, type_id, H5S_ALL, H5S_ALL, H5P_DEFAULT, strings );
00788     H5Dclose( data_id );
00789     H5Tclose( type_id );
00790     if( rval < 0 )
00791     {
00792         H5Gunlink( file_ptr->hdf_handle, HISTORY_PATH );
00793         mhdf_setFail( status, "Failed to write history data." );
00794         return;
00795     }
00796 
00797     mhdf_setOkay( status );
00798     API_END;
00799 }
00800 
00801 char** mhdf_readHistory( mhdf_FileHandle file_handle, int* num_strings, mhdf_Status* status )
00802 {
00803     FileHandle* file_ptr;
00804     hid_t       data_id, type_id, space_id, group_id;
00805     hsize_t     dim;
00806     herr_t      rval;
00807     char**      array;
00808     API_BEGIN;
00809 
00810     file_ptr = (FileHandle*)( file_handle );
00811     if( !mhdf_check_valid_file( file_ptr, status ) ) return NULL;
00812 
00813         /* check if file contains history data */
00814 #if defined( H5Gopen_vers ) && H5Gopen_vers > 1
00815     group_id = H5Gopen2( file_ptr->hdf_handle, ROOT_GROUP, H5P_DEFAULT );
00816 #else
00817     group_id = H5Gopen( file_ptr->hdf_handle, ROOT_GROUP );
00818 #endif
00819     if( group_id < 0 )
00820     {
00821         mhdf_setFail( status, "Could not open root group.  Invalid file." );
00822         return NULL;
00823     }
00824 
00825     rval = mhdf_is_in_group( group_id, HISTORY_NAME, status );
00826     if( rval < 1 )
00827     {
00828         H5Gclose( group_id );
00829         *num_strings = 0;
00830         if( 0 == rval ) mhdf_setOkay( status );
00831         return NULL;
00832     }
00833 
00834 #if defined( H5Dopen_vers ) && H5Dopen_vers > 1
00835     data_id = H5Dopen2( group_id, HISTORY_NAME, H5P_DEFAULT );
00836 #else
00837     data_id = H5Dopen( group_id, HISTORY_NAME );
00838 #endif
00839     H5Gclose( group_id );
00840     if( data_id < 0 )
00841     {
00842         mhdf_setFail( status, "Failed to open \"%s\".", HISTORY_PATH );
00843         return NULL;
00844     }
00845 
00846     space_id = H5Dget_space( data_id );
00847     if( space_id < 0 )
00848     {
00849         H5Dclose( data_id );
00850         mhdf_setFail( status, "Internal error calling H5Dget_space." );
00851         return NULL;
00852     }
00853 
00854     if( 1 != H5Sget_simple_extent_ndims( space_id ) || 1 != H5Sget_simple_extent_dims( space_id, &dim, NULL ) )
00855     {
00856         H5Dclose( data_id );
00857         mhdf_setFail( status, "Invalid dimension for \"%s\".", HISTORY_PATH );
00858         return NULL;
00859     }
00860     H5Sclose( space_id );
00861 
00862     if( 0 == dim )
00863     {
00864         H5Dclose( data_id );
00865         *num_strings = 0;
00866         mhdf_setOkay( status );
00867         return NULL;
00868     }
00869 
00870     array = (char**)mhdf_malloc( dim * sizeof( char* ), status );
00871     if( !array )
00872     {
00873         H5Dclose( data_id );
00874         return NULL;
00875     }
00876 
00877     type_id = H5Tcopy( H5T_C_S1 );
00878     if( type_id < 0 || H5Tset_size( type_id, H5T_VARIABLE ) < 0 )
00879     {
00880         H5Dclose( data_id );
00881         if( type_id >= 0 ) H5Tclose( type_id );
00882         mhdf_setFail( status, "Could not create variable length string type." );
00883         free( array );
00884         return NULL;
00885     }
00886 
00887     rval = H5Dread( data_id, type_id, H5S_ALL, H5S_ALL, H5P_DEFAULT, array );
00888     H5Tclose( type_id );
00889     H5Dclose( data_id );
00890     if( rval < 0 )
00891     {
00892         free( array );
00893         mhdf_setFail( status, "H5Dread failed." );
00894         return NULL;
00895     }
00896 
00897     *num_strings = dim;
00898     mhdf_setOkay( status );
00899     API_END;
00900     return array;
00901 }
00902 
00903 void mhdf_getNextStartId( mhdf_FileHandle file, mhdf_index_t* start_id_out, mhdf_Status* status )
00904 {
00905     FileHandle* file_ptr = (FileHandle*)file;
00906     API_BEGIN;
00907 
00908     mhdf_setOkay( status );
00909     if( mhdf_check_valid_file( file_ptr, status ) ) *start_id_out = file_ptr->max_id + 1;
00910 
00911     API_END;
00912 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines