Line data Source code
1 : #include "fd_reqlim.h"
2 :
3 : void *
4 45 : fd_reqlim_new( void * shmem, ulong dedup_max, ulong seed ) {
5 :
6 45 : if( FD_UNLIKELY( !shmem ) ) {
7 0 : FD_LOG_WARNING(( "NULL mem" ));
8 0 : return NULL;
9 0 : }
10 :
11 45 : if( FD_UNLIKELY( !fd_ulong_is_aligned( (ulong)shmem, fd_reqlim_align() ) ) ) {
12 0 : FD_LOG_WARNING(( "misaligned mem" ));
13 0 : return NULL;
14 0 : }
15 :
16 45 : ulong footprint = fd_reqlim_footprint( dedup_max );
17 45 : fd_memset( shmem, 0, footprint );
18 :
19 45 : FD_SCRATCH_ALLOC_INIT( l, shmem );
20 45 : fd_reqlim_t * dedup = FD_SCRATCH_ALLOC_APPEND( l, fd_reqlim_align(), sizeof(fd_reqlim_t) );
21 45 : void * map = FD_SCRATCH_ALLOC_APPEND( l, fd_reqlim_map_align(), fd_reqlim_map_footprint ( dedup_max ) );
22 45 : void * pool = FD_SCRATCH_ALLOC_APPEND( l, fd_reqlim_pool_align(), fd_reqlim_pool_footprint( dedup_max ) );
23 45 : void * lru = FD_SCRATCH_ALLOC_APPEND( l, fd_reqlim_lru_align(), fd_reqlim_lru_footprint() );
24 45 : FD_TEST( FD_SCRATCH_ALLOC_FINI( l, fd_reqlim_align() ) == (ulong)shmem + footprint );
25 :
26 45 : dedup->map = fd_reqlim_map_new ( map, dedup_max, seed );
27 45 : dedup->pool = fd_reqlim_pool_new( pool, dedup_max );
28 45 : dedup->lru = fd_reqlim_lru_new ( lru );
29 :
30 45 : return shmem;
31 45 : }
32 :
33 : fd_reqlim_t *
34 45 : fd_reqlim_join( void * shdedup ) {
35 45 : fd_reqlim_t * dedup = (fd_reqlim_t *)shdedup;
36 :
37 45 : if( FD_UNLIKELY( !dedup ) ) {
38 0 : FD_LOG_WARNING(( "NULL dedup" ));
39 0 : return NULL;
40 0 : }
41 :
42 45 : if( FD_UNLIKELY( !fd_ulong_is_aligned( (ulong)dedup, fd_reqlim_align() ) ) ) {
43 0 : FD_LOG_WARNING(( "misaligned dedup" ));
44 0 : return NULL;
45 0 : }
46 :
47 45 : dedup->map = fd_reqlim_map_join ( dedup->map );
48 45 : dedup->pool = fd_reqlim_pool_join( dedup->pool );
49 45 : dedup->lru = fd_reqlim_lru_join ( dedup->lru );
50 :
51 45 : return dedup;
52 45 : }
53 :
54 : void *
55 0 : fd_reqlim_leave( fd_reqlim_t const * dedup ) {
56 :
57 0 : if( FD_UNLIKELY( !dedup ) ) {
58 0 : FD_LOG_WARNING(( "NULL dedup" ));
59 0 : return NULL;
60 0 : }
61 :
62 0 : return (void *)dedup;
63 0 : }
64 :
65 : void *
66 0 : fd_reqlim_delete( void * dedup ) {
67 :
68 0 : if( FD_UNLIKELY( !dedup ) ) {
69 0 : FD_LOG_WARNING(( "NULL dedup" ));
70 0 : return NULL;
71 0 : }
72 :
73 0 : if( FD_UNLIKELY( !fd_ulong_is_aligned( (ulong)dedup, fd_reqlim_align() ) ) ) {
74 0 : FD_LOG_WARNING(( "misaligned dedup" ));
75 0 : return NULL;
76 0 : }
77 :
78 0 : return dedup;
79 0 : }
80 :
81 : /* dedup_evict evicts the least recently used element from the cache. */
82 :
83 : static void
84 0 : dedup_evict( fd_reqlim_t * dedup ) {
85 0 : fd_reqlim_ele_t * ele = fd_reqlim_lru_ele_pop_head( dedup->lru, dedup->pool );
86 0 : fd_reqlim_map_ele_remove( dedup->map, &ele->key, NULL, dedup->pool );
87 0 : fd_reqlim_pool_ele_release( dedup->pool, ele );
88 0 : }
89 :
90 : int
91 162 : fd_reqlim_next( fd_reqlim_t * dedup, ulong key, long now ) {
92 162 : fd_reqlim_ele_t * ele = fd_reqlim_map_ele_query( dedup->map, &key, NULL, dedup->pool );
93 162 : if( FD_UNLIKELY( !ele ) ) {
94 57 : if( FD_UNLIKELY( !fd_reqlim_pool_free( dedup->pool ) ) ) dedup_evict( dedup );
95 57 : ele = fd_reqlim_pool_ele_acquire( dedup->pool );
96 57 : ele->key = key;
97 57 : ele->req_ts = 0;
98 57 : fd_reqlim_map_ele_insert ( dedup->map, ele, dedup->pool );
99 57 : fd_reqlim_lru_ele_push_tail( dedup->lru, ele, dedup->pool );
100 57 : }
101 162 : if( FD_LIKELY( now < ele->req_ts + (long)FD_REQLIM_DEDUP_TIMEOUT ) ) {
102 105 : fd_reqlim_lru_ele_remove ( dedup->lru, ele, dedup->pool );
103 105 : fd_reqlim_lru_ele_push_tail( dedup->lru, ele, dedup->pool );
104 105 : return 1;
105 105 : }
106 57 : ele->req_ts = now;
107 57 : fd_reqlim_lru_ele_remove ( dedup->lru, ele, dedup->pool );
108 57 : fd_reqlim_lru_ele_push_tail( dedup->lru, ele, dedup->pool );
109 57 : return 0;
110 162 : }
111 :
112 : int
113 0 : fd_reqlim_query( fd_reqlim_t const * dedup, ulong key, long now ) {
114 0 : fd_reqlim_ele_t const * ele = fd_reqlim_map_ele_query_const( dedup->map, &key, NULL, dedup->pool );
115 0 : if( FD_LIKELY( ele && now < ele->req_ts + (long)FD_REQLIM_DEDUP_TIMEOUT ) ) {
116 0 : return 1;
117 0 : }
118 0 : return 0;
119 0 : }
120 :
121 : long
122 0 : fd_reqlim_next_due( fd_reqlim_t const * dedup, ulong key, long now ) {
123 0 : fd_reqlim_ele_t const * ele = fd_reqlim_map_ele_query_const( dedup->map, &key, NULL, dedup->pool );
124 0 : if( FD_LIKELY( ele ) ) {
125 0 : long next_due = ele->req_ts + (long)FD_REQLIM_DEDUP_TIMEOUT;
126 0 : if( FD_LIKELY( now < next_due ) ) return next_due;
127 0 : }
128 0 : return now;
129 0 : }
|