// Diagnostics: txn_info, reader list, commit latency; mdbx_chk
// Textbook section: Volume V, chapter 30, "Diagnostics", §30.2 "Tools", §30.4 "Scenarios".
// What it demonstrates: a helper dumper — mdbx_txn_info (id/lag/space),
//   mdbx_reader_list (reader slots), parsing of commit_latency; instructions
//   for running mdbx_chk to verify integrity.
// Build: g++ -std=c++17 -I<libmdbx-include> -I../common 37-diagnostics.c++ -lmdbx
// Run: ./37-diagnostics
// Expected output:
//   txn_info: id=<N> lag=<L> used=<U> dirty=<D>
//   ok: diagnostics dumpers work
// On failure — message to stderr and exit 1.
//
// SPDX-License-Identifier: Apache-2.0

#include <iostream>
#include <string>

#include "common.h++"
#include <mdbx.h++>

int main() {
  try {
    const std::string path = std::string(example::tmpdir()) + "/mdbx-37-diagnostics.mdbx";
    mdbx::env::remove(path);
    mdbx::env_managed env = example::env_open(path);

    {
      auto txn = env.start_write();
      auto table = txn.open_map(nullptr);
      for (int i = 0; i < 100; ++i)
        txn.insert(table, mdbx::slice("k" + std::to_string(i)), mdbx::slice("v"));

      // Information about the current writing transaction.
      const auto info = txn.get_info(true /* scan_rlt */);
      std::cout << "txn_info: id=" << info.txn_id << " lag=" << info.txn_reader_lag << " used=" << info.txn_space_used
                << " dirty=" << info.txn_space_dirty << "\n";
      txn.commit();
    }

    // The reader list (RLT).
    struct visitor {
      int operator()(const mdbx::env::reader_info &ri, int) {
        std::cout << "reader slot=" << ri.slot << " pid=" << ri.pid << " tid=" << ri.thread
                  << " txnid=" << ri.transaction_id << " lag=" << ri.transaction_lag << "\n";
        return mdbx::continue_loop;
      }
    } v;
    env.enumerate_readers(v);

    // Latency of the last commit (see S20).
    {
      auto txn = env.start_write();
      auto table = txn.open_map(nullptr);
      txn.insert(table, mdbx::slice("last"), mdbx::slice("v"));
      const auto lat = txn.commit_get_latency();
      std::cout << "commit latency: whole=" << lat.whole << " us\n";
    }

    // Integrity check (CLI): mdbx_chk -w <path> [-vvv]
    std::cout << "hint: run 'mdbx_chk -w -vvv " << path << "' to verify integrity\n";

    std::cout << "ok: diagnostics dumpers work\n";
    return EXIT_SUCCESS;
  } catch (const std::exception &ex) {
    std::cerr << "error: " << ex.what() << "\n";
    return EXIT_FAILURE;
  }
}