XrdCpWorkLst.cc

Go to the documentation of this file.
00001 //////////////////////////////////////////////////////////////////////////
00002 //                                                                      //
00003 // XrdCpWorkLst                                                         //
00004 //                                                                      //
00005 // Author: Fabrizio Furano (INFN Padova, 2004)                          //
00006 //                                                                      //
00007 // A class implementing a list of cps to do for XrdCp                   //
00008 //                                                                      //
00009 //////////////////////////////////////////////////////////////////////////
00010 
00011 //   $Id: XrdCpWorkLst.cc 30949 2009-11-02 16:37:58Z ganis $
00012 
00013 const char *XrdCpWorkLstCVSID = "$Id: XrdCpWorkLst.cc 30949 2009-11-02 16:37:58Z ganis $";
00014 
00015 #include "XrdClient/XrdCpWorkLst.hh"
00016 #include "XrdOuc/XrdOucErrInfo.hh"
00017 #include "XrdSys/XrdSysDir.hh"
00018 #include "XrdSys/XrdSysHeaders.hh"
00019 #include <sys/stat.h>
00020 #include <errno.h>
00021 #ifndef WIN32
00022 #include <unistd.h>
00023 #else
00024 #include "XrdSys/XrdWin32.hh"
00025 #endif
00026 
00027 using namespace std;
00028 
00029 // To print out the last server error info
00030 //____________________________________________________________________________
00031 void PrintLastServerError(XrdClient *cli) {
00032   struct ServerResponseBody_Error *e;
00033 
00034   if ( cli && (e = cli->LastServerError()) )
00035     cerr << "Last server error " << e->errnum << " ('" << e->errmsg << "')" <<
00036       endl;
00037 
00038 }
00039 
00040 
00041 
00042 bool PedanticOpen4Write(XrdClient *cli, kXR_unt16 mode, kXR_unt16 options) {
00043    // To be really pedantic we must disable the parallel open
00044    bool paropen = !(options & kXR_delete);
00045 
00046    if (!cli) return false;
00047 
00048    if ( !cli->Open(mode, options, paropen) ) {
00049 
00050       if ( (cli->LastServerError()->errnum == kXR_NotFound)
00051            && (options & kXR_delete) ) {
00052          // We silently try to remove the dest file, ignoring the result
00053          XrdClientAdmin adm(cli->GetCurrentUrl().GetUrl().c_str());
00054          if (adm.Connect()) {
00055             adm.Rm( cli->GetCurrentUrl().File.c_str() );
00056          }
00057 
00058          // And then we try again
00059          if ( !cli->Open(mode, options, paropen) )
00060             return false;
00061 
00062       }
00063       else return false;
00064    }
00065 
00066    return true;
00067 }
00068 
00069 
00070 
00071 
00072 XrdCpWorkLst::XrdCpWorkLst() {
00073    fWorkList.Clear();
00074    xrda_src = 0;
00075    xrda_dst = 0;
00076 }
00077 
00078 XrdCpWorkLst::~XrdCpWorkLst() {
00079    fWorkList.Clear();
00080 }
00081 
00082 // Sets the source path for the file copy
00083 // i.e. expand the given url to the list of the files it involves
00084 int XrdCpWorkLst::SetSrc(XrdClient **srccli, XrdOucString url,
00085               XrdOucString urlopaquedata, bool do_recurse) {
00086 
00087    XrdOucString fullurl(url);
00088 
00089    if (urlopaquedata.length())
00090       fullurl = url + "?" + urlopaquedata;
00091 
00092    fSrcIsDir = FALSE;
00093 
00094    if (fullurl.beginswith("root://") || fullurl.beginswith("xroot://") ) {
00095       // It's an xrd url
00096 
00097       fSrc = url;
00098 
00099       // We must see if it's a dir
00100       if (!*srccli)
00101          (*srccli) = new XrdClient(fullurl.c_str());
00102 
00103       if ((*srccli)->Open(0, kXR_async) &&
00104           ((*srccli)->LastServerResp()->status == kXR_ok)) {
00105          // If the file has been succesfully opened, we use this url
00106          fWorkList.Push_back(fSrc);
00107       }
00108       else 
00109          if ( do_recurse && 
00110               ((*srccli)->LastServerError()->errnum == kXR_isDirectory) ){
00111 
00112 
00113             delete (*srccli);
00114             *srccli = 0;
00115 
00116             // So, it's a dir for sure
00117             // Let's process it recursively
00118 
00119             fSrcIsDir = TRUE;
00120 
00121             xrda_src = new XrdClientAdmin(fullurl.c_str());
00122 
00123             if (xrda_src->Connect()) {
00124 
00125                BuildWorkList_xrd(fSrc, urlopaquedata);
00126             }
00127 
00128             delete xrda_src;
00129             xrda_src = 0;    
00130 
00131          }
00132          else {
00133             // It was not opened, nor it was a dir.
00134             PrintLastServerError(*srccli);
00135             return 1;
00136             //fWorkList.Push_back(fSrc);
00137          }
00138 
00139  
00140 
00141 
00142    }
00143    else {
00144       // It's a local file or path
00145       fSrc = url;
00146       fSrcIsDir = FALSE;
00147 
00148       // We must see if it's a dir
00149       XrdSysDir d(url.c_str());
00150       if (!d.isValid()) {
00151          if (d.lastError() == ENOTDIR)
00152             fWorkList.Push_back(fSrc);
00153          else
00154             return d.lastError();
00155       } else {
00156          fSrcIsDir = TRUE;
00157          BuildWorkList_loc(&d, url);
00158       }
00159    }
00160 
00161    fWorkIt = 0;
00162    return 0;
00163 }
00164 
00165 // Sets the destination of the file copy
00166 // i.e. decides if it's a directory or file name
00167 // It will delete and set to 0 xrddest if it's not a file
00168 int XrdCpWorkLst::SetDest(XrdClient **xrddest, const char *url,
00169                const char *urlopaquedata,
00170                kXR_unt16 xrdopenflags) {
00171    int retval = 0;
00172 
00173    // Special case: if url terminates with "/" then it's a dir
00174    if (url[strlen(url)-1] == '/') {
00175       fDest = url;
00176       fDestIsDir = TRUE;
00177       return 0;
00178    }
00179 
00180    if ( (strstr(url, "root://") == url) ||
00181         (strstr(url, "xroot://") == url) ) {
00182       // It's an xrd url
00183 
00184       fDest = url;
00185 
00186       if (fSrcIsDir) {
00187          fDestIsDir = TRUE;
00188          // Make sure fDest ends with a '/' to avoid problems in 
00189          // path formation later on
00190          if (!fDest.endswith('/'))
00191             fDest += '/';
00192          return 0;
00193       }
00194       else {
00195 
00196          // The source is a single file
00197          fDestIsDir = FALSE;
00198          XrdOucString fullurl(url);
00199 
00200          if (urlopaquedata) {
00201             fullurl += "?";
00202             fullurl += urlopaquedata;
00203          }
00204 
00205          // let's see if url can be opened as a file (file-to-file copy)
00206          *xrddest = new XrdClient(fullurl.c_str());
00207 
00208          if ( PedanticOpen4Write(*xrddest, kXR_ur | kXR_uw | kXR_gw | kXR_gr | kXR_or,
00209                                  xrdopenflags) &&
00210               ((*xrddest)->LastServerResp()->status == kXR_ok) ) {
00211 
00212             return 0;
00213 
00214             //XrdClientUrlInfo u(url);
00215 
00216 //          // If a file open succeeded, then it's a file good for writing to!
00217 //          fDestIsDir = FALSE;
00218 
00219 //          // In any case we might have been assigned a destination data server
00220 //          // Better to take this into account instead of the former one
00221 //          if ((*xrddest)->GetCurrentUrl().IsValid()) {
00222 //             XrdClientUrlInfo uu;
00223 //             uu = (*xrddest)->GetCurrentUrl();
00224 //             u.Host = uu.Host;
00225 //             u.Port = uu.Port;
00226 //             fDest = u.GetUrl();
00227 //          }    
00228 
00229          } else {
00230 
00231             // The file open was not successful. Let's see why.
00232 
00233             if ((*xrddest)->LastServerError()->errnum == kXR_isDirectory) {
00234 
00235                // It may be only a dir
00236                fDestIsDir = TRUE;
00237 
00238                // Make sure fDest ends with a '/' to avoid problems in 
00239                // path formation later on
00240                if (!fDest.endswith('/'))
00241                   fDest += '/';
00242 
00243                // Anyway, it's ok
00244                retval = 0;
00245             }
00246             else {
00247                PrintLastServerError(*xrddest);
00248                retval = 1;
00249             }
00250             
00251             // If the file has not been opened for writing,
00252             // there is no need to keep this instance alive.
00253             delete *xrddest;
00254             *xrddest = 0;
00255             
00256             return retval;
00257          }
00258 
00259       }
00260 
00261    }
00262    else {
00263       // It's a local file or path
00264       
00265       if (strcmp(url, "-")) {
00266 
00267          fDestIsDir = TRUE;
00268          // We must see if it's a dir
00269          struct stat st;
00270          if (lstat(url, &st) == 0) {
00271             if (!S_ISDIR(st.st_mode))
00272                fDestIsDir = FALSE;
00273          } else {
00274             if (errno == ENOENT)
00275                fDestIsDir = FALSE;
00276             else
00277                return errno;
00278          }
00279          fDest = url;
00280          // Make sure fDest ends with a '/' to avoid problems in 
00281          // path formation later on
00282          if (fDestIsDir && !fDest.endswith('/'))
00283             fDest += '/';
00284          return 0;
00285       }
00286       else {
00287          // dest is stdout
00288          fDest = url;
00289          fDestIsDir = FALSE;
00290       }
00291 
00292    }
00293    
00294    fWorkIt = 0;
00295    return 0;
00296 }
00297 
00298 // Actually builds the worklist expanding the source of the files
00299 int XrdCpWorkLst::BuildWorkList_xrd(XrdOucString url, XrdOucString opaquedata) {
00300    vecString entries;
00301    int it;
00302    long id, flags, modtime;
00303    long long size;
00304    XrdOucString fullpath;
00305    XrdClientUrlInfo u(url);
00306 
00307    // Invoke the DirList cmd to get the content of the dir
00308    if (!xrda_src->DirList(u.File.c_str(), entries)) return -1;
00309 
00310    // Cycle on the content and spot all the files
00311    for (it = 0; it < entries.GetSize(); it++) {
00312       fullpath = url + "/" + entries[it];
00313 
00314       XrdClientUrlInfo u(fullpath);
00315 
00316       // We must see if it's a dir
00317       // If a dir is found, do it recursively
00318       if ( xrda_src->Stat((char *)u.File.c_str(), id, size, flags, modtime) &&
00319            (flags & kXR_isDir) ) {
00320 
00321          BuildWorkList_xrd(fullpath, opaquedata);
00322       }
00323       else
00324          fWorkList.Push_back(fullpath);
00325       
00326 
00327    }
00328 
00329    return 0;
00330 }
00331 
00332 
00333 int XrdCpWorkLst::BuildWorkList_loc(XrdSysDir *dir, XrdOucString path)
00334 {
00335 
00336    char *ent = 0;
00337    XrdOucString fullpath;
00338 
00339    // Here we already have an usable dir handle
00340    // Cycle on the content and spot all the files
00341    while (dir && (ent = dir->nextEntry())) {
00342 
00343       if (!strcmp(ent, ".") || !strcmp(ent, ".."))
00344          continue;
00345 
00346       // Assemble full path name.
00347       fullpath = path + "/" + ent;
00348 
00349       // Get info for the entry
00350       struct stat ftype;
00351       if ( lstat(fullpath.c_str(), &ftype) < 0 )
00352          continue;
00353 
00354       // If it's a dir, then proceed recursively
00355       if (S_ISDIR(ftype.st_mode)) {
00356          XrdSysDir d(fullpath.c_str());
00357 
00358          if (d.isValid())
00359             BuildWorkList_loc(&d, fullpath);
00360       } else
00361          // If it's a file, then add it to the worklist
00362          if (S_ISREG(ftype.st_mode))
00363             fWorkList.Push_back(fullpath);
00364    }
00365 
00366    return 0;
00367 }
00368 
00369 
00370 // Get the next cp job to do
00371 bool XrdCpWorkLst::GetCpJob(XrdOucString &src, XrdOucString &dest) {
00372 
00373    if (fWorkIt >= fWorkList.GetSize()) return FALSE;
00374 
00375    src = fWorkList[fWorkIt];
00376    dest = fDest;
00377 
00378    if (fDestIsDir) {
00379 
00380       // If the dest is a directory name, we must concatenate
00381       // the actual filename, i.e. the token in src following the last /
00382       int slpos = src.rfind('/');
00383 
00384       if (slpos != STR_NPOS)
00385          dest += XrdOucString(src, slpos);
00386    }
00387 
00388    fWorkIt++;
00389 
00390    return TRUE;
00391 }
00392 

Generated on Tue Jul 5 14:46:22 2011 for ROOT_528-00b_version by  doxygen 1.5.1