Line data Source code
1 : #include "fd_reqlim.h"
2 :
3 : void *
4 0 : fd_reqlim_new( void * shmem, ulong dedup_max, ulong seed ) {
5 :
6 0 : if( FD_UNLIKELY( !shmem ) ) {
7 0 : FD_LOG_WARNING(( "NULL mem" ));
8 0 : return NULL;
9 0 : }
10 :
11 0 : 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 0 : ulong footprint = fd_reqlim_footprint( dedup_max );
17 0 : fd_memset( shmem, 0, footprint );
18 :
19 0 : FD_SCRATCH_ALLOC_INIT( l, shmem );
20 0 : fd_reqlim_t * dedup = FD_SCRATCH_ALLOC_APPEND( l, fd_reqlim_align(), sizeof(fd_reqlim_t) );
21 0 : void * map = FD_SCRATCH_ALLOC_APPEND( l, fd_reqlim_map_align(), fd_reqlim_map_footprint ( dedup_max ) );
22 0 : void * pool = FD_SCRATCH_ALLOC_APPEND( l, fd_reqlim_pool_align(), fd_reqlim_pool_footprint( dedup_max ) );
23 0 : void * lru = FD_SCRATCH_ALLOC_APPEND( l, fd_reqlim_lru_align(), fd_reqlim_lru_footprint() );
24 0 : FD_TEST( FD_SCRATCH_ALLOC_FINI( l, fd_reqlim_align() ) == (ulong)shmem + footprint );
25 :
26 0 : dedup->map = fd_reqlim_map_new ( map, dedup_max, seed );
27 0 : dedup->pool = fd_reqlim_pool_new( pool, dedup_max );
28 0 : dedup->lru = fd_reqlim_lru_new ( lru );
29 :
30 0 : return shmem;
31 0 : }
32 :
33 : fd_reqlim_t *
34 0 : fd_reqlim_join( void * shdedup ) {
35 0 : fd_reqlim_t * dedup = (fd_reqlim_t *)shdedup;
36 :
37 0 : if( FD_UNLIKELY( !dedup ) ) {
38 0 : FD_LOG_WARNING(( "NULL dedup" ));
39 0 : return NULL;
40 0 : }
41 :
42 0 : 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 0 : dedup->map = fd_reqlim_map_join ( dedup->map );
48 0 : dedup->pool = fd_reqlim_pool_join( dedup->pool );
49 0 : dedup->lru = fd_reqlim_lru_join ( dedup->lru );
50 :
51 0 : return dedup;
52 0 : }
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 0 : fd_reqlim_next( fd_reqlim_t * dedup, ulong key, long now ) {
92 0 : fd_reqlim_ele_t * ele = fd_reqlim_map_ele_query( dedup->map, &key, NULL, dedup->pool );
93 0 : if( FD_UNLIKELY( !ele ) ) {
94 0 : if( FD_UNLIKELY( !fd_reqlim_pool_free( dedup->pool ) ) ) dedup_evict( dedup );
95 0 : ele = fd_reqlim_pool_ele_acquire( dedup->pool );
96 0 : ele->key = key;
97 0 : ele->req_ts = 0;
98 0 : fd_reqlim_map_ele_insert ( dedup->map, ele, dedup->pool );
99 0 : fd_reqlim_lru_ele_push_tail( dedup->lru, ele, dedup->pool );
100 0 : }
101 0 : if( FD_LIKELY( now < ele->req_ts + (long)FD_REQLIM_DEDUP_TIMEOUT ) ) {
102 0 : fd_reqlim_lru_ele_remove ( dedup->lru, ele, dedup->pool );
103 0 : fd_reqlim_lru_ele_push_tail( dedup->lru, ele, dedup->pool );
104 0 : return 1;
105 0 : }
106 0 : ele->req_ts = now;
107 0 : return 0;
108 0 : }
109 :
110 : int
111 0 : fd_reqlim_query( fd_reqlim_t const * dedup, ulong key, long now ) {
112 0 : fd_reqlim_ele_t const * ele = fd_reqlim_map_ele_query_const( dedup->map, &key, NULL, dedup->pool );
113 0 : if( FD_LIKELY( ele && now < ele->req_ts + (long)FD_REQLIM_DEDUP_TIMEOUT ) ) {
114 0 : return 1;
115 0 : }
116 0 : return 0;
117 0 : }
|