lsquic_eng_hist.h revision 7d09751d
1/* Copyright (c) 2017 - 2020 LiteSpeed Technologies Inc.  See LICENSE. */
2/*
3 * lsquic_eng_hist.h - Engine history.
4 *
5 * Keep track of new and destroyed connections, packets in and packets out.
6 */
7
8#ifndef LSQUIC_ENG_HIST
9#define LSQUIC_ENG_HIST
10
11#define ENG_HIST_ENABLED 1
12
13#define ENG_HIST_BITS    2
14#define ENG_HIST_NELEMS (1 << ENG_HIST_BITS)
15
16#ifndef ENG_HIST_N_TO_PRINT
17    /* By default, we do not print the whole history every second just
18     * the latest entry.
19     */
20#   define ENG_HIST_N_TO_PRINT 1
21#endif
22
23
24/* Keeps history per slice of time -- one second */
25struct hist_slice
26{
27    unsigned    sl_packets_in,
28                sl_packets_out,
29                sl_new_full_conns,
30                sl_new_mini_conns,
31                sl_del_full_conns,
32                sl_del_mini_conns;
33};
34
35
36struct eng_hist
37{
38    struct hist_slice   eh_slices[ENG_HIST_NELEMS];
39    unsigned            eh_cur_idx,
40                        eh_prev_idx;
41};
42
43
44#if ENG_HIST_ENABLED
45
46/* Initialize engine history */
47#define eng_hist_init(eh) do {                                              \
48    memset(eh, 0, sizeof(*(eh)));                                           \
49    (eh)->eh_cur_idx = (eh)->eh_prev_idx =                                  \
50                            time(NULL) & (ENG_HIST_NELEMS - 1);             \
51} while (0)
52
53
54/* Clear slice at current index */
55#define eng_hist_clear_cur(eh) do {                                         \
56    memset(&(eh)->eh_slices[(eh)->eh_cur_idx], 0,                           \
57                                    sizeof(struct hist_slice));             \
58} while (0)
59
60
61void
62eng_hist_log (const struct eng_hist *);
63
64
65/* Switch to next slice if necessary */
66#define eng_hist_tick(eh, now) do {                                         \
67    if (0 == (now))                                                         \
68        (eh)->eh_cur_idx = time(NULL)        & (ENG_HIST_NELEMS - 1);       \
69    else                                                                    \
70        (eh)->eh_cur_idx = ((now) / 1000000) & (ENG_HIST_NELEMS - 1);       \
71    if ((eh)->eh_cur_idx != (eh)->eh_prev_idx)                              \
72    {                                                                       \
73        eng_hist_log(eh);                                                   \
74        eng_hist_clear_cur(eh);                                             \
75        (eh)->eh_prev_idx = (eh)->eh_cur_idx;                               \
76    }                                                                       \
77} while (0)
78
79
80/* Increment element `what'.  Slice increment is handled in this macro, too. */
81#define eng_hist_inc(eh, now, what) do {                                    \
82    eng_hist_tick(eh, now);                                                 \
83    ++(eh)->eh_slices[(eh)->eh_cur_idx].what;                               \
84} while (0)
85
86#else /* !ENG_HIST_ENABLED */
87
88#define eng_hist_init(eh)
89#define eng_hist_clear_cur(eh)
90#define eng_hist_tick(eh, now)
91#define eng_hist_inc(eh, now, what)
92#define eng_hist_log(eh)
93
94#endif  /* ENG_HIST_ENABLED */
95
96#endif  /* LSQUIC_ENG_HIST */
97