Back to home page

EIC code displayed by LXR

 
 

    


Warning, file /include/root/ROOT/RNTupleParallelWriter.hxx was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).

0001 /// \file ROOT/RNTupleParallelWriter.hxx
0002 /// \ingroup NTuple
0003 /// \author Jonas Hahnfeld <jonas.hahnfeld@cern.ch>
0004 /// \date 2024-02-01
0005 
0006 /*************************************************************************
0007  * Copyright (C) 1995-2024, Rene Brun and Fons Rademakers.               *
0008  * All rights reserved.                                                  *
0009  *                                                                       *
0010  * For the licensing terms see $ROOTSYS/LICENSE.                         *
0011  * For the list of contributors see $ROOTSYS/README/CREDITS.             *
0012  *************************************************************************/
0013 
0014 #ifndef ROOT_RNTupleParallelWriter
0015 #define ROOT_RNTupleParallelWriter
0016 
0017 #include <ROOT/RNTupleMetrics.hxx>
0018 #include <ROOT/RNTupleWriteOptions.hxx>
0019 
0020 #include <memory>
0021 #include <mutex>
0022 #include <string_view>
0023 #include <vector>
0024 
0025 class TDirectory;
0026 
0027 namespace ROOT {
0028 
0029 class RNTupleModel;
0030 
0031 namespace Internal {
0032 class RPageSink;
0033 } // namespace Internal
0034 
0035 class RNTupleFillContext;
0036 
0037 /**
0038 \class ROOT::RNTupleParallelWriter
0039 \ingroup NTuple
0040 \brief A writer to fill an RNTuple from multiple contexts
0041 
0042 Compared to the sequential RNTupleWriter, a parallel writer enables the creation of multiple RNTupleFillContext (see
0043 CreateFillContext()).  Each fill context prepares independent clusters that are appended to the common RNTuple with
0044 internal synchronization.  Before destruction, all fill contexts must have flushed their data and been destroyed (or
0045 data could be lost!).
0046 
0047 For user convenience, CreateFillContext() is thread-safe and may be called from multiple threads in parallel at any
0048 time, also after some data has already been written.  Internally, the original model is cloned and ownership is passed
0049 to a newly created RNTupleFillContext.  For that reason, it is recommended to use RNTupleModel::CreateBare when creating
0050 the model for parallel writing and avoid the allocation of a useless default REntry per context.
0051 
0052 Note that the sequence of independently prepared clusters is indeterminate and therefore entries are only partially
0053 ordered:  Entries from one context are totally ordered as they were filled.  However, there is no orderering with other
0054 contexts and the entries may be appended to the RNTuple either before or after other entries written in parallel into
0055 other contexts.  In addition, two consecutive entries in one fill context can end up separated in the final RNTuple, if
0056 they happen to fall onto a cluster boundary and other contexts append more entries before the next cluster is full.
0057 
0058 At the moment, the parallel writer does not (yet) support incremental updates of the underlying model. Please refer to
0059 RNTupleWriter::CreateModelUpdater if required for your use case.
0060 */
0061 class RNTupleParallelWriter {
0062 private:
0063    /// A global mutex to protect the internal data structures of this object.
0064    std::mutex fMutex;
0065    /// A mutex to synchronize the final page sink.
0066    std::mutex fSinkMutex;
0067    /// The final RPageSink that represents the synchronization point.
0068    std::unique_ptr<ROOT::Internal::RPageSink> fSink;
0069    /// The original RNTupleModel connected to fSink; needs to be destructed before it.
0070    std::unique_ptr<ROOT::RNTupleModel> fModel;
0071    Experimental::Detail::RNTupleMetrics fMetrics;
0072    /// List of all created helpers. They must be destroyed before this RNTupleParallelWriter is destructed.
0073    std::vector<std::weak_ptr<RNTupleFillContext>> fFillContexts;
0074 
0075    RNTupleParallelWriter(std::unique_ptr<ROOT::RNTupleModel> model, std::unique_ptr<ROOT::Internal::RPageSink> sink);
0076    RNTupleParallelWriter(const RNTupleParallelWriter &) = delete;
0077    RNTupleParallelWriter &operator=(const RNTupleParallelWriter &) = delete;
0078 
0079 public:
0080    /// Recreate a new file and return a writer to write an RNTuple.
0081    static std::unique_ptr<RNTupleParallelWriter>
0082    Recreate(std::unique_ptr<ROOT::RNTupleModel> model, std::string_view ntupleName, std::string_view storage,
0083             const ROOT::RNTupleWriteOptions &options = ROOT::RNTupleWriteOptions());
0084    /// Append an RNTuple to the existing file.
0085    ///
0086    /// While the writer synchronizes between multiple fill contexts created from the same writer, there is no
0087    /// synchronization with other writers or other clients that write into the same file. The caller must ensure that
0088    /// the underlying file is not be accessed while data is filled into any created context. To improve performance, it
0089    /// is allowed to use special methods that are guaranteed to not interact with the underlying file, such as
0090    /// RNTupleFillContext::FillNoFlush().
0091    static std::unique_ptr<RNTupleParallelWriter>
0092    Append(std::unique_ptr<ROOT::RNTupleModel> model, std::string_view ntupleName, TDirectory &fileOrDirectory,
0093           const ROOT::RNTupleWriteOptions &options = ROOT::RNTupleWriteOptions());
0094 
0095    ~RNTupleParallelWriter();
0096 
0097    /// Create a new RNTupleFillContext that can be used to fill entries and prepare clusters in parallel. This method is
0098    /// thread-safe and may be called from multiple threads in parallel at any time, also after some data has already
0099    /// been written.
0100    ///
0101    /// Note that all fill contexts must be destroyed before CommitDataset() is called.
0102    std::shared_ptr<RNTupleFillContext> CreateFillContext();
0103 
0104    /// Automatically called by the destructor
0105    void CommitDataset();
0106 
0107    void EnableMetrics() { fMetrics.Enable(); }
0108    const Experimental::Detail::RNTupleMetrics &GetMetrics() const { return fMetrics; }
0109 };
0110 
0111 } // namespace ROOT
0112 
0113 #endif