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::string type = checkSum.substr( 0, i );
267 std::string value = checkSum.substr( i+1, checkSum.length()-i );
274 if( ( type ==
"adler32" || type ==
"crc32" ) && value.length() < 8 )
275 value.insert( 0, 8 - value.length(),
'0' );
277 std::cerr << type <<
": " << value <<
" ";
280 std::cerr << url->
GetPath() <<
" ";
284 std::cerr << url->
GetPath() <<
" ";
288 std::cerr << std::endl;
302 JobData(): bytesProcessed(0), bytesTotal(0),
303 started(0), source(0), target(0) {}
304 uint64_t bytesProcessed;
307 const XrdCl::URL *source;
308 const XrdCl::URL *target;
312 bool pPrintProgressBar;
313 bool pPrintSourceCheckSum;
314 bool pPrintTargetCheckSum;
315 bool pPrintAdditionalCheckSum;
316 std::map<uint32_t, JobData> pOngoingJobs;
317 XrdSysRecMutex pMutex;
327 std::cerr <<
"SOCKS Proxies are not yet supported" << std::endl;
339 if( !newCGI || !(*newCGI) )
345 if( url.find(
'?' ) == std::string::npos )
348 if( url.find(
'&' ) == std::string::npos )
365 cursor = cursor->
Next;
372 cursor = cursor->
Next;
390 default:
return "other";
400 for( count = 0; file; file = file->
Next, ++count ) {};
413 if( file->
Doff == 0 )
415 char *slash = file->
Path;
416 for( ; *slash; ++slash ) {};
417 for( ; *slash !=
'/' && slash > file->
Path; --slash ) {};
426 std::string basePath,
429 using namespace XrdCl;
432 log->
Debug(
AppMsg,
"Indexing %s", basePath.c_str() );
439 log->
Info(
AppMsg,
"Failed to get directory listing for %s: %s",
448 for(
auto itr = dirList->
Begin(); itr != dirList->
End(); ++itr )
453 std::string path = basePath +
'/' + e->
GetName();
454 current =
new XrdCpFile( path.c_str(), badUrl );
462 current->
Doff = dirOffset;
477 std::vector<XrdCl::PropertyList *>::iterator it;
478 for( it = results.begin(); it != results.end(); ++it )
485int main(
int argc,
char **argv )
487 using namespace XrdCl;
517 bool makedir =
false;
519 bool delegate =
false;
520 bool preserveXAttr =
false;
521 bool rmOnBadCksum =
false;
522 bool continue_ =
false;
523 bool zipappend =
false;
524 bool doserver =
false;
525 std::string thirdParty =
"none"s;
526 std::string thirdPartyMode =
"pull"s;
557 if( force && continue_ )
559 std::cerr <<
"Invalid argument combination: continue + force." << std::endl;
566 std::string checkSumType;
567 std::string checkSumPreset;
568 std::string checkSumMode =
"none";
571 checkSumMode =
"end2end";
572 std::vector<std::string> ckSumParams;
574 if( ckSumParams.size() > 1 )
576 if( ckSumParams[1] ==
"print" )
578 checkSumMode =
"target";
582 checkSumPreset = ckSumParams[1];
584 checkSumType = ckSumParams[0];
589 checkSumMode =
"source";
590 std::vector<std::string> ckSumParams;
592 if( ckSumParams.size() == 2 )
594 checkSumMode =
"source";
595 checkSumType = ckSumParams[0];
600 std::cerr <<
"Invalid parameter: " << config.
CksVal << std::endl;
626 nbSources = config.
nSrcs;
640 if( config.
nStrm != 0 )
641 env->
PutInt(
"SubStreamsPerChannel", config.
nStrm + 1 );
643 if( config.
Retry != -1 )
650 env->
PutInt(
"NoTlsOK", 1 );
653 env->
PutInt(
"TlsNoData", 1 );
656 env->
PutInt(
"TlsMetalink", 1 );
659 env->
PutInt(
"ZipMtlnCksum", 1 );
671 if( !headers.empty() ) headers +=
'\n';
674 env->
PutString(
"HttpHeaders", headers );
678 env->
GetInt(
"CPChunkSize", chunkSize );
681 env->
GetInt(
"XCpBlockSize", blockSize );
684 env->
GetInt(
"CPParallelChunks", parallelChunks );
685 if( parallelChunks < 1 ||
686 parallelChunks > std::numeric_limits<uint8_t>::max() )
688 std::cerr <<
"Can only handle between 1 and ";
689 std::cerr << (int)std::numeric_limits<uint8_t>::max();
690 std::cerr <<
" chunks in parallel. You asked for " << parallelChunks;
691 std::cerr <<
"." << std::endl;
698 env->
GetInt(
"PreserveXAttrs", val );
699 if( val ) preserveXAttr =
true;
702 log->
Dump(
AppMsg,
"Chunk size: %d, parallel chunks %d, streams: %d",
703 chunkSize, parallelChunks, config.
nStrm + 1 );
708 std::vector<XrdCl::PropertyList*> resultVect;
719 char buf[FILENAME_MAX];
720 char *cwd = getcwd( buf, FILENAME_MAX );
747 const std::string path = target.
GetPath();
749 targetIsDir = path.back() ==
'/';
753 const size_t query = spec.find(
'?' );
754 const size_t end = query == std::string::npos ? spec.size() : query;
755 targetIsDir = end > 0 && spec[end - 1] ==
'/';
765 if( strncmp( file->ProtName,
"file", 4 ) == 0 &&
766 std::string( file->Path ).size() ==
size_t( file->Doff + file->Dlen ) )
782 FileSystem fs( target );
790 std::cerr << st.
ToStr() << std::endl;
804 std::cerr <<
"Multiple sources were given but target is not a directory.";
805 std::cerr << std::endl;
813 bool remoteSrcIsDir =
false;
819 FileSystem *fs =
new FileSystem( source );
825 remoteSrcIsDir =
true;
832 std::string url = source.
GetURL();
836 std::cerr <<
"Error indexing remote directory.";
858 std::string source = sourceFile->
Path;
862 if( source[0] ==
'/' )
863 source =
"file://" + source;
866 char buf[FILENAME_MAX];
867 char *cwd = getcwd( buf, FILENAME_MAX );
874 source =
"file://" + std::string( cwd ) +
'/' + source;
880 std::string sourcePathObf = sourceFile->
Path;
881 std::string destPathObf = dest;
886 log->
Dump(
AppMsg,
"Processing source entry: %s, type %s, target file: %s, logLevel = %d",
888 destPathObf.c_str(), log->
GetLevel() );
893 std::string target = dest;
896 bool srcIsDir =
false;
898 if( strncmp( sourceFile->
ProtName,
"file", 4 ) == 0 )
899 srcIsDir = std::string( sourceFile->
Path ).size() == size_t( sourceFile->
Doff + sourceFile->
Dlen );
902 srcIsDir = remoteSrcIsDir;
907 std::string srcDir( sourceFile->
Path, sourceFile->
Doff );
909 if( !srcDir.empty() && srcDir.back() ==
'/' )
911 size_t diroff = srcDir.rfind(
'/' );
915 if( diroff == std::string::npos )
919 if( target.empty() || target.back() !=
'/' )
921 target += sourceFile->
Path + diroff;
923 target = target.substr( 0 , target.rfind(
'/') );
927 properties.
Set(
"source", source );
928 properties.
Set(
"target", target );
929 properties.
Set(
"force", force );
930 properties.
Set(
"posc", posc );
931 properties.
Set(
"coerce", coerce );
932 properties.
Set(
"makeDir", makedir );
933 properties.
Set(
"dynamicSource", dynSrc );
934 properties.
Set(
"thirdParty", thirdParty );
935 properties.
Set(
"thirdPartyMode", thirdPartyMode );
936 properties.
Set(
"checkSumMode", checkSumMode );
937 properties.
Set(
"checkSumType", checkSumType );
938 properties.
Set(
"checkSumPreset", checkSumPreset );
939 properties.
Set(
"chunkSize", chunkSize );
940 properties.
Set(
"parallelChunks", parallelChunks );
941 properties.
Set(
"zipArchive", zip );
942 properties.
Set(
"xcp", xcp );
943 properties.
Set(
"xcpBlockSize", blockSize );
944 properties.
Set(
"delegate", delegate );
945 properties.
Set(
"targetIsDir", targetIsDir );
946 properties.
Set(
"preserveXAttr", preserveXAttr );
947 properties.
Set(
"xrate", config.
xRate );
949 properties.
Set(
"rmOnBadCksum", rmOnBadCksum );
950 properties.
Set(
"continue", continue_ );
951 properties.
Set(
"zipAppend", zipappend );
953 properties.
Set(
"doServer", doserver );
956 properties.
Set(
"zipSource", zipFile );
959 properties.
Set(
"nbXcpSources", nbSources );
961 if( !thirdPartyTokenFile.empty() )
962 properties.
Set(
"thirdPartyTokenFile", thirdPartyTokenFile );
967 std::cerr <<
"AddJob " << source <<
" -> " << target <<
": ";
968 std::cerr << st.
ToStr() << std::endl;
970 resultVect.push_back( results );
971 sourceFile = sourceFile->
Next;
978 processConfig.
Set(
"jobType",
"configuration" );
980 process.
AddJob( processConfig, 0 );
989 std::cerr <<
"Prepare: " << st.
ToStr() << std::endl;
993 st = process.
Run( &progress );
996 if( resultVect.size() == 1 )
997 std::cerr <<
"Run: " << st.
ToStr() << std::endl;
1000 std::vector<XrdCl::PropertyList*>::iterator it;
1002 uint32_t jobsRun = 0;
1003 uint32_t errors = 0;
1004 for( it = resultVect.begin(); it != resultVect.end(); ++it, ++i )
1006 if( !(*it)->HasProperty(
"status" ) )
1012 std::cerr <<
"Job #" << i <<
": " << st.
ToStr();
1017 std::cerr <<
"Jobs total: " << resultVect.size();
1018 std::cerr <<
", run: " << jobsRun;
1019 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 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.