ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/group/trunk/OOPSE-4/src/io/basic_ifstrstream.hpp
Revision: 2165
Committed: Mon Apr 11 21:58:05 2005 UTC (19 years, 2 months ago) by tim
File size: 12645 byte(s)
Log Message:
avoid multiple inherit in basic_ifstrstream

File Contents

# User Rev Content
1 gezelter 1930 /*
2     * Copyright (c) 2005 The University of Notre Dame. All Rights Reserved.
3 tim 1570 *
4 gezelter 1930 * The University of Notre Dame grants you ("Licensee") a
5     * non-exclusive, royalty free, license to use, modify and
6     * redistribute this software in source and binary code form, provided
7     * that the following conditions are met:
8     *
9     * 1. Acknowledgement of the program authors must be made in any
10     * publication of scientific results based in part on use of the
11     * program. An acceptable form of acknowledgement is citation of
12     * the article in which the program was described (Matthew
13     * A. Meineke, Charles F. Vardeman II, Teng Lin, Christopher
14     * J. Fennell and J. Daniel Gezelter, "OOPSE: An Object-Oriented
15     * Parallel Simulation Engine for Molecular Dynamics,"
16     * J. Comput. Chem. 26, pp. 252-271 (2005))
17     *
18     * 2. Redistributions of source code must retain the above copyright
19     * notice, this list of conditions and the following disclaimer.
20     *
21     * 3. Redistributions in binary form must reproduce the above copyright
22     * notice, this list of conditions and the following disclaimer in the
23     * documentation and/or other materials provided with the
24     * distribution.
25     *
26     * This software is provided "AS IS," without a warranty of any
27     * kind. All express or implied conditions, representations and
28     * warranties, including any implied warranty of merchantability,
29     * fitness for a particular purpose or non-infringement, are hereby
30     * excluded. The University of Notre Dame and its licensors shall not
31     * be liable for any damages suffered by licensee as a result of
32     * using, modifying or distributing the software or its
33     * derivatives. In no event will the University of Notre Dame or its
34     * licensors be liable for any lost revenue, profit or data, or for
35     * direct, indirect, special, consequential, incidental or punitive
36     * damages, however caused and regardless of the theory of liability,
37     * arising out of the use of or inability to use software, even if the
38     * University of Notre Dame has been advised of the possibility of
39     * such damages.
40 tim 1570 */
41 gezelter 1930
42 tim 1570 /**
43     * @file basic_ifstrstream.hpp
44     * @author Teng Lin
45     * @date 10/14/2004
46     * @version 1.0
47     */
48    
49     #ifndef IO_IFSTRSTREAM_HPP
50     #define IO_IFSTRSTREAM_HPP
51    
52 tim 1583 #include <cassert>
53 tim 1572 #include <cstring>
54 tim 1570 #include <fstream>
55     #include <sstream>
56    
57 tim 1572 #ifdef IS_MPI
58 tim 1577 #include <mpi.h>
59 tim 1572 #endif
60    
61 tim 1570 namespace oopse {
62 gezelter 1930
63 tim 1570 /**
64     * @class basic_ifstrstream basic_ifstrstream.hpp "io/basic_ifstrstream.hpp"
65 gezelter 1930 * @brief basic_ifstrstream class provides a stream interface to read data from files.
66 tim 1570 * <p>In single mode, it falls back to ifstream. Don't need to read the whole file into memory.
67     * In parallel mode, the master node will read the whole file and brocast it to other slave nodes.
68     * After brocasting, every node will fall back to stringstream.</p>
69     *
70     * @code
71     * const int MAXLEN = 1024;
72     * char buffer[MAXLEN];
73     * ifstrstream in;
74     * in.open("Shapes.frc");
75 tim 1572 * if (in.is_open()) {
76 tim 1570 * in.getline(buffer, MAXLEN);
77     * }
78     * in.close();
79     * @endcode
80     */
81     template <class _CharT, class _Traits, class _Alloc>
82 gezelter 1930 class basic_ifstrstream : public std::basic_istream<_CharT, _Traits> {
83 tim 1570 public:
84     //traits
85     typedef _CharT char_type;
86     typedef typename _Traits::int_type int_type;
87     typedef typename _Traits::pos_type pos_type;
88     typedef typename _Traits::off_type off_type;
89     typedef _Traits traits_type;
90    
91 gezelter 1930 typedef std::basic_ios<_CharT, _Traits> _Basic_ios;
92     typedef std::basic_istream<_CharT, _Traits> _Base;
93 tim 1570
94     #ifdef IS_MPI
95 gezelter 1930 typedef std::basic_stringbuf<_CharT, _Traits, _Alloc> _Buf;
96 tim 1570 #else
97 gezelter 1930 typedef std::basic_filebuf<_CharT, _Traits> _Buf;
98 tim 1570 #endif
99    
100 gezelter 1930 static const int FileNotExists = -1;
101 tim 1570 static const int FileIOError = -2;
102    
103     public:
104    
105     /** Constructs an object of class ifstream. */
106     basic_ifstrstream()
107 tim 2165 : std::basic_istream<_CharT, _Traits>(0),
108     internalBuf_(), isRead(false) {
109    
110     this->init(&internalBuf_);
111 tim 1570 }
112    
113     /**
114     * Explicit constructor
115     * @filename String containing the name of the file to be opened
116 tim 1572 * @mode Flags describing the requested i/o mode for the file, default value is ios_base::in
117     * @checkFilename Flags indicating checking the file name in parallel
118 tim 1570 */
119 gezelter 1930 explicit basic_ifstrstream(const char* filename, std::ios_base::openmode mode = std::ios_base::in, bool checkFilename = false)
120 tim 2165 : std::basic_istream<_CharT, _Traits>(0),
121     internalBuf_(), isRead(false) {
122 tim 1570
123 tim 2165 this->init(&internalBuf_);
124     isRead = internalOpen(filename, mode | std::ios_base::in, checkFilename);
125 tim 1570 }
126    
127     /**
128 tim 1577 * virtual destructor will close the file(in single mode) and clear the stream buffer
129 tim 1570 */
130     ~basic_ifstrstream(){
131     close();
132     }
133    
134     /**
135     * Opens a file and associats a buffer with the specified file to perform the i/o operations
136     * (single mode). Master reads a file and brocasts its content to the other slave nodes. After
137     * brocasting, every nodes fall back to stringstream (parallel mode).
138     * @filename String containing the name of the file to be opened
139     * @mode Flags describing the requested i/o mode for the file
140 tim 1572 * @checkFilename Flags indicating checking the file name in parallel
141 tim 1570 */
142 gezelter 1930 void open(const char* filename, std::ios_base::openmode mode = std::ios_base::in, bool checkFilename = false){
143 tim 1570
144     if (!isRead ) {
145 tim 1572 isRead = internalOpen(filename, mode, checkFilename);
146 tim 1570 }
147     }
148    
149     /**
150     * Tests if the stream is currently associated with a valid buffer.
151     * @return true if a file has successfully been opened (single mode) or the whole file is read
152     * and spreaded among all of the processors (parallel mode), otherwise false is returned
153     */
154     bool is_open ( ) {
155     #ifdef IS_MPI
156     return isRead;
157     #else
158     //single version fall back to ifstream
159 tim 2165 return internalBuf_.is_open();
160 tim 1570 #endif
161     }
162    
163     /**
164     * In single mode, closes a file. The stream's file buffer is released from its association with
165     * the currently open file. In parallel mode, clean the
166     */
167     void close() {
168     #ifndef IS_MPI
169     //single version fall back to ifstream
170 tim 2165 if (!internalBuf_.close())
171 gezelter 1930 this->setstate(std::ios_base::failbit);
172 tim 1570 #endif
173    
174     isRead = false;
175     }
176    
177     /**
178     * Gets the stream buffer object associated with the stream
179     * @return A pointer to the stream buffe object(filebuf in single mode, stringbuf in
180     * parallel mode) associated with the stream.
181     */
182     _Buf* rdbuf() const{
183 tim 2165 return static_cast<_Buf*>(&internalBuf_);
184 tim 1570 }
185    
186     private:
187    
188     /**
189     * Internal function used to open the file
190     * @return true if succesfully opens a file (single mode) or gets the file content (parallel mode)
191     * otherwise return false
192     * @filename String containing the name of the file to be opened
193     * @mode Flags describing the requested i/o mode for the file
194     * @todo use try - catch syntax to make the program more readable
195     */
196 gezelter 1930 bool internalOpen(const char* filename, std::ios_base::openmode mode, bool checkFilename){
197 tim 1570
198     #ifdef IS_MPI
199     int commStatus;
200     long fileSize;
201     char* fbuf;
202     int filenameLen;
203     int diffFilename;
204     int error;
205 tim 1572 int myRank;
206     int masterNode;
207 tim 1570
208 tim 1572 commStatus = MPI_Comm_rank(MPI_COMM_WORLD, &myRank);
209     masterNode = 0;
210    
211     if (myRank == masterNode) {
212 tim 1570
213 tim 1572 if (checkFilename) {
214 tim 1570
215 tim 1572 //check the filename is the same
216     filenameLen = strlen(filename);
217 tim 1583 commStatus = MPI_Bcast(&filenameLen, 1, MPI_INT, masterNode, MPI_COMM_WORLD);
218     commStatus = MPI_Bcast((void*)filename, filenameLen, MPI_CHAR, masterNode, MPI_COMM_WORLD);
219 tim 1570
220 tim 1572 diffFilename = 0;
221 tim 1583 commStatus = MPI_Allreduce(&diffFilename, &error, 1, MPI_INT, MPI_SUM, MPI_COMM_WORLD);
222 tim 1572
223     //if file names are different just return false
224     if (error > 0)
225 tim 1570 return false;
226 tim 1572 }
227 tim 1570
228 gezelter 1930 std::ifstream fin(filename, mode);
229 tim 1570
230     if (fin.is_open()) {
231    
232 gezelter 1930 fin.seekg(0, std::ios::end);
233 tim 1570 fileSize = fin.tellg();
234 gezelter 1930 fin.seekg(0, std::ios::beg);
235 tim 1583
236 tim 1570 // '\0' need one more char
237     fbuf = new char[fileSize+1];
238    
239     assert(fbuf != 0);
240    
241     fin.read(fbuf, fileSize);
242    
243     if (fin.fail())
244     fileSize = FileIOError;
245    
246     //brocasting the file size
247     commStatus = MPI_Bcast(&fileSize, 1, MPI_LONG, masterNode, MPI_COMM_WORLD);
248    
249     if (fileSize < 0) {
250     fin.close();
251     delete fbuf;
252    
253     return false;
254     }
255    
256 gezelter 1930 // make a c-style std::string and brocasting it
257 tim 1570 fbuf[fileSize] = '\0';
258     commStatus = MPI_Bcast(fbuf, fileSize + 1, MPI_CHAR, masterNode, MPI_COMM_WORLD);
259    
260     //close the file and delete the buffer
261 tim 2165 fin.close();
262     internalBuf_.str(fbuf);
263 tim 1570 delete fbuf;
264     }else{
265 gezelter 1930 fileSize = FileNotExists;
266 tim 1570 commStatus = MPI_Bcast(&fileSize, 1, MPI_LONG, masterNode, MPI_COMM_WORLD);
267     return false;
268     }
269    
270 gezelter 1930 } else{ //slave nodes
271    
272 tim 1570 //check file name
273 tim 1572 if (checkFilename) {
274 tim 1583 commStatus = MPI_Bcast(&filenameLen, 1, MPI_INT, masterNode, MPI_COMM_WORLD);
275 tim 1570
276 tim 1572 char * masterFilename = new char[filenameLen];
277     commStatus = MPI_Bcast(masterFilename, filenameLen, MPI_CHAR, masterNode, MPI_COMM_WORLD);
278    
279     if( strcmp(masterFilename, filename) == 0)
280     diffFilename = 0;
281     else
282     diffFilename = 1;
283 tim 1570
284 tim 1572 delete masterFilename;
285    
286 tim 1583 commStatus = MPI_Allreduce(&diffFilename, &error, 1, MPI_INT, MPI_SUM, MPI_COMM_WORLD);
287 tim 1570
288 tim 1572 if (error > 0)
289     return false;
290     }
291 tim 1570 //get file size
292     commStatus = MPI_Bcast(&fileSize, 1, MPI_LONG, masterNode, MPI_COMM_WORLD);
293    
294     if (fileSize >= 0 ) {
295     fbuf = new char[fileSize+1];
296     assert(fbuf);
297    
298     //receive file content
299     commStatus = MPI_Bcast(fbuf, fileSize + 1, MPI_CHAR, masterNode, MPI_COMM_WORLD);
300    
301 tim 2165 internalBuf_.str(fbuf);
302 tim 1570 delete fbuf;
303    
304 gezelter 1930 } else if (fileSize == FileNotExists ) {
305 tim 1570 return false;
306    
307     } else if (fileSize == FileIOError ) {
308     return false;
309     }
310     }
311    
312     #else
313     //in single version, fall back to ifstream
314 tim 2165 if (!internalBuf_.open(filename, mode)) {
315 gezelter 1930 this->setstate(std::ios_base::failbit);
316     return false;
317     }
318    
319 tim 1570 #endif
320 tim 2165 this->clear();
321 tim 1570 return true;
322     }
323    
324 tim 2165 _Buf internalBuf_; /** internal stream buffer */
325 tim 1570 bool isRead; /** file opened flag */
326     };
327    
328 gezelter 1930 typedef basic_ifstrstream<char, std::char_traits<char>, std::allocator<char> > ifstrstream;
329 tim 1570 }//namespace oopse
330     #endif //IO_IFSTRSTREAM_HPP