Line data Source code
1 : #include "fd_accdb_impl_v2.h"
2 : #include "fd_vinyl_req_pool.h"
3 :
4 : FD_STATIC_ASSERT( alignof(fd_accdb_user_v2_t)<=alignof(fd_accdb_user_t), layout );
5 : FD_STATIC_ASSERT( sizeof (fd_accdb_user_v2_t)<=sizeof(fd_accdb_user_t), layout );
6 :
7 : fd_accdb_peek_t *
8 : fd_accdb_peek_funk( fd_accdb_user_v1_t * accdb,
9 : fd_accdb_peek_t * peek,
10 : fd_funk_txn_xid_t const * xid,
11 : void const * address );
12 :
13 : void
14 : fd_accdb_load_fork_slow( fd_accdb_user_v1_t * accdb,
15 : fd_funk_txn_xid_t const * xid );
16 :
17 : static inline void
18 : fd_accdb_load_fork( fd_accdb_user_v1_t * accdb,
19 0 : fd_funk_txn_xid_t const * xid ) {
20 : /* Skip if already on the correct fork */
21 0 : if( FD_LIKELY( (!!accdb->fork_depth) & (!!fd_funk_txn_xid_eq( &accdb->fork[ 0 ], xid ) ) ) ) return;
22 0 : if( FD_UNLIKELY( accdb->base.rw_active ) ) {
23 0 : FD_LOG_CRIT(( "Invariant violation: all active account references of an accdb_user must be accessed through the same XID (active XID %lu:%lu, requested XID %lu:%lu)",
24 0 : accdb->fork[0].ul[0], accdb->fork[0].ul[1],
25 0 : xid ->ul[0], xid ->ul[1] ));
26 0 : }
27 0 : fd_accdb_load_fork_slow( accdb, xid ); /* switch fork */
28 0 : }
29 :
30 : void
31 0 : fd_accdb_user_v2_fini( fd_accdb_user_t * accdb ) {
32 0 : fd_accdb_user_v2_t * user = (fd_accdb_user_v2_t *)accdb;
33 :
34 0 : fd_vinyl_rq_leave( user->vinyl_rq );
35 :
36 : /* superclass destructor */
37 0 : user->base.accdb_type = FD_ACCDB_TYPE_V1;
38 0 : fd_accdb_user_v1_fini( accdb );
39 0 : }
40 :
41 : fd_accdb_peek_t *
42 : fd_accdb_user_v2_peek( fd_accdb_user_t * accdb,
43 : fd_accdb_peek_t * peek,
44 : fd_funk_txn_xid_t const * xid,
45 0 : void const * address ) {
46 : /* FIXME this should query vinyl cache too (via vinyl_meta/vinyl_data) */
47 0 : return fd_accdb_user_v1_peek( accdb, peek, xid, address );
48 0 : }
49 :
50 : void
51 : fd_accdb_user_v2_close_ro( fd_accdb_user_t * accdb_,
52 : fd_accdb_ro_t * ro );
53 :
54 : fd_accdb_ro_t *
55 : fd_accdb_user_v2_open_ro( fd_accdb_user_t * accdb_,
56 : fd_accdb_ro_t * ro,
57 : fd_funk_txn_xid_t const * xid,
58 0 : void const * address ) {
59 0 : fd_accdb_user_v2_t * accdb = (fd_accdb_user_v2_t *)accdb_;
60 0 : fd_accdb_load_fork( &accdb->v1, xid );
61 :
62 : /* Check whether value is present in funk overlay */
63 :
64 0 : fd_accdb_peek_t peek[1];
65 0 : if( fd_accdb_peek_funk( &accdb->v1, peek, xid, address ) ) {
66 0 : if( FD_UNLIKELY( !peek->acc->meta->lamports ) ) return NULL;
67 0 : accdb->base.ro_active++;
68 0 : *ro = *peek->acc;
69 0 : return ro;
70 0 : }
71 :
72 : /* Nothing found in funk, query vinyl */
73 : /* FIXME potential here to do a pre-flight check against vinyl_meta to
74 : reduce the amount of requests we're sending to vinyl */
75 :
76 : /* Send an ACQUIRE request */
77 :
78 0 : ulong batch_idx = fd_vinyl_req_pool_acquire ( accdb->vinyl_req_pool );
79 0 : fd_vinyl_key_t * req_key = fd_vinyl_req_batch_key ( accdb->vinyl_req_pool, batch_idx );
80 0 : ulong * req_val_gaddr = fd_vinyl_req_batch_val_gaddr( accdb->vinyl_req_pool, batch_idx );
81 0 : schar * req_err = fd_vinyl_req_batch_err ( accdb->vinyl_req_pool, batch_idx );
82 0 : fd_vinyl_comp_t * comp = fd_vinyl_req_batch_comp ( accdb->vinyl_req_pool, batch_idx );
83 0 : fd_vinyl_key_init( req_key, address, 32UL );
84 0 : memset( comp, 0, sizeof(fd_vinyl_comp_t) );
85 0 : fd_vinyl_req_send_batch(
86 0 : accdb->vinyl_rq,
87 0 : accdb->vinyl_req_pool,
88 0 : accdb->vinyl_req_id++,
89 0 : accdb->vinyl_link_id,
90 0 : FD_VINYL_REQ_TYPE_ACQUIRE,
91 0 : 0UL, /* flags */
92 0 : batch_idx,
93 0 : 1UL, /* batch_cnt */
94 0 : 0UL /* val_max */
95 0 : );
96 :
97 : /* Poll for completion */
98 :
99 0 : while( FD_VOLATILE_CONST( comp->seq )!=1UL ) FD_SPIN_PAUSE();
100 0 : FD_COMPILER_MFENCE();
101 0 : int comp_err = FD_VOLATILE_CONST( comp->err );
102 0 : if( FD_UNLIKELY( comp_err!=FD_VINYL_SUCCESS ) ) {
103 0 : FD_LOG_CRIT(( "vinyl tile rejected my ACQUIRE request: %i-%s", comp_err, fd_vinyl_strerror( comp_err ) ));
104 0 : }
105 0 : int err = FD_VOLATILE_CONST( req_err[0] );
106 0 : if( err==FD_VINYL_ERR_KEY ) { /* not found */
107 0 : fd_vinyl_req_pool_release( accdb->vinyl_req_pool, batch_idx );
108 0 : return NULL;
109 0 : }
110 0 : if( FD_UNLIKELY( err!=FD_VINYL_SUCCESS ) ) {
111 0 : FD_LOG_CRIT(( "vinyl tile ACQUIRE request failed: %i-%s", err, fd_vinyl_strerror( err ) ));
112 0 : }
113 :
114 : /* Return result */
115 :
116 0 : ulong val_gaddr = FD_VOLATILE_CONST( req_val_gaddr[0] );
117 0 : fd_account_meta_t const * meta = fd_wksp_laddr_fast( accdb->vinyl_data_wksp, val_gaddr );
118 0 : fd_vinyl_req_pool_release( accdb->vinyl_req_pool, batch_idx );
119 :
120 0 : accdb->base.ro_active++;
121 0 : *ro = (fd_accdb_ro_t) {
122 0 : .meta = meta
123 0 : };
124 0 : memcpy( ro->ref->address, address, 32UL );
125 :
126 : /* Hide tombstones */
127 :
128 0 : if( FD_UNLIKELY( !meta->lamports ) ) {
129 0 : fd_accdb_user_v2_close_ro( accdb_, ro );
130 0 : return NULL;
131 0 : }
132 :
133 0 : return ro;
134 0 : }
135 :
136 : void
137 : fd_accdb_user_v2_close_ro( fd_accdb_user_t * accdb_,
138 0 : fd_accdb_ro_t * ro ) {
139 0 : fd_accdb_user_v2_t * accdb = (fd_accdb_user_v2_t *)accdb_;
140 :
141 0 : if( ro->rec ) {
142 0 : accdb->base.ro_active--;
143 0 : return;
144 0 : }
145 :
146 : /* Send a RELEASE request */
147 :
148 0 : ulong batch_idx = fd_vinyl_req_pool_acquire ( accdb->vinyl_req_pool );
149 0 : fd_vinyl_key_t * req_key = fd_vinyl_req_batch_key ( accdb->vinyl_req_pool, batch_idx );
150 0 : ulong * req_val_gaddr = fd_vinyl_req_batch_val_gaddr( accdb->vinyl_req_pool, batch_idx );
151 0 : schar * req_err = fd_vinyl_req_batch_err ( accdb->vinyl_req_pool, batch_idx );
152 0 : fd_vinyl_comp_t * comp = fd_vinyl_req_batch_comp ( accdb->vinyl_req_pool, batch_idx );
153 0 : fd_vinyl_key_init( req_key, ro->ref->address, 32UL );
154 0 : req_val_gaddr[0] = fd_wksp_gaddr_fast( accdb->vinyl_data_wksp, (void *)ro->meta );
155 0 : memset( comp, 0, sizeof(fd_vinyl_comp_t) );
156 0 : fd_vinyl_req_send_batch(
157 0 : accdb->vinyl_rq,
158 0 : accdb->vinyl_req_pool,
159 0 : accdb->vinyl_req_id++,
160 0 : accdb->vinyl_link_id,
161 0 : FD_VINYL_REQ_TYPE_RELEASE,
162 0 : 0UL, /* flags */
163 0 : batch_idx,
164 0 : 1UL, /* batch_cnt */
165 0 : 0UL /* val_max */
166 0 : );
167 :
168 : /* Poll for completion */
169 :
170 0 : while( FD_VOLATILE_CONST( comp->seq )!=1UL ) FD_SPIN_PAUSE();
171 0 : FD_COMPILER_MFENCE();
172 0 : int comp_err = FD_VOLATILE_CONST( comp->err );
173 0 : if( FD_UNLIKELY( comp_err!=FD_VINYL_SUCCESS ) ) {
174 0 : FD_LOG_CRIT(( "vinyl tile rejected my RELEASE request: %i-%s", comp_err, fd_vinyl_strerror( comp_err ) ));
175 0 : }
176 0 : int err = FD_VOLATILE_CONST( req_err[0] );
177 0 : if( FD_UNLIKELY( err!=FD_VINYL_SUCCESS ) ) {
178 0 : FD_LOG_CRIT(( "vinyl tile RELEASE request failed: %i-%s", err, fd_vinyl_strerror( err ) ));
179 0 : }
180 0 : fd_vinyl_req_pool_release( accdb->vinyl_req_pool, batch_idx );
181 :
182 0 : accdb->base.ro_active--;
183 0 : }
184 :
185 : fd_accdb_rw_t *
186 : fd_accdb_user_v2_open_rw( fd_accdb_user_t * accdb,
187 : fd_accdb_rw_t * rw,
188 : fd_funk_txn_xid_t const * xid,
189 : void const * address,
190 : ulong data_max,
191 0 : int do_create ) {
192 0 : return fd_accdb_user_v1_open_rw( accdb, rw, xid, address, data_max, do_create );
193 0 : }
194 :
195 : void
196 : fd_accdb_user_v2_close_rw( fd_accdb_user_t * accdb,
197 0 : fd_accdb_rw_t * write ) {
198 0 : fd_accdb_user_v1_close_rw( accdb, write );
199 0 : }
200 :
201 : fd_accdb_user_vt_t const fd_accdb_user_v2_vt = {
202 : .fini = fd_accdb_user_v2_fini,
203 : .peek = fd_accdb_user_v2_peek,
204 : .open_ro = fd_accdb_user_v2_open_ro,
205 : .close_ro = fd_accdb_user_v2_close_ro,
206 : .open_rw = fd_accdb_user_v2_open_rw,
207 : .close_rw = fd_accdb_user_v2_close_rw
208 : };
209 :
210 : fd_accdb_user_t *
211 : fd_accdb_user_v2_init( fd_accdb_user_t * accdb_,
212 : void * funk,
213 : void * vinyl_rq,
214 : void * vinyl_data,
215 : void * vinyl_req_pool,
216 0 : ulong vinyl_link_id ) {
217 : /* Call superclass constructor */
218 0 : if( FD_UNLIKELY( !fd_accdb_user_v1_init( accdb_, funk ) ) ) {
219 0 : return NULL;
220 0 : }
221 :
222 0 : fd_vinyl_rq_t * rq = fd_vinyl_rq_join( vinyl_rq );
223 0 : fd_vinyl_req_pool_t * req_pool = fd_vinyl_req_pool_join( vinyl_req_pool );
224 0 : if( FD_UNLIKELY( !rq || !req_pool ) ) {
225 : /* component joins log warning if this is reached */
226 0 : FD_LOG_WARNING(( "Failed to initialize database client" ));
227 0 : return NULL;
228 0 : }
229 :
230 0 : fd_accdb_user_v2_t * accdb = fd_type_pun( accdb_ );
231 0 : accdb->vinyl_req_id = fd_vinyl_rq_seq( vinyl_rq );
232 0 : accdb->vinyl_rq = rq;
233 0 : accdb->vinyl_link_id = vinyl_link_id;
234 0 : accdb->vinyl_data_wksp = vinyl_data;
235 0 : accdb->vinyl_req_pool = req_pool;
236 0 : accdb->base.accdb_type = FD_ACCDB_TYPE_V2;
237 0 : accdb->base.vt = &fd_accdb_user_v2_vt;
238 0 : return accdb_;
239 0 : }
|