Logo ROOT   6.30.04
Reference Guide
 All Namespaces Files Pages
TBufferMerger.hxx
Go to the documentation of this file.
1 // @(#)root/io:$Id$
2 // Author: Philippe Canal, Witold Pokorski, and Guilherme Amadio
3 
4 /*************************************************************************
5  * Copyright (C) 1995-2017, Rene Brun and Fons Rademakers. *
6  * All rights reserved. *
7  * *
8  * For the licensing terms see $ROOTSYS/LICENSE. *
9  * For the list of contributors see $ROOTSYS/README/CREDITS. *
10  *************************************************************************/
11 
12 #ifndef ROOT_TBufferMerger
13 #define ROOT_TBufferMerger
14 
15 #include "TFileMerger.h"
16 #include "TMemFile.h"
17 
18 #include <functional>
19 #include <memory>
20 #include <mutex>
21 #include <queue>
22 
23 namespace ROOT {
24 namespace Experimental {
25 
26 class TBufferMergerFile;
27 
28 /**
29  * \class TBufferMerger TBufferMerger.hxx
30  * \ingroup IO
31  *
32  * TBufferMerger is a class to facilitate writing data in
33  * parallel from multiple threads, while writing to a single
34  * output file. Its purpose is similar to TParallelMergingFile,
35  * but instead of using processes that connect to a network
36  * socket, TBufferMerger uses threads that each write to a
37  * TBufferMergerFile, which in turn push data into a queue
38  * managed by the TBufferMerger.
39  */
40 
41 class TBufferMerger {
42 public:
43  /** Constructor
44  * @param name Output file name
45  * @param option Output file creation options
46  * @param compression Output file compression level
47  */
48  TBufferMerger(const char *name, Option_t *option = "RECREATE", Int_t compress = ROOT::RCompressionSetting::EDefaults::kUseCompiledDefault);
49 
50  /** Constructor
51  * @param output Output \c TFile
52  */
53  TBufferMerger(std::unique_ptr<TFile> output);
54 
55  /** Destructor */
56  virtual ~TBufferMerger();
57 
58  /** Returns a TBufferMergerFile to which data can be written.
59  * At the end, all TBufferMergerFiles get merged into the output file.
60  * The user is responsible to "cd" into the file to associate objects
61  * such as histograms or trees to it.
62  *
63  * After the creation of this file, the user must reset the kMustCleanup
64  * bit on any objects attached to it and take care of their deletion, as
65  * there is a possibility that a race condition will happen that causes
66  * a crash if ROOT manages these objects.
67  */
68  std::shared_ptr<TBufferMergerFile> GetFile();
69 
70  /** Returns the number of buffers currently in the queue. */
71  size_t GetQueueSize() const;
72 
73  /** Returns the current value of the auto save setting in bytes (default = 0). */
74  size_t GetAutoSave() const;
75 
76  /** Returns the current merge options. */
77  const char* GetMergeOptions();
78 
79  /** By default, TBufferMerger will call TFileMerger::PartialMerge() for each
80  * buffer pushed onto its merge queue. This function lets the user change
81  * this behaviour by telling TBufferMerger to accumulate at least size
82  * bytes in memory before performing a partial merge and flushing to disk.
83  * This can be useful to avoid an excessive amount of work to happen in the
84  * output thread, as the number of TTree headers (which require compression)
85  * written to disk can be reduced.
86  */
87  void SetAutoSave(size_t size);
88 
89  /** Sets the merge options. SetMergeOptions("fast") will disable
90  * recompression of input data into the output if they have different
91  * compression settings.
92  * @param options TFileMerger/TFileMergeInfo merge options
93  */
94  void SetMergeOptions(const TString& options);
95 
96  friend class TBufferMergerFile;
97 
98 private:
99  /** TBufferMerger has no default constructor */
100  TBufferMerger();
101 
102  /** TBufferMerger has no copy constructor */
103  TBufferMerger(const TBufferMerger &);
104 
105  /** TBufferMerger has no copy operator */
106  TBufferMerger &operator=(const TBufferMerger &);
107 
108  void Init(std::unique_ptr<TFile>);
109 
110  void Merge();
111  void Push(TBufferFile *buffer);
112 
113  size_t fAutoSave{0}; //< AutoSave only every fAutoSave bytes
114  size_t fBuffered{0}; //< Number of bytes currently buffered
115  TFileMerger fMerger{false, false}; //< TFileMerger used to merge all buffers
116  std::mutex fMergeMutex; //< Mutex used to lock fMerger
117  std::mutex fQueueMutex; //< Mutex used to lock fQueue
118  std::queue<TBufferFile *> fQueue; //< Queue to which data is pushed and merged
119  std::vector<std::weak_ptr<TBufferMergerFile>> fAttachedFiles; //< Attached files
120 };
121 
122 /**
123  * \class TBufferMerger TBufferMerger.hxx
124  * \ingroup IO
125  *
126  * A TBufferMergerFile is similar to a TMemFile, but when data
127  * is written to it, it is appended to the TBufferMerger queue.
128  * The TBufferMerger merges all data into the output file on disk.
129  */
130 
131 class TBufferMergerFile : public TMemFile {
132 private:
133  TBufferMerger &fMerger; //< TBufferMerger this file is attached to
134 
135  /** Constructor. Can only be called by TBufferMerger.
136  * @param m Merger this file is attached to. */
137  TBufferMergerFile(TBufferMerger &m);
138 
139  /** TBufferMergerFile has no default constructor. */
140  TBufferMergerFile();
141 
142  /** TBufferMergerFile has no copy constructor. */
143  TBufferMergerFile(const TBufferMergerFile &);
144 
145  /** TBufferMergerFile has no copy operator */
146  TBufferMergerFile &operator=(const TBufferMergerFile &);
147 
148  friend class TBufferMerger;
149 
150 public:
151  /** Destructor */
152  ~TBufferMergerFile();
153 
154  using TMemFile::Write;
155 
156  /** Write data into a TBufferFile and append it to TBufferMerger.
157  * @param name Name
158  * @param opt Options
159  * @param bufsize Buffer size
160  * This function must be called before the TBufferMergerFile gets destroyed,
161  * or no data is appended to the TBufferMerger.
162  */
163  virtual Int_t Write(const char *name = nullptr, Int_t opt = 0, Int_t bufsize = 0) override;
164 
165  ClassDefOverride(TBufferMergerFile, 0);
166 };
167 
168 } // namespace Experimental
169 } // namespace ROOT
170 
171 #endif