470{
471 using namespace XrdCl;
472
473
474
475
479 return 50;
481
482
483
484
486 Log *log = DefaultEnv::GetLog();
487 if( config.Dlvl )
488 {
489 if( config.Dlvl == 1 ) log->
SetLevel( Log::InfoMsg );
490 else if( config.Dlvl == 2 ) log->
SetLevel( Log::DebugMsg );
491 else if( config.Dlvl == 3 ) log->
SetLevel( Log::DumpMsg );
492 }
493
497
498 bool posc = false;
499 bool force = false;
500 bool coerce = false;
501 bool makedir = false;
502 bool dynSrc = false;
503 bool delegate = false;
504 bool preserveXAttr = false;
505 bool rmOnBadCksum = false;
506 bool continue_ = false;
507 bool recurse = false;
508 bool zipappend = false;
509 bool doserver = false;
510 std::string thirdParty = "none";
511
520 {
521
522
523
524
525 DlgEnv::Instance().Enable();
526 delegate = true;
527 }
528 else
529 DlgEnv::Instance().Disable();
530
532 {
533 makedir = true;
534 recurse = true;
535 }
541
542 if( force && continue_ )
543 {
544 std::cerr << "Invalid argument combination: continue + force." << std::endl;
545 return 50;
546 }
547
548
549
550
551 std::string checkSumType;
552 std::string checkSumPreset;
553 std::string checkSumMode = "none";
555 {
556 checkSumMode = "end2end";
557 std::vector<std::string> ckSumParams;
558 Utils::splitString( ckSumParams, config.CksVal, ":" );
559 if( ckSumParams.size() > 1 )
560 {
561 if( ckSumParams[1] == "print" )
562 {
563 checkSumMode = "target";
565 }
566 else
567 checkSumPreset = ckSumParams[1];
568 }
569 checkSumType = ckSumParams[0];
570 }
571
573 {
574 checkSumMode = "source";
575 std::vector<std::string> ckSumParams;
576 Utils::splitString( ckSumParams, config.CksVal, ":" );
577 if( ckSumParams.size() == 2 )
578 {
579 checkSumMode = "source";
580 checkSumType = ckSumParams[0];
582 }
583 else
584 {
585 std::cerr << "Invalid parameter: " << config.CksVal << std::endl;
586 return 50;
587 }
588 }
589
590 if( !config.AddCksVal.empty() )
592
593
594
595
596 std::string zipFile;
597 bool zip = false;
599 {
600 zipFile = config.zipFile;
601 zip = true;
602 }
603
604
605
606
607 int nbSources = 0;
608 bool xcp = false;
610 {
611 nbSources = config.nSrcs;
612 xcp = true;
613 }
614
615
616
617
619
620
621 struct scope_exit {
623 } stopPostMaster;
624
625 if( config.nStrm != 0 )
626 env->
PutInt(
"SubStreamsPerChannel", config.nStrm + 1 );
627
628 if( config.Retry != -1 )
629 {
630 env->
PutInt(
"CpRetry", config.Retry );
631 env->
PutString(
"CpRetryPolicy", config.RetryPolicy );
632 }
633
635 env->
PutInt(
"NoTlsOK", 1 );
636
638 env->
PutInt(
"TlsNoData", 1 );
639
641 env->
PutInt(
"TlsMetalink", 1 );
642
644 env->
PutInt(
"ZipMtlnCksum", 1 );
645
647 env->
GetInt(
"CPChunkSize", chunkSize );
648
650 env->
GetInt(
"XCpBlockSize", blockSize );
651
653 env->
GetInt(
"CPParallelChunks", parallelChunks );
654 if( parallelChunks < 1 ||
655 parallelChunks > std::numeric_limits<uint8_t>::max() )
656 {
657 std::cerr << "Can only handle between 1 and ";
658 std::cerr << (int)std::numeric_limits<uint8_t>::max();
659 std::cerr << " chunks in parallel. You asked for " << parallelChunks;
660 std::cerr << "." << std::endl;
661 return 50;
662 }
663
664 if( !preserveXAttr )
665 {
667 env->
GetInt(
"PreserveXAttrs", val );
668 if( val ) preserveXAttr = true;
669 }
670
671 log->
Dump( AppMsg,
"Chunk size: %d, parallel chunks %d, streams: %d",
672 chunkSize, parallelChunks, config.nStrm + 1 );
673
674
675
676
677 std::vector<XrdCl::PropertyList*> resultVect;
678
679 std::string dest;
682 {
683 dest = "file://";
684
685
686 if( config.dstFile->Path[0] != '/' )
687 {
688 char buf[FILENAME_MAX];
689 char *cwd = getcwd( buf, FILENAME_MAX );
690 if( !cwd )
691 {
693 std::cerr << st.GetErrorMessage() << std::endl;
694 return st.GetShellCode();
695 }
696 dest += cwd;
697 dest += '/';
698 }
699 }
700 dest += config.dstFile->Path;
701
702
703
704
705
706
707
708
709 bool targetIsDir = false;
710 bool targetExists = false;
712 targetIsDir = true;
715 {
719 XRootDStatus st = fs.Stat( target.GetPathWithParams(), statInfo );
721 {
722 if( statInfo->
TestFlags( StatInfo::IsDir ) )
723 targetIsDir = true;
724 targetExists = true;
725 }
727 {
728 int n = strlen(config.dstFile->Path);
729 if( config.dstFile->Path[n-1] == '/' )
730 targetIsDir = true;
731 }
733 {
734 log->
Error( AppMsg,
"%s (destination)", st.
ToString().c_str() );
735 std::cerr << st.
ToStr() << std::endl;
737 }
738
739 delete statInfo;
740 }
741
742 if( !targetIsDir && targetExists && !force && !recurse && !zipappend )
743 {
745
746 log->
Error( AppMsg,
"%s (destination)", st.
ToString().c_str() );
747 std::cerr <<
"Run: " << st.
ToStr() << std::endl;
749 }
750
751
752
753
754
757 {
758 std::cerr << "Multiple sources were given but target is not a directory.";
759 std::cerr << std::endl;
760 return 50;
761 }
762
763
764
765
766
767 bool remoteSrcIsDir = false;
770 {
771 URL source( config.srcFile->Path );
774
777 {
778 remoteSrcIsDir = true;
779
780
781
782 delete config.srcFile;
783 std::string url = source.GetURL();
784 config.srcFile =
IndexRemote( fs, url, url.size() );
785 if ( !config.srcFile )
786 {
787 std::cerr << "Error indexing remote directory.";
788 return 50;
789 }
790 }
791
792 delete fs;
793 delete statInfo;
794 }
795
797
798
799
800 while( sourceFile )
801 {
803
804
805
806
809 std::string source = sourceFile->
Path;
811 {
812
813 if( source[0] == '/' )
814 source = "file://" + source;
815 else
816 {
817 char buf[FILENAME_MAX];
818 char *cwd = getcwd( buf, FILENAME_MAX );
819 if( !cwd )
820 {
824 }
825 source = "file://" + std::string( cwd ) + '/' + source;
826 }
827 }
828
830
831 log->
Dump( AppMsg,
"Processing source entry: %s, type %s, target file: %s",
833 dest.c_str() );
834
835
836
837
838 std::string target = dest;
839
840
841 bool srcIsDir = false;
842
843 if( strncmp( sourceFile->
ProtName,
"file", 4 ) == 0 )
844 srcIsDir = std::string( sourceFile->
Path ).size() == size_t( sourceFile->
Doff + sourceFile->
Dlen );
845
846 else
847 srcIsDir = remoteSrcIsDir;
848
850 {
851
852 std::string srcDir( sourceFile->
Path, sourceFile->
Doff );
853
854 if( srcDir[srcDir.size() - 1] == '/' )
855 srcDir = srcDir.substr( 0, srcDir.size() - 1 );
856 size_t diroff = srcDir.rfind( '/' );
857
858 if( diroff == std::string::npos ) diroff = 0;
859 target += '/';
860 target += sourceFile->
Path + diroff;
861
862 target = target.substr( 0 , target.rfind('/') );
863 }
865
866 properties.
Set(
"source", source );
867 properties.
Set(
"target", target );
868 properties.
Set(
"force", force );
869 properties.
Set(
"posc", posc );
870 properties.
Set(
"coerce", coerce );
871 properties.
Set(
"makeDir", makedir );
872 properties.
Set(
"dynamicSource", dynSrc );
873 properties.
Set(
"thirdParty", thirdParty );
874 properties.
Set(
"checkSumMode", checkSumMode );
875 properties.
Set(
"checkSumType", checkSumType );
876 properties.
Set(
"checkSumPreset", checkSumPreset );
877 properties.
Set(
"chunkSize", chunkSize );
878 properties.
Set(
"parallelChunks", parallelChunks );
879 properties.
Set(
"zipArchive", zip );
880 properties.
Set(
"xcp", xcp );
881 properties.
Set(
"xcpBlockSize", blockSize );
882 properties.
Set(
"delegate", delegate );
883 properties.
Set(
"targetIsDir", targetIsDir );
884 properties.
Set(
"preserveXAttr", preserveXAttr );
885 properties.
Set(
"xrate", config.xRate );
886 properties.
Set(
"xrateThreshold", config.xRateThreshold );
887 properties.
Set(
"rmOnBadCksum", rmOnBadCksum );
888 properties.
Set(
"continue", continue_ );
889 properties.
Set(
"zipAppend", zipappend );
890 properties.
Set(
"addcksums", config.AddCksVal );
891 properties.
Set(
"doServer", doserver );
892
893 if( zip )
894 properties.
Set(
"zipSource", zipFile );
895
896 if( xcp )
897 properties.
Set(
"nbXcpSources", nbSources );
898
899
902 {
903 std::cerr << "AddJob " << source << " -> " << target << ": ";
904 std::cerr << st.
ToStr() << std::endl;
905 }
906 resultVect.push_back( results );
907 sourceFile = sourceFile->
Next;
908 }
909
910
911
912
914 processConfig.
Set(
"jobType",
"configuration" );
915 processConfig.
Set(
"parallel", config.Parallel );
916 process.
AddJob( processConfig, 0 );
917
918
919
920
923 {
925 std::cerr <<
"Prepare: " << st.
ToStr() << std::endl;
927 }
928
929 st = process.
Run( &progress );
931 {
932 if( resultVect.size() == 1 )
933 std::cerr <<
"Run: " << st.
ToStr() << std::endl;
934 else
935 {
936 std::vector<XrdCl::PropertyList*>::iterator it;
937 uint16_t i = 1;
938 uint16_t jobsRun = 0;
939 uint16_t errors = 0;
940 for( it = resultVect.begin(); it != resultVect.end(); ++it, ++i )
941 {
942 if( !(*it)->HasProperty( "status" ) )
943 continue;
944
947 {
948 std::cerr <<
"Job #" << i <<
": " << st.
ToStr();
949 ++errors;
950 }
951 ++jobsRun;
952 }
953 std::cerr << "Jobs total: " << resultVect.size();
954 std::cerr << ", run: " << jobsRun;
955 std::cerr << ", errors: " << errors << std::endl;
956 }
959 }
961 return 0;
962}
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)
void PrintAdditionalCheckSum(bool print)
void PrintSourceCheckSum(bool print)
void PrintProgressBar(bool print)
void PrintTargetCheckSum(bool print)
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)
static PostMaster * GetPostMaster()
Get default post master.
static Env * GetEnv()
Get default client environment.
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 Stat(const std::string &path, ResponseHandler *handler, uint16_t timeout=0) XRD_WARN_UNUSED_RESULT
void SetLevel(LogLevel level)
Set the level of the messages that should be sent to the destination.
void Dump(uint64_t topic, const char *format,...)
Print a dump 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)
std::string ToStr() const
Convert to string.
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
static const uint64_t DoCksum
static const uint64_t DoCksrc
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 int DefaultCPParallelChunks
const int DefaultXCpBlockSize
const int DefaultPreserveXAttrs
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.