Rosetta 3.5
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
SingleFileBuffer.cc
Go to the documentation of this file.
1 // -*- mode:c++;tab-width:2;indent-tabs-mode:t;show-trailing-whitespace:t;rm-trailing-spaces:t -*-
2 // vi: set ts=2 noet:
3 //
4 // This file is part of the Rosetta software suite and is made available under license.
5 // The Rosetta software is developed by the contributing members of the Rosetta Commons consortium.
6 // (C) 199x-2009 Rosetta Commons participating institutions and developers.
7 // For more information, see http://www.rosettacommons.org/.
8 
9 /// @file protocols/jd2/MpiFileBuffer.hh
10 /// @brief header file for MPISilentFileJobOutputter class, part of August 2008 job distributor as planned at RosettaCon08
11 /// @detail this outputter will send silentstructs via MPI to dedicated node that will collect all structures
12 /// @author Oliver Lange olange@u.washington.edu
13 
15 //#include <protocols/jd2/MpiFileBuffer.hh> //only needed for the runtime_assert grumpf.
16 #include <iostream>
17 #include <utility/io/mpistream.hh>
18 #include <utility/exit.hh>
19 #include <utility/file/file_sys_util.hh>
20 
21 #include <basic/Tracer.hh>
22 #include <iterator>
23 
24 #include <utility/vector1.hh>
25 
26 #ifdef WIN32
27 #include <windows.h> // for sleep()
28 #include <ctime> // for clock()
29 #endif
30 
31 namespace protocols {
32 namespace jd2 {
33 
34 using namespace core;
35 using namespace utility::io::mpi_stream;
36 
37 static basic::Tracer tr("protocols.jd2.MpiFileBuffer");
38 
39 ///@details this is a implementation of Buffer for silent-file-based output.
40 std::string const START_BLOCK( "MPI_FILE_BUFFER_BLOCK_START" );
41 std::string const END_BLOCK( "MPI_FILE_BUFFER_BLOCK_END" );
42 
43 SingleFileBuffer::~SingleFileBuffer() { runtime_assert( !has_open_slaves() ); }
44 
46  // std::cout << "flush channel: " << filename() << " for slave : " << slave << std::endl;
47  if ( unfinished_blocks_[ slave ].size() ) {
48  write_lines( unfinished_blocks_[ slave ] );
49  unfinished_blocks_[ slave ].clear();
50  }
51 }
52 
54  for ( BufferMap::const_iterator it = unfinished_blocks_.begin(); it != unfinished_blocks_.end(); ++it ) {
55  if ( it->second.size() > 0 ) {
56  return true;
57  }
58  }
59  return false;
60 }
61 
63  return unfinished_blocks_.size();
64 }
65 
67  if ( unfinished_blocks_[ slave ].size() == 0 ) {
68  tr.Trace << "EMPTY OPEN/CLOSE Operation from slave " << slave << std::endl;
69  }
70  tr.Debug << "close " << filename_ << " from slave " << slave << std::endl;
71  flush( slave );
72  //BufferMap::iterator iter = unfinished_blocks_.find( slave );
73  // if ( iter!=unfinished_blocks_.end() ) {
74  // unfinished_blocks_.erase( iter );
75  //} else {
76  // tr.Warning << "tried to close non-existant channel to slave-node " << slave << " for file " << filename_ << std::endl;
77  //}
78 }
79 
80 void SingleFileBuffer::store_line( Size slave, Size channel, std::string const& line ) {
81  runtime_assert( channel == mpi_channel_ );
82  unfinished_blocks_[ slave ].push_back( line );
83  // std::cout << "channel: " << mpi_channel_ << " slave: " << slave <<std::endl;// << "line: " << line << std::endl;
84 }
85 
87 
88  core::Size length = 0;
89  LineBuffer & buf( unfinished_blocks_[ slave ] );
90  for (LineBuffer::iterator iter = buf.begin(); iter != buf.end(); ++iter) {
91  length += iter->length();
92  }
93 
94  return length;
95 }
96 
98  std::cout << "START_BLOCK" << std::endl;
99  copy( buf.begin(), buf.end(), std::ostream_iterator< std::string>( std::cout ) );
100  std::cout << "END_BLOCK" << std::endl;
101 }
102 
103 
104 void SingleFileBuffer::block( core::Size MPI_ONLY( slave ) ) {
105 #ifdef USEMPI
106  int status = 1;
107  tr.Debug << "send blocking confirmation... " << filename() << std::endl;
108  MPI_Send( &status, 1, MPI_INT, slave, MPI_STREAM_TAG, MPI_COMM_WORLD );
109  tr.Debug << "blocked..." << std::endl;
110  int buf[ 4 ];
111  MPI_Status stat;
112  MPI_Recv( &buf, 4, MPI_INT, slave, MPI_STREAM_TAG, MPI_COMM_WORLD, &stat );
113  tr.Debug << "release file? : received: " << buf[ 0 ] << " " << buf[ 1 ] << " " << buf[ 2 ] << " " << buf[ 3 ] << std::endl;
114  // runtime_assert( (Size) buf[ 2 ] == MPI_RELEASE_FILE && (Size) buf[ 1 ] == filename().size() ); //check of sizes ..
115 #endif
116 }
117 
119  SingleFileBuffer( filename, channel, status ) {//, out_( filename.c_str() )
120  //if ( append ) out_.open_append(filename); //still problems with this ???
121  status = MPI_FAIL;
122  int trials = 5;
123  while ( status == MPI_FAIL && trials > 0 ) {
124  --trials;
125  if ( append ) {
126  if ( !utility::file::file_exists( filename ) ) {
127  // out_.open( filename.c_str() );
128  tr.Debug << "open file " << filename << " ... " << std::endl;
129  out_.open( filename.c_str() );
130  if ( out_.good() ) status = MPI_SUCCESS_NEW;
131  } else {
132 
133  tr.Debug << "open file (append) " << filename << " ... " << std::endl;
134  // out_.open_append( filename.c_str() );
135  out_.open( filename.c_str(), std::ios::app );
136  if ( out_.good() ) status = MPI_SUCCESS_APPEND;
137  }
138  } else {
139  // out_.open( filename.c_str() );
140  tr.Debug << "open file " << filename << " ... " << std::endl;
141  out_.open( filename.c_str() );
142  if ( out_.good() ) status = MPI_SUCCESS_NEW;
143  }
144  if ( status == MPI_FAIL ) {
145  std::cerr << "failing to write file " << filename << " try again after 1 second of sleep ... " << std::endl;
146 
147 #ifdef WIN32
148  Sleep(1000);
149 #else
150  sleep( 1 );
151 #endif
152  }
153  }
154 }
155 
157  tr.Debug << "close file " << filename() << std::endl;
158  out_.close();
159 }
160 
162  static time_t const all_start_time = clock();
163  static time_t ntime;
164  static time_t last_time;
165  ntime = clock();
166  if ( buf.size()==1 ) tr.Debug << -1.0*(all_start_time-ntime)/CLOCKS_PER_SEC << " " << 1.0*( ntime-last_time )/CLOCKS_PER_SEC << " seconds: write block of " << buf.begin()->size() << " characters to file " << filename() << std::endl;
167  else tr.Debug << -1.0*(all_start_time-ntime)/CLOCKS_PER_SEC << " " <<1.0*( ntime-last_time )/CLOCKS_PER_SEC << " seconds: write " << buf.size() << " blocks of data to file " << filename() << std::endl;
168  last_time = ntime;
169 
170  copy( buf.begin(), buf.end(), std::ostream_iterator< std::string>( out_ ) );
171  if ( tr.Trace.visible() ) {
172  copy( buf.begin(), buf.end(), std::ostream_iterator< std::string>( tr.Trace ) );
173  tr.Trace << std::endl;
174  }
175 }
176 
178  out_.close();
179  tr.Debug << "block file " << filename() << std::endl;
180  //out_.flush();
181  Base::block(slave);
182  tr.Debug << "open file (append): " << filename() << std::endl;
183  out_.open( filename().c_str() , std::ios::app );
184 }
185 
186 }
187 }