473{
474 using namespace XrdCl;
475
476
477
478
482 return 50;
484
485
486
487
489 Log *log = DefaultEnv::GetLog();
490 if( config.Dlvl )
491 {
492 if( config.Dlvl == 1 ) log->
SetLevel( Log::InfoMsg );
493 else if( config.Dlvl == 2 ) log->
SetLevel( Log::DebugMsg );
494 else if( config.Dlvl == 3 ) log->
SetLevel( Log::DumpMsg );
495 }
496
500
501 bool posc = false;
502 bool force = false;
503 bool coerce = false;
504 bool makedir = false;
505 bool dynSrc = false;
506 bool delegate = false;
507 bool preserveXAttr = false;
508 bool rmOnBadCksum = false;
509 bool continue_ = false;
510 bool recurse = false;
511 bool zipappend = false;
512 bool doserver = false;
513 std::string thirdParty = "none";
514
523 {
524
525
526
527
528 DlgEnv::Instance().Enable();
529 delegate = true;
530 }
531 else
532 DlgEnv::Instance().Disable();
533
535 {
536 makedir = true;
537 recurse = true;
538 }
544
545 if( force && continue_ )
546 {
547 std::cerr << "Invalid argument combination: continue + force." << std::endl;
548 return 50;
549 }
550
551
552
553
554 std::string checkSumType;
555 std::string checkSumPreset;
556 std::string checkSumMode = "none";
558 {
559 checkSumMode = "end2end";
560 std::vector<std::string> ckSumParams;
561 Utils::splitString( ckSumParams, config.CksVal, ":" );
562 if( ckSumParams.size() > 1 )
563 {
564 if( ckSumParams[1] == "print" )
565 {
566 checkSumMode = "target";
568 }
569 else
570 checkSumPreset = ckSumParams[1];
571 }
572 checkSumType = ckSumParams[0];
573 }
574
576 {
577 checkSumMode = "source";
578 std::vector<std::string> ckSumParams;
579 Utils::splitString( ckSumParams, config.CksVal, ":" );
580 if( ckSumParams.size() == 2 )
581 {
582 checkSumMode = "source";
583 checkSumType = ckSumParams[0];
585 }
586 else
587 {
588 std::cerr << "Invalid parameter: " << config.CksVal << std::endl;
589 return 50;
590 }
591 }
592
593 if( !config.AddCksVal.empty() )
595
596
597
598
599 std::string zipFile;
600 bool zip = false;
602 {
603 zipFile = config.zipFile;
604 zip = true;
605 }
606
607
608
609
610 int nbSources = 0;
611 bool xcp = false;
613 {
614 nbSources = config.nSrcs;
615 xcp = true;
616 }
617
618
619
620
622
623
624 struct scope_exit {
626 } stopPostMaster;
627
628 if( config.nStrm != 0 )
629 env->
PutInt(
"SubStreamsPerChannel", config.nStrm + 1 );
630
631 if( config.Retry != -1 )
632 {
633 env->
PutInt(
"CpRetry", config.Retry );
634 env->
PutString(
"CpRetryPolicy", config.RetryPolicy );
635 }
636
638 env->
PutInt(
"NoTlsOK", 1 );
639
641 env->
PutInt(
"TlsNoData", 1 );
642
644 env->
PutInt(
"TlsMetalink", 1 );
645
647 env->
PutInt(
"ZipMtlnCksum", 1 );
648
650 env->
GetInt(
"CPChunkSize", chunkSize );
651
653 env->
GetInt(
"XCpBlockSize", blockSize );
654
656 env->
GetInt(
"CPParallelChunks", parallelChunks );
657 if( parallelChunks < 1 ||
658 parallelChunks > std::numeric_limits<uint8_t>::max() )
659 {
660 std::cerr << "Can only handle between 1 and ";
661 std::cerr << (int)std::numeric_limits<uint8_t>::max();
662 std::cerr << " chunks in parallel. You asked for " << parallelChunks;
663 std::cerr << "." << std::endl;
664 return 50;
665 }
666
667 if( !preserveXAttr )
668 {
670 env->
GetInt(
"PreserveXAttrs", val );
671 if( val ) preserveXAttr = true;
672 }
673
674 log->
Dump( AppMsg,
"Chunk size: %d, parallel chunks %d, streams: %d",
675 chunkSize, parallelChunks, config.nStrm + 1 );
676
677
678
679
680 std::vector<XrdCl::PropertyList*> resultVect;
681
682 std::string dest;
685 {
686 dest = "file://";
687
688
689 if( config.dstFile->Path[0] != '/' )
690 {
691 char buf[FILENAME_MAX];
692 char *cwd = getcwd( buf, FILENAME_MAX );
693 if( !cwd )
694 {
696 std::cerr << st.GetErrorMessage() << std::endl;
697 return st.GetShellCode();
698 }
699 dest += cwd;
700 dest += '/';
701 }
702 }
703 dest += config.dstFile->Path;
704
705
706
707
708
709
710
711
712 bool targetIsDir = false;
713 bool targetExists = false;
715 targetIsDir = true;
718 {
722 XRootDStatus st = fs.Stat( target.GetPathWithParams(), statInfo );
724 {
725 if( statInfo->
TestFlags( StatInfo::IsDir ) )
726 targetIsDir = true;
727 targetExists = true;
728 }
730 {
731 int n = strlen(config.dstFile->Path);
732 if( config.dstFile->Path[n-1] == '/' )
733 targetIsDir = true;
734 }
736 {
737 log->
Error( AppMsg,
"%s (destination)", st.
ToString().c_str() );
738 std::cerr << st.
ToStr() << std::endl;
740 }
741
742 delete statInfo;
743 }
744
745 if( !targetIsDir && targetExists && !force && !recurse && !zipappend )
746 {
748
749 log->
Error( AppMsg,
"%s (destination)", st.
ToString().c_str() );
750 std::cerr <<
"Run: " << st.
ToStr() << std::endl;
752 }
753
754
755
756
757
760 {
761 std::cerr << "Multiple sources were given but target is not a directory.";
762 std::cerr << std::endl;
763 return 50;
764 }
765
766
767
768
769
770 bool remoteSrcIsDir = false;
774 {
775 URL source( config.srcFile->Path );
778
781 {
782 remoteSrcIsDir = true;
783
784
785
786 delete config.srcFile;
787 std::string url = source.GetURL();
788 config.srcFile =
IndexRemote( fs, url, url.size() );
789 if ( !config.srcFile )
790 {
791 std::cerr << "Error indexing remote directory.";
792 return 50;
793 }
794 }
795
796 delete fs;
797 delete statInfo;
798 }
799
801
802
803
804 while( sourceFile )
805 {
807
808
809
810
813 std::string source = sourceFile->
Path;
815 {
816
817 if( source[0] == '/' )
818 source = "file://" + source;
819 else
820 {
821 char buf[FILENAME_MAX];
822 char *cwd = getcwd( buf, FILENAME_MAX );
823 if( !cwd )
824 {
828 }
829 source = "file://" + std::string( cwd ) + '/' + source;
830 }
831 }
832
834
835 std::string sourcePathObf = sourceFile->
Path;
836 std::string destPathObf = dest;
840 }
841 log->
Dump( AppMsg,
"Processing source entry: %s, type %s, target file: %s, logLevel = %d",
843 destPathObf.c_str(), log->
GetLevel() );
844
845
846
847
848 std::string target = dest;
849
850
851 bool srcIsDir = false;
852
853 if( strncmp( sourceFile->
ProtName,
"file", 4 ) == 0 )
854 srcIsDir = std::string( sourceFile->
Path ).size() == size_t( sourceFile->
Doff + sourceFile->
Dlen );
855
856 else
857 srcIsDir = remoteSrcIsDir;
858
860 {
861
862 std::string srcDir( sourceFile->
Path, sourceFile->
Doff );
863
864 if( srcDir[srcDir.size() - 1] == '/' )
865 srcDir = srcDir.substr( 0, srcDir.size() - 1 );
866 size_t diroff = srcDir.rfind( '/' );
867
868 if( diroff == std::string::npos ) diroff = 0;
869 target += '/';
870 target += sourceFile->
Path + diroff;
871
872 target = target.substr( 0 , target.rfind('/') );
873 }
875
876 properties.
Set(
"source", source );
877 properties.
Set(
"target", target );
878 properties.
Set(
"force", force );
879 properties.
Set(
"posc", posc );
880 properties.
Set(
"coerce", coerce );
881 properties.
Set(
"makeDir", makedir );
882 properties.
Set(
"dynamicSource", dynSrc );
883 properties.
Set(
"thirdParty", thirdParty );
884 properties.
Set(
"checkSumMode", checkSumMode );
885 properties.
Set(
"checkSumType", checkSumType );
886 properties.
Set(
"checkSumPreset", checkSumPreset );
887 properties.
Set(
"chunkSize", chunkSize );
888 properties.
Set(
"parallelChunks", parallelChunks );
889 properties.
Set(
"zipArchive", zip );
890 properties.
Set(
"xcp", xcp );
891 properties.
Set(
"xcpBlockSize", blockSize );
892 properties.
Set(
"delegate", delegate );
893 properties.
Set(
"targetIsDir", targetIsDir );
894 properties.
Set(
"preserveXAttr", preserveXAttr );
895 properties.
Set(
"xrate", config.xRate );
896 properties.
Set(
"xrateThreshold", config.xRateThreshold );
897 properties.
Set(
"rmOnBadCksum", rmOnBadCksum );
898 properties.
Set(
"continue", continue_ );
899 properties.
Set(
"zipAppend", zipappend );
900 properties.
Set(
"addcksums", config.AddCksVal );
901 properties.
Set(
"doServer", doserver );
902
903 if( zip )
904 properties.
Set(
"zipSource", zipFile );
905
906 if( xcp )
907 properties.
Set(
"nbXcpSources", nbSources );
908
909
912 {
913 std::cerr << "AddJob " << source << " -> " << target << ": ";
914 std::cerr << st.
ToStr() << std::endl;
915 }
916 resultVect.push_back( results );
917 sourceFile = sourceFile->
Next;
918 }
919
920
921
922
924 processConfig.
Set(
"jobType",
"configuration" );
925 processConfig.
Set(
"parallel", config.Parallel );
926 process.
AddJob( processConfig, 0 );
927
928
929
930
933 {
935 std::cerr <<
"Prepare: " << st.
ToStr() << std::endl;
937 }
938
939 st = process.
Run( &progress );
941 {
942 if( resultVect.size() == 1 )
943 std::cerr <<
"Run: " << st.
ToStr() << std::endl;
944 else
945 {
946 std::vector<XrdCl::PropertyList*>::iterator it;
947 uint16_t i = 1;
948 uint16_t jobsRun = 0;
949 uint16_t errors = 0;
950 for( it = resultVect.begin(); it != resultVect.end(); ++it, ++i )
951 {
952 if( !(*it)->HasProperty( "status" ) )
953 continue;
954
957 {
958 std::cerr <<
"Job #" << i <<
": " << st.
ToStr();
959 ++errors;
960 }
961 ++jobsRun;
962 }
963 std::cerr << "Jobs total: " << resultVect.size();
964 std::cerr << ", run: " << jobsRun;
965 std::cerr << ", errors: " << errors << std::endl;
966 }
969 }
971 return 0;
972}
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)
std::string obfuscateAuth(const std::string &input)
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.
LogLevel GetLevel() const
Get the log level.
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.