ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/OpenMD/branches/development/src/io/ifstrstream.cpp
Revision: 1627
Committed: Tue Sep 13 22:05:04 2011 UTC (13 years, 7 months ago) by gezelter
File size: 9968 byte(s)
Log Message:
Splitting out ifstrstream into a header and an implementation.  This
means that much of the code that depends on it can be compiled only
once and the parallel I/O is concentrated into a few files.  To do
this, a number of files that relied on basic_ifstrstream to load the
mpi header had to be modified to manage their own headers.


File Contents

# User Rev Content
1 gezelter 1627 /*
2     * Copyright (c) 2005 The University of Notre Dame. All Rights Reserved.
3     *
4     * 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. Redistributions of source code must retain the above copyright
10     * notice, this list of conditions and the following disclaimer.
11     *
12     * 2. Redistributions in binary form must reproduce the above copyright
13     * notice, this list of conditions and the following disclaimer in the
14     * documentation and/or other materials provided with the
15     * distribution.
16     *
17     * This software is provided "AS IS," without a warranty of any
18     * kind. All express or implied conditions, representations and
19     * warranties, including any implied warranty of merchantability,
20     * fitness for a particular purpose or non-infringement, are hereby
21     * excluded. The University of Notre Dame and its licensors shall not
22     * be liable for any damages suffered by licensee as a result of
23     * using, modifying or distributing the software or its
24     * derivatives. In no event will the University of Notre Dame or its
25     * licensors be liable for any lost revenue, profit or data, or for
26     * direct, indirect, special, consequential, incidental or punitive
27     * damages, however caused and regardless of the theory of liability,
28     * arising out of the use of or inability to use software, even if the
29     * University of Notre Dame has been advised of the possibility of
30     * such damages.
31     *
32     * SUPPORT OPEN SCIENCE! If you use OpenMD or its source code in your
33     * research, please cite the appropriate papers when you publish your
34     * work. Good starting points are:
35     *
36     * [1] Meineke, et al., J. Comp. Chem. 26, 252-271 (2005).
37     * [2] Fennell & Gezelter, J. Chem. Phys. 124, 234104 (2006).
38     * [3] Sun, Lin & Gezelter, J. Chem. Phys. 128, 24107 (2008).
39     * [4] Vardeman & Gezelter, in progress (2009).
40     */
41    
42     /**
43     * @file basic_ifstrstream.cpp
44     * @author Teng Lin
45     * @date 10/14/2004
46     * @version 1.0
47     */
48    
49     #include "io/ifstrstream.hpp"
50    
51     #ifdef IS_MPI
52     #include <mpi.h>
53     #endif
54    
55     namespace OpenMD {
56    
57     /** Constructs an object of class ifstream. */
58     #ifdef IS_MPI
59     ifstrstream::ifstrstream()
60     : std::basic_istream<char, std::char_traits<char> >(0),
61     internalStringBuf_(), isRead(false) {
62     this->init(&internalStringBuf_);
63     }
64     #else
65     ifstrstream::ifstrstream()
66     : std::basic_istream<char, std::char_traits<char> >(0),
67     internalFileBuf_(), isRead(false) {
68     this->init(&internalFileBuf_);
69     }
70     #endif
71    
72     /**
73     * Explicit constructor
74     * @filename String containing the name of the file to be opened
75     * @mode Flags describing the requested i/o mode for the file, default value is ios_base::in
76     * @checkFilename Flags indicating checking the file name in parallel
77     */
78     #ifdef IS_MPI
79     ifstrstream::ifstrstream(const char* filename, std::ios_base::openmode mode, bool checkFilename)
80     : std::basic_istream<char, std::char_traits<char> >(0),
81     internalStringBuf_(), isRead(false) {
82     this->init(&internalStringBuf_);
83     isRead = internalOpen(filename, mode | std::ios_base::in, checkFilename);
84     }
85     #else
86     ifstrstream::ifstrstream(const char* filename, std::ios_base::openmode mode, bool checkFilename)
87     : std::basic_istream<char, std::char_traits<char> >(0),
88     internalFileBuf_(), isRead(false) {
89    
90     this->init(&internalFileBuf_);
91     isRead = internalOpen(filename, mode | std::ios_base::in, checkFilename);
92     }
93     #endif
94     /**
95     * virtual destructor will close the file(in single mode) and clear the stream buffer
96     */
97     ifstrstream::~ifstrstream(){
98     close();
99     }
100    
101     /**
102     * Opens a file and associats a buffer with the specified file to perform the i/o operations
103     * (single mode). Master reads a file and brocasts its content to the other slave nodes. After
104     * brocasting, every nodes fall back to stringstream (parallel mode).
105     * @filename String containing the name of the file to be opened
106     * @mode Flags describing the requested i/o mode for the file
107     * @checkFilename Flags indicating checking the file name in parallel
108     */
109     void ifstrstream::open(const char* filename, std::ios_base::openmode mode, bool checkFilename){
110    
111     if (!isRead ) {
112     isRead = internalOpen(filename, mode, checkFilename);
113     }
114     }
115    
116     /**
117     * Tests if the stream is currently associated with a valid buffer.
118     * @return true if a file has successfully been opened (single mode) or the whole file is read
119     * and spreaded among all of the processors (parallel mode), otherwise false is returned
120     */
121     bool ifstrstream::is_open ( ) {
122     #ifdef IS_MPI
123     return isRead;
124     #else
125     //single version fall back to ifstream
126     return internalFileBuf_.is_open();
127     #endif
128     }
129    
130     /**
131     * In single mode, closes a file. The stream's file buffer is
132     * released from its association with the currently open file. In
133     * parallel mode, clean the
134     */
135     void ifstrstream::close() {
136     #ifndef IS_MPI
137     //single version fall back to ifstream
138     if (!internalFileBuf_.close())
139     this->setstate(std::ios_base::failbit);
140     #endif
141    
142     isRead = false;
143     }
144    
145     /**
146     * Gets the stream buffer object associated with the stream
147     * @return A pointer to the stream buffer object(filebuf in single
148     * mode, stringbuf in parallel mode) associated with the stream.
149     */
150     std::basic_streambuf<char, std::char_traits<char> >* ifstrstream::rdbuf() {
151     #ifdef IS_MPI
152     return static_cast<_StringBuf*>(&internalStringBuf_);
153     #else
154     return static_cast<_FileBuf*>(&internalFileBuf_);
155     #endif
156     }
157    
158     /**
159     * Internal function used to open the file
160     * @return true if succesfully opens a file (single mode) or gets the file content (parallel mode)
161     * otherwise return false
162     * @filename String containing the name of the file to be opened
163     * @mode Flags describing the requested i/o mode for the file
164     * @todo use try - catch syntax to make the program more readable
165     */
166    
167     bool ifstrstream::internalOpen(const char* filename, std::ios_base::openmode mode, bool checkFilename){
168    
169     #ifdef IS_MPI
170     int commStatus;
171     long fileSize;
172     char* fbuf;
173     int filenameLen;
174     int diffFilename;
175     int error;
176     int myRank;
177     int masterNode;
178    
179     commStatus = MPI_Comm_rank(MPI_COMM_WORLD, &myRank);
180     masterNode = 0;
181    
182     if (myRank == masterNode) {
183    
184     if (checkFilename) {
185    
186     //check the filename is the same
187     filenameLen = strlen(filename);
188     commStatus = MPI_Bcast(&filenameLen, 1, MPI_INT, masterNode, MPI_COMM_WORLD);
189     commStatus = MPI_Bcast((void*)filename, filenameLen, MPI_CHAR, masterNode, MPI_COMM_WORLD);
190    
191     diffFilename = 0;
192     commStatus = MPI_Allreduce(&diffFilename, &error, 1, MPI_INT, MPI_SUM, MPI_COMM_WORLD);
193    
194     //if file names are different just return false
195     if (error > 0)
196     return false;
197     }
198    
199     std::ifstream fin(filename, mode);
200    
201     if (fin.is_open()) {
202    
203     fin.seekg(0, std::ios::end);
204     fileSize = fin.tellg();
205     fin.seekg(0, std::ios::beg);
206    
207     // '\0' need one more char
208     fbuf = new char[fileSize+1];
209    
210     assert(fbuf != 0);
211    
212     fin.read(fbuf, fileSize);
213    
214     if (fin.fail())
215     fileSize = FileIOError;
216    
217     //brocasting the file size
218     commStatus = MPI_Bcast(&fileSize, 1, MPI_LONG, masterNode, MPI_COMM_WORLD);
219    
220     if (fileSize < 0) {
221     fin.close();
222     delete fbuf;
223    
224     return false;
225     }
226    
227     // make a c-style std::string and brocasting it
228     fbuf[fileSize] = '\0';
229     commStatus = MPI_Bcast(fbuf, fileSize + 1, MPI_CHAR, masterNode, MPI_COMM_WORLD);
230    
231     //close the file and delete the buffer
232     fin.close();
233     internalStringBuf_.str(fbuf);
234     delete [] fbuf;
235     }else{
236     fileSize = FileNotExists;
237     commStatus = MPI_Bcast(&fileSize, 1, MPI_LONG, masterNode, MPI_COMM_WORLD);
238     return false;
239     }
240    
241     } else{ //slave nodes
242    
243     //check file name
244     if (checkFilename) {
245     commStatus = MPI_Bcast(&filenameLen, 1, MPI_INT, masterNode, MPI_COMM_WORLD);
246    
247     char * masterFilename = new char[filenameLen];
248     commStatus = MPI_Bcast(masterFilename, filenameLen, MPI_CHAR, masterNode, MPI_COMM_WORLD);
249    
250     if( strcmp(masterFilename, filename) == 0)
251     diffFilename = 0;
252     else
253     diffFilename = 1;
254    
255     delete masterFilename;
256    
257     commStatus = MPI_Allreduce(&diffFilename, &error, 1, MPI_INT, MPI_SUM, MPI_COMM_WORLD);
258    
259     if (error > 0)
260     return false;
261     }
262     //get file size
263     commStatus = MPI_Bcast(&fileSize, 1, MPI_LONG, masterNode, MPI_COMM_WORLD);
264    
265     if (fileSize >= 0 ) {
266     fbuf = new char[fileSize+1];
267     assert(fbuf);
268    
269     //receive file content
270     commStatus = MPI_Bcast(fbuf, fileSize + 1, MPI_CHAR, masterNode, MPI_COMM_WORLD);
271    
272     internalStringBuf_.str(fbuf);
273     delete [] fbuf;
274    
275     } else if (fileSize == FileNotExists ) {
276     return false;
277    
278     } else if (fileSize == FileIOError ) {
279     return false;
280     }
281     }
282    
283     #else
284     //in single version, fall back to ifstream
285     if (!internalFileBuf_.open(filename, mode)) {
286     this->setstate(std::ios_base::failbit);
287     return false;
288     }
289    
290     #endif
291     this->clear();
292     return true;
293     }
294     }

Properties

Name Value
svn:eol-style native