TFileMerger
This class provides file copy and merging services.
It can be used to copy files (not only ROOT files), using TFile or
any of its remote file access plugins. It is therefore useful in
a Grid environment where the files might be accessible via Castor,
rfio, dcap, etc.
The merging interface allows files containing histograms and trees
to be merged, like the standalone hadd program.
class TFileMerger : public TObject
class
private:
using TIOFeatures = ROOT::TIOFeatures;
TFileMerger(const TFileMerger&) = delete;
TFileMerger& operator=(const TFileMerger&) = delete;
protected:
TStopwatch fWatch; ///< Stop watch to measure file copy speed
TList fFileList; ///< A list the file (TFile*) which shall be merged
TFile *fOutputFile{nullptr}; ///< The outputfile for merging
TString fOutputFilename; ///< The name of the outputfile for merging
Bool_t fFastMethod{kTRUE}; ///< True if using Fast merging algorithm (default)
Bool_t fNoTrees{kFALSE}; ///< True if Trees should not be merged (default is kFALSE)
Bool_t fExplicitCompLevel{kFALSE}; ///< True if the user explicitly requested a compressio level change (default kFALSE)
Bool_t fCompressionChange{kFALSE}; ///< True if the output and input have different compression level (default kFALSE)
Int_t fPrintLevel{0}; ///< How much information to print out at run time
TString fMergeOptions; ///< Options (in string format) to be passed down to the Merge functions
TIOFeatures *fIOFeatures{nullptr}; ///< IO features to use in the output file.
TString fMsgPrefix{"TFileMerger"}; ///< Prefix to be used when printing informational message (default TFileMerger)
Int_t fMaxOpenedFiles; ///< Maximum number of files opened at the same time by the TFileMerger
Bool_t fLocal; ///< Makes local copies of merging files if True (default is kTRUE)
Bool_t fHistoOneGo; ///< Merger histos in one go (default is kTRUE)
TString fObjectNames; ///< List of object names to be either merged exclusively or skipped
TList fMergeList; ///< list of TObjString containing the name of the files need to be merged
TList fExcessFiles; ///<! List of TObjString containing the name of the files not yet added to fFileList due to user or system limitiation on the max number of files opened.
Bool_t OpenExcessFiles();/// Open up to fMaxOpenedFiles of the excess files.
virtual Bool_t AddFile(TFile *source, Bool_t own, Bool_t cpProgress);
/// Add the TFile to this file merger and give ownership of the TFile to this
/// object (unless kFALSE is returned).
/// Return kTRUE if the addition was successful.
virtual Bool_t MergeRecursive(TDirectory *target, TList *sourcelist, Int_t type = kRegular | kAll);
/// Merge all objects in a directory
/// The type is defined by the bit values in TFileMerger::EPartialMergeType.
public:
/// Type of the partial merge
enum EPartialMergeType {
kRegular = 0, ///< Normal merge, overwritting the output file.
kIncremental = BIT(1), ///< Merge the input file with the content of the output file (if already exising).
kResetable = BIT(2), ///< Only the objects with a MergeAfterReset member function.
kNonResetable = BIT(3), ///< Only the objects without a MergeAfterReset member function.
kAll = BIT(2)|BIT(3), ///< Merge all type of objects (default)
kAllIncremental = kIncremental | kAll, ///< Merge incrementally all type of objects.
kOnlyListed = BIT(4), ///< Only the objects specified in fObjectNames list
kSkipListed = BIT(5), ///< Skip objects specified in fObjectNames list
kKeepCompression= BIT(6) ///< Keep compression level unchanged for each input files
};
TFileMerger(Bool_t isLocal = kTRUE, Bool_t histoOneGo = kTRUE);
virtual ~TFileMerger();
Int_t GetPrintLevel() const { return fPrintLevel; }
void SetPrintLevel(Int_t level) { fPrintLevel = level; }
Bool_t HasCompressionChange() const { return fCompressionChange; }
const char *GetOutputFileName() const { return fOutputFilename; }
TList *GetMergeList() { return &fMergeList; }
TFile *GetOutputFile() const { return fOutputFile; }
Int_t GetMaxOpenedFiles() const { return fMaxOpenedFiles; }
void SetMaxOpenedFiles(Int_t newmax);
/// Set a limit to the number of files that TFileMerger will open simultaneously.
/// If the request is higher than the system limit, we reset it to the system limit.
/// If the request is less than two, we reset it to 2 (one for the output file and one for the input file).
const char *GetMsgPrefix() const { return fMsgPrefix; }
void SetMsgPrefix(const char *prefix);/// Set the prefix to be used when printing informational message.
const char *GetMergeOptions() { return fMergeOptions; }
void SetMergeOptions(const TString &options) { fMergeOptions = options; }
void SetMergeOptions(const std::string_view &options) { fMergeOptions = options; }
void SetIOFeatures(ROOT::TIOFeatures &features) { fIOFeatures = &features; }
void AddObjectNames(const char *name) {fObjectNames += name; fObjectNames += " ";}
const char *GetObjectNames() const {return fObjectNames.Data();}
void ClearObjectNames() {fObjectNames.Clear();}
//--- file management interface
virtual Bool_t SetCWD(const char * /*path*/) { MayNotUse("SetCWD"); return kFALSE; }
virtual const char *GetCWD() { MayNotUse("GetCWD"); return 0; }
//--- file merging interface
virtual void Reset();/// Reset merger file list.
virtual Bool_t AddFile(const char *url, Bool_t cpProgress = kTRUE);
/// Add file to file merger.
virtual Bool_t AddFile(TFile *source, Bool_t cpProgress = kTRUE);
/// Add the TFile to this file merger and *do not* give ownership of the TFile to this
/// object.
/// Return kTRUE if the addition was successful.
virtual Bool_t AddAdoptFile(TFile *source, Bool_t cpProgress = kTRUE);
/// Add the TFile to this file merger and give ownership of the TFile to this
/// object (unless kFALSE is returned).
/// Return kTRUE if the addition was successful.
virtual Bool_t OutputFile(const char *url, Bool_t force);/// Open merger output file.
virtual Bool_t OutputFile(const char *url, Bool_t force, Int_t compressionLevel);/// Open merger output file.
virtual Bool_t OutputFile(const char *url, const char *mode = "RECREATE");
/// Open merger output file. 'mode' is passed to the TFile constructor as the option, it should
/// be one of 'NEW','CREATE','RECREATE','UPDATE'
/// 'UPDATE' is usually used in conjunction with IncrementalMerge.
virtual Bool_t OutputFile(const char *url, const char *mode, Int_t compressionLevel);
/// Open merger output file.
/// The 'mode' parameter is passed to the TFile constructor as the option, it
/// should be one of 'NEW','CREATE','RECREATE','UPDATE'
/// 'UPDATE' is usually used in conjunction with IncrementalMerge.
virtual Bool_t OutputFile(std::unique_ptr<TFile> file);/// Set an output file opened externally by the users
virtual void PrintFiles(Option_t *options);/// Print list of files being merged.
virtual Bool_t Merge(Bool_t = kTRUE);
/// Merge the files.
/// If no output file was specified it will write into
/// the file "FileMerger.root" in the working directory. Returns true
/// on success, false in case of error.
virtual Bool_t PartialMerge(Int_t type = kAll | kIncremental);
/// Merge the files. If no output file was specified it will write into
/// the file "FileMerger.root" in the working directory. Returns true
/// on success, false in case of error.
/// The type is defined by the bit values in EPartialMergeType:
/// kRegular : normal merge, overwritting the output file
/// kIncremental : merge the input file with the content of the output file (if already exising) (default)
/// kAll : merge all type of objects (default)
/// kResetable : merge only the objects with a MergeAfterReset member function.
/// kNonResetable : merge only the objects without a MergeAfterReset member function.
/// If the type is set to kIncremental the output file is done deleted at the end of
/// this operation. If the type is not set to kIncremental, the output file is closed.
virtual void SetFastMethod(Bool_t fast=kTRUE) {fFastMethod = fast;}
virtual void SetNotrees(Bool_t notrees=kFALSE) {fNoTrees = notrees;}
virtual void RecursiveRemove(TObject *obj);/// Intercept the case where the output TFile is deleted!