ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/OpenMD/trunk/src/io/ifstrstream.cpp
Revision: 1969
Committed: Wed Feb 26 14:14:50 2014 UTC (11 years, 2 months ago) by gezelter
File size: 10033 byte(s)
Log Message:
Fixes to deal with deprecation of MPI C++ bindings.  We've reverted back to the
C calls.

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, 234107 (2008).
39 * [4] Kuang & Gezelter, J. Chem. Phys. 133, 164101 (2010).
40 * [5] Vardeman, Stocker & Gezelter, J. Chem. Theory Comput. 7, 834 (2011).
41 */
42
43 /**
44 * @file ifstrstream.cpp
45 * @author Teng Lin
46 * @date 10/14/2004
47 * @version 1.0
48 */
49
50 #ifdef IS_MPI
51 #include <mpi.h>
52 #endif
53
54 #include "io/ifstrstream.hpp"
55
56 namespace OpenMD {
57
58 /** Constructs an object of class ifstream. */
59 #ifdef IS_MPI
60 ifstrstream::ifstrstream()
61 : std::basic_istream<char, std::char_traits<char> >(0),
62 internalStringBuf_(), isRead(false) {
63 this->init(&internalStringBuf_);
64 }
65 #else
66 ifstrstream::ifstrstream()
67 : std::basic_istream<char, std::char_traits<char> >(0),
68 internalFileBuf_(), isRead(false) {
69 this->init(&internalFileBuf_);
70 }
71 #endif
72
73 /**
74 * Explicit constructor
75 * @param filename String containing the name of the file to be opened
76 * @param mode Flags describing the requested i/o mode for the file,
77 * default value is ios_base::in
78 * @param checkFilename Flags indicating checking the file name in parallel
79 */
80 #ifdef IS_MPI
81 ifstrstream::ifstrstream(const char* filename, std::ios_base::openmode mode, bool checkFilename)
82 : std::basic_istream<char, std::char_traits<char> >(0),
83 internalStringBuf_(), isRead(false) {
84 this->init(&internalStringBuf_);
85 isRead = internalOpen(filename, mode | std::ios_base::in, checkFilename);
86 }
87 #else
88 ifstrstream::ifstrstream(const char* filename, std::ios_base::openmode mode, bool checkFilename)
89 : std::basic_istream<char, std::char_traits<char> >(0),
90 internalFileBuf_(), isRead(false) {
91
92 this->init(&internalFileBuf_);
93 isRead = internalOpen(filename, mode | std::ios_base::in, checkFilename);
94 }
95 #endif
96 /**
97 * virtual destructor will close the file (in single mode) and clear
98 * the stream buffer
99 */
100 ifstrstream::~ifstrstream(){ close();
101 }
102
103 /**
104 * Opens a file and associates a buffer with the specified file to
105 * perform the i/o operations (single mode). The master node reads a
106 * file and broadcasts its content to the other slave nodes. After
107 * broadcasting, all nodes fall back to stringstream (parallel
108 * mode).
109 * @param filename String containing the name of the file to be opened
110 * @param mode Flags describing the requested i/o mode for the file
111 * @param checkFilename Flags indicating checking the file name in parallel
112 */
113 void ifstrstream::open(const char* filename, std::ios_base::openmode mode, bool checkFilename){
114
115 if (!isRead ) {
116 isRead = internalOpen(filename, mode, checkFilename);
117 }
118 }
119
120 /**
121 * Tests if the stream is currently associated with a valid buffer.
122 * @return true if a file has successfully been opened (single mode)
123 * or the whole file has been read and spread among all of the
124 * processors (parallel mode), otherwise false is returned
125 */
126 bool ifstrstream::is_open ( ) {
127 #ifdef IS_MPI
128 return isRead;
129 #else
130 //single version fall back to ifstream
131 return internalFileBuf_.is_open();
132 #endif
133 }
134
135 /**
136 * In single mode, closes a file. The stream's file buffer is
137 * released from its association with the currently open file. In
138 * parallel mode, cleans up.
139 */
140 void ifstrstream::close() {
141 #ifndef IS_MPI
142 //single version fall back to ifstream
143 if (!internalFileBuf_.close())
144 this->setstate(std::ios_base::failbit);
145 #endif
146
147 isRead = false;
148 }
149
150 /**
151 * Gets the stream buffer object associated with the stream
152 * @return A pointer to the stream buffer object(filebuf in single
153 * mode, stringbuf in parallel mode) associated with the stream.
154 */
155 std::basic_streambuf<char, std::char_traits<char> >* ifstrstream::rdbuf() {
156 #ifdef IS_MPI
157 return static_cast<_StringBuf*>(&internalStringBuf_);
158 #else
159 return static_cast<_FileBuf*>(&internalFileBuf_);
160 #endif
161 }
162
163 /**
164 * Internal function used to open the file
165 * @return true if succesfully opens a file (single mode) or gets
166 * the file content (parallel mode) otherwise return false
167 * @param filename String containing the name of the file to be opened
168 * @param mode Flags describing the requested i/o mode for the file
169 * @param checkFilename Flags indicating checking the file name in parallel
170 * @todo use try - catch syntax to make the program more readable
171 */
172
173 bool ifstrstream::internalOpen(const char* filename, std::ios_base::openmode mode, bool checkFilename){
174
175 #ifdef IS_MPI
176 //int commStatus;
177 long fileSize;
178 char* fbuf;
179 int filenameLen;
180 int diffFilename;
181 int error;
182 int myRank;
183 int masterNode;
184
185 MPI_Comm_rank( MPI_COMM_WORLD, &myRank);
186
187 masterNode = 0;
188
189 if (myRank == masterNode) {
190
191 if (checkFilename) {
192
193 //check the filename is the same
194 filenameLen = strlen(filename);
195 MPI_Bcast(&filenameLen, 1, MPI_INT, masterNode, MPI_COMM_WORLD);
196 MPI_Bcast((void*)filename, filenameLen, MPI_CHAR,
197 masterNode, MPI_COMM_WORLD);
198
199 diffFilename = 0;
200 MPI_Allreduce(&diffFilename, &error, 1, MPI_INT, MPI_SUM,
201 MPI_COMM_WORLD);
202
203 //if file names are different just return false
204 if (error > 0)
205 return false;
206 }
207
208 std::ifstream fin(filename, mode);
209
210 if (fin.is_open()) {
211
212 fin.seekg(0, std::ios::end);
213 fileSize = fin.tellg();
214 fin.seekg(0, std::ios::beg);
215
216 // '\0' need one more char
217 fbuf = new char[fileSize+1];
218
219 assert(fbuf != 0);
220
221 fin.read(fbuf, fileSize);
222
223 if (fin.fail())
224 fileSize = FileIOError;
225
226 //broadcast the file size
227 MPI_Bcast(&fileSize, 1, MPI_LONG, masterNode, MPI_COMM_WORLD);
228
229 if (fileSize < 0) {
230 fin.close();
231 delete[] fbuf;
232
233 return false;
234 }
235
236 // make a c-style std::string and broadcast it
237 fbuf[fileSize] = '\0';
238 MPI_Bcast(fbuf, fileSize + 1, MPI_CHAR, masterNode, MPI_COMM_WORLD);
239
240 //close the file and delete the buffer
241 fin.close();
242 internalStringBuf_.str(fbuf);
243 delete[] fbuf;
244 }else{
245 fileSize = FileNotExists;
246 MPI_Bcast(&fileSize, 1, MPI_LONG, masterNode, MPI_COMM_WORLD);
247 return false;
248 }
249
250 } else{ //slave nodes
251
252 //check file name
253 if (checkFilename) {
254 MPI_Bcast(&filenameLen, 1, MPI_INT, masterNode, MPI_COMM_WORLD);
255
256 char * masterFilename = new char[filenameLen];
257 MPI_Bcast(masterFilename, filenameLen, MPI_CHAR,
258 masterNode, MPI_COMM_WORLD);
259
260 if( strcmp(masterFilename, filename) == 0)
261 diffFilename = 0;
262 else
263 diffFilename = 1;
264
265 delete[] masterFilename;
266
267 MPI_Allreduce(&diffFilename, &error, 1, MPI_INT, MPI_SUM,
268 MPI_COMM_WORLD);
269
270 if (error > 0)
271 return false;
272 }
273 //get file size
274 MPI_Bcast(&fileSize, 1, MPI_LONG, masterNode, MPI_COMM_WORLD);
275
276 if (fileSize >= 0 ) {
277 fbuf = new char[fileSize+1];
278 assert(fbuf);
279
280 //receive file content
281 MPI_Bcast(fbuf, fileSize + 1, MPI_CHAR, masterNode, MPI_COMM_WORLD);
282
283 internalStringBuf_.str(fbuf);
284 delete [] fbuf;
285
286 } else if (fileSize == FileNotExists ) {
287 return false;
288
289 } else if (fileSize == FileIOError ) {
290 return false;
291 }
292 }
293
294 #else
295 //in single version, fall back to ifstream
296 if (!internalFileBuf_.open(filename, mode)) {
297 this->setstate(std::ios_base::failbit);
298 return false;
299 }
300
301 #endif
302 this->clear();
303 return true;
304 }
305 }

Properties

Name Value
svn:eol-style native