// dial_scheduler_service_imp.cxx // Functions to support the dial_scheduler service. #include #include "dataset_util/FileStatus.h" #include "dataset_util/Environment.h" #include "dataset_util/FileName.h" #include "dataset_util/DtdRegistry.h" #include "dataset_util/ThreadCredential.h" #include "dataset_id/UniqueIdGenerator.h" #include "dataset_base/Dataset.h" #include "dataset_base/DatasetCreator.h" #include "dataset_base/DatasetRepository.h" #include "dataset_catalog/DatasetReplicaCatalog.h" #include "dataset_catalog/DatasetSelectionCatalog.h" #include "dataset_xml/XmlParser.h" #include "dial_ws/DialWs.h" #include "dial_ws/GsoapRegistry.h" #include "dial_task/Task.h" #include "dial_task/TaskRepository.h" #include "dial_app/Application.h" #include "dial_app/ApplicationRepository.h" #include "dial_job/JobId.h" #include "dial_job/Job.h" #include "dial_job/JobRepository.h" #include "dial_sched/JobUpdater.h" #include "dial_sched/Scheduler.h" #include "dial_sched/MasterScheduler.h" #include "dial_webcat/register_catalog_web_pages.h" #include "../gsoap/dial_ws_schedulerH.h" using std::string; using std::ostream; using std::cout; using std::cerr; using std::endl; using std::ofstream; using dset::Dataset; using dset::DatasetCreator; using dset::DatasetRepository; using dset::DatasetReplicaCatalog; using dset::DatasetSelectionCatalog; using dial::TaskId; using dial::Task; using dial::TaskRepository; using dial::ApplicationId; using dial::Application; using dial::ApplicationRepository; using dial::JobPreferences; using dial::JobId; using dial::JobIdList; using dial::Job; using dial::JobRepository; using dial::JobUpdater; using dial::Scheduler; using dial::MasterScheduler; using dial::DialWs; using dial::register_catalog_web_pages; typedef Job::UrlMap UrlMap; extern SOAP_NMAC struct Namespace dial_ws_scheduler_namespaces[]; //********************************************************************** // Helper functions. //********************************************************************** namespace { //********************************************************************** // Output stream for logging. std::ostream& lout() { return dial::DialWs::lout(); } //********************************************************************** // XML parser. XmlParser& parser() { static XmlParser psr; return psr; } //********************************************************************** // Fetch the scheduler. Scheduler* psch(bool kill =false) { static Scheduler* psched = 0; static bool killed = false; if ( killed ) return 0; if ( kill ) { delete psched; killed = true; } if ( psched == 0 ) { DtdRegistry::instance("dataset").write(); DtdRegistry::instance("dial").write(); string file = "scheduler.xml"; string exename = "dialws-scheduler"; if ( ! FileStatus(file).is_readable() ) { cout << exename << ": Unable to open " << file << endl; return 0; } const XmlElement* pxsch = parser().parse("scheduler.xml"); if ( pxsch == 0 ) { cout << exename << ": Unable to parse " << file << endl; return 0; } psched = Scheduler::create(*pxsch); delete pxsch; if ( psched == 0 ) { cout << exename << ": Unable to create scheduler" << endl; return 0; } } return psched; } //********************************************************************** // Map of URL's. const UrlMap& urls() { static UrlMap val; if ( val.size() == 0 ) { val["jobs"] = "topjob_repository"; val["subjobs"] = "subjob_repository"; val["applications"] = "application_repository"; val["tasks"] = "task_repository"; val["datasets"] = "dataset_repository"; } return val; } //********************************************************************** // Create web page for job repository. void job_repository_web_page(string page, string entry) { static string savepage = page; assert( page == savepage ); // Find subjob repository. JobRepository* pjr = psch()->job_repository(); if ( pjr == 0 ) { Text tjr; tjr.append("No job repository"); DialWs::insert_web_page(page, entry, tjr); return; } // Find subjob repository. JobRepository* psjr = 0; MasterScheduler* pmsch = dynamic_cast(psch()); if ( pmsch != 0 ) { psjr = pmsch->slave().job_repository(); } // Register web page. Text wp; if ( entry == "" ) { wp = pjr->web_page(urls(), "maxent=100", psjr); } else { wp = pjr->web_page(urls(), entry, psjr); } DialWs::insert_web_page(page, entry, wp); } //********************************************************************** // Create web page for subjob repository. void subjob_repository_web_page(string page, string entry) { static string savepage = page; assert( page == savepage ); // Find subjob repository. MasterScheduler* pmsch = dynamic_cast(psch()); JobRepository* pjr = 0; if ( pmsch != 0 ) { pjr = pmsch->slave().job_repository(); } if ( pjr == 0 ) { Text tjr; tjr.append("No subjob repository"); DialWs::insert_web_page(page, entry, tjr); return; } // Register web page. Text wp; UrlMap newurls = urls(); newurls["jobs"] = newurls["subjobs"]; newurls["subjobs"] = ""; if ( entry == "" ) { wp = pjr->web_page(newurls, "maxent=100", 0); } else { wp = pjr->web_page(newurls, entry, 0); } DialWs::insert_web_page(page, entry, wp); } //********************************************************************** // Service initialization. int init() { static int done = 0; if ( done ) { cout << "Skipping scheduler intialization" << endl; return 0; } cout << "Carrying out scheduler intialization" << endl; // Set the UniqueIdGenerator connection with $DIAL_UIDS. string dial_uids; if ( dial_uids.size() == 0 ) { const Environment* penv = &Environment::initial(); dial_uids = penv->value("DIAL_UIDS"); } if ( dial_uids.size() == 0 ) { lout() << "DIAL_UIDS not defined or provided on command line" << endl; cerr << "DIAL_UIDS not defined or provided on command line" << endl; return 11; } int gstat = UniqueIdGenerator::set_generator(dial_uids); if ( gstat != 0 ) { lout() << "Error setting unique ID generator" << endl; lout() << " " << dial_uids << endl; lout() << " Error code is " << gstat << endl; return 12; } if ( ! Dataset::id_generator().is_global() ) { lout() << "Dataset ID generator is not global: " << endl; lout() << Dataset::id_generator() << endl; lout() << "Requested connection was" << endl; lout() << " " << dial_uids << endl; cerr << "Dataset ID generator is not global: " << endl; return 13; } lout() << "DatasetID generator:" << endl; lout() << Dataset::id_generator() << endl; lout() << endl; { ofstream didfile("dataset_id"); didfile << Dataset::id_generator() << endl; } // Set WS mutex. MasterScheduler* pmsch = dynamic_cast(psch()); if ( pmsch != 0 ) { JobUpdater* pup = const_cast(pmsch->updater()); if ( pup != 0 ) { DialWs::condition() = &pup->condition(); } } done = 1; return 0; } //********************************************************************** int init_http() { cout << "Carrying out scheduler_http intialization" << endl; init(); // Register web pages. register_catalog_web_pages(); DialWs::insert_web_page_update(Job::url(urls(), "jobs"), job_repository_web_page); DialWs::insert_web_page_update(Job::url(urls(), "subjobs"), subjob_repository_web_page); // Append to home page. Text hpi; string indent = "
  "; hpi.append("

This is a DIAL analysis service"); // Job repository. MasterScheduler* pmsch = dynamic_cast(psch()); if ( psch()->job_repository_connection().size() ) { string conn = pmsch->job_repository_connection(); Text::text_to_xml(conn); hpi.append("

Primary job repository"); hpi.append(" (provenance view)"); hpi.append(indent + "connection: " + conn); } else { hpi.append("

No primary job repository"); } // Subjob repository. if ( psch()->job_repository_connection().size() ) { string conn = pmsch->slave().job_repository_connection(); Text::text_to_xml(conn); hpi.append("

Subjob repository"); hpi.append(indent + "connection: " + conn); } else { hpi.append("

No subjob repository"); } // Job archive. if ( DialWs::web_page("job_repository").size() ) { hpi.append( "

Job archive"); } // Application repository. if ( DialWs::web_page("application_repository").size() ) { hpi.append( "

Application repository"); } // Task repository. if ( DialWs::web_page("task_repository").size() ) { hpi.append( "

Task repository"); } // Dataset repository. if ( DialWs::web_page("dataset_repository").size() ) { hpi.append( "

Dataset repository"); } // Unique ID source. string dial_uids; if ( dial_uids.size() == 0 ) { const Environment* penv = &Environment::initial(); dial_uids = penv->value("DIAL_UIDS"); } hpi.append("

Unique ID"); hpi.append(indent + "connection: " + dial_uids); DialWs::insert_home_page(hpi); return 0; } //********************************************************************** // Error return. // Writes the Gsoap error string and messages to the server log. // name = name of the calling method // msg2 = GSoap message 2 // extra = additonal message for the server log // Client side error. int errc(struct soap* psoap, string name, string msg2, string extra ="") { lout() << msg2 << endl; if ( extra.size() ) { lout() << extra; if ( extra[extra.size()-1] != '\n' ) lout() << endl; } string msg1 = "Error in "; msg1 += name; return soap_sender_fault(psoap, msg1.c_str(), msg2.c_str()); } // Server side error. int errs(struct soap* psoap, string name, string msg2, string extra ="") { lout() << msg2 << endl; if ( extra.size() ) { lout() << extra; if ( extra[extra.size()-1] != '\n' ) lout() << endl; } string msg1 = "Error in "; msg1 += name; return soap_sender_fault(psoap, msg1.c_str(), msg2.c_str()); } //********************************************************************** } // end unnamed namespace //********************************************************************** // Register the service. int ireg = dial::GsoapRegistry::insert( "scheduler", init, dial_ws_scheduler::dial_ws_scheduler_serve, dial_ws_scheduler_namespaces ); int ireg_http = dial::GsoapRegistry::insert( "scheduler_http", init_http, dial_ws_scheduler::dial_ws_scheduler_serve, dial_ws_scheduler_namespaces ); //********************************************************************** // SOAP functions for Scheduler. //********************************************************************** // Validity. int dial_ws_scheduler::dial__scheduler_is_valid(soap* psoap, bool& valid) { string name = "scheduler_is_valid"; if ( psch() == 0 ) { valid = false; return errs(psoap, name, "DIAL scheduler undefined"); } valid = psch()->is_valid(); lout() << ">>>Checking scheduler validity: " << endl; if ( ! valid ) lout() << "not "; lout() << "valid" << endl; return SOAP_OK; } //********************************************************************** // Has application. int dial_ws_scheduler:: dial__has_application(soap* psoap, string sxapp, bool& response) { response = false; string name = "has_application"; if ( psch() == 0 ) { return errs(psoap, name, "Scheduler undefined"); } const XmlElement* pxapp = parser().parse(sxapp); if ( pxapp == 0 ) { return errc(psoap, name, "Unable to parse XML"); } Application app(*pxapp); delete pxapp; response = psch()->has_application(app); return SOAP_OK; } //********************************************************************** // Has task. int dial_ws_scheduler:: dial__has_task(soap* psoap, string sxapp, string sxtsk, bool& response) { response = false; string name = "Error in DIAL Scheduler has_task"; lout() << ">>>Has task" << endl; if ( psch() == 0 ) { return errs(psoap, name, "Scheduler undefined"); } // Extract application. const XmlElement* pxapp = parser().parse(sxapp); if ( pxapp == 0 ) { return errc(psoap, name, "Unable to parse application XML"); } Application app(*pxapp); delete pxapp; if ( ! app.is_valid() ) { return errc(psoap, name, "Application is invalid"); } // Extract task. const XmlElement* pxtsk = parser().parse(sxtsk); if ( pxtsk == 0 ) { return errc(psoap, name, "Unable to parse task XML"); } Task tsk(*pxtsk); delete pxtsk; if ( ! tsk.is_valid() ) { return errc(psoap, name, "Task is invalid"); } // Make check. response = psch()->has_task(app, tsk); return SOAP_OK; } //********************************************************************** // Task job. int dial_ws_scheduler:: dial__task_job(soap* psoap, string sxapp, string sxtsk, std::string& response) { response = ""; string name = "Error in DIAL Scheduler has_application"; lout() << ">>>Task job" << endl; if ( psch() == 0 ) { return errs(psoap, name, "Scheduler undefined"); } // Extract application. const XmlElement* pxapp = parser().parse(sxapp); if ( pxapp == 0 ) { return errc(psoap, name, "Unable to parse application XML"); } Application app(*pxapp); delete pxapp; if ( ! app.is_valid() ) { return errc(psoap, name, "Application is invalid"); } // Extract task. const XmlElement* pxtsk = parser().parse(sxtsk); if ( pxtsk == 0 ) { return errc(psoap, name, "Unable to parse task XML"); } Task tsk(*pxtsk); delete pxtsk; if ( ! tsk.is_valid() ) { return errc(psoap, name, "Task is invalid"); } // Make check. response = psch()->task_job(app, tsk).to_string(); return SOAP_OK; } //********************************************************************** // List of jobs. int dial_ws_scheduler::dial__jobs(soap* psoap, string& sjids) { string name = "jobs"; if ( psch() == 0 ) { return errs(psoap, name, "Scheduler undefined"); } sjids = ""; JobIdList jids = psch()->jobs(); for ( JobIdList::const_iterator ijid=jids.begin(); ijid!=jids.end(); ++ijid ) { JobId jid = *ijid; if ( ijid != jids.begin() ) sjids += " "; sjids += jid.to_string(); } lout() << ">>>Returning list of jobs:\n" << sjids << endl; return SOAP_OK; } //********************************************************************** // Job count. int dial_ws_scheduler::dial__njobs(soap* psoap, int& njobs) { njobs = 0; string name = "njobs"; if ( psch() == 0 ) { njobs = 0; return errs(psoap, name, "Scheduler undefined"); } njobs = psch()->jobs().size(); return SOAP_OK; } //********************************************************************** // Check job presence. int dial_ws_scheduler:: dial__has_job(soap* psoap, string sxjid, bool& has) { has = false; string name = "has_job"; if ( psch() == 0 ) { return errs(psoap, name, "Scheduler undefined"); } // Extract job ID. const XmlElement* pxjid = parser().parse(sxjid); if ( pxjid == 0 ) { return errc(psoap, name, "Unable to parse job ID XML", sxjid); } JobId jid(*pxjid); delete pxjid; if ( ! jid.is_valid() ) { return errc(psoap, name, "Job ID is invalid"); } has = psch()->has_job(jid); return SOAP_OK; } //********************************************************************** // Fetch job. int dial_ws_scheduler:: dial__job(soap* psoap, string sxjid, string& sxjob) { lout() << ">>>Fetch job" << endl; string name = "job"; if ( psch() == 0 ) { return errs(psoap, name, "Scheduler undefined"); } // Extract job ID. const XmlElement* pxjid = parser().parse(sxjid); if ( pxjid == 0 ) { return errc(psoap, name, "Unable to parse job ID XML"); } JobId jid(*pxjid); delete pxjid; lout() << "Job ID is " << jid.to_string() << endl; if ( ! jid.is_valid() ) { return errc(psoap, name, "Job ID is invalid"); } static DatasetRepository& dr = DatasetRepository::default_instance(); // Fetch job. const Job& job = psch()->job(jid); job.lock_mutex(); lout() << job << endl; if ( job.has_result() ) { const Dataset* pres= job.result(); if ( pres == 0 ) { lout() << "Dataset is null!" << endl; } else { lout() << *pres << endl; if ( ! dr.has(pres->id()) ) { lout() << "Inserting result in DR" << endl; DatasetId iid = dr.insert(pres); } if ( dr.has(pres->id()) ) { lout() << "Result is in DR" << endl; } else { lout() << "Result is not in DR!" << endl; } } } const XmlElement* pxjob = job.xml(); job.unlock_mutex(); if ( pxjob == 0 ) { lout() << "Unable to create job XML" << endl; return errs(psoap, name, "Unable to extract job XML"); } sxjob = pxjob->to_xml_text(); return SOAP_OK; } //********************************************************************** // Add a task. int dial_ws_scheduler::dial__add_task(soap* psoap, string sxapp, string sxtsk, int& result) { lout() << ">>>Add task" << endl; result = false; string name = "add_task"; if ( psch() == 0 ) { return errs(psoap, name, "Scheduler undefined"); } // Check authorization. if ( ThreadCredential().owner() == "" ) { return errc(psoap, name, "Credential owner not defined."); } // Extract application. const XmlElement* pxapp = parser().parse(sxapp); if ( pxapp == 0 ) { return errc(psoap, name, "Unable to parse application XML"); } Application app(*pxapp); delete pxapp; // Extract task. const XmlElement* pxtsk = parser().parse(sxtsk); if ( pxtsk == 0 ) { return errc(psoap, name, "Unable to parse task XML"); } Task tsk(*pxtsk); delete pxtsk; // Add task. result = psch()->add_task(app, tsk); if ( result ) { lout() << "Add task succeeded " << endl; } else { lout() << "Add task failed " << endl; } lout() << "Application is " << app << endl; lout() << "Task ID is " << tsk.id().to_string() << endl; return SOAP_OK; } //********************************************************************** // Remove a task. int dial_ws_scheduler::dial__remove_task(soap* psoap, string sxapp, string sxtsk, int& result) { lout() << ">>>Remove task" << endl; result = false; string name = "remove_task"; if ( psch() == 0 ) { return errs(psoap, name, "Scheduler undefined"); } // Check authorization. if ( ThreadCredential().owner() == "" ) { return errc(psoap, name, "Credential owner not defined."); } // Extract application. const XmlElement* pxapp = parser().parse(sxapp); if ( pxapp == 0 ) { return errc(psoap, name, "Unable to parse application XML"); } Application app(*pxapp); delete pxapp; // Extract task. const XmlElement* pxtsk = parser().parse(sxtsk); if ( pxtsk == 0 ) { return errc(psoap, name, "Unable to parse task XML"); } Task tsk(*pxtsk); delete pxtsk; // Remove task. result = psch()->remove_task(app, tsk); if ( result ) { lout() << "Add task succeeded " << endl; } else { lout() << "Add task failed " << endl; } lout() << "Application is " << app << endl; lout() << "Task ID is " << tsk.id().to_string() << endl; return SOAP_OK; } //********************************************************************** // Resource report. int dial_ws_scheduler:: dial__resource_report(soap* psoap, string& srep) { lout() << ">>>Resource report" << endl; srep = psch()->resource_report(); lout() << srep << endl; return SOAP_OK; } //********************************************************************** // Submit job. int dial_ws_scheduler::dial__submit(soap* psoap, string sxapp, string sxtsk, string sxdst, string sxprf, string& sxjid) { lout() << ">>>Submit job" << endl; sxjid = ""; string name = "submit"; if ( psch() == 0 ) { return errs(psoap, name, "Scheduler undefined"); } // Check authorization. if ( ThreadCredential().owner() == "" ) { return errc(psoap, name, "Credential owner not defined."); } // Extract the application, task, dataset and preferences from their // XML descriptions, construct each and (except for preferences) // insert each in its default repository. If an object is already // in the repository, then use that description and ignore the input. // // Later on, the description may contain only ID's. // ...application. const XmlElement* pxapp = parser().parse(sxapp); if ( pxapp == 0 ) { return errc(psoap, name, "Unable to parse application XML"); } const Application* papp = new Application(*pxapp); delete pxapp; ApplicationId aid = papp->id(); if ( ! papp->is_valid() ) { return errc(psoap, name, "Invalid application"); } ApplicationRepository& ar = ApplicationRepository::default_instance(); if ( ! ar.has(aid) ) { lout() << "Inserting application" << endl; ApplicationId newid = ar.insert(papp, true); if ( newid != aid ) { delete papp; return errc(psoap, name, "Unable to insert application"); } } else { delete papp; lout() << "Extracting application" << endl; papp = ar.extract(aid); if ( ! papp->is_valid() ) { return errc(psoap, name, "Unable to extract application"); } } // ...task. const XmlElement* pxtsk = parser().parse(sxtsk); if ( pxtsk == 0 ) { return errc(psoap, name, "Unable to parse task XML"); } const Task* ptsk = new Task(*pxtsk); delete pxtsk; TaskId tid = ptsk->id(); if ( ! ptsk->is_valid() ) { return errc(psoap, name, "Invalid task"); } TaskRepository& tr = TaskRepository::default_instance(); if ( ! tr.has(tid) ) { lout() << "Inserting task" << endl; TaskId newid = tr.insert(ptsk, true); if ( newid != tid ) { delete ptsk; return errc(psoap, name, "Unable to insert task"); } } else { delete ptsk; lout() << "Extracting task" << endl; ptsk = tr.extract(tid); if ( ! ptsk->is_valid() ) { return errc(psoap, name, "Unable to extract task"); } } // ...dataset. const XmlElement* pxdst = parser().parse(sxdst); if ( pxdst == 0 ) { return errc(psoap, name, "Unable to parse dataset XML"); } const Dataset* pdst = DatasetCreator::create(*pxdst); delete pxdst; DatasetId did = pdst->id(); if ( ! pdst->is_valid() ) { return errc(psoap, name, "Invalid dataset"); } DatasetRepository& dr = DatasetRepository::default_instance(); if ( ! dr.has(did) ) { lout() << "Inserting dataset" << endl; DatasetId newid = dr.insert(pdst, true); if ( newid != did ) { delete pdst; return errc(psoap, name, "Unable to insert dataset"); } } else { delete pdst; lout() << "Extracting dataset" << endl; pdst = dr.extract(did); if ( ! pdst->is_valid() ) { return errc(psoap, name, "Unable to extract dataset"); } } // Extract preferences. const XmlElement* pxprf = parser().parse(sxprf); if ( pxprf == 0 ) { return errc(psoap, name, "Unable to parse preferences XML"); } JobPreferences prf(*pxprf); delete pxprf; // Submit. JobId jid = psch()->submit(*papp, *ptsk, *pdst, prf); if ( jid.is_valid() ) { lout() << "Started job " << jid.to_string() << endl; lout() << "Scheduler has " << psch()->jobs().size() << " job"; if ( psch()->jobs().size() != 1 ) lout() << "s"; } else { lout() << "Job submission failed"; } lout() << endl; const XmlElement* pxjid = jid.xml(); if ( pxjid == 0 ) { return errs(psoap, name, "Unable to generate job ID XML"); } sxjid = pxjid->to_xml_text(); return SOAP_OK; } //********************************************************************** // Start job. int dial_ws_scheduler::dial__start(soap* psoap, string sxjid, int& result) { result = -999; string name = "start"; if ( psch() == 0 ) { return errs(psoap, name, "Scheduler undefined"); } // Check authorization. if ( ThreadCredential().owner() == "" ) { return errc(psoap, name, "Credential owner not defined."); } // Extract job ID. const XmlElement* pxjid = parser().parse(sxjid); if ( pxjid == 0 ) { return errc(psoap, name, "Unable to parse job ID XML"); } JobId jid(*pxjid); delete pxjid; if ( ! jid.is_valid() ) { return errc(psoap, name, "Job ID is invalid"); } result = psch()->start(jid); return SOAP_OK; } //********************************************************************** // Kill job. int dial_ws_scheduler:: dial__kill(soap* psoap, string sxjid, int& result) { result = -999; string name = "kill"; if ( psch() == 0 ) { return errs(psoap, name, "Scheduler undefined"); } // Check authorization. if ( ThreadCredential().owner() == "" ) { return errc(psoap, name, "Credential owner not defined."); } // Extract job ID. const XmlElement* pxjid = parser().parse(sxjid); if ( pxjid == 0 ) { return errc(psoap, name, "Unable to parse job ID XML"); } JobId jid(*pxjid); delete pxjid; if ( ! jid.is_valid() ) { return errc(psoap, name, "Job ID is invalid"); } result = psch()->kill(jid); return SOAP_OK; } //********************************************************************** // Remove job. int dial_ws_scheduler:: dial__remove(soap* psoap, string sxjid, int& result) { result = -999; string name = "remove"; if ( psch() == 0 ) { return errs(psoap, name, "Scheduler undefined"); } // Check authorization. if ( ThreadCredential().owner() == "" ) { return errc(psoap, name, "Credential owner not defined."); } // Extract job ID. const XmlElement* pxjid = parser().parse(sxjid); if ( pxjid == 0 ) { return errc(psoap, name, "Unable to parse job ID XML"); } JobId jid(*pxjid); delete pxjid; if ( ! jid.is_valid() ) { return errc(psoap, name, "Job ID is invalid"); } result = psch()->remove(jid); return SOAP_OK; } //********************************************************************** // Test string. int dial_ws_scheduler:: dial__test_string(soap*, string xin, string& response) { response = "" + xin + ""; return SOAP_OK; } //********************************************************************** // Write the log. int dial_ws_scheduler::dial__write_log(soap*, int& result) { lout() << ">>>Write scheduler logs." << endl; psch()->log().write("master_scheduler.log"); lout() << "Wrote master_scheduler.log." << endl; MasterScheduler* pmsch = dynamic_cast(psch()); if ( pmsch != 0 ) { pmsch->slave().log().write("slave_scheduler.log"); lout() << "Wrote slave_scheduler.log." << endl; } result = 0; return SOAP_OK; } //********************************************************************** // Validity. int dial_ws_scheduler::dial__is_valid(soap*, bool& stat) { lout() << ">>>Received request for validity " << endl; string name = "uid_is_valid"; stat = true; lout() << "valid" << endl; return SOAP_OK; } //********************************************************************** // Termination. int dial_ws_scheduler::dial__terminate(soap*, int& stat) { lout() << ">>>Received request for termination " << endl; DialWs::terminate() = true; stat = 0; return SOAP_OK; } //**********************************************************************