Uni20
Asynchronous tensor and runtime library.
Loading...
Searching...
No Matches
output_session.hpp
Go to the documentation of this file.
1
5#pragma once
7#include "run_context.hpp"
8#include <cstddef>
9#include <exception>
10#include <filesystem>
11#include <functional>
12#include <map>
13#include <memory>
14#include <optional>
15#include <ostream>
16#include <set>
17#include <stdexcept>
18#include <string>
19#include <utility>
20#include <variant>
21#include <vector>
22
23namespace uni20
24{
25enum class output_format
26{
28 csv,
29 tsv,
32 json,
34};
36{
37 open,
38 begin,
39 row,
41 flush,
42 finish,
43 close
44};
45
58
60{
61 std::size_t destination;
62 std::string name;
65 std::exception_ptr exception;
66};
68{
69 std::vector<output_failure> failures = {};
70};
71class output_error : public std::runtime_error {
72 public:
74 : std::runtime_error("required run output failed"), report_(std::move(report))
75 {}
76 [[nodiscard]] output_report const& report() const { return report_; }
77
78 private:
79 output_report report_;
80};
81
82namespace output_detail
83{
84constexpr bool is_commented(output_format format)
85{
87}
88
89struct destination
90{
91 std::size_t id;
92 std::string name;
93 output_format format;
94 output_destination_options options;
95 std::filesystem::path path = {};
96 std::shared_ptr<std::ostream> stream = {};
97 std::function<void()> close = {};
98 bool opened = false;
99 bool active_table = false;
100 bool closed = false;
101 bool suppressed = false;
102 std::set<std::string> tables = {};
103 std::vector<output_failure> failures = {};
104 presentation::table_metadata initial = {};
105
106 void check() const;
107 void fail(output_operation operation, std::exception_ptr error);
108 void flush();
109 void comments(presentation::table_metadata const& fields);
110 presentation::table_metadata metadata_fields(metadata_document const& metadata) const;
111 void preamble(metadata_document const& metadata);
112};
113
115class table_sink {
116 public:
117 table_sink(std::shared_ptr<destination> output, std::string name);
118 template <typename Schema>
119 void begin(std::string const& title, Schema const& schema, presentation::table_metadata const& metadata,
121 {
122 this->attempt(output_operation::begin, [&] {
123 auto& d = *output_;
124 if (d.active_table) throw std::logic_error("previous output table is still active");
125 auto combined = d.initial;
126 for (auto const& [key, value] : metadata)
127 if (!combined.emplace(key, value).second) throw std::invalid_argument("table/run metadata collision: " + key);
128 if (d.format == output_format::named_json)
129 {
130 if (d.tables.size() > 1) *d.stream << ',';
131 *d.stream << "{\"name\":";
133 *d.stream << ",\"data\":";
134 }
135 if (is_commented(d.format) && d.options.preamble)
136 {
137 d.comments(metadata);
138 if (start.first_row) d.comments({{"first_row", std::to_string(start.first_row)}});
139 }
140 d.active_table = true;
141 std::visit([&](auto& sink) { sink.begin(title, schema, combined, start); }, sink_);
142 });
143 }
144 template <typename Schema, typename Row> void row(Schema const& schema, Row const& row)
145 {
146 this->attempt(output_operation::row, [&] {
147 std::visit([&](auto& sink) { sink.row(schema, row); }, sink_);
148 if (output_->format == output_format::terminal || output_->options.flush_each_row) output_->flush();
149 });
150 }
151 void finish(presentation::table_metadata const& summary);
152
153 private:
154 template <typename F> void attempt(output_operation operation, F&& fn)
155 {
156 output_->check();
157 try
158 {
159 fn();
161 }
162 catch (...)
163 {
164 output_->fail(operation, std::current_exception());
165 throw;
166 }
167 }
168 using adapter = std::variant<presentation::data_table_detail::delimited_sink,
169 presentation::data_table_detail::json_sink_adapter,
170 presentation::data_table_detail::terminal_sink_adapter>;
171 static adapter make_adapter(std::shared_ptr<destination> const& output);
172 std::shared_ptr<destination> output_;
173 std::string name_;
174 adapter sink_;
175};
176} // namespace output_detail
177
185 public:
186 explicit output_session(metadata_document initial = {}, bool quiet = false)
187 : initial_(std::move(initial)), quiet_(quiet)
188 {}
193
194 std::size_t file(std::filesystem::path path, output_format format, output_destination_options options = {});
196 std::size_t stream(std::string name, std::shared_ptr<std::ostream> out, output_format format,
197 output_destination_options options = {}, std::function<void()> close = {});
199 output_destination_options options = {});
200
202 output_report open();
203
205 template <presentation::DataTableValue... Ts>
208 std::vector<std::size_t> destinations = {})
209 {
210 return this->attach_impl(table, std::move(name), replay, std::move(destinations), std::nullopt);
211 }
212
215 template <presentation::DataTableValue... Ts>
217 presentation::table_metadata summary = {})
218 {
219 if (table.retention_policy() != presentation::retention::all)
220 throw std::logic_error("snapshot export requires retained history");
221 if (table.finished() && !summary.empty() && summary != *table.summary())
222 throw std::invalid_argument("finished table summary cannot be changed by a snapshot export");
223 return this->attach_impl(table, std::move(name), presentation::sink_replay::all, {}, std::move(summary));
224 }
225
227 output_report flush();
232 output_report finish(metadata_document summary = {});
233 [[nodiscard]] output_report report() const;
234
235 private:
236 template <presentation::DataTableValue... Ts>
237 output_report attach_impl(presentation::data_table<Ts...>& table, std::string name,
238 presentation::sink_replay replay, std::vector<std::size_t> destinations,
239 std::optional<presentation::table_metadata> snapshot_summary)
240 {
241 if (finished_) throw std::logic_error("output session is finished");
242 metadata_detail::dt::validate_identifier(name);
243 if (replay == presentation::sink_replay::all && table.retention_policy() == presentation::retention::none &&
244 table.size())
245 throw std::logic_error("table history is unavailable; request future_only explicitly");
246 auto selected = this->select(destinations);
247 for (auto const& d : selected)
248 {
249 if (d->active_table || d->tables.contains(name))
250 throw std::logic_error("table already attached or previous table active");
251 if (!d->tables.empty() && d->format != output_format::terminal && d->format != output_format::named_json)
252 throw std::logic_error("multiple tables require terminal or named_json output");
253 }
254 try
255 {
256 (void)this->open();
257 }
258 catch (output_error const&)
259 {} // Still attempt healthy destinations.
260 for (auto const& d : selected)
261 {
262 if (d->suppressed || !d->failures.empty()) continue;
263 d->tables.insert(name);
264 try
265 {
266 auto attachment =
267 table.attach(output_detail::table_sink(d, name), {.required = d->options.required, .replay = replay});
268 if (snapshot_summary && !table.finished()) (void)table.finish_sink(attachment.id, *snapshot_summary);
269 }
271 {} // table has already recorded/disabled this sink.
272 }
273 return this->checked_report();
274 }
275
276 std::vector<std::shared_ptr<output_detail::destination>> select(std::vector<std::size_t> const& ids) const;
277 std::size_t register_destination(std::shared_ptr<output_detail::destination> destination);
278 void preflight() const;
279 output_report checked_report() const;
280 metadata_document initial_;
281 bool quiet_ = false;
282 bool finished_ = false;
283 std::vector<std::shared_ptr<output_detail::destination>> outputs_;
284};
285} // namespace uni20
Ordered, uniquely identified metadata. Copies are independent snapshots.
Definition metadata.hpp:306
Definition output_session.hpp:71
output_error(output_report report)
Definition output_session.hpp:73
output_report const & report() const
Definition output_session.hpp:76
An explicitly finalized set of owned result streams, with no global display changes.
Definition output_session.hpp:184
std::size_t file(std::filesystem::path path, output_format format, output_destination_options options={})
Definition output_session.cpp:102
output_report attach(presentation::data_table< Ts... > &table, std::string name, presentation::sink_replay replay=presentation::sink_replay::all, std::vector< std::size_t > destinations={})
Replay selected destinations, then subscribe them to future rows.
Definition output_session.hpp:206
output_report open()
Preflight aliases before opening any files, then emit the human/comment preamble once.
Definition output_session.cpp:189
output_session & operator=(output_session const &)=delete
output_session(metadata_document initial={}, bool quiet=false)
Definition output_session.hpp:186
std::size_t standard_output(output_format format=output_format::terminal, output_destination_options options={})
Definition output_session.cpp:124
output_session(output_session const &)=delete
output_report write_table(presentation::data_table< Ts... > &table, std::string name, presentation::table_metadata summary={})
Export retained rows, closing only these subscriptions and leaving the source table appendable.
Definition output_session.hpp:216
output_report flush()
Flush all active destinations without ending tables or writing summaries. Does not fsync.
Definition output_session.cpp:252
output_session & operator=(output_session &&)=delete
output_session(output_session &&)=default
output_report report() const
Definition output_session.cpp:239
std::size_t stream(std::string name, std::shared_ptr< std::ostream > out, output_format format, output_destination_options options={}, std::function< void()> close={})
Retain a shared stream owner. An optional explicit closer participates in finish error reporting.
Definition output_session.cpp:110
Required output failed after all eligible sinks were attempted; retained rows are not rolled back.
Definition data_table.hpp:383
Typed result table with synchronous sinks and optional retained history.
Definition data_table.hpp:404
locale_t value
Definition data_table.cpp:49
Synchronous CSV, TSV, JSON and terminal adapters for typed table subscriptions.
Definition qnum.hpp:403
void check(cublasStatus_t status, std::string_view operation, int device, std::source_location where)
Raise unless a cuBLAS call returned CUBLAS_STATUS_SUCCESS.
Definition cublas_error.cpp:52
stream
Selects the ordinary display stream for a message.
Definition display.hpp:25
streaming_table table(std::string title, stream destination)
Create a schema-first streaming display table.
Definition display.cpp:800
std::function< void(event const &)> sink
Callable that receives display events for final routing and rendering.
Definition display.hpp:126
void check_output(std::ostream &out)
Definition data_table.cpp:40
void write_json_string(std::ostream &out, std::string_view value)
Definition data_table.cpp:71
output_policy plain_policy()
Build a policy for plain file/log rendering with no ANSI color.
Definition presentation.cpp:1195
std::map< std::string, std::string > table_metadata
Application metadata is owned text, independent of numerical rows.
Definition data_table.hpp:314
sink_replay
Full replay is the default. Future-only attachment explicitly opts out of history.
Definition data_table.hpp:332
Definition async/async.hpp:26
output_format
Definition output_session.hpp:26
output_operation
Definition output_session.hpp:36
Owned run provenance, typed documents and explicitly scoped computation timing.
Definition output_session.hpp:47
bool flush_each_row
Definition output_session.hpp:50
presentation::table_projection projection
Definition output_session.hpp:52
std::map< std::string, std::string > metadata_keys
Map run field IDs to exported keys wherever they occur in initial metadata or final summaries.
Definition output_session.hpp:55
bool required
Definition output_session.hpp:48
bool overwrite
Definition output_session.hpp:49
bool preamble
Definition output_session.hpp:51
presentation::output_policy human_policy
Definition output_session.hpp:56
Definition output_session.hpp:60
std::string name
Definition output_session.hpp:62
std::size_t destination
Definition output_session.hpp:61
std::exception_ptr exception
Definition output_session.hpp:65
output_operation operation
Definition output_session.hpp:64
bool required
Definition output_session.hpp:63
Definition output_session.hpp:68
std::vector< output_failure > failures
Definition output_session.hpp:69
The index of the first row this attachment can emit (zero for full replay).
Definition data_table.hpp:344
std::size_t first_row
Definition data_table.hpp:345
Output policy shared by presentation renderers and layout helpers.
Definition presentation.hpp:186
Ordered output columns and independent display overrides. Empty columns selects the full schema.
Definition data_table.hpp:308