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