ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/group/trunk/OOPSE-2.0/src/io/basic_ifstrstream.hpp
Revision: 1583
Committed: Fri Oct 15 21:10:50 2004 UTC (19 years, 8 months ago) by tim
File size: 13055 byte(s)
Log Message:
fix a bunch of bugs

File Contents

# User Rev Content
1 tim 1570 /*
2     * Copyright (C) 2000-2004 Object Oriented Parallel Simulation Engine (OOPSE) project
3     *
4     * Contact: oopse@oopse.org
5     *
6     * This program is free software; you can redistribute it and/or
7     * modify it under the terms of the GNU Lesser General Public License
8     * as published by the Free Software Foundation; either version 2.1
9     * of the License, or (at your option) any later version.
10     * All we ask is that proper credit is given for our work, which includes
11     * - but is not limited to - adding the above copyright notice to the beginning
12     * of your source code files, and to any copyright notice that you may distribute
13     * with programs based on this work.
14     *
15     * This program is distributed in the hope that it will be useful,
16     * but WITHOUT ANY WARRANTY; without even the implied warranty of
17     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18     * GNU Lesser General Public License for more details.
19     *
20     * You should have received a copy of the GNU Lesser General Public License
21     * along with this program; if not, write to the Free Software
22     * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23     *
24     */
25    
26     /**
27     * @file basic_ifstrstream.hpp
28     * @author Teng Lin
29     * @date 10/14/2004
30     * @version 1.0
31     */
32    
33     #ifndef IO_IFSTRSTREAM_HPP
34     #define IO_IFSTRSTREAM_HPP
35    
36 tim 1583 #include <cassert>
37 tim 1572 #include <cstring>
38 tim 1570 #include <fstream>
39     #include <sstream>
40    
41 tim 1572 #ifdef IS_MPI
42 tim 1577 #include <mpi.h>
43 tim 1572 #endif
44    
45 tim 1570 namespace oopse {
46     using namespace std;
47     /**
48     * @class basic_ifstrstream basic_ifstrstream.hpp "io/basic_ifstrstream.hpp"
49     * @brief class provides a stream interface to read data from files.
50     * <p>In single mode, it falls back to ifstream. Don't need to read the whole file into memory.
51     * In parallel mode, the master node will read the whole file and brocast it to other slave nodes.
52     * After brocasting, every node will fall back to stringstream.</p>
53     *
54     * @code
55     * const int MAXLEN = 1024;
56     * char buffer[MAXLEN];
57     * ifstrstream in;
58     * in.open("Shapes.frc");
59 tim 1572 * if (in.is_open()) {
60 tim 1570 * in.getline(buffer, MAXLEN);
61     * }
62     * in.close();
63     * @endcode
64     */
65     template <class _CharT, class _Traits, class _Alloc>
66     class basic_ifstrstream : public basic_istream<_CharT, _Traits> {
67     public:
68     //traits
69     typedef _CharT char_type;
70     typedef typename _Traits::int_type int_type;
71     typedef typename _Traits::pos_type pos_type;
72     typedef typename _Traits::off_type off_type;
73     typedef _Traits traits_type;
74    
75     typedef basic_ios<_CharT, _Traits> _Basic_ios;
76     typedef basic_istream<_CharT, _Traits> _Base;
77    
78     #ifdef IS_MPI
79     typedef basic_stringbuf<_CharT, _Traits, _Alloc> _Buf;
80     #else
81     typedef basic_filebuf<_CharT, _Traits> _Buf;
82     #endif
83    
84     static const int FileNoExists = -1;
85     static const int FileIOError = -2;
86    
87     public:
88    
89     /** Constructs an object of class ifstream. */
90     basic_ifstrstream()
91     : basic_ios<_CharT, _Traits>(), basic_istream<_CharT, _Traits>(0),
92     internalBuf_(NULL), isRead(false) {
93    
94     #ifdef IS_MPI
95     //in parallel mode, fall back to istringstream
96     basic_stringbuf<_CharT, _Traits, _Alloc>* stringBuffer = new basic_stringbuf<_CharT, _Traits, _Alloc>();
97     internalBuf_ = stringBuffer;
98     #else
99     //in single version, fall back to ifstream
100     basic_filebuf<_CharT, _Traits>* fileBuffer = new basic_filebuf<_CharT, _Traits>();
101     internalBuf_ = fileBuffer;
102     #endif
103    
104     this->init(internalBuf_);
105     isRead = false;
106     }
107    
108     /**
109     * Explicit constructor
110     * @filename String containing the name of the file to be opened
111 tim 1572 * @mode Flags describing the requested i/o mode for the file, default value is ios_base::in
112     * @checkFilename Flags indicating checking the file name in parallel
113 tim 1570 */
114 tim 1572 explicit basic_ifstrstream(const char* filename, ios_base::openmode mode = ios_base::in, bool checkFilename = false)
115 tim 1570 : basic_ios<_CharT, _Traits>(), basic_istream<_CharT, _Traits>(0),
116     internalBuf_(NULL), isRead(false) {
117    
118 tim 1572 isRead = internalOpen(filename, mode | ios_base::in, checkFilename);
119 tim 1570 }
120    
121     /**
122 tim 1577 * virtual destructor will close the file(in single mode) and clear the stream buffer
123 tim 1570 */
124     ~basic_ifstrstream(){
125     close();
126     delete internalBuf_;
127     internalBuf_ = NULL;
128     }
129    
130     /**
131     * Opens a file and associats a buffer with the specified file to perform the i/o operations
132     * (single mode). Master reads a file and brocasts its content to the other slave nodes. After
133     * brocasting, every nodes fall back to stringstream (parallel mode).
134     * @filename String containing the name of the file to be opened
135     * @mode Flags describing the requested i/o mode for the file
136 tim 1572 * @checkFilename Flags indicating checking the file name in parallel
137 tim 1570 */
138 tim 1572 void open(const char* filename, ios_base::openmode mode = ios_base::in, bool checkFilename = false){
139 tim 1570
140     if (!isRead ) {
141 tim 1572 isRead = internalOpen(filename, mode, checkFilename);
142 tim 1570 }
143     }
144    
145     /**
146     * Tests if the stream is currently associated with a valid buffer.
147     * @return true if a file has successfully been opened (single mode) or the whole file is read
148     * and spreaded among all of the processors (parallel mode), otherwise false is returned
149     */
150     bool is_open ( ) {
151     #ifdef IS_MPI
152     return isRead;
153     #else
154     //single version fall back to ifstream
155     return this->rdbuf()->is_open();
156     #endif
157     }
158    
159     /**
160     * In single mode, closes a file. The stream's file buffer is released from its association with
161     * the currently open file. In parallel mode, clean the
162     */
163     void close() {
164     #ifndef IS_MPI
165     //single version fall back to ifstream
166     if (!this->rdbuf()->close())
167     this->setstate(ios_base::failbit);
168     #endif
169    
170     isRead = false;
171     }
172    
173     /**
174     * Gets the stream buffer object associated with the stream
175     * @return A pointer to the stream buffe object(filebuf in single mode, stringbuf in
176     * parallel mode) associated with the stream.
177     */
178     _Buf* rdbuf() const{
179 tim 1582 return static_cast<_Buf*>(internalBuf_);
180 tim 1570 }
181    
182     private:
183    
184     /**
185     * Internal function used to open the file
186     * @return true if succesfully opens a file (single mode) or gets the file content (parallel mode)
187     * otherwise return false
188     * @filename String containing the name of the file to be opened
189     * @mode Flags describing the requested i/o mode for the file
190     * @todo use try - catch syntax to make the program more readable
191     */
192 tim 1572 bool internalOpen(const char* filename, ios_base::openmode mode, bool checkFilename){
193 tim 1570
194     #ifdef IS_MPI
195     int commStatus;
196     long fileSize;
197     char* fbuf;
198     int filenameLen;
199     int diffFilename;
200     int error;
201 tim 1572 int myRank;
202     int masterNode;
203 tim 1570
204 tim 1572 commStatus = MPI_Comm_rank(MPI_COMM_WORLD, &myRank);
205     masterNode = 0;
206    
207     if (myRank == masterNode) {
208 tim 1570
209 tim 1572 if (checkFilename) {
210 tim 1570
211 tim 1572 //check the filename is the same
212     filenameLen = strlen(filename);
213 tim 1583 commStatus = MPI_Bcast(&filenameLen, 1, MPI_INT, masterNode, MPI_COMM_WORLD);
214     commStatus = MPI_Bcast((void*)filename, filenameLen, MPI_CHAR, masterNode, MPI_COMM_WORLD);
215 tim 1570
216 tim 1572 diffFilename = 0;
217 tim 1583 commStatus = MPI_Allreduce(&diffFilename, &error, 1, MPI_INT, MPI_SUM, MPI_COMM_WORLD);
218 tim 1572
219     //if file names are different just return false
220     if (error > 0)
221 tim 1570 return false;
222 tim 1572 }
223 tim 1570
224 tim 1572 ifstream fin(filename, mode);
225 tim 1570 basic_stringbuf<_CharT, _Traits, _Alloc>* sbuf;
226    
227     if (fin.is_open()) {
228    
229 tim 1583 fin.seekg(0, ios::end);
230 tim 1570 fileSize = fin.tellg();
231 tim 1583 fin.seekg(0, ios::beg);
232    
233 tim 1570 // '\0' need one more char
234     fbuf = new char[fileSize+1];
235    
236     assert(fbuf != 0);
237    
238     fin.read(fbuf, fileSize);
239    
240     if (fin.fail())
241     fileSize = FileIOError;
242    
243     //brocasting the file size
244     commStatus = MPI_Bcast(&fileSize, 1, MPI_LONG, masterNode, MPI_COMM_WORLD);
245    
246     if (fileSize < 0) {
247     fin.close();
248     delete fbuf;
249    
250     return false;
251     }
252    
253     // make a c-style string and brocasting it
254     fbuf[fileSize] = '\0';
255     commStatus = MPI_Bcast(fbuf, fileSize + 1, MPI_CHAR, masterNode, MPI_COMM_WORLD);
256    
257     //it is safe to delete null pointer
258     delete internalBuf_;
259    
260     //initilaize istream
261     internalBuf_ = new basic_stringbuf<_CharT, _Traits, _Alloc>(fbuf, mode);
262     assert(internalBuf_);
263     this->init(internalBuf_);
264    
265     //close the file and delete the buffer
266     fin.close();
267     delete fbuf;
268     }else{
269     fileSize = FileNoExists;
270     commStatus = MPI_Bcast(&fileSize, 1, MPI_LONG, masterNode, MPI_COMM_WORLD);
271     return false;
272     }
273    
274     } else{
275     //check file name
276 tim 1572 if (checkFilename) {
277 tim 1583 commStatus = MPI_Bcast(&filenameLen, 1, MPI_INT, masterNode, MPI_COMM_WORLD);
278 tim 1570
279 tim 1572 char * masterFilename = new char[filenameLen];
280     commStatus = MPI_Bcast(masterFilename, filenameLen, MPI_CHAR, masterNode, MPI_COMM_WORLD);
281    
282     if( strcmp(masterFilename, filename) == 0)
283     diffFilename = 0;
284     else
285     diffFilename = 1;
286 tim 1570
287 tim 1572 delete masterFilename;
288    
289 tim 1583 commStatus = MPI_Allreduce(&diffFilename, &error, 1, MPI_INT, MPI_SUM, MPI_COMM_WORLD);
290 tim 1570
291 tim 1572 if (error > 0)
292     return false;
293     }
294 tim 1570 //get file size
295     commStatus = MPI_Bcast(&fileSize, 1, MPI_LONG, masterNode, MPI_COMM_WORLD);
296    
297     if (fileSize >= 0 ) {
298     fbuf = new char[fileSize+1];
299     assert(fbuf);
300    
301     //receive file content
302     commStatus = MPI_Bcast(fbuf, fileSize + 1, MPI_CHAR, masterNode, MPI_COMM_WORLD);
303    
304     //it is safe to delete null pointer
305     delete internalBuf_;
306    
307     //initilaize istream
308     internalBuf_ = new basic_stringbuf<_CharT, _Traits, _Alloc>(fbuf, mode);
309     assert(internalBuf_);
310     this->init(internalBuf_);
311    
312     delete fbuf;
313    
314     } else if (fileSize == FileNoExists ) {
315     return false;
316    
317     } else if (fileSize == FileIOError ) {
318     return false;
319     }
320     }
321    
322     #else
323     //in single version, fall back to ifstream
324     basic_filebuf<_CharT, _Traits>* fileBuffer = new basic_filebuf<_CharT, _Traits>();
325    
326     this->init(fileBuffer);
327     if (!fileBuffer->open(filename, mode))
328     this->setstate(ios_base::failbit);
329    
330     //it is safe to delete null pointer
331     delete internalBuf_;
332    
333     internalBuf_ = fileBuffer;
334     #endif
335    
336     return true;
337     }
338    
339     basic_streambuf<_CharT, _Traits>* internalBuf_; /** internal stream buffer */
340     bool isRead; /** file opened flag */
341     };
342    
343 tim 1581 typedef basic_ifstrstream<char, char_traits<char>, allocator<char> > ifstrstream;
344 tim 1570 }//namespace oopse
345     #endif //IO_IFSTRSTREAM_HPP