Sierra Toolkit  Version of the Day
mpi_filebuf.hpp
1 /* ------------------------------------------------------------------ */
2 /* Copyright 2000 Sandia Corporation, Albuquerque, NM. */
3 /* ------------------------------------------------------------------ */
4 
5 #ifndef STK_UTIL_PARALLEL_mpi_filebuf_hpp
6 #define STK_UTIL_PARALLEL_mpi_filebuf_hpp
7 
8 #include <ios>
9 #include <iostream>
10 #include <cstdio>
11 #include <mpi.h>
12 
13 //: Specialize the ANSI Standard C++ streambuf class
14 //: for a parallel file buffer. The actual file is
15 //: only touched by the root processor.
16 //
17 // READ MODE: The file is read on the root processor and
18 // broadcast one buffer at a time to the remaining processors.
19 //
20 // WRITE MODE: Each processor has a buffer that is locally
21 // filled. When the buffer is full on the root processor the
22 // buffer is written to the output file. When the buffer is
23 // full on any other processor the size of the buffer is doubled.
24 // The 'mpi_filebuf::flush' method gathers all buffers on the
25 // root processor and writes the buffers to the output file.
26 //
27 // GLOBAL: Calls to the 'open', 'flush', 'close', destructor,
28 // and 'underflow' methods are global; these calls must be
29 // made on all processors. The 'underflow' method is called
30 // by the 'istream' that uses the 'mpi_filebuf' object when
31 // ever the input buffer is empty. Thus reading from an 'istream'
32 // that uses an 'mpi_filebuf' must be globally consistent.
33 
34 class mpi_filebuf : public std::streambuf {
35 public:
36 
37  //: Construct an MPI-parallel input/output file buffer
38  mpi_filebuf();
39 
40  //: GLOBAL: Open a file.
41  // The file name is only significant on the root processsor.
42  // May only be opened as ios::in, ios::out, ios:app.
43  mpi_filebuf * open(
44  MPI_Comm communicator , /* All processors */
45  const int root_processor , /* All processors */
46  const std::ios_base::openmode file_mode , /* All processors */
47  const char * const file_name = NULL ); /* Root processor */
48 
49  //: GLOBAL: Close the file.
50  // If output mode then flush the output.
51  mpi_filebuf * close();
52 
53  //: GLOBAL: Flush the buffered output to the file.
54  // Sends all buffers to the root processor,
55  // write to the file, and flushes the file.
56  mpi_filebuf * flush();
57 
58  //: GLOBAL: Destructor
59  // Close and then reclaim memory.
60  virtual ~mpi_filebuf();
61 
62  //: Query if open, a local operations
63  int is_open() const ;
64 
65  //: When the file buffer is in the 'closed' state set the buffer length,
66  // The input argument must be consistent on all processors; however,
67  // this condition is not checked until the next 'open' operation.
68  mpi_filebuf * set_buffer_length( const size_t buffer_length );
69 
70  //: Query the current buffer
71  void get_buffer( const char * & , size_t & ) const ;
72 
73  //: Query wall-clock time spent communicating.
74  double wtime() const ;
75 
76 protected:
77 
78  //: Called to refill the input buffer
79  virtual int underflow();
80 
81  //: Called when output buffer is filled
82  virtual int overflow( int c = EOF );
83 
84  //: Sync is a no-op
85  virtual int sync();
86 
87  //: Setbuf is a no-op
88  virtual std::streambuf * setbuf( char * s , std::streamsize n );
89 
90 private:
91 
92  mpi_filebuf( const mpi_filebuf & ); // Not allowed
93  mpi_filebuf & operator = ( const mpi_filebuf & ); // Not allowed
94 
95  MPI_Comm comm ; // Communicator
96  int comm_root ; // Rank of root processor
97  std::FILE * comm_root_fp ; // Root processor's file
98  int comm_output ; // Output file
99  char * comm_buffer ; // local buffer
100  size_t comm_buffer_len ; // length of buffer
101  double comm_time ; // wall-time spent communicating
102 };
103 
104 /*--------------------------------------------------------------------*/
105 
106 inline int mpi_filebuf::is_open() const { return NULL != comm_buffer ; }
107 
108 /* The SUN has the 'streambuf::pptr()' as a non-const method,
109  which violates the ISO/ANSI standard specification.
110  Therefore, must cast away the const. */
111 
112 inline void mpi_filebuf::get_buffer( const char * & b , size_t & n ) const
113  { b = comm_buffer ; n = ((mpi_filebuf*)this)->pptr() - comm_buffer ; }
114 
115 inline double mpi_filebuf::wtime() const { return comm_time ; }
116 
117 #endif // STK_UTIL_PARALLEL_mpi_filebuf_hpp