ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/group/trunk/OOPSE-4/src/io/basic_ifstrstream.hpp
Revision: 2204
Committed: Fri Apr 15 22:04:00 2005 UTC (19 years, 2 months ago) by gezelter
File size: 10832 byte(s)
Log Message:
xemacs has been drafted to perform our indentation services

File Contents

# User Rev Content
1 gezelter 2204 /*
2 gezelter 1930 * 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 gezelter 2204 /**
64     * @class basic_ifstrstream basic_ifstrstream.hpp "io/basic_ifstrstream.hpp"
65     * @brief basic_ifstrstream class provides a stream interface to read data from files.
66     * <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     * if (in.is_open()) {
76     * in.getline(buffer, MAXLEN);
77     * }
78     * in.close();
79     * @endcode
80     */
81     template <class _CharT, class _Traits, class _Alloc>
82     class basic_ifstrstream : public std::basic_istream<_CharT, _Traits> {
83     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 tim 1570
91 gezelter 2204 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 2204 typedef std::basic_stringbuf<_CharT, _Traits, _Alloc> _Buf;
96 tim 1570 #else
97 gezelter 2204 typedef std::basic_filebuf<_CharT, _Traits> _Buf;
98 tim 1570 #endif
99    
100 gezelter 2204 static const int FileNotExists = -1;
101     static const int FileIOError = -2;
102 tim 1570
103 gezelter 2204 public:
104 tim 1570
105 gezelter 2204 /** Constructs an object of class ifstream. */
106     basic_ifstrstream()
107     : std::basic_istream<_CharT, _Traits>(0),
108     internalBuf_(), isRead(false) {
109 tim 2165
110 gezelter 2204 this->init(&internalBuf_);
111     }
112 tim 1570
113 gezelter 2204 /**
114     * Explicit constructor
115     * @filename String containing the name of the file to be opened
116     * @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     */
119     explicit basic_ifstrstream(const char* filename, std::ios_base::openmode mode = std::ios_base::in, bool checkFilename = false)
120     : std::basic_istream<_CharT, _Traits>(0),
121     internalBuf_(), isRead(false) {
122 tim 1570
123 gezelter 2204 this->init(&internalBuf_);
124     isRead = internalOpen(filename, mode | std::ios_base::in, checkFilename);
125     }
126 tim 1570
127 gezelter 2204 /**
128     * virtual destructor will close the file(in single mode) and clear the stream buffer
129     */
130     ~basic_ifstrstream(){
131     close();
132     }
133 tim 1570
134 gezelter 2204 /**
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     * @checkFilename Flags indicating checking the file name in parallel
141     */
142     void open(const char* filename, std::ios_base::openmode mode = std::ios_base::in, bool checkFilename = false){
143 tim 1570
144 gezelter 2204 if (!isRead ) {
145     isRead = internalOpen(filename, mode, checkFilename);
146     }
147     }
148 tim 1570
149 gezelter 2204 /**
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 tim 1570 #ifdef IS_MPI
156 gezelter 2204 return isRead;
157 tim 1570 #else
158 gezelter 2204 //single version fall back to ifstream
159     return internalBuf_.is_open();
160 tim 1570 #endif
161 gezelter 2204 }
162 tim 1570
163 gezelter 2204 /**
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 tim 1570 #ifndef IS_MPI
169 gezelter 2204 //single version fall back to ifstream
170     if (!internalBuf_.close())
171     this->setstate(std::ios_base::failbit);
172 tim 1570 #endif
173    
174 gezelter 2204 isRead = false;
175     }
176 tim 1570
177 gezelter 2204 /**
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     return static_cast<_Buf*>(&internalBuf_);
184     }
185 tim 1570
186 gezelter 2204 private:
187 tim 1570
188 gezelter 2204 /**
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     bool internalOpen(const char* filename, std::ios_base::openmode mode, bool checkFilename){
197 tim 1570
198     #ifdef IS_MPI
199 gezelter 2204 int commStatus;
200     long fileSize;
201     char* fbuf;
202     int filenameLen;
203     int diffFilename;
204     int error;
205     int myRank;
206     int masterNode;
207 tim 1570
208 gezelter 2204 commStatus = MPI_Comm_rank(MPI_COMM_WORLD, &myRank);
209     masterNode = 0;
210 tim 1572
211 gezelter 2204 if (myRank == masterNode) {
212 tim 1570
213 gezelter 2204 if (checkFilename) {
214 tim 1570
215 gezelter 2204 //check the filename is the same
216     filenameLen = strlen(filename);
217     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 gezelter 2204 diffFilename = 0;
221     commStatus = MPI_Allreduce(&diffFilename, &error, 1, MPI_INT, MPI_SUM, MPI_COMM_WORLD);
222 tim 1572
223 gezelter 2204 //if file names are different just return false
224     if (error > 0)
225     return false;
226     }
227 tim 1570
228 gezelter 2204 std::ifstream fin(filename, mode);
229 tim 1570
230 gezelter 2204 if (fin.is_open()) {
231 tim 1570
232 gezelter 2204 fin.seekg(0, std::ios::end);
233     fileSize = fin.tellg();
234     fin.seekg(0, std::ios::beg);
235 tim 1583
236 gezelter 2204 // '\0' need one more char
237     fbuf = new char[fileSize+1];
238 tim 1570
239 gezelter 2204 assert(fbuf != 0);
240 tim 1570
241 gezelter 2204 fin.read(fbuf, fileSize);
242 tim 1570
243 gezelter 2204 if (fin.fail())
244     fileSize = FileIOError;
245 tim 1570
246 gezelter 2204 //brocasting the file size
247     commStatus = MPI_Bcast(&fileSize, 1, MPI_LONG, masterNode, MPI_COMM_WORLD);
248 tim 1570
249 gezelter 2204 if (fileSize < 0) {
250     fin.close();
251     delete fbuf;
252 tim 1570
253 gezelter 2204 return false;
254     }
255 tim 1570
256 gezelter 2204 // make a c-style std::string and brocasting it
257     fbuf[fileSize] = '\0';
258     commStatus = MPI_Bcast(fbuf, fileSize + 1, MPI_CHAR, masterNode, MPI_COMM_WORLD);
259 tim 1570
260 gezelter 2204 //close the file and delete the buffer
261     fin.close();
262     internalBuf_.str(fbuf);
263     delete fbuf;
264     }else{
265     fileSize = FileNotExists;
266     commStatus = MPI_Bcast(&fileSize, 1, MPI_LONG, masterNode, MPI_COMM_WORLD);
267     return false;
268     }
269 tim 1570
270 gezelter 2204 } else{ //slave nodes
271 gezelter 1930
272 gezelter 2204 //check file name
273     if (checkFilename) {
274     commStatus = MPI_Bcast(&filenameLen, 1, MPI_INT, masterNode, MPI_COMM_WORLD);
275 tim 1570
276 gezelter 2204 char * masterFilename = new char[filenameLen];
277     commStatus = MPI_Bcast(masterFilename, filenameLen, MPI_CHAR, masterNode, MPI_COMM_WORLD);
278 tim 1572
279 gezelter 2204 if( strcmp(masterFilename, filename) == 0)
280     diffFilename = 0;
281     else
282     diffFilename = 1;
283 tim 1570
284 gezelter 2204 delete masterFilename;
285 tim 1572
286 gezelter 2204 commStatus = MPI_Allreduce(&diffFilename, &error, 1, MPI_INT, MPI_SUM, MPI_COMM_WORLD);
287 tim 1570
288 gezelter 2204 if (error > 0)
289     return false;
290     }
291     //get file size
292     commStatus = MPI_Bcast(&fileSize, 1, MPI_LONG, masterNode, MPI_COMM_WORLD);
293 tim 1570
294 gezelter 2204 if (fileSize >= 0 ) {
295     fbuf = new char[fileSize+1];
296     assert(fbuf);
297 tim 1570
298 gezelter 2204 //receive file content
299     commStatus = MPI_Bcast(fbuf, fileSize + 1, MPI_CHAR, masterNode, MPI_COMM_WORLD);
300 tim 1570
301 gezelter 2204 internalBuf_.str(fbuf);
302     delete fbuf;
303 tim 1570
304 gezelter 2204 } else if (fileSize == FileNotExists ) {
305     return false;
306 tim 1570
307 gezelter 2204 } else if (fileSize == FileIOError ) {
308     return false;
309     }
310     }
311 tim 1570
312     #else
313 gezelter 2204 //in single version, fall back to ifstream
314     if (!internalBuf_.open(filename, mode)) {
315     this->setstate(std::ios_base::failbit);
316     return false;
317     }
318 gezelter 1930
319 tim 1570 #endif
320 gezelter 2204 this->clear();
321     return true;
322     }
323 tim 1570
324 gezelter 2204 _Buf internalBuf_; /** internal stream buffer */
325     bool isRead; /** file opened flag */
326     };
327 tim 1570
328 gezelter 2204 typedef basic_ifstrstream<char, std::char_traits<char>, std::allocator<char> > ifstrstream;
329 tim 1570 }//namespace oopse
330     #endif //IO_IFSTRSTREAM_HPP