Back to index

nordugrid-arc-nox  1.1.0~rc6
get.cpp
Go to the documentation of this file.
00001 #ifdef HAVE_CONFIG_H
00002 #include <config.h>
00003 #endif
00004 
00005 #include <sys/types.h>
00006 #include <sys/stat.h>
00007 #include <unistd.h>
00008 #include <fcntl.h>
00009 
00010 #include <string>
00011 
00012 #include <glibmm.h>
00013 
00014 #include <arc/StringConv.h>
00015 #include <arc/message/PayloadRaw.h>
00016 #include "PayloadFile.h"
00017 #include "job.h"
00018 
00019 #include "arex.h"
00020 
00021 #define MAX_CHUNK_SIZE (10*1024*1024)
00022 
00023 namespace ARex {
00024 
00025 static Arc::MCC_Status http_get(Arc::Message& outmsg,const std::string& burl,ARexJob& job,std::string hpath,size_t start,size_t end);
00026 
00027 Arc::MCC_Status ARexService::Get(Arc::Message& inmsg,Arc::Message& outmsg,ARexGMConfig& config,const std::string& id,const std::string& subpath) {
00028   size_t range_start = 0;
00029   size_t range_end = (size_t)(-1);
00030   {
00031     std::string val;
00032     val=inmsg.Attributes()->get("HTTP:RANGESTART");
00033     if(!val.empty()) { // Negative ranges not supported
00034       if(!Arc::stringto<size_t>(val,range_start)) {
00035         range_start=0;
00036       } else {
00037         val=inmsg.Attributes()->get("HTTP:RANGEEND");
00038         if(!val.empty()) {
00039           if(!Arc::stringto<size_t>(val,range_end)) {
00040             range_end=(size_t)(-1);
00041           };
00042         };
00043       };
00044     };
00045   };
00046   if(id.empty()) {
00047     // Make list of jobs
00048     std::string html;
00049     html="<HTML>\r\n<HEAD>\r\n<TITLE>ARex: Jobs list</TITLE>\r\n</HEAD>\r\n<BODY>\r\n<UL>\r\n";
00050     std::list<std::string> jobs = ARexJob::Jobs(config,logger_);
00051     for(std::list<std::string>::iterator job = jobs.begin();job!=jobs.end();++job) {
00052       std::string line = "<LI><I>job</I> <A HREF=\"";
00053       line+=config.Endpoint()+"/"+(*job);
00054       line+="\">";
00055       line+=(*job);
00056       line+="</A>\r\n";
00057       html+=line;
00058     };
00059     html+="</UL>\r\n";
00060     // Service description access
00061     html+="<A HREF=\""+config.Endpoint()+"/?info>SERVICE DESCRIPTION</A>";
00062     html+="</BODY>\r\n</HTML>";
00063     Arc::PayloadRaw* buf = NULL;
00064     buf=new Arc::PayloadRaw;
00065     if(buf) buf->Insert(html.c_str(),0,html.length());
00066     outmsg.Payload(buf);
00067     outmsg.Attributes()->set("HTTP:content-type","text/html");
00068     return Arc::MCC_Status(Arc::STATUS_OK);
00069   };
00070   if(id == "?info") {
00071     int h = infodoc_.OpenDocument();
00072     if(h == -1) return Arc::MCC_Status();
00073     Arc::MessagePayload* payload = newFileRead(h);
00074     if(!payload) {
00075       ::close(h);
00076       return Arc::MCC_Status();
00077     };
00078     outmsg.Payload(payload);
00079     outmsg.Attributes()->set("HTTP:content-type","text/xml");
00080     return Arc::MCC_Status(Arc::STATUS_OK);
00081   };
00082   ARexJob job(id,config,logger_);
00083   if(!job) {
00084     // There is no such job
00085     logger_.msg(Arc::ERROR, "Get: there is no job %s - %s", id, job.Failure());
00086     // TODO: make proper html message
00087     return Arc::MCC_Status();
00088   };
00089   if(!http_get(outmsg,config.Endpoint()+"/"+id,job,subpath,range_start,range_end)) {
00090     // Can't get file
00091     logger.msg(Arc::ERROR, "Get: can't process file %s", subpath);
00092     // TODO: make proper html message
00093     return Arc::MCC_Status();
00094   };
00095   return Arc::MCC_Status(Arc::STATUS_OK);
00096 } 
00097 
00098 // burl - base URL
00099 // bpath - base path
00100 // hpath - path relative to base path and base URL
00101 // start - chunk start
00102 // start - chunk end
00103 static Arc::MCC_Status http_get(Arc::Message& outmsg,const std::string& burl,ARexJob& job,std::string hpath,size_t start,size_t end) {
00104 Arc::Logger::rootLogger.msg(Arc::VERBOSE, "http_get: start=%u, end=%u, burl=%s, hpath=%s", (unsigned int)start, (unsigned int)end, burl, hpath);
00105   if(!hpath.empty()) if(hpath[0] == '/') hpath=hpath.substr(1);
00106   if(!hpath.empty()) if(hpath[hpath.length()-1] == '/') hpath.resize(hpath.length()-1);
00107   std::string joblog = job.LogDir();
00108   if(!joblog.empty()) {
00109     if((strncmp(joblog.c_str(),hpath.c_str(),joblog.length()) == 0)  && 
00110        ((hpath[joblog.length()] == '/') || (hpath[joblog.length()] == 0))) {
00111       hpath.erase(0,joblog.length()+1);
00112       if(hpath.empty()) {
00113         std::list<std::string> logs = job.LogFiles();
00114         std::string html;
00115         html="<HTML>\r\n<HEAD>\r\n<TITLE>ARex: Job Logs</TITLE>\r\n</HEAD>\r\n<BODY>\r\n<UL>\r\n";
00116         for(std::list<std::string>::iterator l = logs.begin();l != logs.end();++l) {
00117           if(strncmp(l->c_str(),"proxy",5) == 0) continue;
00118           std::string line = "<LI><I>file</I> <A HREF=\"";
00119           line+=burl+"/"+joblog+"/"+(*l);
00120           line+="\">";
00121           line+=*l;
00122           line+="</A> - log file\r\n";
00123           html+=line;
00124         };
00125         html+="</UL>\r\n</BODY>\r\n</HTML>";
00126         Arc::PayloadRaw* buf = new Arc::PayloadRaw;
00127         if(buf) buf->Insert(html.c_str(),0,html.length());
00128         outmsg.Payload(buf);
00129         outmsg.Attributes()->set("HTTP:content-type","text/html");
00130         return Arc::MCC_Status(Arc::STATUS_OK);
00131       } else {
00132         int file = job.OpenLogFile(hpath);
00133         if(file != -1) {
00134           Arc::MessagePayload* h = newFileRead(file,start,end);
00135           outmsg.Payload(h);
00136           outmsg.Attributes()->set("HTTP:content-type","application/octet-stream");
00137           return Arc::MCC_Status(Arc::STATUS_OK);
00138         };
00139         return Arc::MCC_Status();
00140       };
00141     };
00142   };
00143   Glib::Dir* dir = job.OpenDir(hpath);
00144   if(dir) {
00145     // Directory - html with file list
00146     std::string file;
00147     std::string html;
00148     html="<HTML>\r\n<HEAD>\r\n<TITLE>ARex: Job</TITLE>\r\n</HEAD>\r\n<BODY>\r\n<UL>\r\n";
00149     std::string furl = burl;
00150     if(!hpath.empty()) furl+="/"+hpath;
00151     std::string path = job.GetFilePath(hpath);
00152     for(;;) {
00153       file=dir->read_name();
00154       if(file.empty()) break;
00155       if(file == ".") continue;
00156       if(file == "..") continue;
00157       std::string fpath = path+"/"+file;
00158       struct stat st;
00159       if(lstat(fpath.c_str(),&st) == 0) {
00160         if(S_ISREG(st.st_mode)) {
00161           std::string line = "<LI><I>file</I> <A HREF=\"";
00162           line+=furl+"/"+file;
00163           line+="\">";
00164           line+=file;
00165           line+="</A> - "+Arc::tostring(st.st_size)+" bytes"+"\r\n";
00166           html+=line;
00167         } else if(S_ISDIR(st.st_mode)) {
00168           std::string line = "<LI><I>dir</I> <A HREF=\"";
00169           line+=furl+"/"+file+"/";
00170           line+="\">";
00171           line+=file;
00172           line+="</A>\r\n";
00173           html+=line;
00174         };
00175       } else {
00176         std::string line = "<LI><I>unknown</I> <A HREF=\"";
00177         line+=furl+"/"+file;
00178         line+="\">";
00179         line+=file;
00180         line+="</A>\r\n";
00181         html+=line;
00182       };
00183     };
00184     if((hpath.empty()) && (!joblog.empty())) {
00185       std::string line = "<LI><I>dir</I> <A HREF=\"";
00186       line+=furl+"/"+joblog;
00187       line+="\">";
00188       line+=joblog;
00189       line+="</A> - log directory\r\n";
00190       html+=line;
00191     };
00192     html+="</UL>\r\n</BODY>\r\n</HTML>";
00193     Arc::PayloadRaw* buf = new Arc::PayloadRaw;
00194     if(buf) buf->Insert(html.c_str(),0,html.length());
00195     outmsg.Payload(buf);
00196     outmsg.Attributes()->set("HTTP:content-type","text/html");
00197     delete dir;
00198     return Arc::MCC_Status(Arc::STATUS_OK);
00199   };
00200   int file = job.OpenFile(hpath,true,false);
00201   if(file != -1) {
00202     // File 
00203     Arc::MessagePayload* h = newFileRead(file,start,end);
00204     outmsg.Payload(h);
00205     outmsg.Attributes()->set("HTTP:content-type","application/octet-stream");
00206     return Arc::MCC_Status(Arc::STATUS_OK);
00207   };
00208   // Can't process this path
00209   // offset=0; size=0;
00210   return Arc::MCC_Status();
00211 }
00212 
00213 } // namespace ARex
00214