Back to index

nordugrid-arc-nox  1.1.0~rc6
arex.cpp
Go to the documentation of this file.
00001 #ifdef HAVE_CONFIG_H
00002 #include <config.h>
00003 #endif
00004 
00005 #include <iostream>
00006 
00007 #include <sys/types.h>
00008 #include <sys/stat.h>
00009 #include <pwd.h>
00010 #include <unistd.h>
00011 
00012 #include <arc/loader/Loader.h>
00013 #include <arc/message/MCCLoader.h>
00014 #include <arc/message/Plexer.h>
00015 #include <arc/message/PayloadSOAP.h>
00016 #include <arc/message/PayloadRaw.h>
00017 #include <arc/message/PayloadStream.h>
00018 #include <arc/ws-addressing/WSA.h>
00019 #include <arc/Thread.h>
00020 #include <arc/StringConv.h>
00021 #include <arc/Utils.h>
00022 
00023 #include "job.h"
00024 #include "grid-manager/conf/conf_pre.h"
00025 #include "arex.h"
00026 
00027 namespace ARex {
00028 
00029 #define DEFAULT_INFOPROVIDER_WAKEUP_PERIOD (60)
00030 #define DEFAULT_INFOSYS_MAX_CLIENTS (1)
00031 #define DEFAULT_JOBCONTROL_MAX_CLIENTS (100)
00032 #define DEFAULT_DATATRANSFER_MAX_CLIENTS (100)
00033  
00034 static const std::string BES_FACTORY_ACTIONS_BASE_URL("http://schemas.ggf.org/bes/2006/08/bes-factory/BESFactoryPortType/");
00035 static const std::string BES_FACTORY_NPREFIX("bes-factory");
00036 static const std::string BES_FACTORY_NAMESPACE("http://schemas.ggf.org/bes/2006/08/bes-factory");
00037 
00038 static const std::string BES_MANAGEMENT_ACTIONS_BASE_URL("http://schemas.ggf.org/bes/2006/08/bes-management/BESManagementPortType/");
00039 static const std::string BES_MANAGEMENT_NPREFIX("bes-management");
00040 static const std::string BES_MANAGEMENT_NAMESPACE("http://schemas.ggf.org/bes/2006/08/bes-management");
00041 
00042 static const std::string BES_ARC_NPREFIX("a-rex");
00043 static const std::string BES_ARC_NAMESPACE("http://www.nordugrid.org/schemas/a-rex");
00044 
00045 static const std::string BES_GLUE_NPREFIX("glue");
00046 static const std::string BES_GLUE_NAMESPACE("http://schemas.ogf.org/glue/2008/05/spec_2.0_d41_r01");
00047 
00048 
00049 static Arc::XMLNode BESFactoryResponse(Arc::PayloadSOAP& res,const char* opname) {
00050   Arc::XMLNode response = res.NewChild(BES_FACTORY_NPREFIX + ":" + opname + "Response");
00051   Arc::WSAHeader(res).Action(BES_FACTORY_ACTIONS_BASE_URL + opname + "Response");
00052   return response;
00053 }
00054 
00055 static Arc::XMLNode BESManagementResponse(Arc::PayloadSOAP& res,const char* opname) {
00056   Arc::XMLNode response = res.NewChild(BES_MANAGEMENT_NPREFIX + ":" + opname + "Response");
00057   Arc::WSAHeader(res).Action(BES_MANAGEMENT_ACTIONS_BASE_URL + opname + "Response");
00058   return response;
00059 }
00060 
00061 static Arc::XMLNode BESARCResponse(Arc::PayloadSOAP& res,const char* opname) {
00062   Arc::XMLNode response = res.NewChild(BES_ARC_NPREFIX + ":" + opname + "Response");
00063   return response;
00064 }
00065 
00066 //static Arc::LogStream logcerr(std::cerr);
00067 
00068 static Arc::Plugin* get_service(Arc::PluginArgument* arg) {
00069     Arc::ServicePluginArgument* srvarg =
00070             arg?dynamic_cast<Arc::ServicePluginArgument*>(arg):NULL;
00071     if(!srvarg) return NULL;
00072     ARexService* arex = new ARexService((Arc::Config*)(*srvarg));
00073     if(!*arex) { delete arex; arex=NULL; };
00074     return arex;
00075 }
00076 
00077 class ARexConfigContext:public Arc::MessageContextElement, public ARexGMConfig {
00078  public:
00079   ARexConfigContext(const std::string& config_file,const std::string& uname,const std::string& grid_name,const std::string& service_endpoint):ARexGMConfig(config_file,uname,grid_name,service_endpoint) { };
00080   virtual ~ARexConfigContext(void) { };
00081 };
00082 
00083 void CountedResource::Acquire(void) {
00084   lock_.lock();
00085   while((limit_ >= 0) && (count_ >= limit_)) {
00086     cond_.wait(lock_);
00087   };
00088   ++count_;
00089   lock_.unlock();
00090 }
00091 
00092 void CountedResource::Release(void) {
00093   lock_.lock();
00094   --count_;
00095   cond_.signal();
00096   lock_.unlock();
00097 }
00098 
00099 void CountedResource::MaxConsumers(int maxconsumers) {
00100   limit_ = maxconsumers;
00101 }
00102 
00103 CountedResource::CountedResource(int maxconsumers):
00104                         limit_(maxconsumers),count_(0) {
00105 }
00106 
00107 CountedResource::~CountedResource(void) {
00108 }
00109 
00110 class CountedResourceLock {
00111  private:
00112   CountedResource& r_;
00113  public:
00114   CountedResourceLock(CountedResource& resource):r_(resource) {
00115     r_.Acquire();
00116   };
00117   ~CountedResourceLock(void) {
00118     r_.Release();
00119   };
00120 };
00121 
00122 static std::string GetPath(std::string url){
00123   std::string::size_type ds, ps;
00124   ds=url.find("//");
00125   if (ds==std::string::npos)
00126     ps=url.find("/");
00127   else
00128     ps=url.find("/", ds+2);
00129   if (ps==std::string::npos)
00130     return "";
00131   else
00132     return url.substr(ps);
00133 }
00134 
00135 
00136 Arc::MCC_Status ARexService::StopAcceptingNewActivities(ARexGMConfig& /*config*/,Arc::XMLNode /*in*/,Arc::XMLNode /*out*/) {
00137   return Arc::MCC_Status();
00138 }
00139 
00140 Arc::MCC_Status ARexService::StartAcceptingNewActivities(ARexGMConfig& /*config*/,Arc::XMLNode /*in*/,Arc::XMLNode /*out*/) {
00141   return Arc::MCC_Status();
00142 }
00143 
00144 Arc::MCC_Status ARexService::make_soap_fault(Arc::Message& outmsg) {
00145   Arc::PayloadSOAP* outpayload = new Arc::PayloadSOAP(ns_,true);
00146   Arc::SOAPFault* fault = outpayload?outpayload->Fault():NULL;
00147   if(fault) {
00148     fault->Code(Arc::SOAPFault::Sender);
00149     fault->Reason("Failed processing request");
00150   };
00151   outmsg.Payload(outpayload);
00152   return Arc::MCC_Status(Arc::STATUS_OK);
00153 }
00154 
00155 Arc::MCC_Status ARexService::make_fault(Arc::Message& /*outmsg*/) {
00156   return Arc::MCC_Status();
00157 }
00158 
00159 Arc::MCC_Status ARexService::make_response(Arc::Message& outmsg) {
00160   Arc::PayloadRaw* outpayload = new Arc::PayloadRaw();
00161   outmsg.Payload(outpayload);
00162   return Arc::MCC_Status(Arc::STATUS_OK);
00163 }
00164 
00165 ARexConfigContext* ARexService::get_configuration(Arc::Message& inmsg) {
00166   ARexConfigContext* config = NULL;
00167   Arc::MessageContextElement* mcontext = (*inmsg.Context())["arex.gmconfig"];
00168   if(mcontext) {
00169     try {
00170       config = dynamic_cast<ARexConfigContext*>(mcontext);
00171     } catch(std::exception& e) { };
00172   };
00173   if(config) return config;
00174   // TODO: do configuration detection
00175   // TODO: do mapping to local unix name
00176   std::string uname;
00177   uname=inmsg.Attributes()->get("SEC:LOCALID");
00178   if(uname.empty()) uname=uname_;
00179   if(uname.empty()) {
00180     if(getuid() == 0) {
00181       logger_.msg(Arc::ERROR, "Will not map to 'root' account by default");
00182       return NULL;
00183     };
00184     struct passwd pwbuf;
00185     char buf[4096];
00186     struct passwd* pw;
00187     if(getpwuid_r(getuid(),&pwbuf,buf,sizeof(buf),&pw) == 0) {
00188       if(pw && pw->pw_name) {
00189         uname = pw->pw_name;
00190       };
00191     };
00192   };
00193   if(uname.empty()) {
00194     logger_.msg(Arc::ERROR, "No local account name specified");
00195     return NULL;
00196   };
00197   logger_.msg(Arc::DEBUG,"Using local account '%s'",uname);
00198   std::string grid_name = inmsg.Attributes()->get("TLS:IDENTITYDN");
00199   std::string endpoint = endpoint_;
00200   if(endpoint.empty()) {
00201     std::string http_endpoint = inmsg.Attributes()->get("HTTP:ENDPOINT");
00202     std::string tcp_endpoint = inmsg.Attributes()->get("TCP:ENDPOINT");
00203     bool https_proto = !grid_name.empty();
00204     endpoint = tcp_endpoint;
00205     if(https_proto) {
00206       endpoint="https"+endpoint;
00207     } else {
00208       endpoint="http"+endpoint;
00209     };
00210     endpoint+=GetPath(http_endpoint);
00211   };
00212   config=new ARexConfigContext(gmconfig_,uname,grid_name,endpoint);
00213   if(config) {
00214     if(*config) {
00215       inmsg.Context()->Add("arex.gmconfig",config);
00216     } else {
00217       delete config; config=NULL;
00218       logger_.msg(Arc::ERROR, "Failed to acquire grid-manager's configuration");
00219     };
00220   };
00221   return config;
00222 }
00223 
00224 static std::string GetPath(Arc::Message &inmsg,std::string &base) {
00225   base = inmsg.Attributes()->get("HTTP:ENDPOINT");
00226   Arc::AttributeIterator iterator = inmsg.Attributes()->getAll("PLEXER:EXTENSION");
00227   std::string path;
00228   if(iterator.hasMore()) {
00229     // Service is behind plexer
00230     path = *iterator;
00231     if(base.length() > path.length()) base.resize(base.length()-path.length());
00232   } else {
00233     // Standalone service
00234     path=Arc::URL(base).Path();
00235     base.resize(0);
00236   };
00237   return path;
00238 }
00239 
00240 Arc::MCC_Status ARexService::process(Arc::Message& inmsg,Arc::Message& outmsg) {
00241   // Split request path into parts: service, job and file path. 
00242   // TODO: make it HTTP independent
00243   std::string endpoint;
00244   std::string method = inmsg.Attributes()->get("HTTP:METHOD");
00245   std::string id = GetPath(inmsg,endpoint);
00246   std::string clientid = (inmsg.Attributes()->get("TCP:REMOTEHOST"))+":"+(inmsg.Attributes()->get("TCP:REMOTEPORT"));
00247   if((inmsg.Attributes()->get("PLEXER:PATTERN").empty()) && id.empty()) id=endpoint;
00248   logger_.msg(Arc::VERBOSE, "process: method: %s", method);
00249   logger_.msg(Arc::VERBOSE, "process: endpoint: %s", endpoint);
00250   while(id[0] == '/') id=id.substr(1);
00251   std::string subpath;
00252   {
00253     std::string::size_type p = id.find('/');
00254     if(p != std::string::npos) {
00255       subpath = id.substr(p);
00256       id.resize(p);
00257       while(subpath[0] == '/') subpath=subpath.substr(1);
00258     };
00259   };
00260   logger_.msg(Arc::VERBOSE, "process: id: %s", id);
00261   logger_.msg(Arc::VERBOSE, "process: subpath: %s", subpath);
00262 
00263   // Process grid-manager configuration if not done yet
00264   ARexConfigContext* config = get_configuration(inmsg);
00265   if(!config) {
00266     logger_.msg(Arc::ERROR, "Can't obtain configuration");
00267     // Service is not operational
00268     return Arc::MCC_Status();
00269   };
00270   config->ClearAuths();
00271   config->AddAuth(inmsg.Auth());
00272   config->AddAuth(inmsg.AuthContext());
00273 
00274   // Collect any service specific Security Attributes here
00275   if(!ProcessSecHandlers(inmsg,"incoming")) {
00276     logger_.msg(Arc::ERROR, "Security Handlers processing failed");
00277     return Arc::MCC_Status();
00278   };
00279 
00280   // Identify which of served endpoints request is for.
00281   // Using simplified algorithm - POST for SOAP messages,
00282   // GET and PUT for data transfer
00283   if(method == "POST") {
00284     logger_.msg(Arc::VERBOSE, "process: POST");
00285     // Both input and output are supposed to be SOAP
00286     // Extracting payload
00287     Arc::PayloadSOAP* inpayload = NULL;
00288     try {
00289       inpayload = dynamic_cast<Arc::PayloadSOAP*>(inmsg.Payload());
00290     } catch(std::exception& e) { };
00291     if(!inpayload) {
00292       logger_.msg(Arc::ERROR, "input is not SOAP");
00293       return make_soap_fault(outmsg);
00294     };
00295     // Aplying known namespaces
00296     inpayload->Namespaces(ns_);
00297     if(logger_.getThreshold() <= Arc::VERBOSE) {
00298         std::string str;
00299         inpayload->GetDoc(str, true);
00300         logger_.msg(Arc::VERBOSE, "process: request=%s",str);
00301     };
00302     // Analyzing request
00303     Arc::XMLNode op = inpayload->Child(0);
00304     if(!op) {
00305       logger_.msg(Arc::ERROR, "input does not define operation");
00306       return make_soap_fault(outmsg);
00307     };
00308     logger_.msg(Arc::VERBOSE, "process: operation: %s",op.Name());
00309     // Check if request is for top of tree (BES factory) or particular 
00310     // job (listing activity)
00311     if(id.empty()) {
00312       // Factory operations
00313       logger_.msg(Arc::VERBOSE, "process: factory endpoint");
00314       Arc::PayloadSOAP* outpayload = new Arc::PayloadSOAP(ns_);
00315       Arc::PayloadSOAP& res = *outpayload;
00316       // Preparing known namespaces
00317       outpayload->Namespaces(ns_);
00318       if(MatchXMLName(op,"CreateActivity")) {
00319         CountedResourceLock cl_lock(beslimit_);
00320         CreateActivity(*config,op,BESFactoryResponse(res,"CreateActivity"),clientid);
00321       } else if(MatchXMLName(op,"GetActivityStatuses")) {
00322         CountedResourceLock cl_lock(beslimit_);
00323         GetActivityStatuses(*config,op,BESFactoryResponse(res,"GetActivityStatuses"));
00324       } else if(MatchXMLName(op,"TerminateActivities")) {
00325         CountedResourceLock cl_lock(beslimit_);
00326         TerminateActivities(*config,op,BESFactoryResponse(res,"TerminateActivities"));
00327       } else if(MatchXMLName(op,"GetActivityDocuments")) {
00328         CountedResourceLock cl_lock(beslimit_);
00329         GetActivityDocuments(*config,op,BESFactoryResponse(res,"GetActivityDocuments"));
00330       } else if(MatchXMLName(op,"GetFactoryAttributesDocument")) {
00331         CountedResourceLock cl_lock(beslimit_);
00332         GetFactoryAttributesDocument(*config,op,BESFactoryResponse(res,"GetFactoryAttributesDocument"));
00333       } else if(MatchXMLName(op,"StopAcceptingNewActivities")) {
00334         CountedResourceLock cl_lock(beslimit_);
00335         StopAcceptingNewActivities(*config,op,BESManagementResponse(res,"StopAcceptingNewActivities"));
00336       } else if(MatchXMLName(op,"StartAcceptingNewActivities")) {
00337         CountedResourceLock cl_lock(beslimit_);
00338         StartAcceptingNewActivities(*config,op,BESManagementResponse(res,"StartAcceptingNewActivities"));
00339       } else if(MatchXMLName(op,"ChangeActivityStatus")) {
00340         CountedResourceLock cl_lock(beslimit_);
00341         ChangeActivityStatus(*config,op,BESARCResponse(res,"ChangeActivityStatus"));
00342       } else if(MatchXMLName(op,"MigrateActivity")) {
00343         CountedResourceLock cl_lock(beslimit_);
00344         MigrateActivity(*config,op,BESFactoryResponse(res,"MigrateActivity"),clientid);
00345       } else if(MatchXMLName(op,"CacheCheck")) {
00346         CacheCheck(*config,*inpayload,*outpayload);
00347       } else if(MatchXMLName(op,"DelegateCredentialsInit")) {
00348         CountedResourceLock cl_lock(beslimit_);
00349         if(!delegations_.DelegateCredentialsInit(*inpayload,*outpayload)) {
00350           delete outpayload;
00351           return make_soap_fault(outmsg);
00352         };
00353       } else if(MatchXMLName(op,"UpdateCredentials")) {
00354         CountedResourceLock cl_lock(beslimit_);
00355         std::string credentials;
00356         if(!delegations_.UpdateCredentials(credentials,*inpayload,*outpayload)) {
00357           delete outpayload;
00358           return make_soap_fault(outmsg);
00359         };
00360         UpdateCredentials(*config,op,outpayload->Child(),credentials);
00361       } else if(MatchXMLNamespace(op,"http://docs.oasis-open.org/wsrf/rp-2")) {
00362         CountedResourceLock cl_lock(infolimit_);
00363         /*
00364         Arc::SOAPEnvelope* out_ = infodoc_.Arc::InformationInterface::Process(*inpayload);
00365         if(out_) {
00366           out_->Swap(*outpayload);
00367           delete out_;
00368         } else {
00369           delete outpayload;
00370           return make_soap_fault(outmsg);
00371         };
00372         */
00373         delete outpayload;
00374         Arc::MessagePayload* mpayload = infodoc_.Process(*inpayload);
00375         if(!mpayload) {
00376           return make_soap_fault(outmsg);
00377         };
00378         try {
00379           outpayload = dynamic_cast<Arc::PayloadSOAP*>(mpayload);
00380         } catch(std::exception& e) { };
00381         outmsg.Payload(mpayload);
00382         if(logger_.getThreshold() <= Arc::VERBOSE) {
00383           if(outpayload) {
00384             std::string str;
00385             outpayload->GetDoc(str, true);
00386             logger_.msg(Arc::VERBOSE, "process: response=%s",str);
00387           } else {
00388             logger_.msg(Arc::VERBOSE, "process: response is not SOAP");
00389           };
00390         };
00391         if(!ProcessSecHandlers(outmsg,"outgoing")) {
00392           logger_.msg(Arc::ERROR, "Security Handlers processing failed");
00393           delete outmsg.Payload(NULL);
00394           return Arc::MCC_Status();
00395         };
00396         return Arc::MCC_Status(Arc::STATUS_OK);
00397       } else {
00398         logger_.msg(Arc::ERROR, "SOAP operation is not supported: %s", op.Name());
00399         delete outpayload;
00400         return make_soap_fault(outmsg);
00401       };
00402       if(logger_.getThreshold() <= Arc::VERBOSE) {
00403         std::string str;
00404         outpayload->GetDoc(str, true);
00405         logger_.msg(Arc::VERBOSE, "process: response=%s",str);
00406       };
00407       outmsg.Payload(outpayload);
00408     } else {
00409       // Listing operations for session directories
00410       // TODO: proper failure like interface is not supported
00411     };
00412     if(!ProcessSecHandlers(outmsg,"outgoing")) {
00413       logger_.msg(Arc::ERROR, "Security Handlers processing failed");
00414       delete outmsg.Payload(NULL);
00415       return Arc::MCC_Status();
00416     };
00417     return Arc::MCC_Status(Arc::STATUS_OK);
00418   } else if(method == "GET") {
00419     // HTTP plugin either provides buffer or stream
00420     logger_.msg(Arc::VERBOSE, "process: GET");
00421     CountedResourceLock cl_lock(datalimit_);
00422     // TODO: in case of error generate some content
00423     Arc::MCC_Status ret = Get(inmsg,outmsg,*config,id,subpath);
00424     if(ret) {
00425       if(!ProcessSecHandlers(outmsg,"outgoing")) {
00426         logger_.msg(Arc::ERROR, "Security Handlers processing failed");
00427         delete outmsg.Payload(NULL);
00428         return Arc::MCC_Status();
00429       };
00430     };
00431     return ret;
00432   } else if(method == "PUT") {
00433     logger_.msg(Arc::VERBOSE, "process: PUT");
00434     CountedResourceLock cl_lock(datalimit_);
00435     Arc::MCC_Status ret = Put(inmsg,outmsg,*config,id,subpath);
00436     if(!ret) return make_fault(outmsg);
00437     // Put() does not generate response yet
00438     ret=make_response(outmsg);
00439     if(ret) {
00440       if(!ProcessSecHandlers(outmsg,"outgoing")) {
00441         logger_.msg(Arc::ERROR, "Security Handlers processing failed");
00442         delete outmsg.Payload(NULL);
00443         return Arc::MCC_Status();
00444       };
00445     };
00446     return ret;
00447   } else {
00448     logger_.msg(Arc::VERBOSE, "process: method %s is not supported",method);
00449     // TODO: make useful response
00450     return Arc::MCC_Status();
00451   };
00452   return Arc::MCC_Status();
00453 }
00454 
00455 static void information_collector_starter(void* arg) {
00456   if(!arg) return;
00457   ((ARexService*)arg)->InformationCollector();
00458 }
00459 
00460 ARexService::ARexService(Arc::Config *cfg):RegisteredService(cfg),
00461               logger_(Arc::Logger::rootLogger, "A-REX"),
00462               inforeg_(*cfg,this),
00463               gmconfig_temporary_(false),
00464               gm_(NULL),
00465               valid_(false) {
00466   // logger_.addDestination(logcerr);
00467   // Define supported namespaces
00468   ns_[BES_ARC_NPREFIX]=BES_ARC_NAMESPACE;
00469   ns_[BES_GLUE_NPREFIX]=BES_GLUE_NAMESPACE;
00470   ns_[BES_FACTORY_NPREFIX]=BES_FACTORY_NAMESPACE;
00471   ns_[BES_MANAGEMENT_NPREFIX]=BES_MANAGEMENT_NAMESPACE;
00472   ns_["deleg"]="http://www.nordugrid.org/schemas/delegation";
00473   ns_["wsa"]="http://www.w3.org/2005/08/addressing";
00474   ns_["jsdl"]="http://schemas.ggf.org/jsdl/2005/11/jsdl";
00475   ns_["wsrf-bf"]="http://docs.oasis-open.org/wsrf/bf-2";
00476   ns_["wsrf-r"]="http://docs.oasis-open.org/wsrf/r-2";
00477   ns_["wsrf-rw"]="http://docs.oasis-open.org/wsrf/rw-2";
00478   // Obtain information from configuration
00479 
00480   endpoint_=(std::string)((*cfg)["endpoint"]);
00481   uname_=(std::string)((*cfg)["usermap"]["defaultLocalName"]);
00482   gmconfig_=(std::string)((*cfg)["gmconfig"]);
00483 
00484   JobUsers users;
00485   if(gmconfig_.empty()) {
00486     // No external configuration file means configuration is
00487     // directly embedded into this configuration node.
00488     // TODO: merge external and internal configuration elements
00489     // Configuration is stored into temporary file and file is 
00490     // deleted in destructor. File is created in one of configured
00491     // control directories. There is still a problem if destructor
00492     // is not called. So code must be changed to use 
00493     // some better approach - maybe like creating file with service
00494     // id in its name.
00495     try {
00496       if(!configure_users_dirs(*cfg,users)) {
00497         logger_.msg(Arc::ERROR, "Failed to process service configuration");
00498         return;
00499       }
00500       // create control and session directories if not yet done
00501       // extract control directories to be used for temp configuration
00502       std::list<std::string> tmp_dirs;
00503       for(JobUsers::iterator user = users.begin();user != users.end();++user) {
00504         std::string tmp_dir = user->ControlDir();
00505         std::list<std::string>::iterator t = tmp_dirs.begin();
00506         for(;t != tmp_dirs.end();++t) {
00507           if(*t == tmp_dir) break;
00508         };
00509         if(t == tmp_dirs.end()) {
00510           tmp_dirs.push_back(tmp_dir);
00511         };
00512         if(!user->CreateDirectories()) {
00513           logger_.msg(Arc::ERROR, "Failed to create control (%s) or session (%s) directories",user->ControlDir(),user->SessionRoot());
00514           return;
00515         };
00516       };
00517       if(tmp_dirs.size() <= 0) {
00518         throw Glib::FileError(Glib::FileError::FAILED,"Failed to find control directories in configuration");
00519       };
00520       int h = -1;
00521       for(std::list<std::string>::iterator t = tmp_dirs.begin();
00522                                          t != tmp_dirs.end();++t) {
00523         std::string tmp_path = Glib::build_filename(*t,"arexcfgXXXXXX");
00524         h = Glib::mkstemp(tmp_path);
00525         if(h != -1) {
00526           gmconfig_ = tmp_path;
00527           ::chmod(gmconfig_.c_str(), S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
00528           break;
00529         };
00530         logger_.msg(Arc::DEBUG, "Failed to create temporary file in %s - %s",*t,Arc::StrError(errno));
00531       };
00532       if(h == -1) {
00533         throw Glib::FileError(Glib::FileError::FAILED,"Failed to create temporary file in any of control directories");
00534       };
00535       logger_.msg(Arc::DEBUG, "Storing configuration into temporary file - %s",gmconfig_);
00536       Arc::XMLNode gmxml;
00537       cfg->New(gmxml);
00538       // Storing configuration into temporary file
00539       // Maybe XMLNode needs method SaveToHandle ?
00540       std::string gmstr;
00541       gmxml.GetDoc(gmstr);
00542       // Candidate for common function ?
00543       for(int p = 0;p<gmstr.length();) {
00544         int l = write(h,gmstr.c_str()+p,gmstr.length()-p);
00545         if(l == -1) throw Glib::FileError(Glib::FileError::IO_ERROR,""); // TODO: process error
00546         p+=l;
00547       };
00548       close(h);
00549       gmconfig_temporary_=true;
00550       nordugrid_config_loc(gmconfig_);
00551     } catch(Glib::FileError& e) {
00552       logger_.msg(Arc::ERROR, "Failed to store configuration into temporary file: %s",e.what());
00553       if(!gmconfig_.empty()) {
00554         ::unlink(gmconfig_.c_str());
00555         gmconfig_.resize(0);
00556       };
00557       return; // GM configuration file is required
00558     };
00559   } else {
00560     // External configuration file
00561     nordugrid_config_loc(gmconfig_);
00562     if(!configure_users_dirs(users)) {
00563       logger_.msg(Arc::ERROR, "Failed to process configuration in %s",gmconfig_);
00564     }
00565     // create control and session directories if not yet done
00566     for(JobUsers::iterator user = users.begin();user != users.end();++user) {
00567       if(!user->CreateDirectories()) {
00568         logger_.msg(Arc::ERROR, "Failed to create control (%s) or session (%s) directories",user->ControlDir(),user->SessionRoot());
00569       };
00570     };
00571   };
00572   std::string gmrun_ = (std::string)((*cfg)["gmrun"]);
00573   common_name_ = (std::string)((*cfg)["commonName"]);
00574   long_description_ = (std::string)((*cfg)["longDescription"]);
00575   lrms_name_ = (std::string)((*cfg)["LRMSName"]);
00576   os_name_ = (std::string)((*cfg)["OperatingSystem"]);
00577   int valuei;
00578   if ((!(*cfg)["InfoproviderWakeupPeriod"]) ||
00579       (!Arc::stringto((std::string)((*cfg)["InfoproviderWakeupPeriod"]),infoprovider_wakeup_period_))) {
00580     infoprovider_wakeup_period_ = DEFAULT_INFOPROVIDER_WAKEUP_PERIOD;
00581   };
00582   if ((!(*cfg)["InfosysInterfaceMaxClients"]) ||
00583       (!Arc::stringto((std::string)((*cfg)["InfosysInterfaceMaxClients"]),valuei))) {
00584     valuei = DEFAULT_INFOSYS_MAX_CLIENTS;
00585   };
00586   infolimit_.MaxConsumers(valuei);
00587   if ((!(*cfg)["JobControlInterfaceMaxClients"]) ||
00588       (!Arc::stringto((std::string)((*cfg)["JobControlInterfaceMaxClients"]),valuei))) {
00589     valuei = DEFAULT_JOBCONTROL_MAX_CLIENTS;
00590   };
00591   beslimit_.MaxConsumers(valuei);
00592   if ((!(*cfg)["DataTransferInterfaceMaxClients"]) ||
00593       (!Arc::stringto((std::string)((*cfg)["DataTransferInterfaceMaxClients"]),valuei))) {
00594     valuei = DEFAULT_DATATRANSFER_MAX_CLIENTS;
00595   };
00596   datalimit_.MaxConsumers(valuei);
00597 
00598   // Run grid-manager in thread
00599   if((gmrun_.empty()) || (gmrun_ == "internal")) {
00600     gm_=new GridManager(gmconfig_.empty()?NULL:gmconfig_.c_str());
00601     if(!(*gm_)) { delete gm_; gm_=NULL; return; };
00602   };
00603   CreateThreadFunction(&information_collector_starter,this);
00604   valid_=true;
00605 }
00606 
00607 ARexService::~ARexService(void) {
00608   thread_count_.RequestCancel();
00609   if(gm_) delete gm_;
00610   if(gmconfig_temporary_) {
00611     if(!gmconfig_.empty()) unlink(gmconfig_.c_str());
00612   };
00613   thread_count_.WaitForExit();
00614 }
00615 
00616 } // namespace ARex
00617 
00618 Arc::PluginDescriptor PLUGINS_TABLE_NAME[] = {
00619     { "a-rex", "HED:SERVICE", 0, &ARex::get_service },
00620     { NULL, NULL, 0, NULL }
00621 };
00622