/*
**  Private declarations for the hissqlite history backend.
**
**  Written by Kevin Bowling in 2026.
*/

#ifndef HISSQLITE_PRIVATE_H
#define HISSQLITE_PRIVATE_H

#include "config.h"
#include "inn/history.h"
#include "inn/libinn.h"
#include "inn/storage.h"

#include <sqlite3.h>

/*
**  Generated by sqlite-helper-gen from the .sql files at build time:
**    hissqlite-init.{c,h}  -> hissqlite_init_t  / hissqlite_init_helper
**    hissqlite-main.{c,h}  -> hissqlite_main_t  / hissqlite_main_helper
**    hissqlite-read.{c,h}  -> hissqlite_read_t  / hissqlite_read_helper
**  sqlite-helper.{c,h} and sqlite-helper-gen are shared with the ovsqlite
**  overview backend (lib/ and include/inn/).
*/
#include "hissqlite-init.h"
#include "hissqlite-main.h"
#include "hissqlite-read.h"

#define HISSQLITE_SCHEMA_VERSION  1

/* Checkpoint the WAL once it has grown past this many frames (mirrors
   ovsqlite's threshold).  Done as a non-blocking PASSIVE checkpoint from
   HISsync; TRUNCATE (disk reclaim) is left to close. */
#define HISSQLITE_WAL_CKPT_PAGES  1000

/* Expire streams pass 1 in hash-keyset pages of this many rows: bounds the
   in-memory action buffer and releases the read snapshot between pages so a
   long expire does not pin the WAL. */
#define HISSQLITE_EXPIRE_BATCH    10000

/* Smallest possible on-disk footprint of a hist row, for the
   HISCTLG_ENTRYESTIMATE overestimate (allocated bytes / this >= row count).
   The minimum row is a remembered entry (expires/token NULL): record header
   (6) + hash (16) + arrived (4) + posted (4) payload, plus the payload-length
   varint and 2-byte cell pointer, ~33 bytes; real article rows, page headers,
   B-tree fill factor, and interior pages only push the true per-row cost
   higher.  32 keeps the division a strict overestimate. */
#define HISSQLITE_MIN_ROW_BYTES   32

/* HIS_INCORE (a bulk rebuild, makehistory) commits writes in transactions of
   this many rows instead of one each; matches hissqlite-convert's
   COMMIT_EVERY.  See the batch_* helpers in hissqlite.c. */
#define HISSQLITE_BULK_BATCH      50000

/* Fallback values for the inn.conf tunables (hissqlitepagesize,
   hissqlitecachesize, hissqlitemmapsize, hissqlitereadercachesize), used when
   inn.conf has not been read -- offline tools and unit tests that open history
   without innconf_read().
   When inn.conf is loaded, these are superseded by the configured values
   (whose own defaults, set in lib/innconf.c, match these). */
#define HISSQLITE_DEF_PAGE_SIZE   4096  /* bytes; before first table write */
#define HISSQLITE_DEF_CACHE_SIZE  65536 /* writer page cache, kB */
#define HISSQLITE_DEF_MMAP_SIZE   0 /* bytes; 0 disables mmap (as ovsqlite) */
#define HISSQLITE_DEF_RCACHE_SIZE 2000 /* per-nnrpd reader page cache, kB */

struct hissqlite {
    char *path;              /* SQLite database file path. */
    struct history *history; /* For his_seterror(). */
    sqlite3 *db;
    int flags; /* HIS_RDONLY / HIS_RDWR / HIS_CREAT / ... */

    /* Writer side (NULL for a pure read-only direct reader).  Writes
       autocommit unless the handle was opened HIS_INCORE, the bulk-rebuild
       hint, which enables transaction batching (see hissqlite.c). */
    hissqlite_main_t main;
    int wal_pages;        /* WAL frame count, updated by the wal_hook. */
    size_t batch_size;    /* writes per transaction; 0 = autocommit. */
    size_t batch_pending; /* writes in the currently open batch. */
    bool batch_open;      /* an explicit batch transaction is open. */

    /* Reader side (used when opened HIS_RDONLY in WAL mode). */
    hissqlite_read_t read;
    bool direct_reader;
};

#endif /* HISSQLITE_PRIVATE_H */
