You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
102 lines
2.6 KiB
102 lines
2.6 KiB
// leaf_mutable_block.cpp |
|
#include <boost/leaf.hpp> |
|
#include <ctime> |
|
#include <iostream> |
|
#include <optional> |
|
#include <string> |
|
#include <utility> |
|
|
|
namespace leaf = boost::leaf; |
|
|
|
struct error_tag {}; |
|
struct open_error {}; |
|
struct write_error {}; |
|
|
|
struct diagnostic_context { |
|
std::string file; |
|
std::optional<std::string> user; |
|
std::optional<int> privileges; |
|
std::optional<int> chunk; |
|
std::optional<std::size_t> chunk_size; |
|
std::optional<std::time_t> timestamp; |
|
}; |
|
|
|
leaf::result<void> write_chunk(int chunk, std::size_t size) |
|
{ |
|
if (chunk == 3) |
|
return leaf::new_error(write_error{}); |
|
|
|
return {}; |
|
} |
|
|
|
leaf::result<void> process_file(std::string path, std::string user) |
|
{ |
|
error_tag tag; |
|
diagnostic_context diag; |
|
|
|
diag.file = path; |
|
diag.user = std::move(user); |
|
diag.privileges = 0600; |
|
|
|
[[maybe_unused]] auto tag_ctx = leaf::on_error(tag); |
|
// on_error captures a snapshot of diag, not a reference, so any |
|
// fields mutated later would be invisible unless re-registered. |
|
[[maybe_unused]] auto diag_ctx = leaf::on_error(diag); |
|
|
|
if (diag.file.empty()) |
|
return leaf::new_error(open_error{}); |
|
|
|
for (int i = 0; i != 5; ++i) { |
|
diag.chunk = i; |
|
diag.chunk_size = 4096; |
|
diag.timestamp = std::time(nullptr); |
|
// Re-registering publishes the updated snapshot; the newest |
|
// registration wins for the handler. |
|
[[maybe_unused]] auto refresh = leaf::on_error(diag); |
|
|
|
auto r = write_chunk(i, 4096); |
|
if (!r) |
|
return r; |
|
} |
|
|
|
return {}; |
|
} |
|
|
|
int main() |
|
{ |
|
return leaf::try_handle_all( |
|
[]() -> leaf::result<int> { |
|
BOOST_LEAF_CHECK(process_file("data.bin", "alice")); |
|
return 0; |
|
}, |
|
|
|
[](error_tag const&, diagnostic_context const& d) { |
|
// d is the newest snapshot taken before the error was raised, |
|
// which is why chunk/chunk_size/timestamp are filled in here. |
|
std::cerr << "operation failed: file=" << d.file; |
|
|
|
if (d.user) |
|
std::cerr << ", user=" << *d.user; |
|
|
|
if (d.privileges) |
|
std::cerr << ", privileges=" << *d.privileges; |
|
|
|
if (d.chunk) |
|
std::cerr << ", chunk=" << *d.chunk; |
|
|
|
if (d.chunk_size) |
|
std::cerr << ", chunk_size=" << *d.chunk_size; |
|
|
|
if (d.timestamp) |
|
std::cerr << ", time=" << *d.timestamp; |
|
|
|
std::cerr << '\n'; |
|
return 1; |
|
}, |
|
|
|
[] { |
|
std::cerr << "operation failed before diagnostic context existed\n"; |
|
return 2; |
|
} |
|
); |
|
}
|
|
|