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

# 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 gezelter 1879 * [3] Sun, Lin & Gezelter, J. Chem. Phys. 128, 234107 (2008).
39 gezelter 1665 * [4] Kuang & Gezelter, J. Chem. Phys. 133, 164101 (2010).
40     * [5] Vardeman, Stocker & Gezelter, J. Chem. Theory Comput. 7, 834 (2011).
41 gezelter 1627 */
42    
43     /**
44 gezelter 1879 * @file ifstrstream.cpp
45 gezelter 1627 * @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 gezelter 1938 #include "io/ifstrstream.hpp"
55    
56 gezelter 1627 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 gezelter 1969 internalStringBuf_(), isRead(false) {
63 gezelter 1627 this->init(&internalStringBuf_);
64     }
65     #else
66     ifstrstream::ifstrstream()
67     : std::basic_istream<char, std::char_traits<char> >(0),
68 gezelter 1969 internalFileBuf_(), isRead(false) {
69 gezelter 1627 this->init(&internalFileBuf_);
70     }
71     #endif
72    
73     /**
74     * Explicit constructor
75 gezelter 1879 * @param filename String containing the name of the file to be opened
76 gezelter 1962 * @param mode Flags describing the requested i/o mode for the file,
77     * default value is ios_base::in
78 gezelter 1879 * @param checkFilename Flags indicating checking the file name in parallel
79 gezelter 1627 */
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 gezelter 1969 internalStringBuf_(), isRead(false) {
84 gezelter 1627 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 gezelter 1969 internalFileBuf_(), isRead(false) {
91 gezelter 1627
92     this->init(&internalFileBuf_);
93     isRead = internalOpen(filename, mode | std::ios_base::in, checkFilename);
94     }
95     #endif
96     /**
97 gezelter 1962 * virtual destructor will close the file (in single mode) and clear
98     * the stream buffer
99 gezelter 1627 */
100 gezelter 1969 ifstrstream::~ifstrstream(){ close();
101 gezelter 1627 }
102    
103     /**
104 gezelter 1962 * 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 gezelter 1879 * @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 gezelter 1627 */
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 gezelter 1962 * 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 gezelter 1627 */
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 gezelter 1962 * parallel mode, cleans up.
139 gezelter 1627 */
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 gezelter 1962 * 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 gezelter 1627
173     bool ifstrstream::internalOpen(const char* filename, std::ios_base::openmode mode, bool checkFilename){
174    
175     #ifdef IS_MPI
176 gezelter 1796 //int commStatus;
177 gezelter 1627 long fileSize;
178     char* fbuf;
179     int filenameLen;
180     int diffFilename;
181     int error;
182     int myRank;
183     int masterNode;
184    
185 gezelter 1969 MPI_Comm_rank( MPI_COMM_WORLD, &myRank);
186    
187 gezelter 1627 masterNode = 0;
188    
189     if (myRank == masterNode) {
190    
191     if (checkFilename) {
192    
193     //check the filename is the same
194     filenameLen = strlen(filename);
195 gezelter 1969 MPI_Bcast(&filenameLen, 1, MPI_INT, masterNode, MPI_COMM_WORLD);
196     MPI_Bcast((void*)filename, filenameLen, MPI_CHAR,
197     masterNode, MPI_COMM_WORLD);
198 gezelter 1627
199     diffFilename = 0;
200 gezelter 1969 MPI_Allreduce(&diffFilename, &error, 1, MPI_INT, MPI_SUM,
201     MPI_COMM_WORLD);
202 gezelter 1962
203 gezelter 1627 //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 gezelter 1796 //broadcast the file size
227 gezelter 1969 MPI_Bcast(&fileSize, 1, MPI_LONG, masterNode, MPI_COMM_WORLD);
228 gezelter 1627
229     if (fileSize < 0) {
230     fin.close();
231 gezelter 1879 delete[] fbuf;
232 gezelter 1627
233     return false;
234     }
235    
236 gezelter 1796 // make a c-style std::string and broadcast it
237 gezelter 1627 fbuf[fileSize] = '\0';
238 gezelter 1969 MPI_Bcast(fbuf, fileSize + 1, MPI_CHAR, masterNode, MPI_COMM_WORLD);
239 gezelter 1627
240     //close the file and delete the buffer
241     fin.close();
242     internalStringBuf_.str(fbuf);
243 gezelter 1879 delete[] fbuf;
244 gezelter 1627 }else{
245     fileSize = FileNotExists;
246 gezelter 1969 MPI_Bcast(&fileSize, 1, MPI_LONG, masterNode, MPI_COMM_WORLD);
247 gezelter 1627 return false;
248     }
249    
250     } else{ //slave nodes
251    
252     //check file name
253     if (checkFilename) {
254 gezelter 1969 MPI_Bcast(&filenameLen, 1, MPI_INT, masterNode, MPI_COMM_WORLD);
255 gezelter 1627
256     char * masterFilename = new char[filenameLen];
257 gezelter 1969 MPI_Bcast(masterFilename, filenameLen, MPI_CHAR,
258     masterNode, MPI_COMM_WORLD);
259 gezelter 1627
260     if( strcmp(masterFilename, filename) == 0)
261     diffFilename = 0;
262     else
263     diffFilename = 1;
264    
265 gezelter 1879 delete[] masterFilename;
266 gezelter 1627
267 gezelter 1969 MPI_Allreduce(&diffFilename, &error, 1, MPI_INT, MPI_SUM,
268     MPI_COMM_WORLD);
269 gezelter 1627
270     if (error > 0)
271     return false;
272     }
273     //get file size
274 gezelter 1969 MPI_Bcast(&fileSize, 1, MPI_LONG, masterNode, MPI_COMM_WORLD);
275 gezelter 1627
276     if (fileSize >= 0 ) {
277     fbuf = new char[fileSize+1];
278     assert(fbuf);
279    
280     //receive file content
281 gezelter 1969 MPI_Bcast(fbuf, fileSize + 1, MPI_CHAR, masterNode, MPI_COMM_WORLD);
282 gezelter 1627
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