Rosetta 3.5
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
FileSystemJobDistributor.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 // (c) Copyright Rosetta Commons Member Institutions.
5 // (c) This file is part of the Rosetta software suite and is made available under license.
6 // (c) The Rosetta software is developed by the contributing members of the Rosetta Commons.
7 // (c) For more information, see http://www.rosettacommons.org. Questions about this can be
8 // (c) addressed to University of Washington UW TechTransfer, email: license@u.washington.edu.
9 
10 /// @file protocols/jd2/FileSystemJobDistributor.cc
11 /// @brief August 2008 job distributor as planned at RosettaCon08 - Simplest class FileSystemJobDistributor
12 /// @author Andrew Leaver-Fay
13 /// @author Steven Lewis smlewi@gmail.com
14 
15 // Unit headers
17 
18 //Package headers
20 #include <protocols/jd2/Job.hh>
21 
22 #include <protocols/moves/Mover.hh>
23 
24 ///Utility headers
25 #include <basic/Tracer.hh>
26 #include <basic/options/option.hh>
27 #include <utility/io/ozstream.hh>
28 #include <utility/file/file_sys_util.hh>
29 #include <utility/exit.hh>
30 
31 ///C++ headers
32 #include <string>
33 
34 // option key includes
35 
36 #include <basic/options/keys/out.OptionKeys.gen.hh>
37 #include <basic/options/keys/run.OptionKeys.gen.hh>
38 
39 #include <utility/vector1.hh>
40 
41 
42 using basic::Warning;
43 static basic::Tracer TR("protocols.jd2.FileSystemJobDistributor");
44 
45 namespace protocols {
46 namespace jd2 {
47 
50  extension_(".in_progress"),
51  // next_job_to_try_assigning_( 1 ),
52  retry_count_( 0 )
53 {
54  if ( basic::options::option[ basic::options::OptionKeys::out::path::pdb ].user() ){
55  path_ = basic::options::option[ basic::options::OptionKeys::out::path::pdb ]().path();
56  } else if( basic::options::option[ basic::options::OptionKeys::out::path::all ].user() ){
57  path_ = basic::options::option[ basic::options::OptionKeys::out::path::all ]().path();
58  }else{
59  path_ = "";
60  }
61 
62 }
63 
64 ///WARNING WARNING! SINGLETONS' DESTRUCTORS ARE NEVER CALLED IN MINI! DO NOT TRY TO PUT THINGS IN THIS FUNCTION!
65 ///here's a nice link explaining why: http://www.research.ibm.com/designpatterns/pubs/ph-jun96.txt
67 {}
68 
70  // next_job_to_try_assigning_ = 1;
71  retry_count_ = 0;
73 }
74 
77 {
78  if( basic::options::option[ basic::options::OptionKeys::out::overwrite ].value() &&
79  basic::options::option[ basic::options::OptionKeys::run::multiple_processes_writing_to_one_directory ].value() ){
80  utility_exit_with_message("ambiguous, cannot have both -out::overwrite and -run::multiple_processes_writing_to_one_directory");
81  }
82 
83  Jobs const & jobs( get_jobs() );
84  JobOutputterOP outputter = job_outputter();
85  core::Size next_job_to_try_assigning( current_job_id() + ( retry_count_ > 0 ? 0 : 1 ) );
86  while ( next_job_to_try_assigning <= jobs.size() ) {
87  if ( jobs[ next_job_to_try_assigning ]->bad() ) {
88  ++next_job_to_try_assigning;
89  } else if ( outputter->job_has_completed( jobs[ next_job_to_try_assigning ] ) &&
90  !basic::options::option[ basic::options::OptionKeys::out::overwrite ].value() ) {
91  ++next_job_to_try_assigning;
92  } else if ( basic::options::option[ basic::options::OptionKeys::run::multiple_processes_writing_to_one_directory ].value() ) {
93  std::string const next_job_output_name( temporary_file_name( jobs[ next_job_to_try_assigning ] ) );
94  if ( utility::file::file_exists( next_job_output_name) ) {
95  ++next_job_to_try_assigning;
96  } else {
97  /// create a temporary file in this directory to indicate that the job
98  /// has started to other processes. This is not in any way safe.
99  /// nor does it guarantee that no two processes will attempt to perform the same job.
100  /// If two processes do attempt the same job, then the one that completes last will
101  /// have its data saved, and the other will be overwritten.
102  utility::io::ozstream outfile( next_job_output_name ); //opens automatically
103  outfile << "temp" << std::flush;
104  outfile.close();
105  break;
106  }
107  } else {
108  break;
109  }
110  } //while
111 
112  if ( next_job_to_try_assigning <= jobs.size() ) {
113  // core::Size job_to_assign = next_job_to_try_assigning;
114  // ++next_job_to_try_assigning;
115  return next_job_to_try_assigning;
116  }
117 
118  // indicate that no jobs remain
119  return 0;
120 }
121 
122 void
124 {
125  using namespace basic::options;
126 // if( current_job_id() != next_job_to_try_assigning - 1 ){
127 // std::cerr << current_job_id() << " " << next_job_to_try_assigning << std::endl;
128 // runtime_assert( current_job_id() == next_job_to_try_assigning - 1 );
129 // }
130  ++retry_count_;
131  if( (int)retry_count_ <= (int)basic::options::option[ basic::options::OptionKeys::run::max_retry_job ].value() ) {
132  // --next_job_to_try_assigning;
133  if ( !option[ OptionKeys::run::write_failures ]() ){
134  clear_current_job_output(); // DONT DO THIS WHEN WRITING FAILURES COS IT LOOSES THE PAIR DATA
135  }
136  }else{
137  retry_count_=0; // reset
138  TR << "Too many retries (max_retry_job = " << basic::options::option[ basic::options::OptionKeys::run::max_retry_job ].value() << ") " << std::endl;
139  }
140 }
141 
142 ///@details this function handles the FAIL_BAD_INPUT mover status by removing other jobs with the same input from consideration
143 void
145 {
146  //we should only fail on a job which was the first of its type - if it fails on nstruct=2 with BAD_INPUT then why did it not fail on nstruct=1?
147  //runtime_assert( current_job()->nstruct_index() == 1 );
148  if( !current_job()->nstruct_index() == 1 ){
149  Warning() << "A job reported bad input, but was not the first input of its type! You should figure out why the first one passed if later ones failed!" << std::endl;
150  }
151 
152  // std::string const & current_input_tag(current_job()->inner_job()->input_tag());
153  //std::string const & current_native_tag(current_job()->inner_job()->native_tag());
154 
155  TR << "job failed, reporting bad input; other jobs of same input will be canceled: "
156  << job_outputter()->output_name( current_job() ) << std::endl;
158  // this latter stuff requires that jobs come in sequence of input... some application might prefer to
159  // reshuffle ...
160 
161 // Jobs const & jobs( get_jobs() );
162 // core::Size next_job_to_try_assigning( current_job_id() );
163 // while(next_job_to_try_assigning <= jobs.size() && //MUST BE FIRST for c++ shortcut logical evaluation
164 // jobs[next_job_to_try_assigning]->inner_job()->input_tag() == current_input_tag) {
165 // //&&jobs[next_job_to_try_assigning]->inner_job()->native_tag() == current_native_tag){
166 // TR << "job canceled without trying due to previous bad input: "
167 // << job_outputter()->output_name( jobs[next_job_to_try_assigning] ) << std::endl;
168 // mark_job_as_bad( next_job_to_try_assigning );
169 // ++next_job_to_try_assigning;
170 // }
171 
172 }
173 
174 /// @details when multiple processes are writing to the same directory, then
175 /// after a job completes, the "in_progress" file for the job must be deleted.
176 void
178 {
180 }
181 
182 
183 void
185 {
187  go_main( mover );
189 }
190 
191 
192 std::string const
194  return path_ + job_outputter()->output_name( job ) + extension_;
195 }
196 
197 
198 
199 void
201 {
202  JobDistributor::job_succeeded( pose, run_time );
203  retry_count_ = 0;
204  return;
205 }
206 
207 void
209 {
210  using namespace basic::options;
211 
212  JobDistributor::job_failed( pose, will_retry );
213 
214  if ( option[ OptionKeys::run::write_failures ]() ){
215  current_job()->set_status_prefix("C");
216  job_succeeded( pose, 0 );
217  }
218 
219  if( !will_retry ) retry_count_ = 0;
220 }
221 
223 {
225 }
226 
228 {
229  if ( basic::options::option[ basic::options::OptionKeys::run::multiple_processes_writing_to_one_directory ].value() ) {
230  Jobs const & jobs( get_jobs() );
231  JobOutputterCOP outputter = job_outputter();
232  std::string const output_name( temporary_file_name( jobs[ current_job_id() ] ) );
233  utility::file::file_delete( output_name.c_str() );
234  }
235 }
236 
237 
238 }//jd2
239 }//protocols