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