1 
2 /*
3  * Copyright (C) Igor Sysoev
4  * Copyright (C) NGINX, Inc.
5  */
6 
7 #include <nxt_main.h>
8 
9 
10 static nxt_int_t nxt_fd_event_hash_test(nxt_lvlhsh_query_t *lhq, void *data);
11 static void nxt_fd_event_hash_error(nxt_task_t *task, nxt_fd_t fd);
12 
13 
14 static const nxt_lvlhsh_proto_t  nxt_event_set_fd_hash_proto  nxt_aligned(64) =
15 {
16     NXT_LVLHSH_LARGE_MEMALIGN,
17     nxt_fd_event_hash_test,
18     nxt_lvlhsh_alloc,
19     nxt_lvlhsh_free,
20 };
21 
22 
23 /* nxt_murmur_hash2() is unique for 4 bytes. */
24 
25 static nxt_int_t
nxt_fd_event_hash_test(nxt_lvlhsh_query_t * lhq,void * data)26 nxt_fd_event_hash_test(nxt_lvlhsh_query_t *lhq, void *data)
27 {
28     return NXT_OK;
29 }
30 
31 
32 nxt_int_t
nxt_fd_event_hash_add(nxt_lvlhsh_t * lvlhsh,nxt_fd_t fd,nxt_fd_event_t * ev)33 nxt_fd_event_hash_add(nxt_lvlhsh_t *lvlhsh, nxt_fd_t fd, nxt_fd_event_t *ev)
34 {
35     nxt_int_t           ret;
36     nxt_lvlhsh_query_t  lhq;
37 
38     lhq.key_hash = nxt_murmur_hash2(&fd, sizeof(nxt_fd_t));
39     lhq.replace = 0;
40     lhq.value = ev;
41     lhq.proto = &nxt_event_set_fd_hash_proto;
42 
43     ret = nxt_lvlhsh_insert(lvlhsh, &lhq);
44 
45     if (nxt_fast_path(ret == NXT_OK)) {
46         return NXT_OK;
47     }
48 
49     nxt_alert(ev->task, "fd event %d is already in hash", ev->fd);
50 
51     return NXT_ERROR;
52 }
53 
54 
55 void *
nxt_fd_event_hash_get(nxt_task_t * task,nxt_lvlhsh_t * lvlhsh,nxt_fd_t fd)56 nxt_fd_event_hash_get(nxt_task_t *task, nxt_lvlhsh_t *lvlhsh, nxt_fd_t fd)
57 {
58     nxt_int_t           ret;
59     nxt_lvlhsh_query_t  lhq;
60 
61     lhq.key_hash = nxt_murmur_hash2(&fd, sizeof(nxt_fd_t));
62     lhq.proto = &nxt_event_set_fd_hash_proto;
63 
64     ret = nxt_lvlhsh_find(lvlhsh, &lhq);
65 
66     if (nxt_fast_path(ret == NXT_OK)) {
67         return lhq.value;
68     }
69 
70     nxt_fd_event_hash_error(task, fd);
71 
72     return NULL;
73 }
74 
75 
76 void
nxt_fd_event_hash_delete(nxt_task_t * task,nxt_lvlhsh_t * lvlhsh,nxt_fd_t fd,nxt_bool_t ignore)77 nxt_fd_event_hash_delete(nxt_task_t *task, nxt_lvlhsh_t *lvlhsh, nxt_fd_t fd,
78     nxt_bool_t ignore)
79 {
80     nxt_int_t           ret;
81     nxt_lvlhsh_query_t  lhq;
82 
83     lhq.key_hash = nxt_murmur_hash2(&fd, sizeof(nxt_fd_t));
84     lhq.proto = &nxt_event_set_fd_hash_proto;
85 
86     ret = nxt_lvlhsh_delete(lvlhsh, &lhq);
87 
88     if (nxt_slow_path(ret != NXT_OK)) {
89         if (!ignore) {
90             nxt_fd_event_hash_error(task, fd);
91         }
92     }
93 }
94 
95 
96 void
nxt_fd_event_hash_destroy(nxt_lvlhsh_t * lvlhsh)97 nxt_fd_event_hash_destroy(nxt_lvlhsh_t *lvlhsh)
98 {
99     nxt_fd_event_t  *ev;
100 
101     do {
102         ev = nxt_lvlhsh_retrieve(lvlhsh, &nxt_event_set_fd_hash_proto, NULL);
103 
104     } while (ev != NULL);
105 }
106 
107 
108 static void
nxt_fd_event_hash_error(nxt_task_t * task,nxt_fd_t fd)109 nxt_fd_event_hash_error(nxt_task_t *task, nxt_fd_t fd)
110 {
111     nxt_alert(task, "fd event %d not found in hash", fd);
112 }
113