1
2 /*
3 * Copyright (C) Max Romanov
4 * Copyright (C) NGINX, Inc.
5 */
6
7 #include <nxt_port_hash.h>
8
9
10 // Explicitly using 32 bit types to avoid possible alignment.
11 typedef struct {
12 int32_t pid;
13 uint32_t port_id;
14 } nxt_pid_port_id_t;
15
16
17 static nxt_int_t
nxt_port_hash_test(nxt_lvlhsh_query_t * lhq,void * data)18 nxt_port_hash_test(nxt_lvlhsh_query_t *lhq, void *data)
19 {
20 nxt_port_t *port;
21 nxt_pid_port_id_t *pid_port_id;
22
23 port = data;
24 pid_port_id = (nxt_pid_port_id_t *) lhq->key.start;
25
26 if (lhq->key.length == sizeof(nxt_pid_port_id_t)
27 && pid_port_id->pid == port->pid
28 && pid_port_id->port_id == port->id)
29 {
30 return NXT_OK;
31 }
32
33 return NXT_DECLINED;
34 }
35
36 static const nxt_lvlhsh_proto_t lvlhsh_ports_proto nxt_aligned(64) = {
37 NXT_LVLHSH_DEFAULT,
38 nxt_port_hash_test,
39 nxt_lvlhsh_alloc,
40 nxt_lvlhsh_free,
41 };
42
43
44 nxt_port_t *
nxt_port_hash_retrieve(nxt_lvlhsh_t * port_hash)45 nxt_port_hash_retrieve(nxt_lvlhsh_t *port_hash)
46 {
47 return nxt_lvlhsh_retrieve(port_hash, &lvlhsh_ports_proto, NULL);
48 }
49
50
51 nxt_inline void
nxt_port_hash_lhq(nxt_lvlhsh_query_t * lhq,nxt_pid_port_id_t * pid_port)52 nxt_port_hash_lhq(nxt_lvlhsh_query_t *lhq, nxt_pid_port_id_t *pid_port)
53 {
54 lhq->key_hash = nxt_murmur_hash2(pid_port, sizeof(nxt_pid_port_id_t));
55 lhq->key.length = sizeof(nxt_pid_port_id_t);
56 lhq->key.start = (u_char *) pid_port;
57 lhq->proto = &lvlhsh_ports_proto;
58 lhq->pool = NULL;
59 }
60
61
62 nxt_int_t
nxt_port_hash_add(nxt_lvlhsh_t * port_hash,nxt_port_t * port)63 nxt_port_hash_add(nxt_lvlhsh_t *port_hash, nxt_port_t *port)
64 {
65 nxt_int_t res;
66 nxt_pid_port_id_t pid_port;
67 nxt_lvlhsh_query_t lhq;
68
69 pid_port.pid = port->pid;
70 pid_port.port_id = port->id;
71
72 nxt_port_hash_lhq(&lhq, &pid_port);
73 lhq.replace = 0;
74 lhq.value = port;
75
76 res = nxt_lvlhsh_insert(port_hash, &lhq);
77
78 switch (res) {
79
80 case NXT_OK:
81 break;
82
83 default:
84 nxt_thread_log_error(NXT_LOG_WARN, "port #%d for pid %PI add failed",
85 port->id, port->pid);
86 break;
87 }
88
89 return res;
90 }
91
92
93 nxt_int_t
nxt_port_hash_remove(nxt_lvlhsh_t * port_hash,nxt_port_t * port)94 nxt_port_hash_remove(nxt_lvlhsh_t *port_hash, nxt_port_t *port)
95 {
96 nxt_int_t res;
97 nxt_pid_port_id_t pid_port;
98 nxt_lvlhsh_query_t lhq;
99
100 pid_port.pid = port->pid;
101 pid_port.port_id = port->id;
102
103 nxt_port_hash_lhq(&lhq, &pid_port);
104
105 res = nxt_lvlhsh_delete(port_hash, &lhq);
106
107 switch (res) {
108
109 case NXT_OK:
110 break;
111
112 default:
113 nxt_thread_log_error(NXT_LOG_WARN, "port #%d for pid %PI remove failed",
114 port->id, port->pid);
115 break;
116 }
117
118 return res;
119 }
120
121
122 nxt_port_t *
nxt_port_hash_find(nxt_lvlhsh_t * port_hash,nxt_pid_t pid,nxt_port_id_t port_id)123 nxt_port_hash_find(nxt_lvlhsh_t *port_hash, nxt_pid_t pid,
124 nxt_port_id_t port_id)
125 {
126 nxt_pid_port_id_t pid_port;
127 nxt_lvlhsh_query_t lhq;
128
129 pid_port.pid = pid;
130 pid_port.port_id = port_id;
131
132 nxt_port_hash_lhq(&lhq, &pid_port);
133
134 if (nxt_lvlhsh_find(port_hash, &lhq) == NXT_OK) {
135 nxt_thread_log_debug("process port (%PI, %d) found", pid, port_id);
136 return lhq.value;
137 }
138
139 nxt_thread_log_debug("process port (%PI, %d) not found", pid, port_id);
140
141 return NULL;
142 }
143