ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/OpenMD/trunk/src/io/ifstrstream.cpp
Revision: 1962
Committed: Wed Jan 15 22:26:18 2014 UTC (11 years, 3 months ago) by gezelter
File size: 9977 byte(s)
Log Message:
Some potential bug fixes.

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(){
101 close();
102 }
103
104 /**
105 * Opens a file and associates a buffer with the specified file to
106 * perform the i/o operations (single mode). The master node reads a
107 * file and broadcasts its content to the other slave nodes. After
108 * broadcasting, all nodes fall back to stringstream (parallel
109 * mode).
110 * @param filename String containing the name of the file to be opened
111 * @param mode Flags describing the requested i/o mode for the file
112 * @param checkFilename Flags indicating checking the file name in parallel
113 */
114 void ifstrstream::open(const char* filename, std::ios_base::openmode mode, bool checkFilename){
115
116 if (!isRead ) {
117 isRead = internalOpen(filename, mode, checkFilename);
118 }
119 }
120
121 /**
122 * Tests if the stream is currently associated with a valid buffer.
123 * @return true if a file has successfully been opened (single mode)
124 * or the whole file has been read and spread among all of the
125 * processors (parallel mode), otherwise false is returned
126 */
127 bool ifstrstream::is_open ( ) {
128 #ifdef IS_MPI
129 return isRead;
130 #else
131 //single version fall back to ifstream
132 return internalFileBuf_.is_open();
133 #endif
134 }
135
136 /**
137 * In single mode, closes a file. The stream's file buffer is
138 * released from its association with the currently open file. In
139 * parallel mode, cleans up.
140 */
141 void ifstrstream::close() {
142 #ifndef IS_MPI
143 //single version fall back to ifstream
144 if (!internalFileBuf_.close())
145 this->setstate(std::ios_base::failbit);
146 #endif
147
148 isRead = false;
149 }
150
151 /**
152 * Gets the stream buffer object associated with the stream
153 * @return A pointer to the stream buffer object(filebuf in single
154 * mode, stringbuf in parallel mode) associated with the stream.
155 */
156 std::basic_streambuf<char, std::char_traits<char> >* ifstrstream::rdbuf() {
157 #ifdef IS_MPI
158 return static_cast<_StringBuf*>(&internalStringBuf_);
159 #else
160 return static_cast<_FileBuf*>(&internalFileBuf_);
161 #endif
162 }
163
164 /**
165 * Internal function used to open the file
166 * @return true if succesfully opens a file (single mode) or gets
167 * the file content (parallel mode) otherwise return false
168 * @param filename String containing the name of the file to be opened
169 * @param mode Flags describing the requested i/o mode for the file
170 * @param checkFilename Flags indicating checking the file name in parallel
171 * @todo use try - catch syntax to make the program more readable
172 */
173
174 bool ifstrstream::internalOpen(const char* filename, std::ios_base::openmode mode, bool checkFilename){
175
176 #ifdef IS_MPI
177 //int commStatus;
178 long fileSize;
179 char* fbuf;
180 int filenameLen;
181 int diffFilename;
182 int error;
183 int myRank;
184 int masterNode;
185
186 myRank = MPI::COMM_WORLD.Get_rank();
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::COMM_WORLD.Bcast(&filenameLen, 1, MPI::INT, masterNode);
196 MPI::COMM_WORLD.Bcast((void*)filename, filenameLen, MPI::CHAR,
197 masterNode);
198
199 diffFilename = 0;
200 MPI::COMM_WORLD.Allreduce(&diffFilename, &error, 1, MPI::INT, MPI::SUM);
201
202 //if file names are different just return false
203 if (error > 0)
204 return false;
205 }
206
207 std::ifstream fin(filename, mode);
208
209 if (fin.is_open()) {
210
211 fin.seekg(0, std::ios::end);
212 fileSize = fin.tellg();
213 fin.seekg(0, std::ios::beg);
214
215 // '\0' need one more char
216 fbuf = new char[fileSize+1];
217
218 assert(fbuf != 0);
219
220 fin.read(fbuf, fileSize);
221
222 if (fin.fail())
223 fileSize = FileIOError;
224
225 //broadcast the file size
226 MPI::COMM_WORLD.Bcast(&fileSize, 1, MPI::LONG, masterNode);
227
228 if (fileSize < 0) {
229 fin.close();
230 delete[] fbuf;
231
232 return false;
233 }
234
235 // make a c-style std::string and broadcast it
236 fbuf[fileSize] = '\0';
237 MPI::COMM_WORLD.Bcast(fbuf, fileSize + 1, MPI::CHAR, masterNode);
238
239 //close the file and delete the buffer
240 fin.close();
241 internalStringBuf_.str(fbuf);
242 delete[] fbuf;
243 }else{
244 fileSize = FileNotExists;
245 MPI::COMM_WORLD.Bcast(&fileSize, 1, MPI::LONG, masterNode);
246 return false;
247 }
248
249 } else{ //slave nodes
250
251 //check file name
252 if (checkFilename) {
253 MPI::COMM_WORLD.Bcast(&filenameLen, 1, MPI::INT, masterNode);
254
255 char * masterFilename = new char[filenameLen];
256 MPI::COMM_WORLD.Bcast(masterFilename, filenameLen, MPI::CHAR,
257 masterNode);
258
259 if( strcmp(masterFilename, filename) == 0)
260 diffFilename = 0;
261 else
262 diffFilename = 1;
263
264 delete[] masterFilename;
265
266 MPI::COMM_WORLD.Allreduce(&diffFilename, &error, 1, MPI::INT, MPI::SUM);
267
268 if (error > 0)
269 return false;
270 }
271 //get file size
272 MPI::COMM_WORLD.Bcast(&fileSize, 1, MPI::LONG, masterNode);
273
274 if (fileSize >= 0 ) {
275 fbuf = new char[fileSize+1];
276 assert(fbuf);
277
278 //receive file content
279 MPI::COMM_WORLD.Bcast(fbuf, fileSize + 1, MPI::CHAR, masterNode);
280
281 internalStringBuf_.str(fbuf);
282 delete [] fbuf;
283
284 } else if (fileSize == FileNotExists ) {
285 return false;
286
287 } else if (fileSize == FileIOError ) {
288 return false;
289 }
290 }
291
292 #else
293 //in single version, fall back to ifstream
294 if (!internalFileBuf_.open(filename, mode)) {
295 this->setstate(std::ios_base::failbit);
296 return false;
297 }
298
299 #endif
300 this->clear();
301 return true;
302 }
303 }

Properties

Name Value
svn:eol-style native