LCOV - code coverage report
Current view: top level - disco/gui - fd_gui_hist.h (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 0 23 0.0 %
Date: 2026-11-11 12:40:43 Functions: 0 9 0.0 %

          Line data    Source code
       1             : #ifndef HEADER_fd_src_disco_gui_fd_gui_hist_h
       2             : #define HEADER_fd_src_disco_gui_fd_gui_hist_h
       3             : 
       4             : /* fd_gui_hist is the GUI's historical event store semantics layer.  It
       5             :    sits on top of fd_gui_store and owns everything GUI-specific about
       6             :    the monitoring history: the named DBs (FD_GUI_HIST_* below), their
       7             :    key/value structs, fixed record sizes, the eviction policy, and the
       8             :    query API.
       9             : 
      10             :    There are two kinds of DB:
      11             : 
      12             :      - TIME-SERIES (TS) DBs are append-only streams tagged by a
      13             :        wallclock window. Written by fd_gui_hist_ts_append, read by
      14             :        time-window range scan.
      15             :      - KEY-VALUE (KV) DBs hold one record per key.  Written/read by
      16             :        point key (fd_gui_hist_kv_get_or_create / _get / _get_any).
      17             : */
      18             : 
      19             : #include "../../util/fd_util_base.h"
      20             : #include "fd_gui_store.h"
      21             : #include "../../flamenco/leaders/fd_leaders_base.h"   /* MAX_SLOTS_PER_EPOCH */
      22             : #include "../../flamenco/runtime/fd_slot_params.h"    /* FD_SLOT_PARAMS_200MS */
      23             : 
      24             : struct fd_gui;
      25             : typedef struct fd_gui fd_gui_t;
      26             : 
      27           0 : #define FD_GUI_HIST_MAGIC (0xf17e6d09147802UL)
      28             : 
      29           0 : #define FD_GUI_HIST_RES_1S_NS (1000000000L)
      30             : 
      31           0 : #define FD_GUI_HIST_MAX_LEADER_SLOTS_PER_EPOCH (43200UL) /* 10% capacity should be enough for mainnet/testnet */
      32             : 
      33           0 : #define FD_GUI_HIST_MAX_EPOCHS (64UL) /* Comfortably above typical time between restarts */
      34             : 
      35             : /* Minimum number of epochs of slot, leader slot and epoch records the
      36             :    store always retains, regardless of pressure from other DBs. */
      37           0 : #define FD_GUI_HIST_MIN_EPOCHS (3UL)
      38             : 
      39             : /* Bounds the per-tile CPU day records retained (per tile).  Two months
      40             :    of calendar days, about the span of FD_GUI_HIST_MAX_EPOCHS epochs. */
      41           0 : #define FD_GUI_HIST_MAX_TIMELINE_DAYS (64UL)
      42             : 
      43           0 : #define FD_GUI_HIST_SCHEDULER_COUNTS  (0)  /* (ts, type)            */
      44           0 : #define FD_GUI_HIST_TILE_TIMERS       (1)  /* (ts, type)            */
      45           0 : #define FD_GUI_HIST_SHRED_EVENTS      (2)
      46           0 : #define FD_GUI_HIST_TXN_START         (3)  /* (ts, type, bank, txn) */
      47           0 : #define FD_GUI_HIST_TXN_END           (4)  /* (ts, type, bank, txn) */
      48           0 : #define FD_GUI_HIST_SLOT              (5)  /* (slot, bank_seq)      */
      49           0 : #define FD_GUI_HIST_LEADER_SLOT       (6)  /* (slot, bank_seq)      */
      50           0 : #define FD_GUI_HIST_EPOCH             (7)  /* (epoch)               */
      51           0 : #define FD_GUI_HIST_TILE_STATS        (8)  /* (ts, type)            */
      52           0 : #define FD_GUI_HIST_TXN_WATERFALL     (9)  /* (ts, type)            */
      53           0 : #define FD_GUI_HIST_TIMELINE_DAY      (10)
      54           0 : #define FD_GUI_HIST_REPLAY_TXN        (11)
      55           0 : #define FD_GUI_HIST_TIMELINE_TILE_DAY (12) /* (day_idx, tile_idx)  */
      56           0 : #define FD_GUI_HIST_FEC_EVENTS        (13) /* (FEC event key)      */
      57           0 : #define FD_GUI_HIST_FEC_EVENT_ARCHIVE (14) /* (ts, ...)            */
      58           0 : #define FD_GUI_HIST_CNT               (15)
      59             : 
      60             : struct fd_gui_hist_metrics {
      61             :   /* Writes dropped after exhausting region or KV index capacity. */
      62             :   ulong map_full[ FD_GUI_HIST_CNT ];
      63             :   /* Writes that evicted records before succeeding. */
      64             :   ulong reserves [ FD_GUI_HIST_CNT ];
      65             : };
      66             : typedef struct fd_gui_hist_metrics fd_gui_hist_metrics_t;
      67             : 
      68             : struct fd_gui_hist_slot_key        { ulong slot; ulong bank_seq; };
      69             : struct fd_gui_hist_leader_slot_key { ulong slot; ulong bank_seq; };
      70             : struct fd_gui_hist_epoch_key       { ulong epoch; };
      71             : struct fd_gui_hist_tile_day_key    { ulong day_idx; ulong tile_idx; };
      72             : typedef struct fd_gui_hist_slot_key        fd_gui_hist_slot_key_t;
      73             : typedef struct fd_gui_hist_leader_slot_key fd_gui_hist_leader_slot_key_t;
      74             : typedef struct fd_gui_hist_epoch_key       fd_gui_hist_epoch_key_t;
      75             : typedef struct fd_gui_hist_tile_day_key    fd_gui_hist_tile_day_key_t;
      76             : 
      77             : struct fd_gui_hist_private;
      78             : typedef struct fd_gui_hist_private fd_gui_hist_t;
      79             : 
      80             : /* fd_gui_hist_kv_slot_iter_t iterates every record for `slot` (every
      81             :    fork's block) in a slot-keyed KV DB.  Used to enumerate the
      82             :    equivocating forks of a slot. */
      83             : struct fd_gui_hist_kv_slot_iter {
      84             :   void const *            rec;       /* current record; NULL when done */
      85             :   ulong                   bank_seq;  /* current record's bank_seq      */
      86             :   fd_gui_store_kv_iter_t _it;
      87             : };
      88             : typedef struct fd_gui_hist_kv_slot_iter fd_gui_hist_kv_slot_iter_t;
      89             : 
      90             : /* fd_gui_hist_range_filter_fn is an optional per-record predicate
      91             :    evaluated during a range scan: called with a pointer to the DB's
      92             :    record and the caller's `ctx`, it returns non-zero to emit the record
      93             :    or zero to skip it.  A NULL filter emits every record in the window
      94             :    range. */
      95             : 
      96             : typedef int (*fd_gui_hist_range_filter_fn)( void const * rec, void * ctx );
      97             : 
      98             : /* fd_gui_hist_iter_t iterates the records produced by a time-window
      99             :    range query.
     100             : 
     101             :    Records are emitted oldest-window-first, but the backend does not
     102             :    strictly order records within a window.
     103             : */
     104             : struct fd_gui_hist_iter {
     105             :   void const * rec;
     106             :   ulong        rec_sz;
     107             : 
     108             :   int                         _dbi;
     109             :   int                         _emitted;
     110             :   fd_gui_hist_range_filter_fn _filter;
     111             :   void *                      _filter_ctx;
     112             :   fd_gui_store_ts_iter_t      _it;
     113             : };
     114             : 
     115             : typedef struct fd_gui_hist_iter fd_gui_hist_iter_t;
     116             : 
     117             : FD_PROTOTYPES_BEGIN
     118             : 
     119             : FD_FN_CONST ulong
     120             : fd_gui_hist_align( void );
     121             : 
     122             : FD_FN_CONST ulong
     123             : fd_gui_hist_footprint( void );
     124             : 
     125             : /* fd_gui_hist_new formats the workspace region `mem`
     126             :    (>= fd_gui_hist_footprint bytes, fd_gui_hist_align aligned) as the
     127             :    history semantics layer over the store `db`. Returns `mem` on success
     128             :    or NULL on failure (logged). */
     129             : 
     130             : void *
     131             : fd_gui_hist_new( void *                 mem,
     132             :                  fd_gui_store_t const * db );
     133             : 
     134             : /* fd_gui_hist_join joins a region formatted by fd_gui_hist_new,
     135             :    returning a usable handle (mem may be NULL -> NULL). */
     136             : 
     137             : fd_gui_hist_t *
     138             : fd_gui_hist_join( void * mem );
     139             : 
     140             : void *
     141             : fd_gui_hist_leave( fd_gui_hist_t * hist );
     142             : 
     143             : void *
     144             : fd_gui_hist_delete( void * mem );
     145             : 
     146             : /* fd_gui_hist_db_descs fills descs with the FD_GUI_HIST_CNT DB
     147             :    descriptors for a store of store_bytes, and returns descs. */
     148             : 
     149             : fd_gui_store_desc_t *
     150             : fd_gui_hist_db_descs( fd_gui_store_desc_t descs[ static FD_GUI_HIST_CNT ],
     151             :                       ulong               store_bytes );
     152             : 
     153             : FD_FN_CONST static inline ulong
     154           0 : fd_gui_hist_db_cnt( void ) { return FD_GUI_HIST_CNT; }
     155             : 
     156             : /* fd_gui_hist_store_footprint returns the footprint of a store of
     157             :    store_bytes holding the history DBs, or 0 if store_bytes is too
     158             :    small. */
     159             : 
     160             : ulong
     161             : fd_gui_hist_store_footprint( ulong store_bytes );
     162             : 
     163             : /* fd_gui_hist_store_new formats mem as a store of store_bytes backed
     164             :    by path, holding the history DBs.  The result is ready to join and
     165             :    pass to fd_gui_hist_new.  Returns mem on success or NULL on failure
     166             :    (logged, see fd_gui_store_new). */
     167             : 
     168             : void *
     169             : fd_gui_hist_store_new( void *       mem,
     170             :                        char const * path,
     171             :                        ulong        store_bytes,
     172             :                        ulong        seed );
     173             : 
     174             : fd_gui_hist_metrics_t const *
     175             : fd_gui_hist_metrics( fd_gui_t const * gui );
     176             : 
     177             : /* ---- TS read/write -------------------------------------------------- */
     178             : 
     179             : /* fd_gui_hist_ts_append copies the record at val into time-series DB
     180             :    dbi, preserving its contents.  The timestamp at the DB's configured
     181             :    offset must be >= the timestamp of the last successful append.
     182             : 
     183             :    Returns 0 on success, -1 for an invalid DB, a decreasing timestamp,
     184             :    or a store append failure. */
     185             : 
     186             : int
     187             : fd_gui_hist_ts_append( fd_gui_t *   gui,
     188             :                        int          dbi,
     189             :                        void const * val );
     190             : 
     191             : /* fd_gui_hist_ts_emplace is fd_gui_hist_ts_append without the copy: it
     192             :    appends a record whose timestamp field is stored_ts and returns a
     193             :    pointer to it in the store, or NULL on the same failures. */
     194             : 
     195             : void *
     196             : fd_gui_hist_ts_emplace( fd_gui_t * gui,
     197             :                         int        dbi,
     198             :                         long       stored_ts );
     199             : 
     200             : int
     201             : fd_gui_hist_range_begin( fd_gui_t *                   gui,
     202             :                          fd_gui_hist_iter_t *         iter,
     203             :                          int                          dbi,
     204             :                          long                         lo_ns,
     205             :                          long                         hi_ns,
     206             :                          fd_gui_hist_range_filter_fn  filter,
     207             :                          void *                       filter_ctx );
     208             : 
     209             : int
     210             : fd_gui_hist_range_next( fd_gui_hist_iter_t * iter );
     211             : 
     212             : void
     213             : fd_gui_hist_range_end( fd_gui_hist_iter_t * iter );
     214             : 
     215             : 
     216             : /* ---- KV read/write -------------------------------------------------- */
     217             : 
     218             : /* fd_gui_hist_kv_get_or_create reserves (creating if absent) the record
     219             :    for `*key` in a KV DB and returns a mutable pointer to the record's
     220             :    value, or NULL on failure.
     221             : 
     222             :    Will evict old entries to make room if necessary.  Returns the value
     223             :    pointer on success, or NULL on error. */
     224             : 
     225             : void *
     226             : fd_gui_hist_kv_get_or_create( fd_gui_t *   gui,
     227             :                               int          dbi,
     228             :                               void const * key );
     229             : 
     230             : /* fd_gui_hist_kv_get is like fd_gui_hist_kv_get_or_create, but returns
     231             :    NULL when the record is not found instead of creating one. */
     232             : 
     233             : void *
     234             : fd_gui_hist_kv_get( fd_gui_t *   gui,
     235             :                     int          dbi,
     236             :                     void const * key );
     237             : 
     238             : /* fd_gui_hist_kv_get_slot_any looks up the slot record for the first
     239             :    key matching (slot, *) and returns a pointer to its value. */
     240             : 
     241             : void *
     242             : fd_gui_hist_kv_get_slot_any( fd_gui_t * gui,
     243             :                              int        dbi,
     244             :                              ulong      slot );
     245             : 
     246             : fd_gui_hist_kv_slot_iter_t *
     247             : fd_gui_hist_kv_iter_begin( fd_gui_t *                   gui,
     248             :                            fd_gui_hist_kv_slot_iter_t * iter,
     249             :                            int                          dbi,
     250             :                            ulong                        slot );
     251             : 
     252             : int
     253             : fd_gui_hist_kv_iter_next( fd_gui_hist_kv_slot_iter_t * iter );
     254             : 
     255             : /* ---- Eviction ------------------------------------------------------- */
     256             : 
     257             : /* fd_gui_hist_evict_step reclaims at most FD_GUI_HIST_EVICT_BATCH
     258             :    records from an oldest excess region once at most one shared region
     259             :    remains free.  Every DB's newest base_regions regions are protected
     260             :    (see fd_gui_hist_db_descs).  FEC staging is never evicted; it only
     261             :    drains through fd_gui_fec_archive.  Returns 1 for actual progress, 0
     262             :    when idle or all candidates pinned.  Writes retry on pressure, then
     263             :    recycle only their own eligible history if no excess candidate
     264             :    remains. */
     265             : 
     266             : int
     267             : fd_gui_hist_evict_step( fd_gui_t * gui );
     268             : 
     269             : FD_PROTOTYPES_END
     270             : 
     271             : #endif /* HEADER_fd_src_disco_gui_fd_gui_hist_h */

Generated by: LCOV version 1.14