Back to index

nordugrid-arc-nox  1.1.0~rc6
compiler.cpp
Go to the documentation of this file.
00001 #ifdef HAVE_CONFIG_H
00002 #include <config.h>
00003 #endif
00004 #include <sys/stat.h>
00005 #include <errno.h>
00006 
00007 #include <arc/ArcConfig.h>
00008 #include <arc/Logger.h>
00009 #include <arc/data/DataHandle.h>
00010 
00011 #include <arc/data/DataMover.h>
00012 #include <glibmm.h>
00013 #include <arc/data/URLMap.h>
00014 
00015 #include <iostream>
00016 #include <fstream>
00017 #include <stdexcept>
00018 #include <vector>
00019 #include <stdio.h>
00020 #include <time.h>
00021 #include <sstream>
00022 
00023 #include <arc/message/PayloadSOAP.h>
00024 #include <arc/URL.h>
00025 
00026 #include "arex_client.h"
00027 
00028 #ifdef WIN32
00029 #include <arc/win32.h>
00030 #endif
00031 
00032 #include "compiler.h"
00033 
00034 static Arc::Plugin* get_service(Arc::PluginArgument* arg) {
00035     Arc::ServicePluginArgument* srvarg =
00036             arg?dynamic_cast<Arc::ServicePluginArgument*>(arg):NULL;
00037     if(!srvarg) return NULL;
00038     return new Compiler::Service_Compiler((Arc::Config*)(*srvarg));
00039 }
00040 
00041 Arc::PluginDescriptor PLUGINS_TABLE_NAME[] = {
00042     { "compiler", "HED:SERVICE", 0, &get_service },
00043     { NULL, NULL, 0, NULL }
00044 };
00045 
00046 using namespace Compiler;
00047 
00048 Arc::Logger local_logger(Arc::Logger::getRootLogger(), "Compiler");
00049 
00050 struct CompileInfo {
00051     std::string site_url;
00052     std::string script_url;
00053     std::string architecture;
00054     std::string makefile_name;
00055     std::string cpu_number;
00056     std::string parameters;
00057     bool tar;
00058     std::string compiler;
00059     bool march;
00060     std::string job_name;
00061     std::vector<std::string> sources;
00062 };
00063        
00064 struct ISIS_Info {
00065     std::string arex_url;
00066     std::string url_architecture;
00067     std::string url_cpu_number;
00068 };
00069        
00070        
00071 //to the file transfer
00072 static bool html_to_list(const char* html,const Arc::URL base,std::list<Arc::URL>& urls) {
00073   for(const char* pos = html;;) {
00074     // Looking for tag
00075     const char* tag_start = strchr(pos,'<');
00076     if(!tag_start) break; // No more tags
00077     // Looking for end of tag
00078     const char* tag_end = strchr(tag_start+1,'>');
00079     if(!tag_end) return false; // Broken html?
00080     // 'A' tag?
00081     if(strncasecmp(tag_start,"<A ",3) == 0) {
00082       // Lookig for HREF
00083       const char* href = strstr(tag_start+3,"href=");
00084       if(!href) href=strstr(tag_start+3,"HREF=");
00085       if(href) {
00086         const char* url_start = href+5;
00087         const char* url_end = NULL;
00088         if((*url_start) == '"') {
00089           ++url_start;
00090           url_end=strchr(url_start,'"');
00091           if((!url_end) || (url_end > tag_end)) url_end=NULL;
00092         } else if((*url_start) == '\'') {
00093           url_end=strchr(url_start,'\'');
00094           if((!url_end) || (url_end > tag_end)) url_end=NULL;
00095         } else {
00096           url_end=strchr(url_start,' ');
00097           if((!url_end) || (url_end > tag_end)) url_end=tag_end;
00098         };
00099         if(!url_end) return false; // Broken HTML
00100         std::string url_str(url_start,url_end-url_start);
00101         Arc::URL url(url_str);
00102         if(!url) return false; // Bad URL
00103         if((url.Protocol() == base.Protocol()) &&
00104            (url.Host() == base.Host()) &&
00105            (url.Port() == base.Port())) {
00106           std::string path = url.Path();
00107           std::string base_path = base.Path();
00108           if(base_path.length() < path.length()) {
00109             if(strncmp(base_path.c_str(),path.c_str(),base_path.length()) == 0) {
00110               urls.push_back(url);
00111             };
00112           };
00113         };
00114       };
00115     };
00116     pos=tag_end+1;
00117   };
00118   return true;
00119 }
00120 
00121 static bool PayloadRaw_to_string(Arc::PayloadRawInterface& buf,std::string& str,uint64_t& end) {
00122   end=0;
00123   for(int n = 0;;++n) {
00124     const char* content = buf.Buffer(n);
00125     if(!content) break;
00126     int size = buf.BufferSize(n);
00127     if(size > 0) {
00128       str.append(content,size);
00129     };
00130     end=buf.BufferPos(n)+size;
00131   };
00132   return true;
00133 }
00134 
00135 static bool PayloadRaw_to_stream(Arc::PayloadRawInterface& buf,std::ostream& o,uint64_t& end) {
00136   end=0;
00137   for(int n = 0;;++n) {
00138     const char* content = buf.Buffer(n);
00139     if(!content) break;
00140     uint64_t size = buf.BufferSize(n);
00141     uint64_t pos = buf.BufferPos(n);
00142     if(size > 0) {
00143       o.seekp(pos);
00144       o.write(content,size);
00145       if(!o) return false;
00146     };
00147     end=pos+size;
00148   };
00149   return true;
00150 }
00151 
00152 // TODO: limit recursion depth
00153 static bool get_file(Arc::ClientHTTP& client,const Arc::URL& url,const std::string& dir) {
00154   // Read file in chunks. Use first chunk to determine type of file.
00155   Arc::PayloadRaw req; // Empty request body
00156   Arc::PayloadRawInterface* resp;
00157   Arc::HTTPClientInfo info;
00158   const uint64_t chunk_len = 1024*1024; // Some reasonable size - TODO - make ir configurable
00159   uint64_t chunk_start = 0;
00160   uint64_t chunk_end = chunk_len;
00161   // First chunk
00162   Arc::MCC_Status r = client.process("GET",url.Path(),chunk_start,chunk_end,&req,&info,&resp);
00163   if(!r) return false;
00164   if(!resp) return false;
00165   if((info.code != 200) && (info.code != 206)) { delete resp; return false; };
00166   if(strcasecmp(info.type.c_str(),"text/html") == 0) {
00167     std::string html;
00168     uint64_t file_size = resp->Size();
00169     PayloadRaw_to_string(*resp,html,chunk_end);
00170     delete resp; resp=NULL;
00171     // Fetch whole html
00172     for(;chunk_end<file_size;) {
00173       chunk_start=chunk_end;
00174       chunk_end=chunk_start+chunk_len;
00175       r=client.process("GET",url.Path(),chunk_start,chunk_end,&req,&info,&resp);
00176       if(!r) return false;
00177       if(!resp) return false;
00178       if(resp->Size() <= 0) break;
00179       if((info.code != 200) && (info.code != 206)) { delete resp; return false; };
00180       PayloadRaw_to_string(*resp,html,chunk_end);
00181       delete resp; resp=NULL;
00182     };
00183     if(resp) delete resp;
00184     // Make directory
00185     if(mkdir(dir.c_str(),S_IRWXU) != 0) {
00186       if(errno != EEXIST)  throw std::invalid_argument("Failed to create local directory "+dir+" !");
00187     };
00188     // Fetch files
00189     std::list<Arc::URL> urls;
00190     if(!html_to_list(html.c_str(),url,urls)) return false;
00191     for(std::list<Arc::URL>::iterator u = urls.begin();u!=urls.end();++u) {
00192       if(!get_file(client,*u,dir+(u->Path().substr(url.Path().length())))) return false;
00193     };
00194     return true;
00195   };
00196   // Start storing file
00197   uint64_t file_size = resp->Size();
00198   std::ofstream f(dir.c_str(),std::ios::trunc);
00199   if(!f) { delete resp; return false; };
00200   if(!PayloadRaw_to_stream(*resp,f,chunk_end)) { delete resp; return false; };
00201   delete resp; resp=NULL;
00202   // Continue fetching file
00203   for(;chunk_end<file_size;) {
00204     chunk_start=chunk_end;
00205     chunk_end=chunk_start+chunk_len;
00206     r=client.process("GET",url.Path(),chunk_start,chunk_end,&req,&info,&resp);
00207     if(!r) return false;
00208     if(!resp) return false;
00209     if(resp->Size() <= 0) break;
00210     if((info.code != 200) && (info.code != 206)) { delete resp; return false; };
00211     if(!PayloadRaw_to_stream(*resp,f,chunk_end)) { delete resp; return false; };
00212     delete resp; resp=NULL;
00213   };
00214   if(resp) delete resp;
00215   return true;
00216 }
00217 
00218 //end of "to the file transfer"
00219 
00220 /*  URL => File name
00221        input: URL
00222        return value: File name
00223 */  
00224 std::string File_name(std::string path){
00225      std::string file_name;
00226      size_t pos;
00227      pos = path.find("/");                            // position of "//" in path
00228      file_name = path.substr (pos+2);                 // get from "//" to the end
00229 
00230      pos = file_name.find("/");                       // position of "/" in path         
00231      while( (unsigned int)pos != (unsigned int)-1){   //4294967295 = (2^32)-1=-1
00232         file_name = file_name.substr (pos+1);        // get from "/" to the end
00233         pos = file_name.find("/");                   // position of "/" in  file_name       
00234      }    
00235      return file_name;
00236 }      
00237        
00238        
00239 /*Job submit
00240   input:  job name
00241           URL
00242           script URL
00243           sources
00244           architecture
00245           makefile's name
00246           CPU number
00247           others parameters
00248           source compressed
00249           compile type
00250           march: gcc option
00251                 
00252   return value: Job ID
00253   */
00254 std::string job_submit(const std::string job_name, const std::string site_url, const std::string script_url, 
00255                      std::vector<std::string> sources, const std::string architecture="", 
00256                      const std::string makefile="",   const std::string cpu_number="1",
00257                      const std::string parameters="", bool tar = true,  std::string compiler="make", 
00258                      bool march = false   ){
00259     std::string jobid("");
00260     // call parameter check
00261     if( site_url == "" || script_url == "" ) return jobid;
00262     try{
00263        Arc::URL url(site_url);
00264        if(!url) throw(std::invalid_argument(std::string("Can't parse specified URL")));
00265     
00266        Arc::MCCConfig cfg;
00267        /*if(!tool.proxy_path.empty()) cfg.AddProxy(tool.proxy_path);
00268         if(!tool.key_path.empty()) cfg.AddPrivateKey(tool.key_path);
00269         if(!tool.cert_path.empty()) cfg.AddCertificate(tool.cert_path);
00270         if(!tool.ca_dir.empty()) cfg.AddCADir(tool.ca_dir);
00271         cfg.GetOverlay(tool.config_path);*/
00272        Arc::Compiler_AREXClient ac(url,cfg);
00273     
00274        std::string jsdl_file;
00275        jsdl_file = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"; 
00276        jsdl_file +="<JobDefinition \n";
00277        jsdl_file +=" xmlns=\"http://schemas.ggf.org/jsdl/2005/11/jsdl\"\n";
00278        jsdl_file +=" xmlns:posix=\"http://schemas.ggf.org/jsdl/2005/11/jsdl-posix\">\n";
00279        jsdl_file +=" <JobDescription>\n";
00280        jsdl_file +="   <JobIdentification>\n";
00281        jsdl_file +="     <JobName>";
00282            jsdl_file +=job_name;
00283            jsdl_file +="</JobName>\n";
00284        jsdl_file +="   </JobIdentification>\n";
00285        jsdl_file +="   <Application>\n";
00286        jsdl_file +="     <posix:POSIXApplication>\n";
00287        jsdl_file +="       <posix:Executable>compiler_script</posix:Executable>\n";
00288        if( tar )           jsdl_file +="          <posix:Argument>-t</posix:Argument>\n";
00289        if( compiler =="make" ){
00290              jsdl_file +="          <posix:Argument>make</posix:Argument>\n";
00291              if ( makefile != ""){
00292                 jsdl_file +="          <posix:Argument>-m</posix:Argument>\n";
00293                 jsdl_file +="          <posix:Argument>";
00294                 jsdl_file +=makefile;
00295                 jsdl_file +="</posix:Argument>\n";
00296              }
00297        }      
00298        else{        //gcc
00299              jsdl_file +="          <posix:Argument>gcc</posix:Argument>\n"; 
00300              if ( cpu_number != "1" ){
00301                jsdl_file +="          <posix:Argument>-cpu</posix:Argument>\n";     
00302                jsdl_file +="          <posix:Argument>";
00303                jsdl_file +=cpu_number;
00304                jsdl_file +="</posix:Argument>\n";
00305              }
00306              if ( parameters != ""){                    //gcc parameters
00307                jsdl_file +="          <posix:Argument>-opt</posix:Argument>\n";     
00308                jsdl_file +="          <posix:Argument>";
00309                jsdl_file +=parameters;
00310                jsdl_file +="</posix:Argument>\n";
00311              }
00312              jsdl_file +="          <posix:Argument>";
00313              jsdl_file +=File_name(makefile);           //now this is the gcc sequence file's name
00314              jsdl_file +="</posix:Argument>\n";
00315        }
00316         std::vector<std::string>::iterator it_argname; 
00317        for ( it_argname=sources.begin() ; it_argname < sources.end(); it_argname++ ){
00318            jsdl_file +="       <posix:Argument>";
00319            jsdl_file += File_name(*it_argname);
00320            jsdl_file += "</posix:Argument>\n";
00321        }    
00322        //jsdl_file +="       <posix:Argument>";  //not working yet
00323        //jsdl_file +=cpu_number;
00324        //jsdl_file +="</posix:Argument>\n";
00325                 std::vector<std::string>::iterator it_name; 
00326        for ( it_name=sources.begin() ; it_name < sources.end(); it_name++ ){
00327            jsdl_file +="       <posix:Input>";
00328            jsdl_file += File_name(*it_name);
00329            jsdl_file += "</posix:Input>\n";
00330        }    
00331        jsdl_file +="       <posix:Output>out.txt</posix:Output>\n";
00332        jsdl_file +="       <posix:Error>err.txt</posix:Error>\n";
00333        jsdl_file +="     </posix:POSIXApplication>\n";
00334        jsdl_file +="   </Application>\n";
00335        
00336        if(architecture != ""){
00337            jsdl_file +="   <Resource>\n"; 
00338            jsdl_file +="   <CPUArchitecture>\n";
00339            jsdl_file +="         <CPUArchitectureName>";
00340            jsdl_file +=architecture;
00341            jsdl_file +="</CPUArchitectureName>\n";
00342            jsdl_file +="   </CPUArchitecture>\n";
00343            jsdl_file +="   </Resource>\n"; 
00344        }
00345        if( compiler =="gcc" ){
00346            jsdl_file +="   <DataStaging>\n";
00347            jsdl_file +="     <FileName>";
00348            jsdl_file +=File_name(makefile);
00349            jsdl_file +="</FileName>\n";
00350            jsdl_file +="       <Source><URI>";
00351            jsdl_file +=makefile;
00352            jsdl_file +="</URI></Source>\n";
00353            jsdl_file +="     <DeleteOnTermination>false</DeleteOnTermination>\n";
00354            jsdl_file +="   </DataStaging>\n";
00355        }    
00356        
00357        jsdl_file +="   <DataStaging>\n";
00358        jsdl_file +="     <FileName>compiler_script</FileName>\n";
00359        jsdl_file +="       <Source><URI>";
00360        jsdl_file +=script_url;
00361        
00362        local_logger.msg(Arc::VERBOSE, "file_name:     " + File_name(script_url));
00363  
00364        
00365        jsdl_file +="</URI></Source>\n";
00366        jsdl_file +="     <DeleteOnTermination>false</DeleteOnTermination>\n";
00367        jsdl_file +="   </DataStaging>\n";
00368         std::vector<std::string>::iterator it; 
00369        for ( it=sources.begin() ; it < sources.end(); it++ ){
00370              jsdl_file +="   <DataStaging>\n";
00371              jsdl_file +="     <FileName>";
00372              jsdl_file += File_name(*it);
00373              jsdl_file +="</FileName>\n";
00374              jsdl_file +="       <Source><URI>";
00375              jsdl_file+=  *it;
00376              jsdl_file += "</URI></Source>\n";
00377              jsdl_file +="     <DeleteOnTermination>false</DeleteOnTermination>\n";
00378              jsdl_file +="   </DataStaging>\n";
00379         }
00380        jsdl_file +="   <DataStaging>\n";
00381        jsdl_file +="     <FileName>outputs</FileName>\n";
00382        jsdl_file +="     <DeleteOnTermination>false</DeleteOnTermination>\n";
00383        jsdl_file +="   </DataStaging>\n";
00384         jsdl_file +="   <DataStaging>\n";
00385        jsdl_file +="     <FileName>out.txt</FileName>\n";
00386        jsdl_file +="     <CreationFlag>overwrite</CreationFlag>\n";
00387        jsdl_file +="     <DeleteOnTermination>false</DeleteOnTermination>\n";
00388        jsdl_file +="   </DataStaging>\n";
00389        jsdl_file +="   <DataStaging>\n";
00390        jsdl_file +="     <FileName>err.txt</FileName>\n";
00391        jsdl_file +="     <CreationFlag>overwrite</CreationFlag>\n";
00392        jsdl_file +="     <DeleteOnTermination>false</DeleteOnTermination>\n";
00393        jsdl_file +="   </DataStaging>\n";
00394        jsdl_file +=" </JobDescription>\n";
00395        jsdl_file +="</JobDefinition>";      
00396 
00397        local_logger.msg(Arc::VERBOSE, "Jsdl:  " + jsdl_file);
00398 
00399        //creating the temporary jsdl file
00400        std::time_t rawtime;
00401        std::time ( &rawtime );     //current time
00402        tm * ptm;
00403        ptm = gmtime ( &rawtime );
00404        
00405        std::stringstream out;
00406        out << ptm->tm_year<< ptm->tm_mon<< ptm->tm_mday<< ptm->tm_hour<< ptm->tm_min<< ptm->tm_sec;
00407        std::string local_string;
00408        local_string = out.str() +job_name+ ".jsdl";
00409 
00410        char  jsdl_file_name[ local_string.size()];
00411        for(size_t i = 0; i < local_string.size(); i++)
00412        {
00413            jsdl_file_name[i] = local_string[i];
00414        }
00415        jsdl_file_name[local_string.size()]='\0';        //close character
00416 
00417        local_logger.msg(Arc::VERBOSE, "The submited JSDL file's name: " + (std::string)jsdl_file_name);
00418        std::ofstream jsdlfile_o;
00419        jsdlfile_o.open((const char *)&jsdl_file_name);
00420        jsdlfile_o << jsdl_file;
00421        jsdlfile_o.close();
00422        
00423        std::ifstream jsdlfile((const char *)&jsdl_file_name);
00424        if (!jsdlfile)
00425            throw std::invalid_argument(std::string("Could not open ")+
00426                                          std::string(jsdl_file_name));
00427        
00428        Arc::Compiler_AREXFileList files;
00429     
00430        // Submit job description
00431        bool delegate = false;
00432        jobid = ac.submit(jsdlfile, files, delegate);
00433        if (!jsdlfile)
00434            throw std::invalid_argument(std::string("Failed when reading from ")+
00435                                    std::string(jsdl_file_name)); 
00436        
00437        remove((const char *)&jsdl_file_name);
00438        local_logger.msg(Arc::INFO, "Jod Id:  "+ jobid);
00439 
00440     }  catch(std::exception& err) {
00441        std::cerr << "ERROR: " << err.what() << std::endl;
00442         return "";
00443     };
00444     return  jobid;    
00445 }
00446 
00447 /*
00448      URL, architecture, CPU count, etc informations from the ISIS
00449   */
00450 std::vector<CompileInfo> Info_from_ISIS(Arc::XMLNode soap_xml, Service_Compiler service){
00451     std::vector<CompileInfo> return_List;     
00452        
00453     //ISIS and SOAP
00454     std::vector<ISIS_Info> info_vector;
00455       
00456     //they will be come from the ISIS, when working it
00457     ISIS_Info info;
00458     info.arex_url = "http://knowarc1.grid.niif.hu:50000/arex";
00459     info.url_cpu_number = "1";
00460     info.url_architecture= "x86_32";                  //etc.: ia64,x86_32,sparc
00461     if ((std::string)soap_xml["make"]["cpu_architecture"] != "")
00462        info.url_architecture = (std::string)soap_xml["make"]["cpu_architecture"];
00463        
00464     info_vector.push_back(info);
00465     //end of the connection with the ISIS
00466        
00467        
00468     std::string soap_compiler(soap_xml["make"]["compiler_type"]); 
00469     std::string not_default_make_file(soap_xml["make"]["makefile"]);
00470     std::string gcc_sequence_file(soap_xml["make"]["gcc_sequence"]);
00471     std::string gcc_parameters(soap_xml["make"]["gcc_parameters"]);
00472        
00473     bool tar = false;
00474     if((std::string)soap_xml["make"]["compressed"] == "yes" ||
00475        (std::string)soap_xml["make"]["compressed"] == "YES" ||
00476        (std::string)soap_xml["make"]["compressed"] == "y" ||
00477        (std::string)soap_xml["make"]["compressed"] == "Y" ||
00478        (std::string)soap_xml["make"]["compressed"] == "1" ) tar = true;
00479     const std::string j_name(soap_xml["make"]["name"]);
00480     std::vector<std::string> sources;
00481     bool march = false;     //TODO: not working yet
00482        
00483     int j= 0; 
00484     while( (bool)soap_xml["make"]["sourcefile"][j] ){             
00485        std::stringstream tmp;
00486        tmp << j;
00487        sources.push_back( soap_xml["make"]["sourcefile"][j] );
00488        local_logger.msg(Arc::VERBOSE, "sourcefile"+tmp.str()+ ":  "+ (std::string)soap_xml["make"]["sourcefile"][j]);
00489         j++;
00490        if(tar) break;
00491     }
00492     //end of ISIS and SOAP
00493        
00494     std::vector<ISIS_Info>::iterator it; 
00495     for ( it=info_vector.begin(); it < info_vector.end(); it++ ){
00496         CompileInfo compile_info;
00497        compile_info.site_url =  (*it).arex_url;
00498        compile_info.script_url = service.Get_Script_Url();
00499        compile_info.architecture = (*it).url_architecture;
00500        compile_info.makefile_name=not_default_make_file;
00501         if ( soap_compiler == "gcc"){
00502           compile_info.makefile_name=gcc_sequence_file;
00503        }
00504        compile_info.cpu_number = (*it).url_cpu_number;
00505        compile_info.parameters = gcc_parameters;
00506        compile_info.tar = tar;
00507        compile_info.compiler = soap_compiler; 
00508        compile_info.march = march;
00509        compile_info.job_name = j_name;
00510        compile_info.sources = sources;
00511    
00512        return_List.push_back(compile_info);
00513     }
00514        
00515     return return_List;
00516 }
00517 
00518 /*
00519      When the Job status is Finished, then this function returned with "true",  otherwise returned with "false".
00520      
00521      input: Job ID
00522      return value: true/false
00523 */
00524 bool Job_Status_Finished(std::string jobid){
00525       std::string urlstr;
00526       Arc::XMLNode jobxml(jobid);
00527       if(!jobxml)
00528         throw std::invalid_argument("Could not process Job ID from " + jobid);
00529       urlstr=(std::string)(jobxml["Address"]); // TODO: clever service address extraction
00530       
00531       if(urlstr.empty())
00532       throw std::invalid_argument("Missing service URL");
00533       Arc::URL url(urlstr);
00534       if(!url)
00535                 throw std::invalid_argument("Can't parse service URL " + urlstr);
00536       Arc::MCCConfig cfg;
00537       //    if(!proxy_path.empty()) cfg.AddProxy(proxy_path);
00538       //    if(!key_path.empty()) cfg.AddPrivateKey(key_path);
00539       //    if(!cert_path.empty()) cfg.AddCertificate(cert_path);
00540       //    if(!ca_dir.empty()) cfg.AddCADir(ca_dir);
00541       //    cfg.GetOverlay(config_path);
00542       Arc::Compiler_AREXClient ac(url,cfg);
00543       std::string status= ac.stat(jobid);
00544       local_logger.msg(Arc::INFO, "STATUS: " + status);
00545  
00546       if ( status.substr(0,8) == "Finished" ||                    // status ="Finished/Finished" or "Finished/Deleted"
00547            status.substr(0,6) == "Failed"  ||                     // status ="Failed/Failed" or "Failed/Deleted"
00548            status.substr(0,9) == "Cancelled" ) return true;       // status ="Cancelled/Failed" or "Cancelled/Deleted"
00549       return false; 
00550 }
00551 
00552 Arc::Logger Service_Compiler::logger(Arc::Logger::getRootLogger(), "Compiler");
00553 
00554 Service_Compiler::Service_Compiler(Arc::Config *cfg):Service(cfg) {
00555   ns_["compiler"]="urn:compiler";
00556   script_url_=(std::string)((*cfg)["scriptfile_url"]);
00557 }
00558 
00559 Service_Compiler::~Service_Compiler(void) {
00560 }
00561 
00562 Arc::MCC_Status Service_Compiler::make_fault(Arc::Message& outmsg) {
00563   Arc::PayloadSOAP* outpayload = new Arc::PayloadSOAP(ns_,true);
00564   Arc::SOAPFault* fault = outpayload->Fault();
00565   if(fault) {
00566     fault->Code(Arc::SOAPFault::Sender);
00567     fault->Reason("Failed processing request");
00568   };
00569   outmsg.Payload(outpayload);
00570   return Arc::MCC_Status(Arc::GENERIC_ERROR);
00571 }
00572 
00573 Arc::MCC_Status Service_Compiler::process(Arc::Message& inmsg,Arc::Message& outmsg) {
00574    // Both input and output are supposed to be SOAP 
00575    // Extracting payload
00576    Arc::PayloadSOAP* inpayload = NULL;
00577    try {
00578      inpayload = dynamic_cast<Arc::PayloadSOAP*>(inmsg.Payload());
00579    } catch(std::exception& e) { };
00580    if(!inpayload) {
00581      logger.msg(Arc::ERROR, "Input is not SOAP");
00582      return make_fault(outmsg);
00583    };
00584    // Analyzing request 
00585    Arc::XMLNode compiler_op = (*inpayload)["compiler"];
00586    if(!compiler_op) {
00587      logger.msg(Arc::ERROR, "Request is not supported - %s", compiler_op.Name());
00588      return make_fault(outmsg);
00589    };
00590   
00591    std::string xml;
00592    inpayload->GetDoc(xml, true);
00593    std::cout << "XML: "<< xml << std::endl;
00594    
00595    Arc::PayloadSOAP* outpayload = new Arc::PayloadSOAP(ns_);
00596    Arc::XMLNode outpayload_node = outpayload->NewChild("compiler:compilerResponse");
00597 
00598    //info from the ISIS
00599    logger.msg(Arc::VERBOSE, "Info from the ISIS");
00600    std::vector<CompileInfo> Site_List;
00601    
00602    Site_List = Info_from_ISIS(compiler_op, *this);
00603 
00604    //job submit
00605    logger.msg(Arc::VERBOSE, "job(s) submit");
00606    std::vector<std::string> jobid_request;
00607    std::vector<CompileInfo>::iterator it; 
00608    for ( it=Site_List.begin() ; it < Site_List.end(); it++ ){
00609        
00610        jobid_request.push_back(job_submit((*it).job_name, (*it).site_url, (*it).script_url, (*it).sources,
00611                                          (*it).architecture,  (*it).makefile_name, (*it).cpu_number,
00612                                          (*it).parameters, (*it).tar, 
00613                                          (*it).compiler, (*it).march  ));
00614        if( jobid_request.back() == "" ){
00615               std::string message = "Wrong Job submitting!      URL: " + (*it).site_url;
00616               message =  message + "     Achitecture: " + (*it).architecture;
00617               outpayload_node.NewChild("compiler:error")= message;
00618               
00619               logger.msg(Arc::ERROR, "Wrong Job submitting!      URL: " + (*it).site_url);
00620               logger.msg(Arc::ERROR, "     Achitecture: " + (*it).architecture);
00621         }
00622    }
00623     
00624    //current time (GMT)
00625    std::time_t rawtime;
00626    std::time ( &rawtime );  //current time
00627    tm * ptm;
00628    ptm = gmtime ( &rawtime );
00629 
00630    std::stringstream out;
00631    int year = ptm->tm_year;
00632    year = year +1900;
00633    
00634    int mon = ptm->tm_mon;
00635    mon++;
00636    out << "GMT  "<< year << "."  << mon << "." << ptm->tm_mday;
00637    out << "    " << ptm->tm_hour<< ":" << ptm->tm_min <<  ":" << ptm->tm_sec;
00638    
00639    std::string hear = "All Job(s) submited:    "+ out.str();
00640    outpayload_node.NewChild("compiler:response")=hear;
00641    outmsg.Payload(outpayload);
00642    logger.msg(Arc::VERBOSE, hear);
00643     
00644     
00645    //output file(s) copy to the added directory
00646    logger.msg(Arc::VERBOSE, "Result(s) download");
00647    logger.msg(Arc::VERBOSE, "Download Place: " + compiler_op["make"]["download_place"]);
00648    try{
00649         std::string urlstr;
00650         std::vector<CompileInfo>::iterator it1;
00651         it1=Site_List.end();
00652         std::string Current_Architecture("");
00653        
00654         //sleep(10);
00655         while( !jobid_request.empty() ){
00656              logger.msg(Arc::VERBOSE, "Download cycle: start");              
00657               if(it1 != Site_List.begin())
00658                     it1--;
00659               Current_Architecture = (*it1).architecture;
00660               logger.msg(Arc::VERBOSE, "Current Arhitecture: "+Current_Architecture);
00661              //Job ID checking
00662              if( jobid_request.back() == "" ){
00663                    jobid_request.pop_back();
00664                    logger.msg(Arc::VERBOSE, "Empty Job ID. Go to the next Job ID.");
00665                     continue;
00666              }
00667              //Wait until the job is Finished
00668              while ( !Job_Status_Finished( jobid_request.back() ) ){
00669                    std::string message="Waiting 15 seconds";
00670                    outpayload_node.NewChild("compiler:response")=message;
00671                    outmsg.Payload(outpayload);
00672                    logger.msg(Arc::VERBOSE, message);
00673                    sleep(15);
00674             }
00675             //sleep(10);
00676              Arc::XMLNode jobxml(jobid_request.back());
00677              if(!jobxml)
00678                     throw std::invalid_argument(std::string("Could not process Job ID from ")+jobid_request.back());
00679              urlstr=(std::string)(jobxml["ReferenceParameters"]["JobSessionDir"]); // TODO: clever service address extraction
00680             std::string local_dir(compiler_op["make"]["download_place"]);   // for example: /home/user/tmp/s/
00681             if ( Current_Architecture != "")
00682                local_dir=  local_dir + Current_Architecture + "/";  
00683             jobid_request.pop_back();
00684           
00685             logger.msg(Arc::VERBOSE, "Download url:  " + urlstr);
00686             logger.msg(Arc::VERBOSE, "Download path:  " + local_dir);
00687           
00688             if(urlstr.empty())
00689               throw std::invalid_argument("Missing service URL");
00690             Arc::URL download_url(urlstr);
00691             if(!download_url)
00692               throw std::invalid_argument(std::string("Can't parse service URL ")+urlstr);
00693             Arc::MCCConfig download_cfg;
00694                  //    if(!tool.proxy_path.empty()) download_cfg.AddProxy(tool.proxy_path);
00695                  //    if(!tool.key_path.empty()) download_cfg.AddPrivateKey(tool.key_path);
00696                  //    if(!tool.cert_path.empty()) download_cfg.AddCertificate(tool.cert_path);
00697                  //    if(!tool.ca_dir.empty()) download_cfg.AddCADir(tool.ca_dir);
00698                  //    download_cfg.GetOverlay(tool.config_path);
00699             Arc::Compiler_AREXClient download_ac(download_url,download_cfg);
00700             bool r = get_file(*(download_ac.SOAP()),download_url, local_dir);
00701             if(!r) throw std::invalid_argument("Failed to download files!");
00702             logger.msg(Arc::VERBOSE, "Download cycle: end");
00703         }
00704    }
00705    catch (std::exception& err){
00706          std::cerr << "ERROR: " << err.what() << std::endl;
00707          return  Arc::MCC_Status(Arc::GENERIC_ERROR,"compiler","");
00708    }  
00709    //download end
00710 
00711    std::time ( &rawtime );  //current time
00712    ptm = gmtime ( &rawtime );
00713 
00714    std::stringstream out_finish;
00715    year = ptm->tm_year +1900;
00716    
00717    mon = ptm->tm_mon;
00718    mon++;
00719    out_finish << "GMT  "<< year << "."  << mon << "." << ptm->tm_mday;
00720    out_finish << "    " << ptm->tm_hour<< ":" << ptm->tm_min <<  ":" << ptm->tm_sec;
00721 
00722    logger.msg(Arc::VERBOSE, "Finished the compile:  " + out_finish.str() );
00723     
00724    std::string say = compiler_op["make"]["name"];
00725    hear = "Finished the compile: " + out_finish.str();
00726   
00727    //the response
00728    outpayload_node.NewChild("compiler:response")=hear;
00729    outmsg.Payload(outpayload);
00730    logger.msg(Arc::VERBOSE, "               The SOAP message send and return");
00731 
00732    Arc::MCC_Status return_Status(Arc::STATUS_OK, "compiler" , "this is the explanation" );
00733    return return_Status;
00734 }
00735