153#include "haddCommandLineOptionsHelp.h"
182class NullBuf :
public std::streambuf {
184 int overflow(
int c)
final {
return c; }
187class NullStream :
public std::ostream {
191 NullStream() : std::ostream(&fBuf) {}
202static inline std::ostream &
Err()
204 std::cerr <<
"Error in <hadd>: ";
208static inline std::ostream &
Warn()
211 s <<
"Warning in <hadd>: ";
215static inline std::ostream &
Info(
int minLevel)
218 s <<
"Info in <hadd>: ";
269static std::optional<IntFlag_t>
StrToUInt(
const char *str)
313 Err() <<
"error parsing integer argument '" << arg <<
"'\n";
321 std::stringstream
ss;
324 while (std::getline(
ss,
item,
',')) {
326 Warn() <<
"ignoring unknown feature request: " <<
item <<
"\n";
337 Err() <<
"could not parse the cache size passed after -cachesize: '" << arg <<
"'\n";
341 const char *
munit =
nullptr;
343 Warn() <<
"the cache size passed after -cachesize is too large: " << arg <<
" is greater than " <<
m <<
munit
344 <<
". We will use the maximum value.\n";
347 cacheSize =
"cachesize=";
355 if (
strcmp(arg,
"SkipListed") == 0)
357 if (
strcmp(arg,
"OnlyListed") == 0)
360 Err() <<
"invalid argument for -Ltype: '" << arg <<
"'. Can only be 'SkipListed' or 'OnlyListed' (case matters).\n";
376 const char *
nxtArg =
nullptr;
394 Err() <<
"expected argument after '-" <<
flagStr <<
"' flag.\n";
410 Err() <<
"the argument after '-" <<
flagStr <<
"' flag was not of the expected type.\n";
429 " This behavior is deprecated, please use the full compression settings.\n";
460 const char *
cur = arg + 1;
465 Warn() <<
"duplicate flag: -ff\n";
468 <<
"[err] Cannot specify both -ff and -f[0-9]. Either use the first input compression or specify it.\n";
475 Warn() <<
"duplicate flag: -fk\n";
481 Err() <<
"cannot specify both -ff and -f[0-9]. Either use the first input compression or "
492 Err() << *
compLv <<
" is not a supported compression settings.\n";
496 Err() <<
"failed to parse compression settings '" <<
cur <<
"' as an integer.\n";
500 Err() <<
"cannot specify -f[0-9] multiple times!\n";
504 Err() <<
"invalid flag: " << arg <<
"\n";
532 if (!args.fNoFlagsAfterPositionalArguments &&
argRaw[0] ==
'-' &&
argRaw[1] !=
'\0') {
537 <<
"found `--`, but we've already parsed (or are still parsing) a sequence of positional arguments!"
538 " This is not supported: you must have exactly one sequence of positional arguments, so if you"
539 " need to use `--` make sure to pass *all* positional arguments after it.";
542 args.fNoFlagsAfterPositionalArguments =
true;
549 const char *arg =
argRaw + 1;
552#define PARSE_FLAG(func, ...) \
555 const auto res = func(__VA_ARGS__); \
556 if (res == EFlagResult::kErr) \
558 validFlag = res == EFlagResult::kParsed; \
583 }
else if (!args.fOutputArgIdx) {
585 args.fOutputArgIdx =
argIdx;
591 if (!args.fFirstInputIdx) {
592 args.fFirstInputIdx =
argIdx;
595 Err() <<
"seen a positional argument '" <<
argRaw
596 <<
"' after some flags."
597 " Positional arguments were already parsed at this point (from '"
598 <<
argv[args.fOutputArgIdx]
599 <<
"' onwards), and you can only have one sequence of them, so you cannot pass more."
600 " Please group your positional arguments all together so that hadd works as you expect.\n"
602 for (
int i = 0; i <
argc; ++i)
603 std::cerr <<
argv[i] <<
" ";
629 std::istringstream
ss(
line);
656 if (
argc < 3 ||
"-h" == std::string(
argv[1]) ||
"--help" == std::string(
argv[1])) {
658 return (
argc == 2 && (
"-h" == std::string(
argv[1]) ||
"--help" == std::string(
argv[1]))) ? 0 : 1;
686 Info(2) <<
"parallelizing with " <<
nProcesses <<
" processes.\n";
693 Err() <<
"could not access the directory specified: " << *args.
fWorkingDir <<
".\n";
701 Err() <<
"-L must always be passed along with -Ltype.\n";
707 Err() <<
"missing output file.\n";
711 Err() <<
"missing input file.\n";
719 Info(2) <<
"Using " << cacheSize <<
"\n";
742 Err() <<
"could not open indirect file " << (
argv[
a] + 1) << std::endl;
750 Err() <<
"could not validate the file name \"" <<
line <<
"\" within indirect file "
751 << (
argv[
a] + 1) << std::endl;
755 Err() <<
"file " <<
line <<
" cannot be both the target and an input!\n";
767 Err() <<
"could not validate argument \"" <<
line <<
"\" as input file " << std::endl;
771 Err() <<
"file " <<
line <<
" cannot be both the target and an input!\n";
780 Err() <<
"could not find any valid input file " << std::endl;
800 Info(2) <<
"compression setting for meta data: " <<
newcomp <<
'\n';
802 Info(2) <<
"compression setting for all output: " <<
newcomp <<
'\n';
806 Err() <<
"error opening target file for update :" <<
targetname <<
".\n";
810 std::stringstream
ss;
811 ss <<
"error opening target file (does " <<
targetname <<
" exist?).\n";
813 ss <<
"pass \"-f\" argument to force re-creation of output file.\n";
823 Info(2) <<
"each process should handle at least 3 files for efficiency."
824 " Setting the number of processes to: "
839 for (
auto i = 0; (i * step) <
allSubfiles.size(); i++) {
840 std::stringstream buffer;
853 Warn() <<
"Sources and Target have different compression settings\n"
854 "hadd merging will be slower\n";
881 Err() <<
"exiting due to error in " <<
allSubfiles[i] << std::endl;
897 Err() <<
"error opening target partial file\n";
916 status = std::accumulate(res.begin(), res.end(), 0U) ==
partialFiles.size();
920 Err() <<
"failed at the parallel stage\n";
936 <<
") input (partial) files into " <<
targetname <<
"\n";
940 <<
") input (partial) files into " <<
targetname <<
"\n";
size_t size(const MatrixT &matrix)
retrieve the size of a square matrix
bool Bool_t
Boolean (0=false, 1=true) (bool)
int Int_t
Signed integer 4 bytes (int)
ROOT::Detail::TRangeCast< T, true > TRangeDynCast
TRangeDynCast is an adapter class that allows the typed iteration through a TCollection.
void Info(const char *location, const char *msgfmt,...)
Use this function for informational messages.
winID h TVirtualViewer3D TVirtualGLPainter p
R__EXTERN TSystem * gSystem
TIOFeatures provides the end-user with the ability to change the IO behavior of data written via a TT...
This class provides a simple interface to execute the same task multiple times in parallel,...
This class provides file copy and merging services.
@ kAll
Merge all type of objects (default)
@ kIncremental
Merge the input file with the content of the output file (if already existing).
@ kSkipListed
Skip objects specified in fObjectNames list.
@ kOnlyListed
Only the objects specified in fObjectNames list.
@ kRegular
Normal merge, overwriting the output file.
@ kFailOnError
The merging process will stop and yield failure when encountering invalid objects.
@ kSkipOnError
The merging process will skip invalid objects and continue.
A ROOT file is an on-disk file, usually with extension .root, that stores objects in a file-system-li...
static TFile * Open(const char *name, Option_t *option="", const char *ftitle="", Int_t compress=ROOT::RCompressionSetting::EDefaults::kUseCompiledDefault, Int_t netopt=0)
Create / open a file.
TString & Append(const char *cs)
virtual int GetSysInfo(SysInfo_t *info) const
Returns static system info, like OS type, CPU type, number of CPUs RAM size, etc into the SysInfo_t s...
virtual int Load(const char *module, const char *entry="", Bool_t system=kFALSE)
Load a shared library.
virtual Bool_t AccessPathName(const char *path, EAccessMode mode=kFileExists)
Returns FALSE if one can access a file using the specified access mode.
virtual int Unlink(const char *name)
Unlink, i.e.
virtual const char * TempDirectory() const
Return a user configured or systemwide directory to create temporary files in.
This class defines a UUID (Universally Unique IDentifier), also known as GUIDs (Globally Unique IDent...
static EFlagResult FlagArg(int argc, char **argv, int &argIdxInOut, const char *flagStr, std::optional< T > &flagOut, std::optional< T > defaultVal=std::nullopt, FlagConvResult< T >(*conv)(const char *)=ConvertArg< T >)
static bool ValidCompressionSettings(int compSettings)
FlagConvResult< IntFlag_t > ConvertArg< IntFlag_t >(const char *arg)
#define PARSE_FLAG(func,...)
static FlagConvResult< Int_t > ConvertFilterType(const char *arg)
static Int_t ParseFilterFile(const std::optional< std::string > &filterFileName, std::optional< Int_t > objectFilterType, TFileMerger &fileMerger)
static FlagConvResult< T > ConvertArg(const char *)
static constexpr int kDefaultHaddVerbosity
static std::ostream & Info(int minLevel)
static std::optional< HAddArgs > ParseArgs(int argc, char **argv)
FlagConvResult< ROOT::TIOFeatures > ConvertArg< ROOT::TIOFeatures >(const char *arg)
static int gHaddVerbosity
static std::ostream & Warn()
static FlagConvResult< TString > ConvertCacheSize(const char *arg)
static std::ostream & Err()
static EFlagResult FlagF(const char *arg, HAddArgs &args)
static EFlagResult FlagToggle(const char *arg, const char *flagStr, bool &flagOut)
static NullStream & GetNullStream()
static std::optional< IntFlag_t > StrToUInt(const char *str)
static constexpr const char kCommandLineOptionsHelp[]
void ToHumanReadableSize(value_type bytes, Bool_t si, Double_t *coeff, const char **units)
Return the size expressed in 'human readable' format.
EFromHumanReadableSize FromHumanReadableSize(std::string_view str, T &value)
Convert strings like the following into byte counts 5MB, 5 MB, 5M, 3.7GB, 123b, 456kB,...
bool fNoFlagsAfterPositionalArguments
bool fKeepCompressionAsIs
std::optional< TString > fCacheSize
std::optional< IntFlag_t > fCompressionSettings
std::optional< Int_t > fObjectFilterType
std::optional< IntFlag_t > fNProcesses
bool fUseFirstInputCompression
std::optional< std::string > fObjectFilterFile
std::optional< IntFlag_t > fVerbosity
std::optional< IntFlag_t > fMaxOpenedFiles
std::optional< std::string > fWorkingDir
std::optional< ROOT::TIOFeatures > fFeatures
@ kUseCompiledDefault
Use the compile-time default setting.