saga::task edge::work_start (void) { if ( state_ == Stopped ) return task_; assert ( state_ == Pending ); util::scoped_lock (mtx_); // we have work to do... state_ = Running; // lets see if we actually need to do anything try { saga::filesystem::file f_tgt (session_, tgt_url_); saga::filesystem::file f_src (session_, src_url_); if ( f_src.get_size () == f_tgt.get_size () ) { optimize_ = true; } } catch ( const saga::exception & e ) { // well, we need to run the edge operation to see what's missing... optimize_ = false; } if ( optimize_ || is_void_ ) { // fake a noop task, which does nothing: simply returnh the empty // Done task... task_ = saga::task (saga::task::Done); std::cout << " === edge run : " << get_name () << " (" << src_url_ << " -> " << tgt_url_ << ")" << " [optimized] - " << task_.get_id () << std::endl; } else { saga::filesystem::file f_src (session_, src_url_); task_ = f_src.copy <saga::task::Async> (tgt_url_, saga::filesystem::Overwrite | saga::filesystem::CreateParents); std::cout << " === edge run : " << get_name () << " (" << src_url_ << " -> " << tgt_url_ << ") - " << task_.get_id () << std::endl; } task_valid_ = true; return task_; }
// thread_work is the workload, i.e. the data copy operation void edge::thread_work (void) { try { dag_->log (std::string ("edge run: ") + src_url_.get_string () + "->" + tgt_url_.get_string ()); // dump (); dag_->lock (); // the local file adaptor is not thread save if operating on the same // directory structure saga::session session = scheduler_->hook_saga_get_session (dag_); saga::filesystem::file f_src (session, src_url_); // first check if file exists bool exists = false; try { saga::filesystem::file f_tgt (session, tgt_url_); std::cout << " ### edge size: " << get_name_s () << " : " << f_tgt.get_size () << "\t (" << src_url_.get_path () << ")" << std::endl; if ( f_tgt.get_size () == f_src.get_size () ) { exists = true; } } catch ( ... ) { // does not exist } if ( ! exists ) { f_src.copy (tgt_url_, saga::filesystem::Overwrite | saga::filesystem::CreateParents); } dag_->unlock (); } catch ( const saga::exception & e ) { dag_->unlock (); // FIXME: the local adaptor is not doing nicely in multithreaded // environments. Thus, we ignore all errors for now, and rely on the // ability of the nodes to flag any missing data files. #if 1 dag_->log (std::string ("edge failed to copy data ") + src_url_.get_string () + "->" + tgt_url_.get_string () + "\n" + e.what ()); { state_ = Failed; } // ### scheduler hook scheduler_->hook_edge_run_fail (dag_, this); return; #else state_ = Done; // ### scheduler hook scheduler_->hook_edge_run_done (dag_, this); #endif } // if we are done copying data, we fire the dependend node // this fire may succeed or not - that depends on the availability // of _other_ input data to that node. Only if all data are Done, // the fire will actually do anything. Thus, only the last fire // called on a node (i.e. called from its last Pending Edge) will // result in a Running node. { if ( state_ != Stopped ) { // done state_ = Done; // fire dependent node tgt_node_->fire (); } } // ### scheduler hook scheduler_->hook_edge_run_done (dag_, this); return; }