45using namespace std::string_literals;
57 pPrintSourceCheckSum(false), pPrintTargetCheckSum(false),
58 pPrintAdditionalCheckSum(false)
70 if( pPrintProgressBar )
74 std::cerr <<
"Job: " << jobNum <<
"/" << jobTotal << std::endl;
75 std::cerr <<
"Source: " << source->
GetURL() << std::endl;
76 std::cerr <<
"Target: " << destination->
GetURL() << std::endl;
84 d.target = destination;
85 pOngoingJobs[jobNum] = d;
95 std::map<uint32_t, JobData>::iterator it = pOngoingJobs.find( jobNum );
96 if( it == pOngoingJobs.end() )
99 JobData &d = it->second;
104 JobProgress( jobNum, d.bytesProcessed, d.bytesTotal );
106 if( pPrintProgressBar )
108 if( pOngoingJobs.size() > 1 )
109 std::cerr <<
"\r" << std::string(70,
' ') <<
"\r";
111 std::cerr << std::endl;
115 results->
Get(
"status", st );
118 pOngoingJobs.erase(it);
122 std::string checkSum;
124 results->
Get(
"size", size );
125 if( pPrintSourceCheckSum )
127 results->
Get(
"sourceCheckSum", checkSum );
131 if( pPrintTargetCheckSum )
133 results->
Get(
"targetCheckSum", checkSum );
137 if( pPrintAdditionalCheckSum )
139 std::vector<std::string> addcksums;
140 results->
Get(
"additionalCkeckSum", addcksums );
141 for(
auto &cks : addcksums )
145 pOngoingJobs.erase(it);
153 JobData &d = pOngoingJobs.begin()->second;
157 speed = d.bytesProcessed/(now-d.started);
159 speed = d.bytesProcessed;
167 prog = (int)((
double)d.bytesProcessed/d.bytesTotal*50);
168 proc = (int)((
double)d.bytesProcessed/d.bytesTotal*100);
175 bar.append( prog,
'=' );
179 std::ostringstream o;
182 o <<
"[" << std::setw(3) << std::right << proc <<
"%]";
183 o <<
"[" << std::setw(50) << std::left;
195 std::map<uint32_t, JobData>::iterator it;
196 std::ostringstream o;
198 for( it = pOngoingJobs.begin(); it != pOngoingJobs.end(); ++it )
200 JobData &d = it->second;
201 uint32_t jobNum = it->first;
205 speed = d.bytesProcessed/(now-d.started);
209 proc = (int)((
double)d.bytesProcessed/d.bytesTotal*100);
213 o <<
"[#" << jobNum <<
": ";
225 uint64_t bytesProcessed,
226 uint64_t bytesTotal )
230 if( pPrintProgressBar )
232 time_t now = time(0);
233 if( (now - pPrevious < 1) && (bytesProcessed != bytesTotal) )
237 std::map<uint32_t, JobData>::iterator it = pOngoingJobs.find( jobNum );
238 if( it == pOngoingJobs.end() )
241 JobData &d = it->second;
243 d.bytesProcessed = bytesProcessed;
244 d.bytesTotal = bytesTotal;
246 std::string progress;
247 if( pOngoingJobs.size() == 1 )
252 std::cerr <<
"\r" << progress << std::flush;
260 const std::string &checkSum,
263 if( checkSum.empty() )
265 std::string::size_type i = checkSum.find(
':' );
266 std::cerr << checkSum.substr( 0, i+1 ) <<
" ";
267 std::cerr << checkSum.substr( i+1, checkSum.length()-i ) <<
" ";
270 std::cerr << url->
GetPath() <<
" ";
274 std::cerr << url->
GetPath() <<
" ";
278 std::cerr << std::endl;
292 JobData(): bytesProcessed(0), bytesTotal(0),
293 started(0), source(0), target(0) {}
294 uint64_t bytesProcessed;
297 const XrdCl::URL *source;
298 const XrdCl::URL *target;
302 bool pPrintProgressBar;
303 bool pPrintSourceCheckSum;
304 bool pPrintTargetCheckSum;
305 bool pPrintAdditionalCheckSum;
306 std::map<uint32_t, JobData> pOngoingJobs;
307 XrdSysRecMutex pMutex;
317 std::cerr <<
"SOCKS Proxies are not yet supported" << std::endl;
329 if( !newCGI || !(*newCGI) )
335 if( url.find(
'?' ) == std::string::npos )
338 if( url.find(
'&' ) == std::string::npos )
355 cursor = cursor->
Next;
362 cursor = cursor->
Next;
380 default:
return "other";
390 for( count = 0; file; file = file->
Next, ++count ) {};
403 if( file->
Doff == 0 )
405 char *slash = file->
Path;
406 for( ; *slash; ++slash ) {};
407 for( ; *slash !=
'/' && slash > file->
Path; --slash ) {};
416 std::string basePath,
419 using namespace XrdCl;
422 log->
Debug(
AppMsg,
"Indexing %s", basePath.c_str() );
429 log->
Info(
AppMsg,
"Failed to get directory listing for %s: %s",
438 for(
auto itr = dirList->
Begin(); itr != dirList->
End(); ++itr )
443 std::string path = basePath +
'/' + e->
GetName();
444 current =
new XrdCpFile( path.c_str(), badUrl );
452 current->
Doff = dirOffset;
467 std::vector<XrdCl::PropertyList *>::iterator it;
468 for( it = results.begin(); it != results.end(); ++it )
475int main(
int argc,
char **argv )
477 using namespace XrdCl;
507 bool makedir =
false;
509 bool delegate =
false;
510 bool preserveXAttr =
false;
511 bool rmOnBadCksum =
false;
512 bool continue_ =
false;
513 bool recurse =
false;
514 bool zipappend =
false;
515 bool doserver =
false;
516 std::string thirdParty =
"none"s;
517 std::string thirdPartyMode =
"pull"s;
552 if( force && continue_ )
554 std::cerr <<
"Invalid argument combination: continue + force." << std::endl;
561 std::string checkSumType;
562 std::string checkSumPreset;
563 std::string checkSumMode =
"none";
566 checkSumMode =
"end2end";
567 std::vector<std::string> ckSumParams;
569 if( ckSumParams.size() > 1 )
571 if( ckSumParams[1] ==
"print" )
573 checkSumMode =
"target";
577 checkSumPreset = ckSumParams[1];
579 checkSumType = ckSumParams[0];
584 checkSumMode =
"source";
585 std::vector<std::string> ckSumParams;
587 if( ckSumParams.size() == 2 )
589 checkSumMode =
"source";
590 checkSumType = ckSumParams[0];
595 std::cerr <<
"Invalid parameter: " << config.
CksVal << std::endl;
621 nbSources = config.
nSrcs;
635 if( config.
nStrm != 0 )
636 env->
PutInt(
"SubStreamsPerChannel", config.
nStrm + 1 );
638 if( config.
Retry != -1 )
645 env->
PutInt(
"NoTlsOK", 1 );
648 env->
PutInt(
"TlsNoData", 1 );
651 env->
PutInt(
"TlsMetalink", 1 );
654 env->
PutInt(
"ZipMtlnCksum", 1 );
666 if( !headers.empty() ) headers +=
'\n';
669 env->
PutString(
"HttpHeaders", headers );
673 env->
GetInt(
"CPChunkSize", chunkSize );
676 env->
GetInt(
"XCpBlockSize", blockSize );
679 env->
GetInt(
"CPParallelChunks", parallelChunks );
680 if( parallelChunks < 1 ||
681 parallelChunks > std::numeric_limits<uint8_t>::max() )
683 std::cerr <<
"Can only handle between 1 and ";
684 std::cerr << (int)std::numeric_limits<uint8_t>::max();
685 std::cerr <<
" chunks in parallel. You asked for " << parallelChunks;
686 std::cerr <<
"." << std::endl;
693 env->
GetInt(
"PreserveXAttrs", val );
694 if( val ) preserveXAttr =
true;
697 log->
Dump(
AppMsg,
"Chunk size: %d, parallel chunks %d, streams: %d",
698 chunkSize, parallelChunks, config.
nStrm + 1 );
703 std::vector<XrdCl::PropertyList*> resultVect;
714 char buf[FILENAME_MAX];
715 char *cwd = getcwd( buf, FILENAME_MAX );
735 bool targetIsDir =
false;
736 bool targetExists =
false;
743 FileSystem fs( target );
761 std::cerr << st.
ToStr() << std::endl;
768 if( !targetIsDir && targetExists && !force && !recurse && !zipappend )
773 std::cerr <<
"Run: " << st.
ToStr() << std::endl;
784 std::cerr <<
"Multiple sources were given but target is not a directory.";
785 std::cerr << std::endl;
793 bool remoteSrcIsDir =
false;
799 FileSystem *fs =
new FileSystem( source );
805 remoteSrcIsDir =
true;
810 std::string url = source.
GetURL();
814 std::cerr <<
"Error indexing remote directory.";
836 std::string source = sourceFile->
Path;
840 if( source[0] ==
'/' )
841 source =
"file://" + source;
844 char buf[FILENAME_MAX];
845 char *cwd = getcwd( buf, FILENAME_MAX );
852 source =
"file://" + std::string( cwd ) +
'/' + source;
858 std::string sourcePathObf = sourceFile->
Path;
859 std::string destPathObf = dest;
864 log->
Dump(
AppMsg,
"Processing source entry: %s, type %s, target file: %s, logLevel = %d",
866 destPathObf.c_str(), log->
GetLevel() );
871 std::string target = dest;
874 bool srcIsDir =
false;
876 if( strncmp( sourceFile->
ProtName,
"file", 4 ) == 0 )
877 srcIsDir = std::string( sourceFile->
Path ).size() == size_t( sourceFile->
Doff + sourceFile->
Dlen );
880 srcIsDir = remoteSrcIsDir;
885 std::string srcDir( sourceFile->
Path, sourceFile->
Doff );
887 if( srcDir[srcDir.size() - 1] ==
'/' )
888 srcDir = srcDir.substr( 0, srcDir.size() - 1 );
889 size_t diroff = srcDir.rfind(
'/' );
891 if( diroff == std::string::npos ) diroff = 0;
893 target += sourceFile->
Path + diroff;
895 target = target.substr( 0 , target.rfind(
'/') );
899 properties.
Set(
"source", source );
900 properties.
Set(
"target", target );
901 properties.
Set(
"force", force );
902 properties.
Set(
"posc", posc );
903 properties.
Set(
"coerce", coerce );
904 properties.
Set(
"makeDir", makedir );
905 properties.
Set(
"dynamicSource", dynSrc );
906 properties.
Set(
"thirdParty", thirdParty );
907 properties.
Set(
"thirdPartyMode", thirdPartyMode );
908 properties.
Set(
"checkSumMode", checkSumMode );
909 properties.
Set(
"checkSumType", checkSumType );
910 properties.
Set(
"checkSumPreset", checkSumPreset );
911 properties.
Set(
"chunkSize", chunkSize );
912 properties.
Set(
"parallelChunks", parallelChunks );
913 properties.
Set(
"zipArchive", zip );
914 properties.
Set(
"xcp", xcp );
915 properties.
Set(
"xcpBlockSize", blockSize );
916 properties.
Set(
"delegate", delegate );
917 properties.
Set(
"targetIsDir", targetIsDir );
918 properties.
Set(
"preserveXAttr", preserveXAttr );
919 properties.
Set(
"xrate", config.
xRate );
921 properties.
Set(
"rmOnBadCksum", rmOnBadCksum );
922 properties.
Set(
"continue", continue_ );
923 properties.
Set(
"zipAppend", zipappend );
925 properties.
Set(
"doServer", doserver );
928 properties.
Set(
"zipSource", zipFile );
931 properties.
Set(
"nbXcpSources", nbSources );
933 if( !thirdPartyTokenFile.empty() )
934 properties.
Set(
"thirdPartyTokenFile", thirdPartyTokenFile );
939 std::cerr <<
"AddJob " << source <<
" -> " << target <<
": ";
940 std::cerr << st.
ToStr() << std::endl;
942 resultVect.push_back( results );
943 sourceFile = sourceFile->
Next;
950 processConfig.
Set(
"jobType",
"configuration" );
952 process.
AddJob( processConfig, 0 );
961 std::cerr <<
"Prepare: " << st.
ToStr() << std::endl;
965 st = process.
Run( &progress );
968 if( resultVect.size() == 1 )
969 std::cerr <<
"Run: " << st.
ToStr() << std::endl;
972 std::vector<XrdCl::PropertyList*>::iterator it;
974 uint32_t jobsRun = 0;
976 for( it = resultVect.begin(); it != resultVect.end(); ++it, ++i )
978 if( !(*it)->HasProperty(
"status" ) )
984 std::cerr <<
"Job #" << i <<
": " << st.
ToStr();
989 std::cerr <<
"Jobs total: " << resultVect.size();
990 std::cerr <<
", run: " << jobsRun;
991 std::cerr <<
", errors: " << errors << std::endl;
bool AllOptionsSupported(XrdCpConfig *config)
const char * FileType2String(XrdCpFile::PType type)
void ProcessCommandLineEnv(XrdCpConfig *config)
void CleanUpResults(std::vector< XrdCl::PropertyList * > &results)
XrdCpFile * IndexRemote(XrdCl::FileSystem *fs, std::string basePath, long dirOffset)
void AdjustFileInfo(XrdCpFile *file)
uint32_t CountSources(XrdCpFile *file)
void AppendCGI(std::string &url, const char *newCGI)
int main(int argc, char *argv[])
std::string obfuscateAuth(const std::string &input)
void PrintAdditionalCheckSum(bool print)
void PrintSourceCheckSum(bool print)
void PrintProgressBar(bool print)
void PrintCheckSum(const XrdCl::URL *url, const std::string &checkSum, uint64_t size)
Print the checksum.
virtual void BeginJob(uint32_t jobNum, uint32_t jobTotal, const XrdCl::URL *source, const XrdCl::URL *destination)
Begin job.
std::string GetProgressBar(time_t now)
Get progress bar.
std::string GetSummaryBar(time_t now)
Get sumary bar.
ProgressDisplay()
Constructor.
virtual void EndJob(uint32_t jobNum, const XrdCl::PropertyList *results)
End job.
void PrintTargetCheckSum(bool print)
virtual void JobProgress(uint32_t jobNum, uint64_t bytesProcessed, uint64_t bytesTotal)
Job progress.
static int mapError(int rc)
Copy the data from one point to another.
XRootDStatus Run(CopyProgressHandler *handler)
Run the copy jobs.
XRootDStatus AddJob(const PropertyList &properties, PropertyList *results)
Interface for copy progress notification.
static Log * GetLog()
Get default log.
static PostMaster * GetPostMaster()
Get default post master.
static Env * GetEnv()
Get default client environment.
const std::string & GetName() const
Get file name.
StatInfo * GetStatInfo()
Get the stat info object.
Iterator End()
Get the end iterator.
Iterator Begin()
Get the begin iterator.
static DlgEnv & Instance()
bool PutInt(const std::string &key, int value)
bool PutString(const std::string &key, const std::string &value)
bool GetInt(const std::string &key, int &value)
Send file/filesystem queries to an XRootD cluster.
XRootDStatus DirList(const std::string &path, DirListFlags::Flags flags, ResponseHandler *handler, time_t timeout=0) XRD_WARN_UNUSED_RESULT
@ DebugMsg
print debug info
@ DumpMsg
print details of the request and responses
void SetLevel(LogLevel level)
Set the level of the messages that should be sent to the destination.
void Error(uint64_t topic, const char *format,...)
Report an error.
LogLevel GetLevel() const
Get the log level.
void Dump(uint64_t topic, const char *format,...)
Print a dump message.
void Info(uint64_t topic, const char *format,...)
Print an info.
void Debug(uint64_t topic, const char *format,...)
Print a debug message.
bool Stop()
Stop the postmaster.
A key-value pair map storing both keys and values as strings.
void Set(const std::string &name, const Item &value)
bool Get(const std::string &name, Item &item) const
bool TestFlags(uint32_t flags) const
Test flags.
@ IsDir
This is a directory.
const std::string & GetPath() const
Get the path.
std::string GetHostId() const
Get the host part of the URL (user:password@host:port).
std::string GetPathWithParams() const
Get the path with params.
std::string GetURL() const
Get the URL.
const std::string & GetProtocol() const
Get the protocol.
static void splitString(Container &result, const std::string &input, const std::string &delimiter)
Split a string.
static std::string BytesToString(uint64_t bytes)
Convert bytes to a human readable string.
const std::string & GetErrorMessage() const
Get error message.
std::string ToStr() const
Convert to string.
void Config(int argc, char **argv, int Opts=0)
std::vector< std::string > AddCksVal
static const uint64_t DoZipMtlnCksum
static const uint64_t DoNoPbar
static const uint64_t DoCoerce
static const uint64_t DoForce
static const uint64_t DoRmOnBadCksum
static const uint64_t DoNoTlsOK
static const uint64_t DoTpc
std::vector< std::string > HttpHeaders
static const uint64_t DoCksum
static const uint64_t DoCksrc
static const uint64_t DoTpcModePush
static const uint64_t DoTpcDlgt
static const uint64_t DoZip
static const uint64_t DoContinue
static const uint64_t DoRecurse
static const uint64_t DoZipAppend
static const uint64_t DoDynaSrc
static const uint64_t DoSources
static const uint64_t DoXAttr
static const uint64_t DoTlsMLF
static const int optRmtRec
static const uint64_t DoPath
static const uint64_t DoPosc
static const uint64_t DoTpcOnly
static const uint64_t DoTlsNoData
static const uint64_t DoServer
const int DefaultCPChunkSize
const uint16_t stError
An error occurred that could potentially be retried.
const uint16_t errInvalidOp
const int DefaultCPParallelChunks
const int DefaultXCpBlockSize
const int DefaultPreserveXAttrs
@ Recursive
Do a recursive listing.
bool IsOK() const
We're fine.
std::string ToString() const
Create a string representation.
uint32_t errNo
Errno, if any.
int GetShellCode() const
Get the status code that may be returned to the shell.