63
63
whitespaces or '/'. You can also pass TDirectory names, which apply to the entire directory
64
64
content. Lines beginning with '#' are ignored. If this flag is passed, "-Ltype" MUST be
65
65
passed as well.
66
- \param -Ltype <SkipListed|OnlyListed> Sets the type of operation performed on the objects listed in FILE given with the
66
+ \param -Ltype <SkipListed|OnlyListed> Sets the type of operation performed on the objects listed in FILE given with
67
+ the
67
68
"-L" flag. "SkipListed" will skip all the listed objects; "OnlyListed" will only merge those
68
69
objects. If this flag is passed, "-L" must be passed as well.
69
70
\param -n <N_FILES> Open at most `N` files at once (use 0 to request to use the system maximum - which is also
70
71
the default). This number includes both the input reading files as well as the output file.
71
- Thus, if set to 1, it will be automatically replaced to a minimum of 2. If set to a too large value,
72
- it will be clipped to the system maximum.
72
+ Thus, if set to 1, it will be automatically replaced to a minimum of 2. If set to a too large
73
+ value, it will be clipped to the system maximum.
73
74
\param -O Re-optimize basket size when merging TTree
74
75
\param -T Do not merge Trees
75
- \param -v [LEVEL] Explicitly set the verbosity level: 0 request no output, 99 is the default
76
+ \param -v [LEVEL] Explicitly set the verbosity level:
77
+ <= 0 = only output errors;
78
+ 1 = only output errors and warnings;
79
+ 2 = output minimal informative messages, errors and warnings;
80
+ >= 3 = output all messages (default).
76
81
\return hadd returns a status code: 0 if OK, 1 otherwise
77
82
78
83
For example assume 3 files f1, f2, f3 containing histograms hn and Trees Tn
155
160
#include < optional>
156
161
#include < sstream>
157
162
#include < string>
163
+ #include < streambuf>
158
164
159
165
#ifndef R__WIN32
160
166
#include " ROOT/TProcessExecutor.hxx"
161
167
#endif
162
168
163
169
// //////////////////////////////////////////////////////////////////////////////
164
170
165
- inline std::ostream &Err ()
171
+ // NOTE: TFileMerger will use PrintLevel = gVerbosity - 1. If PrintLevel is < 1, it will print nothing, otherwise
172
+ // it will print everything. To give some granularity to hadd, we do the following:
173
+ // gVerbosity = 0: only print hadd errors
174
+ // gVerbosity = 1: only print hadd errors + warnings
175
+ // gVerbosity = 2: print hadd errors + warnings and TFileMerger messages
176
+ // gVerbosity > 2: print all hadd and TFileMerger messages.
177
+ static int gVerbosity = 99 ;
178
+
179
+ namespace {
180
+
181
+ class NullBuf : public std ::streambuf {
182
+ public:
183
+ int overflow (int c) final { return c; }
184
+ };
185
+
186
+ class NullStream : public std ::ostream {
187
+ NullBuf fBuf ;
188
+
189
+ public:
190
+ NullStream () : std::ostream(&fBuf ) {}
191
+ };
192
+
193
+ } // namespace
194
+
195
+ static NullStream &GetNullStream ()
196
+ {
197
+ static NullStream nullStream;
198
+ return nullStream;
199
+ }
200
+
201
+ static inline std::ostream &Err ()
166
202
{
167
203
std::cerr << " Error in <hadd>: " ;
168
204
return std::cerr;
169
205
}
170
206
171
- inline std::ostream &Warn ()
207
+ static inline std::ostream &Warn ()
172
208
{
173
- std::cerr << " Warning in <hadd>: " ;
174
- return std::cerr;
209
+ std::ostream &s = gVerbosity < 1 ? GetNullStream () : std::cerr;
210
+ s << " Warning in <hadd>: " ;
211
+ return s;
175
212
}
176
213
177
- inline std::ostream &Info ()
214
+ static inline std::ostream &Info ()
178
215
{
179
- std::cerr << " Info in <hadd>: " ;
180
- return std::cerr;
216
+ std::ostream &s = gVerbosity < 3 ? GetNullStream () : std::cerr;
217
+ s << " Info in <hadd>: " ;
218
+ return s;
181
219
}
182
220
183
221
using IntFlag_t = uint32_t ;
@@ -626,7 +664,7 @@ int main(int argc, char **argv)
626
664
627
665
ROOT::TIOFeatures features = args.fFeatures .value_or (ROOT::TIOFeatures{});
628
666
Int_t maxopenedfiles = args.fMaxOpenedFiles .value_or (0 );
629
- Int_t verbosity = args.fVerbosity .value_or (99 );
667
+ gVerbosity = args.fVerbosity .value_or (99 );
630
668
Int_t newcomp = args.fCompressionSettings .value_or (-1 );
631
669
TString cacheSize = args.fCacheSize .value_or (" " );
632
670
@@ -674,8 +712,7 @@ int main(int argc, char **argv)
674
712
}
675
713
targetname = argv[args.fOutputArgIdx ];
676
714
677
- if (verbosity > 1 )
678
- Info () << " target file: " << targetname << " \n " ;
715
+ Info () << " target file: " << targetname << " \n " ;
679
716
680
717
if (args.fCacheSize )
681
718
Info () << " Using " << cacheSize << " \n " ;
@@ -686,7 +723,7 @@ int main(int argc, char **argv)
686
723
687
724
TFileMerger fileMerger (kFALSE , kFALSE );
688
725
fileMerger.SetMsgPrefix (" hadd" );
689
- fileMerger.SetPrintLevel (verbosity - 1 );
726
+ fileMerger.SetPrintLevel (gVerbosity - 1 );
690
727
if (maxopenedfiles > 0 ) {
691
728
fileMerger.SetMaxOpenedFiles (maxopenedfiles);
692
729
}
@@ -758,21 +795,22 @@ int main(int argc, char **argv)
758
795
fileMerger.SetMergeOptions (TString (" DefaultCompression" ));
759
796
}
760
797
}
761
- if (verbosity > 1 ) {
762
- if (args.fKeepCompressionAsIs && !args.fReoptimize )
763
- Info () << " compression setting for meta data: " << newcomp << ' \n ' ;
764
- else
765
- Info () << " compression setting for all output: " << newcomp << ' \n ' ;
766
- }
798
+ if (args.fKeepCompressionAsIs && !args.fReoptimize )
799
+ Info () << " compression setting for meta data: " << newcomp << ' \n ' ;
800
+ else
801
+ Info () << " compression setting for all output: " << newcomp << ' \n ' ;
802
+
767
803
if (args.fAppend ) {
768
804
if (!fileMerger.OutputFile (targetname, " UPDATE" , newcomp)) {
769
805
Err () << " error opening target file for update :" << targetname << " .\n " ;
770
806
return 2 ;
771
807
}
772
808
} else if (!fileMerger.OutputFile (targetname, args.fForce , newcomp)) {
773
- Err () << " error opening target file (does " << targetname << " exist?).\n " ;
809
+ std::stringstream ss;
810
+ ss << " error opening target file (does " << targetname << " exist?).\n " ;
774
811
if (!args.fForce )
775
- Info () << " pass \" -f\" argument to force re-creation of output file.\n " ;
812
+ ss << " pass \" -f\" argument to force re-creation of output file.\n " ;
813
+ Err () << ss.str ();
776
814
return 1 ;
777
815
}
778
816
@@ -850,7 +888,7 @@ int main(int argc, char **argv)
850
888
auto parallelMerge = [&](int start) {
851
889
TFileMerger mergerP (kFALSE , kFALSE );
852
890
mergerP.SetMsgPrefix (" hadd" );
853
- mergerP.SetPrintLevel (verbosity - 1 );
891
+ mergerP.SetPrintLevel (gVerbosity - 1 );
854
892
if (maxopenedfiles > 0 ) {
855
893
mergerP.SetMaxOpenedFiles (maxopenedfiles / nProcesses);
856
894
}
@@ -893,16 +931,12 @@ int main(int argc, char **argv)
893
931
#endif
894
932
895
933
if (status) {
896
- if (verbosity == 1 ) {
897
- Info () << " merged " << allSubfiles.size () << " (" << fileMerger.GetMergeList ()->GetEntries ()
898
- << " ) input (partial) files into " << targetname << " .\n " ;
899
- }
934
+ Info () << " merged " << allSubfiles.size () << " (" << fileMerger.GetMergeList ()->GetEntries ()
935
+ << " ) input (partial) files into " << targetname << " \n " ;
900
936
return 0 ;
901
937
} else {
902
- if (verbosity == 1 ) {
903
- Err () << " failure during the merge of " << allSubfiles.size () << " ("
904
- << fileMerger.GetMergeList ()->GetEntries () << " ) input (partial) files into " << targetname << " .\n " ;
905
- }
938
+ Err () << " failure during the merge of " << allSubfiles.size () << " (" << fileMerger.GetMergeList ()->GetEntries ()
939
+ << " ) input (partial) files into " << targetname << " \n " ;
906
940
return 1 ;
907
941
}
908
942
}
0 commit comments