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

# Content
1 /*
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