history_config.go RawHistoryFolder
1package vt
2
3import (
4 "errors"
5 "math"
6)
7
8var ErrInvalidHistoryConfig = errors.New("invalid history configuration")
9
10// HistoryConfig enforces limits selected by the application. The library
11// supplies no byte or line defaults. Each positive limit is an independent
12// ceiling; zero omits that ceiling. Both zero disable history. Live grids are
13// excluded. ChunkRows is an internal grouping hint in [1,256]; zero selects
14// 256 and does not grant space beyond the application's retention limits.
15type HistoryConfig struct {
16 MaxRows int
17 MaxBytes uint64
18 ChunkRows int
19}
20
21func (c HistoryConfig) Validate() error {
22 if c.MaxRows < 0 || c.ChunkRows < 0 || c.ChunkRows > maxHistoryChunkRows {
23 return ErrInvalidHistoryConfig
24 }
25 return nil
26}
27
28// NewHistory constructs owned bounded history. Invalid programmer-supplied
29// configuration panics; user-input boundaries should call Validate first.
30func NewHistory(config HistoryConfig) *History {
31 h := &History{nextRowID: 1}
32 if err := h.SetLimits(config); err != nil {
33 panic(err)
34 }
35 return h
36}
37
38// SetLimits validates first, then updates limits and evicts oldest rows before
39// returning. Existing borrowed views remain valid. Disabling history releases
40// its owned backing but preserves the next row identity. The owner must serialize
41// this operation with all other History mutations.
42func (h *History) SetLimits(config HistoryConfig) error {
43 if h == nil {
44 return ErrInvalidHistoryConfig
45 }
46 if err := config.Validate(); err != nil {
47 return err
48 }
49 if config.MaxRows == 0 && config.MaxBytes == 0 {
50 *h = History{nextRowID: h.NextRowID()}
51 return nil
52 }
53 rows := config.MaxRows
54 if rows == 0 {
55 rows = math.MaxInt
56 }
57 chunkRows := config.ChunkRows
58 if chunkRows == 0 {
59 chunkRows = maxHistoryChunkRows
60 }
61 chunkRows = min(chunkRows, rows)
62 bytes := config.MaxBytes
63 if bytes == 0 {
64 bytes = math.MaxUint64
65 }
66 if len(h.tail) >= chunkRows {
67 h.sealTail()
68 }
69 h.maxRows, h.rowCeiling, h.maxBytes, h.chunkRows = rows, config.MaxRows, bytes, chunkRows
70 h.byteCeiling = config.MaxBytes
71 for h.rows > rows || h.logicalBytes > bytes {
72 h.evictOldest()
73 }
74 clear(h.payloadScratch)
75 return nil
76}
77
78// Limits reports the application's policy. A zero limit is omitted; both
79// zero mean history is disabled. ChunkRows reports the resolved grouping size.
80func (h *History) Limits() HistoryConfig {
81 if h == nil {
82 return HistoryConfig{}
83 }
84 return HistoryConfig{MaxRows: h.rowCeiling, MaxBytes: h.byteCeiling, ChunkRows: h.chunkRows}
85}