Back to home page

EIC code displayed by LXR

 
 

    


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

0001 /// \file ROOT/RNTupleWriter.hxx
0002 /// \ingroup NTuple ROOT7
0003 /// \author Jakob Blomer <jblomer@cern.ch>
0004 /// \date 2024-02-20
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_RNTupleWriter
0017 #define ROOT7_RNTupleWriter
0018 
0019 #include <ROOT/RConfig.hxx> // for R__unlikely
0020 #include <ROOT/REntry.hxx>
0021 #include <ROOT/RError.hxx>
0022 #include <ROOT/RNTupleFillContext.hxx>
0023 #include <ROOT/RNTupleMetrics.hxx>
0024 #include <ROOT/RNTupleModel.hxx>
0025 #include <ROOT/RNTupleUtil.hxx>
0026 #include <ROOT/RPageStorage.hxx>
0027 
0028 #include <cstddef>
0029 #include <cstdint>
0030 #include <memory>
0031 #include <string_view>
0032 #include <utility>
0033 
0034 class TFile;
0035 
0036 namespace ROOT {
0037 namespace Experimental {
0038 
0039 class RNTupleWriteOptions;
0040 
0041 namespace Internal {
0042 // Non-public factory method for an RNTuple writer that uses an already constructed page sink
0043 std::unique_ptr<RNTupleWriter>
0044 CreateRNTupleWriter(std::unique_ptr<RNTupleModel> model, std::unique_ptr<Internal::RPageSink> sink);
0045 } // namespace Internal
0046 
0047 // clang-format off
0048 /**
0049 \class ROOT::Experimental::RNTupleWriter
0050 \ingroup NTuple
0051 \brief An RNTuple that gets filled with entries (data) and writes them to storage
0052 
0053 An output ntuple can be filled with entries. The caller has to make sure that the data that gets filled into an ntuple
0054 is not modified for the time of the Fill() call. The fill call serializes the C++ object into the column format and
0055 writes data into the corresponding column page buffers.  Writing of the buffers to storage is deferred and can be
0056 triggered by CommitCluster() or by destructing the writer.  On I/O errors, an exception is thrown.
0057 */
0058 // clang-format on
0059 class RNTupleWriter {
0060    friend RNTupleModel::RUpdater;
0061    friend std::unique_ptr<RNTupleWriter>
0062       Internal::CreateRNTupleWriter(std::unique_ptr<RNTupleModel>, std::unique_ptr<Internal::RPageSink>);
0063 
0064 private:
0065    /// The page sink's parallel page compression scheduler if IMT is on.
0066    /// Needs to be destructed after the page sink (in the fill context) is destructed and so declared before.
0067    std::unique_ptr<Internal::RPageStorage::RTaskScheduler> fZipTasks;
0068    RNTupleFillContext fFillContext;
0069    Detail::RNTupleMetrics fMetrics;
0070 
0071    NTupleSize_t fLastCommittedClusterGroup = 0;
0072 
0073    RNTupleWriter(std::unique_ptr<RNTupleModel> model, std::unique_ptr<Internal::RPageSink> sink);
0074 
0075    RNTupleModel &GetUpdatableModel() { return *fFillContext.fModel; }
0076    Internal::RPageSink &GetSink() { return *fFillContext.fSink; }
0077 
0078    // Helper function that is called from CommitCluster() when necessary
0079    void CommitClusterGroup();
0080 
0081    /// Create a writer, potentially wrapping the sink in a RPageSinkBuf.
0082    static std::unique_ptr<RNTupleWriter> Create(std::unique_ptr<RNTupleModel> model,
0083                                                 std::unique_ptr<Internal::RPageSink> sink,
0084                                                 const RNTupleWriteOptions &options);
0085 
0086 public:
0087    /// Throws an exception if the model is null.
0088    static std::unique_ptr<RNTupleWriter> Recreate(std::unique_ptr<RNTupleModel> model, std::string_view ntupleName,
0089                                                   std::string_view storage,
0090                                                   const RNTupleWriteOptions &options = RNTupleWriteOptions());
0091    static std::unique_ptr<RNTupleWriter>
0092    Recreate(std::initializer_list<std::pair<std::string_view, std::string_view>> fields, std::string_view ntupleName,
0093             std::string_view storage, const RNTupleWriteOptions &options = RNTupleWriteOptions());
0094    /// Throws an exception if the model is null.
0095    static std::unique_ptr<RNTupleWriter> Append(std::unique_ptr<RNTupleModel> model, std::string_view ntupleName,
0096                                                 TFile &file,
0097                                                 const RNTupleWriteOptions &options = RNTupleWriteOptions());
0098    RNTupleWriter(const RNTupleWriter &) = delete;
0099    RNTupleWriter &operator=(const RNTupleWriter &) = delete;
0100    ~RNTupleWriter();
0101 
0102    /// The simplest user interface if the default entry that comes with the ntuple model is used.
0103    /// \return The number of uncompressed bytes written.
0104    std::size_t Fill() { return fFillContext.Fill(fFillContext.fModel->GetDefaultEntry()); }
0105    /// Multiple entries can have been instantiated from the ntuple model.  This method will perform
0106    /// a light check whether the entry comes from the ntuple's own model.
0107    /// \return The number of uncompressed bytes written.
0108    std::size_t Fill(REntry &entry) { return fFillContext.Fill(entry); }
0109    /// Ensure that the data from the so far seen Fill calls has been written to storage
0110    void CommitCluster(bool commitClusterGroup = false)
0111    {
0112       fFillContext.CommitCluster();
0113       if (commitClusterGroup)
0114          CommitClusterGroup();
0115    }
0116 
0117    std::unique_ptr<REntry> CreateEntry() { return fFillContext.CreateEntry(); }
0118 
0119    /// Return the entry number that was last committed in a cluster.
0120    NTupleSize_t GetLastCommitted() const { return fFillContext.GetLastCommitted(); }
0121    /// Return the entry number that was last committed in a cluster group.
0122    NTupleSize_t GetLastCommittedClusterGroup() const { return fLastCommittedClusterGroup; }
0123    /// Return the number of entries filled so far.
0124    NTupleSize_t GetNEntries() const { return fFillContext.GetNEntries(); }
0125 
0126    void EnableMetrics() { fMetrics.Enable(); }
0127    const Detail::RNTupleMetrics &GetMetrics() const { return fMetrics; }
0128 
0129    const RNTupleModel &GetModel() const { return *fFillContext.fModel; }
0130 
0131    /// Get a `RNTupleModel::RUpdater` that provides limited support for incremental updates to the underlying
0132    /// model, e.g. addition of new fields.
0133    ///
0134    /// **Example: add a new field after the model has been used to construct a `RNTupleWriter` object**
0135    /// ~~~ {.cpp}
0136    /// #include <ROOT/RNTuple.hxx>
0137    /// using ROOT::Experimental::RNTupleModel;
0138    /// using ROOT::Experimental::RNTupleWriter;
0139    ///
0140    /// auto model = RNTupleModel::Create();
0141    /// auto fldFloat = model->MakeField<float>("fldFloat");
0142    /// auto writer = RNTupleWriter::Recreate(std::move(model), "myNTuple", "some/file.root");
0143    /// auto updater = writer->CreateModelUpdater();
0144    /// updater->BeginUpdate();
0145    /// updater->AddField(std::make_unique<RField<float>>("pt"));
0146    /// updater->CommitUpdate();
0147    ///
0148    /// // ...
0149    /// ~~~
0150    std::unique_ptr<RNTupleModel::RUpdater> CreateModelUpdater()
0151    {
0152       return std::make_unique<RNTupleModel::RUpdater>(*this);
0153    }
0154 }; // class RNTupleWriter
0155 
0156 } // namespace Experimental
0157 } // namespace ROOT
0158 
0159 #endif // ROOT7_RNTupleWriter