Line data Source code
1 : #ifndef HEADER_fd_src_flamenco_accdb_fd_accdb_shmem_h
2 : #define HEADER_fd_src_flamenco_accdb_fd_accdb_shmem_h
3 :
4 : #include "fd_accdb_cache.h"
5 : #include <stddef.h> /* offsetof */
6 :
7 8592 : #define FD_ACCDB_SHMEM_ALIGN (128UL)
8 :
9 4164 : #define FD_ACCDB_SHMEM_MAGIC (0xF17EDA2CE7ACCDB0UL) /* FIREDANCE ACCDB V0 */
10 :
11 : /* Accounts are written to a tiered partition layout. Layer 0 is the
12 : hot write head used by acquire/release (execution). Layers 1..N-1
13 : are successively colder compaction tiers: partitions at layer K are
14 : compacted into layer K+1. */
15 :
16 13175018 : #define FD_ACCDB_COMPACTION_LAYER_CNT (3UL)
17 :
18 0 : #define FD_ACCDB_COMPACTION_THRESHOLD_PCT (30UL)
19 :
20 : typedef struct fd_accdb_shmem_private fd_accdb_shmem_t;
21 :
22 : struct fd_accdb_shmem_metrics {
23 : ulong accounts_total;
24 : ulong accounts_capacity;
25 : ulong disk_allocated_bytes;
26 : ulong disk_current_bytes;
27 : ulong disk_used_bytes;
28 : int in_compaction;
29 : ulong compactions_requested;
30 : ulong compactions_completed;
31 : ulong accounts_relocated;
32 : ulong accounts_relocated_bytes;
33 : ulong partitions_freed;
34 : };
35 :
36 : typedef struct fd_accdb_shmem_metrics fd_accdb_shmem_metrics_t;
37 :
38 : struct fd_accdb_metrics {
39 : ulong acquire_calls;
40 : ulong accounts_acquired_per_class[ FD_ACCDB_CACHE_CLASS_CNT ];
41 : ulong writable_accounts_acquired_per_class[ FD_ACCDB_CACHE_CLASS_CNT ];
42 : ulong accounts_evicted;
43 : ulong accounts_evicted_per_class[ FD_ACCDB_CACHE_CLASS_CNT ];
44 : ulong accounts_preevicted;
45 : ulong accounts_preevicted_per_class[ FD_ACCDB_CACHE_CLASS_CNT ];
46 : ulong accounts_committed_new_per_class[ FD_ACCDB_CACHE_CLASS_CNT ];
47 : ulong accounts_committed_overwrite_per_class[ FD_ACCDB_CACHE_CLASS_CNT ];
48 : ulong accounts_not_found_per_class[ FD_ACCDB_CACHE_CLASS_CNT ];
49 : ulong accounts_waited;
50 : ulong accounts_deleted;
51 :
52 : ulong acquire_failed;
53 :
54 : ulong bytes_read;
55 : ulong read_ops;
56 : ulong bytes_written;
57 : ulong write_ops;
58 : ulong copy_ops;
59 :
60 : ulong bytes_copied;
61 : };
62 :
63 : typedef struct fd_accdb_metrics fd_accdb_metrics_t;
64 :
65 : /* fd_accdb_disk_meta_t is the on-disk account revision header. */
66 :
67 : union fd_accdb_disk_meta {
68 : struct __attribute__((packed)) {
69 : uchar pubkey[ 32UL ];
70 : uint size;
71 : uint generation;
72 : uchar owner[ 32UL ];
73 : };
74 : uchar b[72];
75 : };
76 :
77 : typedef union fd_accdb_disk_meta fd_accdb_disk_meta_t;
78 :
79 : FD_STATIC_ASSERT( sizeof(fd_accdb_disk_meta_t)==72UL, layout );
80 : FD_STATIC_ASSERT( offsetof(fd_accdb_disk_meta_t,owner)+32UL==sizeof(fd_accdb_disk_meta_t), layout );
81 :
82 : FD_PROTOTYPES_BEGIN
83 :
84 : FD_FN_CONST ulong
85 : fd_accdb_shmem_align( void );
86 :
87 : ulong
88 : fd_accdb_shmem_footprint( ulong max_accounts,
89 : ulong max_live_slots,
90 : ulong max_account_writes_per_slot,
91 : ulong partition_cnt,
92 : ulong cache_footprint,
93 : ulong cache_min_reserved,
94 : ulong joiner_cnt,
95 : ulong max_incremental_accounts );
96 :
97 : void *
98 : fd_accdb_shmem_new( void * shmem,
99 : ulong max_accounts,
100 : ulong max_live_slots,
101 : ulong max_account_writes_per_slot,
102 : ulong partition_cnt,
103 : ulong partition_sz,
104 : ulong cache_footprint,
105 : ulong cache_min_reserved,
106 : int bundle_enabled,
107 : ulong seed,
108 : ulong joiner_cnt,
109 : ulong max_incremental_accounts );
110 :
111 : fd_accdb_shmem_t *
112 : fd_accdb_shmem_join( void * shtc );
113 :
114 : void
115 : fd_accdb_shmem_bytes_freed( fd_accdb_shmem_t * accdb,
116 : ulong offset,
117 : ulong sz );
118 :
119 : /* fd_accdb_shmem_try_enqueue_compaction checks whether the partition
120 : at partition_idx has crossed the compaction threshold and, if so,
121 : enqueues it for compaction. The caller MUST hold partition_lock.
122 : This is factored out of fd_accdb_shmem_bytes_freed so that
123 : change_partition (which already holds the lock) can call it after
124 : updating the write head, avoiding a race where the old write head
125 : is skipped for enqueue. */
126 :
127 : void
128 : fd_accdb_shmem_try_enqueue_compaction( fd_accdb_shmem_t * accdb,
129 : ulong partition_idx );
130 :
131 : /* Per-partition snapshot for read-only consumers (GUI tile). The
132 : underlying per-partition state is updated with relaxed atomics by
133 : writers, so the snapshot is best-effort consistent. compaction_state
134 : is 0=idle, 1=queued, 2=compacting. */
135 :
136 : struct fd_accdb_shmem_partition_info {
137 : ulong file_offset; /* byte offset of partition start in the accdb file */
138 : ulong write_offset; /* current write head within the partition */
139 : ulong write_offset_raw; /* active head's reservation tip, may exceed the partition size */
140 : ulong bytes_freed; /* bytes marked freed within the partition */
141 : ulong compaction_offset; /* current compaction read offset within partition */
142 : ulong read_ops;
143 : ulong bytes_read;
144 : ulong write_ops;
145 : ulong bytes_written;
146 : long created_ticks; /* fd_tickcount when the partition was opened */
147 : long filled_ticks; /* fd_tickcount when partition closed (0 if active) */
148 : uchar layer; /* compaction tier this partition belongs to */
149 : uchar compaction_state; /* 0=idle, 1=queued, 2=compacting */
150 : uchar is_write_head; /* non-zero if this partition is the active write */
151 : /* head for any layer at the time of the snapshot */
152 : };
153 :
154 : typedef struct fd_accdb_shmem_partition_info fd_accdb_shmem_partition_info_t;
155 :
156 : ulong
157 : fd_accdb_shmem_partition_max( fd_accdb_shmem_t const * accdb );
158 :
159 : ulong
160 : fd_accdb_shmem_partition_sz( fd_accdb_shmem_t const * accdb );
161 :
162 : void
163 : fd_accdb_shmem_partition_info( fd_accdb_shmem_t const * accdb,
164 : ulong partition_idx,
165 : fd_accdb_shmem_partition_info_t * out );
166 :
167 : /* Writer barrier. Write heads advance when space is reserved, not
168 : when the write lands, so a sampled offset may cover in-flight
169 : writes. capture records which joiners are mid-write; poll until it
170 : returns 0, and everything below offsets sampled before capture is
171 : on disk. */
172 :
173 : struct fd_accdb_shmem_writer_barrier { ulong bits[ 4UL ]; };
174 :
175 : typedef struct fd_accdb_shmem_writer_barrier fd_accdb_shmem_writer_barrier_t;
176 :
177 : void
178 : fd_accdb_shmem_writer_barrier_capture( fd_accdb_shmem_t const * accdb,
179 : fd_accdb_shmem_writer_barrier_t * barrier );
180 :
181 : ulong
182 : fd_accdb_shmem_writer_barrier_poll( fd_accdb_shmem_t const * accdb,
183 : fd_accdb_shmem_writer_barrier_t * barrier );
184 :
185 : ulong const *
186 : fd_accdb_shmem_snapshot_sync( fd_accdb_shmem_t const * accdb );
187 :
188 : FD_PROTOTYPES_END
189 :
190 : /* fd_accdb_delta tracks account addresses changed since a full snap.
191 : This is used to determine which accounts should be packed into a full
192 : snapshot (including tombstones for accounts no longer present in
193 : accdb, but present in the full snapshot). */
194 :
195 : struct fd_accdb_delta {
196 : uchar pubkey[ 32UL ];
197 : uint next;
198 : };
199 : typedef struct fd_accdb_delta fd_accdb_delta_t;
200 :
201 : FD_STATIC_ASSERT( sizeof(fd_accdb_delta_t)==36UL, delta_ele_sz );
202 : FD_STATIC_ASSERT( __builtin_offsetof(fd_accdb_delta_t, next)==32UL, delta_ele_next_off );
203 :
204 : /* Snapshot sync API */
205 :
206 : /* fd_accdb_shmem_private_t::snapshot_sync values
207 : Legal transitions:
208 : - IDLE -> {START_FULL,START_INCR}
209 : - START_FULL -> RUNNING
210 : - START_INCR -> {RUNNING,FAIL}
211 : - RUNNING -> DONE
212 : - FAIL -> DONE
213 : - DONE -> IDLE */
214 4164 : #define FD_ACCDB_SNAPSHOT_SYNC_IDLE (0UL) /* accdb: steady state */
215 0 : #define FD_ACCDB_SNAPSHOT_SYNC_START_FULL (1UL) /* client: i want to create a full snapshot */
216 0 : #define FD_ACCDB_SNAPSHOT_SYNC_START_INCR (2UL) /* client: i want to create an incremental snapshot */
217 0 : #define FD_ACCDB_SNAPSHOT_SYNC_RUNNING (3UL) /* accdb: ack, snapshot creation active */
218 0 : #define FD_ACCDB_SNAPSHOT_SYNC_DONE (4UL) /* client: i am done snapshotting */
219 0 : #define FD_ACCDB_SNAPSHOT_SYNC_FAIL (5UL) /* accdb: error during incremental creation */
220 :
221 : static inline ulong
222 3269465 : fd_accdb_snapshot_sync_state( ulong const * sync ) {
223 3269465 : return __atomic_load_n( sync, __ATOMIC_ACQUIRE );
224 3269465 : }
225 :
226 : static inline void
227 : fd_accdb_snapshot_sync_advance( ulong * sync,
228 0 : ulong next ) {
229 0 : ulong old = __atomic_load_n( sync, __ATOMIC_RELAXED );
230 0 : for(;;) {
231 0 : if( FD_LIKELY( __atomic_compare_exchange_n( sync, &old, next, 1, __ATOMIC_RELEASE, __ATOMIC_RELAXED ) ) ) return;
232 0 : FD_SPIN_PAUSE();
233 0 : }
234 0 : }
235 :
236 : #endif /* HEADER_fd_src_flamenco_accdb_fd_accdb_shmem_h */
|