[MOAB-dev] r1659 - in MOAB/trunk: . parallel test/h5file

kraftche at mcs.anl.gov kraftche at mcs.anl.gov
Fri Mar 14 09:17:31 CDT 2008


Author: kraftche
Date: 2008-03-14 09:17:31 -0500 (Fri, 14 Mar 2008)
New Revision: 1659

Modified:
   MOAB/trunk/MBReaderWriterSet.cpp
   MOAB/trunk/WriteHDF5.cpp
   MOAB/trunk/WriteHDF5.hpp
   MOAB/trunk/configure.in
   MOAB/trunk/parallel/WriteHDF5Parallel.cpp
   MOAB/trunk/parallel/WriteHDF5Parallel.hpp
   MOAB/trunk/test/h5file/varlen_ll.cpp
Log:
o Make "PARALLEL=FORMAT" option work (use WriteHDF5Parallel)
o Clean up code for error handling and resource cleanup in WriteHDF5
o If writing fails, WriteHDF5 will remove any invalid file it created
  unless the "KEEP" option is specified.



Modified: MOAB/trunk/MBReaderWriterSet.cpp
===================================================================
--- MOAB/trunk/MBReaderWriterSet.cpp	2008-03-14 14:15:30 UTC (rev 1658)
+++ MOAB/trunk/MBReaderWriterSet.cpp	2008-03-14 14:17:31 UTC (rev 1659)
@@ -39,7 +39,11 @@
 
 #ifdef HDF5_FILE
 #  include "ReadHDF5.hpp"
-#  include "WriteHDF5.hpp"
+#  ifdef HDF5_PARALLEL
+#    include "WriteHDF5Parallel.hpp"
+#  else
+#    include "WriteHDF5.hpp"
+#  endif
 #endif
 
 #include <algorithm>
@@ -49,8 +53,14 @@
 {
 #ifdef HDF5_FILE
   const char* hdf5_sufxs[] = { "h5m", "mhdf", NULL };
-  register_factory(  ReadHDF5::factory, WriteHDF5::factory, "MOAB native (HDF5)", hdf5_sufxs, "MOAB" );
+#ifdef HDF5_PARALLEL
+  register_factory(  ReadHDF5::factory, WriteHDF5Parallel::factory, 
+                     "MOAB native (HDF5)", hdf5_sufxs, "MOAB" );
+#else
+  register_factory(  ReadHDF5::factory, WriteHDF5::factory, 
+                     "MOAB native (HDF5)", hdf5_sufxs, "MOAB" );
 #endif
+#endif
 
 #ifdef NETCDF_FILE
   const char* exo_sufxs[] = { "exo", "exoII", "exo2", "g", "gen", NULL };

Modified: MOAB/trunk/WriteHDF5.cpp
===================================================================
--- MOAB/trunk/WriteHDF5.cpp	2008-03-14 14:15:30 UTC (rev 1658)
+++ MOAB/trunk/WriteHDF5.cpp	2008-03-14 14:17:31 UTC (rev 1659)
@@ -45,6 +45,7 @@
 #include "MBCN.hpp"
 #include "WriteHDF5.hpp"
 #include "MBWriteUtilIface.hpp"
+#include "FileOptions.hpp"
 #include "mhdf.h"
 /* Access HDF5 file handle for debugging
 #include <H5Fpublic.h>
@@ -335,17 +336,72 @@
 
 MBErrorCode WriteHDF5::write_file( const char* filename,
                                    bool overwrite,
-                                   const FileOptions& ,
+                                   const FileOptions& opts,
                                    const MBEntityHandle* set_array,
                                    const int num_sets,
                                    std::vector<std::string>& qa_records,
                                    int user_dimension )
 {
+  mhdf_Status status;
+
+    // Allocate internal buffer to use when gathering data to write.
+  dataBuffer = (char*)malloc( bufferSize );
+  if (!dataBuffer)
+    return MB_MEMORY_ALLOCATION_FAILED;
+
+    // Clear filePtr so we know if it is open upon failure
+  filePtr = 0;
+
+    // Do actual write.
+  MBErrorCode result = write_file_impl( filename, overwrite, opts, 
+                                        set_array, num_sets, 
+                                        qa_records, user_dimension );
+  
+    // Free memory buffer
+  free( dataBuffer );
+  dataBuffer = 0;
+  
+    // Close file
+  bool created_file = false;
+  if (filePtr) {
+    created_file = true;
+    mhdf_closeFile( filePtr, &status );
+    filePtr = 0;
+    if (mhdf_isError( &status )) {
+      writeUtil->report_error( "%s\n", mhdf_message( &status ) );
+      if (MB_SUCCESS == result)
+        result = MB_FAILURE;
+    }
+  }
+
+    // Release other resources
+  if (MB_SUCCESS == result)
+    result = write_finished();
+  else
+    write_finished();
+  
+    // If write failed, remove file unless KEEP option was specified
+  if (MB_SUCCESS != result && created_file && 
+      MB_ENTITY_NOT_FOUND == opts.get_null_option( "KEEP" ))
+    remove( filename );
+  
+  return result;
+}  
+
+
+MBErrorCode WriteHDF5::write_file_impl( const char* filename,
+                                        bool overwrite,
+                                        const FileOptions& opts,
+                                        const MBEntityHandle* set_array,
+                                        const int num_sets,
+                                        std::vector<std::string>& qa_records,
+                                        int user_dimension )
+{
   MBErrorCode result;
-  mhdf_Status rval;
   std::list<SparseTag>::const_iterator t_itor;
   std::list<ExportSet>::iterator ex_itor;
   MBEntityHandle elem_count, max_id;
+  bool parallel = false;
   
   if (MB_SUCCESS != init())
     return MB_FAILURE;
@@ -364,7 +420,8 @@
     std::vector<MBEntityHandle> passed_export_list(num_sets);
     memcpy( &passed_export_list[0], set_array, sizeof(MBEntityHandle)*num_sets );
     result = gather_mesh_info( passed_export_list );
-    if (MB_SUCCESS != result) goto write_fail;
+    if (MB_SUCCESS != result) 
+      return result;
     
       // Mark all entities invalid.  Later the ones we are
       // exporting will be marked valid.  This way we can
@@ -373,11 +430,11 @@
       // Don't to this, just set the default value to -1 when
       // the tag is created in the init() function.
     //result = clear_all_id_tags();
-    //if (MB_SUCCESS != result) goto write_fail;
+    //if (MB_SUCCESS != result) return result;
   }
   
   //if (nodeSet.range.size() == 0)
-  //  goto write_fail;
+  //  return MB_ENTITY_NOT_FOUND;
   
 DEBUGOUT("Checking ID space\n");
 
@@ -389,7 +446,7 @@
   if (elem_count > max_id)
   {
     writeUtil->report_error("ID space insufficient for mesh size.\n");
-    goto write_fail;
+    return MB_FAILURE;
   }
 
 DEBUGOUT( "Creating File\n" );  
@@ -403,47 +460,52 @@
     user_dimension = mesh_dim;
   user_dimension = user_dimension > mesh_dim ? mesh_dim : user_dimension;
   
-    // Allocate internal buffer to use when gathering data to write.
-  dataBuffer = (char*)malloc( bufferSize );
-  if (!dataBuffer)
-    goto write_fail;
-  
     // Create the file layout, including all tables (zero-ed) and
     // all structure and meta information.
-  result = create_file( filename, overwrite, qa_records, user_dimension );
+  parallel = (MB_SUCCESS == opts.match_option( "PARALLEL", "FORMAT" ));
+  result = create_file( filename, overwrite, qa_records, user_dimension, parallel );
   if (MB_SUCCESS != result)
-    goto write_fail;
+    return result;
 
 DEBUGOUT("Writing Nodes.\n");
   
     // Write node coordinates
-  if (!nodeSet.range.empty() && write_nodes() != MB_SUCCESS)
-    goto write_fail;
+  if (!nodeSet.range.empty()) {
+    result = write_nodes();
+    if (MB_SUCCESS != result)
+      return result;
+  }
 
 DEBUGOUT("Writing connectivity.\n");
   
     // Write element connectivity
-  for (ex_itor = exportList.begin(); ex_itor != exportList.end(); ++ex_itor)
-    if (MB_SUCCESS != write_elems( *ex_itor ))
-      goto write_fail;
+  for (ex_itor = exportList.begin(); ex_itor != exportList.end(); ++ex_itor) {
+    result = write_elems( *ex_itor );
+    if (MB_SUCCESS != result)
+      return result;
+  }
 
 DEBUGOUT("Writing sets.\n");
   
     // Write meshsets
-  if (write_sets() != MB_SUCCESS)
-    goto write_fail;
+  result = write_sets();
+  if (MB_SUCCESS != result)
+    return result;
 
 DEBUGOUT("Writing adjacencies.\n");
   
     // Write adjacencies
   // Tim says don't save node adjacencies!
 #ifdef WRITE_NODE_ADJACENCIES
-  if (write_adjacencies( nodeSet ) != MB_SUCCESS)
-    goto write_fail;
+  result = write_adjacencies( nodeSet );
+  if (MB_SUCCESS != result) 
+    return result;
 #endif
-  for (ex_itor = exportList.begin(); ex_itor != exportList.end(); ++ex_itor)
-    if (write_adjacencies( *ex_itor ) != MB_SUCCESS)
-      goto write_fail;
+  for (ex_itor = exportList.begin(); ex_itor != exportList.end(); ++ex_itor) {
+    result = write_adjacencies( *ex_itor );
+    if (MB_SUCCESS != result)
+      return result;
+  }
 
 DEBUGOUT("Writing tags.\n");
   
@@ -457,31 +519,10 @@
       else
         result = write_sparse_tag( *t_itor );
       if (MB_SUCCESS != result)
-        goto write_fail;
+        return result;
     }
-    
-DEBUGOUT("Closing file.\n");
-
-    // Clean up and exit.
-  free( dataBuffer );
-  dataBuffer = 0;
-  mhdf_closeFile( filePtr, &rval );
-  filePtr = 0;
-  result = write_finished();
-  CHK_MHDF_ERR_0( rval );
-  return result;
   
-write_fail:
-  
-  if (dataBuffer)
-  {
-    free( dataBuffer );
-    dataBuffer = 0;
-  }
-  mhdf_closeFile( filePtr, &rval );
-  filePtr = 0;
-  write_finished();
-  return MB_FAILURE;
+  return MB_SUCCESS;
 }
 
   // Initialize all file ids to -1.  We do this so that
@@ -1824,7 +1865,8 @@
 MBErrorCode WriteHDF5::create_file( const char* filename,
                                     bool overwrite,
                                     std::vector<std::string>& qa_records,
-                                    int dimension )
+                                    int dimension,
+                                    bool parallel )
 {
   long first_id;
   mhdf_Status status;
@@ -1832,6 +1874,13 @@
   std::list<ExportSet>::iterator ex_itor;
   MBErrorCode rval;
   
+  // If we support paralle, then this function will have been
+  // overridden with an alternate version in WriteHDF5Parallel
+  // that supports parallel I/O.  If we're here and parallel == true,
+  // then MOAB was not built with support for parallel HDF5 I/O.
+  if (parallel)
+    return MB_NOT_IMPLEMENTED;
+  
   const char* type_names[MBMAXTYPE];
   memset( type_names, 0, MBMAXTYPE * sizeof(char*) );
   for (MBEntityType i = MBEDGE; i < MBENTITYSET; ++i)

Modified: MOAB/trunk/WriteHDF5.hpp
===================================================================
--- MOAB/trunk/WriteHDF5.hpp	2008-03-14 14:15:30 UTC (rev 1658)
+++ MOAB/trunk/WriteHDF5.hpp	2008-03-14 14:17:31 UTC (rev 1659)
@@ -80,7 +80,8 @@
   virtual MBErrorCode create_file( const char* filename,
                                    bool overwrite,
                                    std::vector<std::string>& qa_records,
-                                   int dimension = 3 );
+                                   int dimension = 3,
+                                   bool parallel = false );
 
 
   /** Functions that the parallel version overrides*/
@@ -236,6 +237,17 @@
   std::list<SparseTag> tagList;
 
 private:
+
+  //! Do the actual work of write_file.  Separated from write_file
+  //! for easier resource cleanup.
+  MBErrorCode write_file_impl( const char* filename,
+                               const bool overwrite,
+                               const FileOptions& opts,
+                               const MBEntityHandle* export_sets,
+                               const int export_set_count,
+                               std::vector<std::string>& qa_records,
+                               int user_dimension = 3 );
+
   MBErrorCode init();
 
   //! Zero the ID tag on all entities in the mesh.

Modified: MOAB/trunk/configure.in
===================================================================
--- MOAB/trunk/configure.in	2008-03-14 14:15:30 UTC (rev 1658)
+++ MOAB/trunk/configure.in	2008-03-14 14:17:31 UTC (rev 1659)
@@ -125,6 +125,9 @@
   fi
 fi
 AM_CONDITIONAL(PARALLEL_HDF5, [test "xno" != "x$HAVE_HDF5_PARALLEL"])
+if test "xno" != "x$HAVE_HDF5_PARALLEL"; then
+  DEFINES="$DEFINES -DHDF5_PARALLEL"
+fi
 
 ################################################################################
 #                             NetCDF OPTIONS

Modified: MOAB/trunk/parallel/WriteHDF5Parallel.cpp
===================================================================
--- MOAB/trunk/parallel/WriteHDF5Parallel.cpp	2008-03-14 14:15:30 UTC (rev 1658)
+++ MOAB/trunk/parallel/WriteHDF5Parallel.cpp	2008-03-14 14:17:31 UTC (rev 1659)
@@ -209,6 +209,9 @@
   }
 }
 
+MBWriterIface* WriteHDF5Parallel::factory( MBInterface* iface )
+  { return new WriteHDF5Parallel( iface ); }
+
 void WriteHDF5Parallel::MultiProcSetTags::add( const std::string& name )
   { list.push_back( Data(name) ); }
 
@@ -426,8 +429,12 @@
 MBErrorCode WriteHDF5Parallel::create_file( const char* filename,
                                             bool overwrite,
                                             std::vector<std::string>& qa_records,
-                                            int dimension )
+                                            int dimension,
+                                            bool parallel )
 {
+  if (!parallel)
+    return WriteHDF5::create_file(filename, overwrite, qa_records, dimension, false );
+
   MBErrorCode rval;
   int result;
   mhdf_Status status;

Modified: MOAB/trunk/parallel/WriteHDF5Parallel.hpp
===================================================================
--- MOAB/trunk/parallel/WriteHDF5Parallel.hpp	2008-03-14 14:15:30 UTC (rev 1658)
+++ MOAB/trunk/parallel/WriteHDF5Parallel.hpp	2008-03-14 14:17:31 UTC (rev 1659)
@@ -16,6 +16,8 @@
 class MB_DLL_EXPORT WriteHDF5Parallel : public WriteHDF5
 {
   public:
+
+    static MBWriterIface* factory( MBInterface* );
     
       /** Consturctor
        *
@@ -97,7 +99,8 @@
     virtual MBErrorCode create_file( const char* filename,
                                      bool overwrite,
                                      std::vector<std::string>& qa_records,
-                                     int dimension = 3 );
+                                     int dimension = 3,
+                                     bool parallel = false );
     
       //! Figure out which mesh local mesh is duplicated on
       //! remote processors and which processor will write

Modified: MOAB/trunk/test/h5file/varlen_ll.cpp
===================================================================
--- MOAB/trunk/test/h5file/varlen_ll.cpp	2008-03-14 14:15:30 UTC (rev 1658)
+++ MOAB/trunk/test/h5file/varlen_ll.cpp	2008-03-14 14:17:31 UTC (rev 1659)
@@ -4,12 +4,11 @@
  */
 
 #include "MBCore.hpp"
-#define TEST_WITH_MPI
 #include "TestUtil.hpp"
-#include "WriteHDF5Parallel.hpp"
-#include "FileOptions.hpp"
 #include "MBParallelConventions.h"
 
+#include <mpi.h>
+
 bool keep_files = false; // controllable with -k flag
 bool wait_on_start = false; // start all procs and wait for input on root node
 
@@ -95,14 +94,7 @@
   CHECK_ERR(rval);
   
   // Write file
-  WriteHDF5Parallel writer( &mb );
-  FileOptions opts("");
-  std::vector<std::string> qa_records;
-  rval = writer.write_file( filename, 
-                            true,
-                            opts,
-                            0, 0,
-                            qa_records );
+  rval = mb.write_file( filename, "MOAB", "PARALLEL=FORMAT" );
   CHECK_ERR(rval);
   
   // Read file.  We only reset and re-read the file on the




More information about the moab-dev mailing list