Line data Source code
1 0 : case FD_VINYL_REQ_TYPE_TRY: {
2 :
3 0 : FD_STATIC_ASSERT( FD_VINYL_LINE_VER_MAX==((1UL<<32)-1UL), update_impl_for_ver_max );
4 :
5 0 : ulong req_flags = (ulong)req->flags;
6 0 : fd_vinyl_key_t const * req_key = MAP_REQ_GADDR( req->key_gaddr, fd_vinyl_key_t, batch_cnt );
7 0 : ulong * req_val_gaddr = MAP_REQ_GADDR( req->val_gaddr_gaddr, ulong, 2UL*batch_cnt );
8 0 : schar * req_err = MAP_REQ_GADDR( req->err_gaddr, schar, batch_cnt );
9 :
10 0 : int req_evict_prio = fd_vinyl_req_evict_prio( req_flags );
11 :
12 0 : if( FD_UNLIKELY( (!!batch_cnt) & ((!req_key) | (!req_val_gaddr) | (!req_err)) ) ) {
13 0 : comp_err = FD_VINYL_ERR_INVAL;
14 0 : break;
15 0 : }
16 :
17 0 : ulong * req_try = req_val_gaddr + batch_cnt;
18 :
19 0 : for( ulong batch_idx=0UL; batch_idx<batch_cnt; batch_idx++ ) {
20 :
21 0 : # define DONE(err,try) do { \
22 0 : int _err = (err); \
23 0 : req_try[ batch_idx ] = (try); \
24 0 : FD_COMPILER_MFENCE(); \
25 0 : req_err[ batch_idx ] = (schar)_err; \
26 0 : FD_COMPILER_MFENCE(); \
27 0 : fail_cnt += (ulong)!!_err; \
28 0 : goto next_try; /* sigh ... can't use continue */ \
29 0 : } while(0)
30 :
31 : /* Query vinyl meta for key. If pair key does not exist at
32 : bstream seq_present and is not being created, there's nothing
33 : to try and fail with KEY. If it is being created (which
34 : implies it is also acquired for modify), fail with AGAIN. */
35 :
36 0 : fd_vinyl_key_t const * key = req_key + batch_idx;
37 :
38 0 : ulong memo = fd_vinyl_key_memo( meta_seed, key );
39 :
40 0 : ulong _ele_idx; /* avoid pointer escape */
41 0 : int err = fd_vinyl_meta_query_fast( ele0, ele_max, key, memo, &_ele_idx );
42 0 : ulong ele_idx = _ele_idx; /* In [0,ele_max) */
43 :
44 0 : if( FD_UNLIKELY( err ) ) DONE( FD_VINYL_ERR_KEY, ULONG_MAX );
45 :
46 0 : ulong pair_ctl = ele0[ ele_idx ].phdr.ctl;
47 :
48 0 : if( FD_UNLIKELY( pair_ctl==ULONG_MAX ) ) DONE( FD_VINYL_ERR_AGAIN, ULONG_MAX );
49 :
50 0 : FD_CRIT( fd_vinyl_bstream_ctl_type( pair_ctl )==FD_VINYL_BSTREAM_CTL_TYPE_PAIR, "corruption detected" );
51 :
52 0 : ulong val_sz = (ulong)ele0[ ele_idx ].phdr.info.val_sz;
53 :
54 0 : FD_CRIT( val_sz<=FD_VINYL_VAL_MAX, "corruption detected" );
55 :
56 : /* At this point, pair key exists at bstream seq_present */
57 :
58 0 : ulong line_idx = ele0[ ele_idx ].line_idx;
59 :
60 0 : FD_CRIT( (line_idx<line_cnt) | (line_idx==ULONG_MAX), "corruption detected" );
61 :
62 0 : if( FD_LIKELY( line_idx<line_cnt ) ) {
63 :
64 : /* At this point, pair key is already cached. If pair key is
65 : currently acquired for modify or is a redundant try with
66 : in-progress IO, fail with AGAIN. Otherwise, we are clear to
67 : try. */
68 :
69 0 : FD_CRIT( line[ line_idx ].ele_idx==ele_idx, "corruption detected" );
70 :
71 0 : fd_vinyl_data_obj_t * obj = line[ line_idx ].obj;
72 :
73 0 : FD_ALERT( fd_vinyl_data_is_valid_obj( obj, vol, vol_cnt ), "corruption detected" );
74 0 : FD_CRIT ( obj->line_idx==line_idx, "corruption detected" );
75 :
76 0 : ulong line_ctl = line[ line_idx ].ctl;
77 :
78 0 : ulong ver = fd_vinyl_line_ctl_ver( line_ctl );
79 0 : long ref = fd_vinyl_line_ctl_ref( line_ctl );
80 :
81 0 : if( FD_UNLIKELY( ref<0L ) ) DONE( FD_VINYL_ERR_AGAIN, ULONG_MAX );
82 :
83 0 : if( FD_LIKELY( !obj->rd_active ) ) {
84 0 : fd_vinyl_bstream_phdr_t * phdr = fd_vinyl_data_obj_phdr( obj );
85 :
86 0 : FD_CRIT( fd_vinyl_data_obj_val_max( obj ) >= val_sz, "corruption detected" );
87 0 : FD_CRIT( phdr->ctl==fd_vinyl_bstream_ctl( FD_VINYL_BSTREAM_CTL_TYPE_PAIR,
88 0 : FD_VINYL_BSTREAM_CTL_STYLE_RAW, val_sz ), "corruption detected" );
89 0 : FD_CRIT( fd_vinyl_key_eq( &phdr->key, key ), "corruption detected" );
90 0 : FD_CRIT( !memcmp( &phdr->info, &ele0[ ele_idx ].phdr.info, sizeof(fd_vinyl_info_t) ), "corruption detected" );
91 0 : }
92 :
93 0 : fd_vinyl_line_evict_prio( &vinyl->line_idx_lru, line, line_cnt, line_idx, req_evict_prio );
94 :
95 0 : req_val_gaddr[ batch_idx ] = (ulong)fd_vinyl_data_obj_val( obj ) - data_laddr0;
96 :
97 0 : DONE( FD_VINYL_SUCCESS, (ver<<32) | line_idx );
98 :
99 0 : }
100 :
101 : /* At this point, pair key exists but is not cached. Evict the
102 : least recently used evictable line to make room to cache this
103 : pair. Connect this line to meta element ele_idx, set the
104 : line's reference count to zero, bump the line's version and set
105 : the eviction priority as desired. We don't modify any shared
106 : fields in meta element ele_idx so we can do the modification
107 : fast.
108 :
109 : We do this upfront to free data cache for the alloc if the LRU
110 : line is in use and to handle the same pair appearing multiple
111 : times in an acquire.
112 :
113 : The mechanics for try requests with redundant keys are the same
114 : as acquire-for-read requests. */
115 :
116 0 : line_idx = fd_vinyl_line_evict_lru( &vinyl->line_idx_lru, line, line_cnt, ele0, ele_max, data );
117 :
118 0 : ulong line_ctl = line[ line_idx ].ctl;
119 :
120 0 : ulong ver = fd_vinyl_line_ctl_ver( line_ctl );
121 :
122 0 : line[ line_idx ].ele_idx = ele_idx; ele0[ ele_idx ].line_idx = line_idx;
123 0 : line[ line_idx ].ctl = fd_vinyl_line_ctl( ver+1UL, 0L );
124 :
125 0 : fd_vinyl_line_evict_prio( &vinyl->line_idx_lru, line, line_cnt, line_idx, req_evict_prio );
126 :
127 : /* Allocate an appropriately sized object to hold this pair,
128 : connect it to this line and report the location to the client. */
129 :
130 0 : ulong szc = fd_vinyl_data_szc( val_sz );
131 :
132 0 : fd_vinyl_data_obj_t * obj = fd_vinyl_data_alloc( data, szc );
133 0 : if( FD_UNLIKELY( !obj ) ) FD_LOG_CRIT(( "increase data cache size" ));
134 :
135 0 : line[ line_idx ].obj = obj; obj->line_idx = line_idx;
136 :
137 0 : void * val = fd_vinyl_data_obj_val( obj );
138 :
139 0 : req_val_gaddr[ batch_idx ] = (ulong)val - data_laddr0;
140 0 : req_try [ batch_idx ] = ((ver+1UL)<<32) | line_idx;
141 :
142 : /* Start reading encoded pair data and defer validation and
143 : decoding to later (and then in whatever order the I/O layer
144 : sees fit). */
145 :
146 0 : obj->rd_active = (short)1;
147 :
148 0 : int style = fd_vinyl_bstream_ctl_style( pair_ctl );
149 0 : ulong val_esz = fd_vinyl_bstream_ctl_sz ( pair_ctl );
150 :
151 0 : FD_CRIT( val_esz<=FD_VINYL_VAL_MAX, "corruption detected" );
152 0 : FD_CRIT( (style!=FD_VINYL_BSTREAM_CTL_STYLE_RAW) | (val_sz==val_esz), "corruption detected" );
153 :
154 0 : fd_vinyl_data_obj_t * cobj;
155 :
156 0 : if( FD_LIKELY( style==FD_VINYL_BSTREAM_CTL_STYLE_RAW ) ) cobj = obj;
157 0 : else {
158 0 : cobj = fd_vinyl_data_alloc( data, fd_vinyl_data_szc( val_esz ) );
159 0 : if( FD_UNLIKELY( !cobj ) ) FD_LOG_CRIT(( "increase data cache size" ));
160 0 : }
161 :
162 0 : cobj->rd->ctx = (ulong)obj;
163 0 : cobj->rd->seq = ele0[ ele_idx ].seq;
164 0 : cobj->rd->dst = fd_vinyl_data_obj_phdr( cobj );
165 0 : cobj->rd->sz = fd_vinyl_bstream_pair_sz( val_esz );
166 :
167 0 : cobj->rd_err = req_err + batch_idx;
168 :
169 0 : fd_vinyl_io_read( io, cobj->rd );
170 0 : read_cnt++;
171 :
172 0 : next_try: /* silly language restriction */;
173 :
174 0 : # undef DONE
175 :
176 0 : } /* for batch_idx */
177 :
178 0 : comp_err = FD_VINYL_SUCCESS;
179 0 : break;
180 0 : }
|