// Environment configuration: geometry and runtime options
// Раздел учебника: Том II, глава 9, «Конфигурация окружения»,
//   разделы «Геометрия», «Runtime options».
// Что демонстрирует: задание геометрии (lower/now/upper/growth/shrink) при
//   создании окружения; установку и чтение runtime-опций: writethrough_threshold,
//   merge_threshold, sync_period/sync_bytes, prefault_write_enable.
// Сборка: g++ -std=c++17 -I<libmdbx-include> -I../common 11-geometry-options.c++ -lmdbx
// Запуск: ./11-geometry-options
// Ожидаемый вывод (значения могут отличаться на других платформах):
//   geometry: lower=8 MiB now=16 MiB upper=64 MiB grow=8 MiB shrink=2 MiB
//   merge_threshold_dot16=21845 (default ~33%)
//   prefault_write_enable=1
//   ok: geometry and runtime options set/read
// На Windows writethrough_threshold не поддерживается (§10.5): значение
// не устанавливается и печатается эффективное (2147483647).
// При сбое — сообщение в stderr и 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-11-geometry-options.mdbx";
    mdbx::env::remove(path);

    // Геометрия: нижняя/текущая/верхняя границы размера БД, шаг роста,
    // порог сжатия. Здесь — компактная БД для примера.
    mdbx::env::geometry geo;
    geo.size_lower = 8 * mdbx::env::geometry::MB;
    geo.size_now = 16 * mdbx::env::geometry::MB;
    geo.size_upper = 64 * mdbx::env::geometry::MB;
    geo.growth_step = 8 * mdbx::env::geometry::MB;
    geo.shrink_threshold = 2 * mdbx::env::geometry::MB;

    mdbx::env_managed env(path, mdbx::env_managed::create_parameters().set_geometry(geo),
                          mdbx::env::operate_parameters());

    // Runtime-опции: устанавливаем и читаем обратно.
    // MDBX_opt_writethrough_threshold не поддерживается на Windows (Том II, §10.5):
    // там всегда write-through, а set_option принимает только default/0/UINT_MAX,
    // любое другое значение -> MDBX_EINVAL.
#if !defined(_WIN32)
    env.set_extra_option(mdbx::env::extra_runtime_option::writethrough_threshold, 1 << 20);
#endif
    env.set_extra_option(mdbx::env::extra_runtime_option::merge_threshold_dot16, 65536 / 3);
    // sync_bytes = 256 KiB
    env.set_sync_threshold(256 * 1024);
    env.set_extra_option(mdbx::env::extra_runtime_option::prefault_write_enable, 1);

    using opt = mdbx::env::extra_runtime_option;
    const uint64_t wt = env.extra_option(opt::writethrough_threshold);
    const uint64_t mt = env.extra_option(opt::merge_threshold_dot16);
    const uint64_t sb = env.extra_option(opt::sync_bytes);
    const uint64_t pfw = env.extra_option(opt::prefault_write_enable);
    std::cout << "writethrough_threshold=" << wt << "\n";
    std::cout << "merge_threshold_dot16=" << mt << " (" << (mt * 100 / 65536) << "% of page)\n";
    std::cout << "sync_bytes=" << sb << "\n";
    std::cout << "prefault_write_enable=" << pfw << "\n";

    // Прочитанная геометрия после открытия.
    auto info = env.get_info();
    const auto &g = info.mi_geo;
    std::cout << "geometry: lower=" << g.lower / 1000 << " KiB now=" << g.current / 1000
              << " KiB upper=" << g.upper / 1000 << " KiB\n";

    std::cout << "ok: geometry and runtime options set/read\n";
    return EXIT_SUCCESS;
  } catch (const std::exception &ex) {
    std::cerr << "error: " << ex.what() << "\n";
    return EXIT_FAILURE;
  }
}