// Scenario configurations: template for choosing options
// Textbook section: Volume IV, chapter 22, "Choosing a configuration for a scenario".
// What it demonstrates: six typical environment configurations (write-heavy,
//   read-heavy, mobile, analytics, multi-process reading, low latency) as functions
//   returning operate_parameters; applying one of them and setting additional
//   runtime options on the opened environment.
// Build: g++ -std=c++17 -I<libmdbx-include> -I../common 29-scenario-configs.c++ -lmdbx
// Run: ./29-scenario-configs
// Expected output:
//   write-heavy config applied; inserted 1000 keys
//   ok: scenario config template applied
// On failure — message to stderr and exit 1.
//
// SPDX-License-Identifier: Apache-2.0

#include <iostream>
#include <string>

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

namespace {

using params = mdbx::env::operate_parameters;
using opt = mdbx::env::extra_runtime_option;

// Write-heavy: lazy synchronization, a sufficient number of named tables.
params write_heavy() { return params().lazy_weak_tail().set_max_maps(64); }

// Read-heavy: maximum durability, many reader slots.
[[maybe_unused]] params read_heavy() { return params().robust_synchronous().set_max_readers(1024).set_max_maps(64); }

// Mobile device: small file size, gentle treatment of flash memory.
[[maybe_unused]] params mobile() { return params().lazy_weak_tail().set_max_maps(64); }

// Analytics: batch writes, no nitpicking over balancing.
[[maybe_unused]] params analytics() { return params().lazy_weak_tail().set_max_maps(64); }

// Multi-process reading: many reader slots, stable geometry.
[[maybe_unused]] params multi_process_read() { return params().set_max_readers(4096).set_max_maps(64); }

// Low latency: NOMETASYNC (data is on disk, metadata may lag behind).
[[maybe_unused]] params low_latency() { return params().half_synchronous_weak_last().set_max_maps(64); }

} // namespace

int main() {
  try {
    const std::string path = std::string(example::tmpdir()) + "/mdbx-29-scenario-configs.mdbx";
    mdbx::env::remove(path);

    // "Application template": take the configuration for the scenario and work.
    auto env = example::env_open(path, write_heavy());
    // Additional runtime options are set on the opened environment:
    env.set_extra_option(opt::prefault_write_enable, 1);
    // ~33% of the page
    env.set_extra_option(opt::merge_threshold_dot16, 65536 / 3);
    {
      auto txn = env.start_write();
      auto table = txn.open_map(nullptr);
      for (int i = 0; i < 1000; ++i)
        txn.insert(table, mdbx::slice("k" + std::to_string(i)), mdbx::slice("v"));
      txn.commit();
    }
    std::cout << "write-heavy config applied; inserted 1000 keys\n";

    std::cout << "ok: scenario config template applied\n";
    return EXIT_SUCCESS;
  } catch (const std::exception &ex) {
    std::cerr << "error: " << ex.what() << "\n";
    return EXIT_FAILURE;
  }
}