Skip to content

Commit b8042aa

Browse files
riptlripatel-fd
authored andcommitted
accdb: add vinyl-funk overlay prototype
Adds a second accdb backend using a read-only vinyl base layer and a read-write funk overlay. This is close to the target design, but excludes the "migrating records from vinyl to funk" step. This solution is probably not production-shippable, but it allows us to get some real-world exposure to the vinyl top layer.
1 parent 0beeaa5 commit b8042aa

File tree

11 files changed

+1118
-15
lines changed

11 files changed

+1118
-15
lines changed

src/flamenco/accdb/Local.mk

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,19 @@ $(call add-objs,fd_accdb_admin,fd_flamenco)
44

55
# User API
66
$(call add-hdrs,fd_accdb_user.h fd_accdb_sync.h)
7+
8+
# Funk-based database
9+
$(call add-hdrs,fd_accdb_impl_v1.h)
710
$(call add-objs,fd_accdb_impl_v1,fd_flamenco)
811

12+
# Vinyl/funk prototype
13+
$(call add-hdrs,fd_accdb_impl_v2.h)
14+
$(call add-objs,fd_accdb_impl_v2,fd_flamenco)
15+
16+
# Internals
17+
$(call add-hdrs,fd_vinyl_req_pool.h)
18+
$(call add-objs,fd_vinyl_req_pool,fd_flamenco)
19+
920
# Debug APIs
1021
$(call add-hdrs,fd_accdb_fsck.h)
1122
$(call add-objs,fd_accdb_fsck_funk fd_accdb_fsck_vinyl,fd_flamenco)
@@ -14,6 +25,7 @@ $(call make-bin,fd_accdb_ctl,fd_accdb_ctl,fd_vinyl fd_tango fd_ballet fd_util)
1425
endif
1526

1627
ifdef FD_HAS_ATOMIC
17-
$(call make-unit-test,test_accdb,test_accdb,fd_flamenco fd_funk fd_util)
18-
$(call run-unit-test,test_accdb)
28+
$(call make-unit-test,test_accdb_v1,test_accdb_v1,fd_flamenco fd_funk fd_util)
29+
$(call run-unit-test,test_accdb_v1)
30+
$(call make-unit-test,test_accdb_v2,test_accdb_v2,fd_flamenco fd_vinyl fd_funk fd_tango fd_util)
1931
endif

src/flamenco/accdb/fd_accdb_base.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,6 @@ struct fd_accdb_user;
55
typedef struct fd_accdb_user fd_accdb_user_t;
66

77
#define FD_ACCDB_TYPE_V1 (1U) /* funk */
8-
#define FD_ACCDB_TYPE_v2 (2U) /* read-only vinyl + read-write funk */
8+
#define FD_ACCDB_TYPE_V2 (2U) /* read-only vinyl + read-write funk */
99

1010
#endif /* HEADER_fd_src_flamenco_accdb_fd_accdb_base_h */

src/flamenco/accdb/fd_accdb_impl_v1.c

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ fd_accdb_search_chain( fd_accdb_user_v1_t const * accdb,
7272
return FD_MAP_SUCCESS;
7373
}
7474

75-
static void
75+
void
7676
fd_accdb_load_fork_slow( fd_accdb_user_v1_t * accdb,
7777
fd_funk_txn_xid_t const * xid ) {
7878
fd_funk_txn_xid_t next_xid = *xid;
@@ -179,11 +179,11 @@ fd_accdb_load_fork( fd_accdb_user_v1_t * accdb,
179179
fd_accdb_load_fork_slow( accdb, xid ); /* switch fork */
180180
}
181181

182-
static fd_accdb_peek_t *
183-
fd_accdb_peek1( fd_accdb_user_v1_t * accdb,
184-
fd_accdb_peek_t * peek,
185-
fd_funk_txn_xid_t const * xid,
186-
void const * address ) {
182+
fd_accdb_peek_t *
183+
fd_accdb_peek_funk( fd_accdb_user_v1_t * accdb,
184+
fd_accdb_peek_t * peek,
185+
fd_funk_txn_xid_t const * xid,
186+
void const * address ) {
187187
fd_funk_t const * funk = accdb->funk;
188188
fd_funk_rec_key_t key[1]; memcpy( key->uc, address, 32UL );
189189

@@ -227,7 +227,9 @@ fd_accdb_user_v1_peek( fd_accdb_user_t * accdb,
227227
fd_accdb_user_v1_t * v1 = (fd_accdb_user_v1_t *)accdb;
228228
if( FD_UNLIKELY( !v1->funk->shmem ) ) FD_LOG_CRIT(( "NULL funk shmem" ));
229229
fd_accdb_load_fork( v1, xid );
230-
return fd_accdb_peek1( v1, peek, xid, address );
230+
if( !fd_accdb_peek_funk( v1, peek, xid, address ) ) return NULL;
231+
if( FD_UNLIKELY( !peek->acc->meta->lamports ) ) return NULL;
232+
return peek;
231233
}
232234

233235
static void
@@ -316,13 +318,11 @@ fd_accdb_user_v1_open_ro( fd_accdb_user_t * accdb,
316318
fd_funk_txn_xid_t const * xid,
317319
void const * address ) {
318320
fd_accdb_user_v1_t * v1 = (fd_accdb_user_v1_t *)accdb;
319-
320321
fd_accdb_load_fork( v1, xid );
321322

322323
fd_accdb_peek_t peek[1];
323-
if( FD_UNLIKELY( !fd_accdb_peek1( v1, peek, xid, address ) ) ) {
324-
return NULL;
325-
}
324+
if( !fd_accdb_peek_funk( v1, peek, xid, address ) ) return NULL;
325+
if( FD_UNLIKELY( !peek->acc->meta->lamports ) ) return NULL;
326326

327327
v1->base.ro_active++;
328328
*ro = *peek->acc;
@@ -370,7 +370,7 @@ fd_accdb_user_v1_open_rw( fd_accdb_user_t * accdb,
370370
/* Query old record value */
371371

372372
fd_accdb_peek_t peek[1];
373-
if( FD_UNLIKELY( !fd_accdb_peek1( v1, peek, xid, address ) ) ) {
373+
if( FD_UNLIKELY( !fd_accdb_peek_funk( v1, peek, xid, address ) ) ) {
374374

375375
/* Record not found */
376376
if( !do_create ) return NULL;

src/flamenco/accdb/fd_accdb_impl_v1.h

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,38 @@ fd_accdb_user_v1_init( fd_accdb_user_t * ljoin,
3434
fd_funk_t *
3535
fd_accdb_user_v1_funk( fd_accdb_user_t * accdb );
3636

37+
/* Methods (don't call directly, prefer the wrappers fd_accdb_user.h) */
38+
39+
fd_accdb_peek_t *
40+
fd_accdb_user_v1_peek( fd_accdb_user_t * accdb,
41+
fd_accdb_peek_t * peek,
42+
fd_funk_txn_xid_t const * xid,
43+
void const * address );
44+
45+
void
46+
fd_accdb_user_v1_fini( fd_accdb_user_t * accdb );
47+
48+
fd_accdb_ro_t *
49+
fd_accdb_user_v1_open_ro( fd_accdb_user_t * accdb,
50+
fd_accdb_ro_t * ro,
51+
fd_funk_txn_xid_t const * xid,
52+
void const * address );
53+
54+
void
55+
fd_accdb_user_v1_close_ro( fd_accdb_user_t * accdb,
56+
fd_accdb_ro_t * ro );
57+
58+
fd_accdb_rw_t *
59+
fd_accdb_user_v1_open_rw( fd_accdb_user_t * accdb,
60+
fd_accdb_rw_t * rw,
61+
fd_funk_txn_xid_t const * xid,
62+
void const * address,
63+
ulong data_max,
64+
int do_create );
65+
void
66+
fd_accdb_user_v1_close_rw( fd_accdb_user_t * accdb,
67+
fd_accdb_rw_t * write );
68+
3769
FD_PROTOTYPES_END
3870

3971
#endif /* HEADER_fd_src_flamenco_accdb_fd_accdb_impl_v1_h */
Lines changed: 239 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,239 @@
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+
fd_funk_txn_xid_t const * xid ) {
20+
/* Skip if already on the correct fork */
21+
if( FD_LIKELY( (!!accdb->fork_depth) & (!!fd_funk_txn_xid_eq( &accdb->fork[ 0 ], xid ) ) ) ) return;
22+
if( FD_UNLIKELY( accdb->base.rw_active ) ) {
23+
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+
accdb->fork[0].ul[0], accdb->fork[0].ul[1],
25+
xid ->ul[0], xid ->ul[1] ));
26+
}
27+
fd_accdb_load_fork_slow( accdb, xid ); /* switch fork */
28+
}
29+
30+
void
31+
fd_accdb_user_v2_fini( fd_accdb_user_t * accdb ) {
32+
fd_accdb_user_v2_t * user = (fd_accdb_user_v2_t *)accdb;
33+
34+
fd_vinyl_rq_leave( user->vinyl_rq );
35+
36+
/* superclass destructor */
37+
user->base.accdb_type = FD_ACCDB_TYPE_V1;
38+
fd_accdb_user_v1_fini( accdb );
39+
}
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+
void const * address ) {
46+
/* FIXME this should query vinyl cache too (via vinyl_meta/vinyl_data) */
47+
return fd_accdb_user_v1_peek( accdb, peek, xid, address );
48+
}
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+
void const * address ) {
59+
fd_accdb_user_v2_t * accdb = (fd_accdb_user_v2_t *)accdb_;
60+
fd_accdb_load_fork( &accdb->v1, xid );
61+
62+
/* Check whether value is present in funk overlay */
63+
64+
fd_accdb_peek_t peek[1];
65+
if( fd_accdb_peek_funk( &accdb->v1, peek, xid, address ) ) {
66+
if( FD_UNLIKELY( !peek->acc->meta->lamports ) ) return NULL;
67+
accdb->base.ro_active++;
68+
*ro = *peek->acc;
69+
return ro;
70+
}
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+
ulong batch_idx = fd_vinyl_req_pool_acquire ( accdb->vinyl_req_pool );
79+
fd_vinyl_key_t * req_key = fd_vinyl_req_batch_key ( accdb->vinyl_req_pool, batch_idx );
80+
ulong * req_val_gaddr = fd_vinyl_req_batch_val_gaddr( accdb->vinyl_req_pool, batch_idx );
81+
schar * req_err = fd_vinyl_req_batch_err ( accdb->vinyl_req_pool, batch_idx );
82+
fd_vinyl_comp_t * comp = fd_vinyl_req_batch_comp ( accdb->vinyl_req_pool, batch_idx );
83+
fd_vinyl_key_init( req_key, address, 32UL );
84+
memset( comp, 0, sizeof(fd_vinyl_comp_t) );
85+
fd_vinyl_req_send_batch(
86+
accdb->vinyl_rq,
87+
accdb->vinyl_req_pool,
88+
accdb->vinyl_req_id++,
89+
accdb->vinyl_link_id,
90+
FD_VINYL_REQ_TYPE_ACQUIRE,
91+
0UL, /* flags */
92+
batch_idx,
93+
1UL, /* batch_cnt */
94+
0UL /* val_max */
95+
);
96+
97+
/* Poll for completion */
98+
99+
while( FD_VOLATILE_CONST( comp->seq )!=1UL ) FD_SPIN_PAUSE();
100+
FD_COMPILER_MFENCE();
101+
int comp_err = FD_VOLATILE_CONST( comp->err );
102+
if( FD_UNLIKELY( comp_err!=FD_VINYL_SUCCESS ) ) {
103+
FD_LOG_CRIT(( "vinyl tile rejected my ACQUIRE request: %i-%s", comp_err, fd_vinyl_strerror( comp_err ) ));
104+
}
105+
int err = FD_VOLATILE_CONST( req_err[0] );
106+
if( err==FD_VINYL_ERR_KEY ) { /* not found */
107+
fd_vinyl_req_pool_release( accdb->vinyl_req_pool, batch_idx );
108+
return NULL;
109+
}
110+
if( FD_UNLIKELY( err!=FD_VINYL_SUCCESS ) ) {
111+
FD_LOG_CRIT(( "vinyl tile ACQUIRE request failed: %i-%s", err, fd_vinyl_strerror( err ) ));
112+
}
113+
114+
/* Return result */
115+
116+
ulong val_gaddr = FD_VOLATILE_CONST( req_val_gaddr[0] );
117+
fd_account_meta_t const * meta = fd_wksp_laddr_fast( accdb->vinyl_data_wksp, val_gaddr );
118+
fd_vinyl_req_pool_release( accdb->vinyl_req_pool, batch_idx );
119+
120+
accdb->base.ro_active++;
121+
*ro = (fd_accdb_ro_t) {
122+
.meta = meta
123+
};
124+
memcpy( ro->ref->address, address, 32UL );
125+
126+
/* Hide tombstones */
127+
128+
if( FD_UNLIKELY( !meta->lamports ) ) {
129+
fd_accdb_user_v2_close_ro( accdb_, ro );
130+
return NULL;
131+
}
132+
133+
return ro;
134+
}
135+
136+
void
137+
fd_accdb_user_v2_close_ro( fd_accdb_user_t * accdb_,
138+
fd_accdb_ro_t * ro ) {
139+
fd_accdb_user_v2_t * accdb = (fd_accdb_user_v2_t *)accdb_;
140+
141+
if( ro->rec ) {
142+
accdb->base.ro_active--;
143+
return;
144+
}
145+
146+
/* Send a RELEASE request */
147+
148+
ulong batch_idx = fd_vinyl_req_pool_acquire ( accdb->vinyl_req_pool );
149+
fd_vinyl_key_t * req_key = fd_vinyl_req_batch_key ( accdb->vinyl_req_pool, batch_idx );
150+
ulong * req_val_gaddr = fd_vinyl_req_batch_val_gaddr( accdb->vinyl_req_pool, batch_idx );
151+
schar * req_err = fd_vinyl_req_batch_err ( accdb->vinyl_req_pool, batch_idx );
152+
fd_vinyl_comp_t * comp = fd_vinyl_req_batch_comp ( accdb->vinyl_req_pool, batch_idx );
153+
fd_vinyl_key_init( req_key, ro->ref->address, 32UL );
154+
req_val_gaddr[0] = fd_wksp_gaddr_fast( accdb->vinyl_data_wksp, (void *)ro->meta );
155+
memset( comp, 0, sizeof(fd_vinyl_comp_t) );
156+
fd_vinyl_req_send_batch(
157+
accdb->vinyl_rq,
158+
accdb->vinyl_req_pool,
159+
accdb->vinyl_req_id++,
160+
accdb->vinyl_link_id,
161+
FD_VINYL_REQ_TYPE_RELEASE,
162+
0UL, /* flags */
163+
batch_idx,
164+
1UL, /* batch_cnt */
165+
0UL /* val_max */
166+
);
167+
168+
/* Poll for completion */
169+
170+
while( FD_VOLATILE_CONST( comp->seq )!=1UL ) FD_SPIN_PAUSE();
171+
FD_COMPILER_MFENCE();
172+
int comp_err = FD_VOLATILE_CONST( comp->err );
173+
if( FD_UNLIKELY( comp_err!=FD_VINYL_SUCCESS ) ) {
174+
FD_LOG_CRIT(( "vinyl tile rejected my RELEASE request: %i-%s", comp_err, fd_vinyl_strerror( comp_err ) ));
175+
}
176+
int err = FD_VOLATILE_CONST( req_err[0] );
177+
if( FD_UNLIKELY( err!=FD_VINYL_SUCCESS ) ) {
178+
FD_LOG_CRIT(( "vinyl tile RELEASE request failed: %i-%s", err, fd_vinyl_strerror( err ) ));
179+
}
180+
fd_vinyl_req_pool_release( accdb->vinyl_req_pool, batch_idx );
181+
182+
accdb->base.ro_active--;
183+
}
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+
int do_create ) {
192+
return fd_accdb_user_v1_open_rw( accdb, rw, xid, address, data_max, do_create );
193+
}
194+
195+
void
196+
fd_accdb_user_v2_close_rw( fd_accdb_user_t * accdb,
197+
fd_accdb_rw_t * write ) {
198+
fd_accdb_user_v1_close_rw( accdb, write );
199+
}
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+
ulong vinyl_link_id ) {
217+
/* Call superclass constructor */
218+
if( FD_UNLIKELY( !fd_accdb_user_v1_init( accdb_, funk ) ) ) {
219+
return NULL;
220+
}
221+
222+
fd_vinyl_rq_t * rq = fd_vinyl_rq_join( vinyl_rq );
223+
fd_vinyl_req_pool_t * req_pool = fd_vinyl_req_pool_join( vinyl_req_pool );
224+
if( FD_UNLIKELY( !rq || !req_pool ) ) {
225+
/* component joins log warning if this is reached */
226+
FD_LOG_WARNING(( "Failed to initialize database client" ));
227+
return NULL;
228+
}
229+
230+
fd_accdb_user_v2_t * accdb = fd_type_pun( accdb_ );
231+
accdb->vinyl_req_id = fd_vinyl_rq_seq( vinyl_rq );
232+
accdb->vinyl_rq = rq;
233+
accdb->vinyl_link_id = vinyl_link_id;
234+
accdb->vinyl_data_wksp = vinyl_data;
235+
accdb->vinyl_req_pool = req_pool;
236+
accdb->base.accdb_type = FD_ACCDB_TYPE_V2;
237+
accdb->base.vt = &fd_accdb_user_v2_vt;
238+
return accdb_;
239+
}

0 commit comments

Comments
 (0)