Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-30 10:22:37

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