summaryrefslogtreecommitdiffhomepage
path: root/src/nxt_port_hash.c
blob: 93e46cd3660762cdcff60010fd1bc2c732bbe8ce (plain) (blame)
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

/*
 * 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_first(nxt_lvlhsh_t *port_hash, nxt_lvlhsh_each_t *lhe)
{
    nxt_memzero(lhe, sizeof(nxt_lvlhsh_each_t));

    lhe->proto = &lvlhsh_ports_proto;

    return nxt_port_hash_next(port_hash, lhe);
}


void
nxt_port_hash_add(nxt_lvlhsh_t *port_hash, nxt_mp_t *mem_pool,
    nxt_port_t *port)
{
    nxt_pid_port_id_t   pid_port;
    nxt_lvlhsh_query_t  lhq;

    pid_port.pid = port->pid;
    pid_port.port_id = port->id;

    lhq.key_hash = nxt_murmur_hash2(&pid_port, sizeof(pid_port));
    lhq.key.length = sizeof(pid_port);
    lhq.key.start = (u_char *) &pid_port;
    lhq.proto = &lvlhsh_ports_proto;
    lhq.replace = 0;
    lhq.value = port;
    lhq.pool = mem_pool;

    switch (nxt_lvlhsh_insert(port_hash, &lhq)) {

    case NXT_OK:
        break;

    default:
        nxt_thread_log_error(NXT_LOG_WARN, "port #%d for pid %PI add failed",
                             port->id, port->pid);
        break;
    }
}


void
nxt_port_hash_remove(nxt_lvlhsh_t *port_hash, nxt_mp_t *mem_pool,
    nxt_port_t *port)
{
    nxt_pid_port_id_t   pid_port;
    nxt_lvlhsh_query_t  lhq;

    pid_port.pid = port->pid;
    pid_port.port_id = port->id;

    lhq.key_hash = nxt_murmur_hash2(&pid_port, sizeof(pid_port));
    lhq.key.length = sizeof(pid_port);
    lhq.key.start = (u_char *) &pid_port;
    lhq.proto = &lvlhsh_ports_proto;
    lhq.replace = 0;
    lhq.value = port;
    lhq.pool = mem_pool;

    switch (nxt_lvlhsh_delete(port_hash, &lhq)) {

    case NXT_OK:
        break;

    default:
        break;
    }
}


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;

    lhq.key_hash = nxt_murmur_hash2(&pid_port, sizeof(pid_port));
    lhq.key.length = sizeof(pid_port);
    lhq.key.start = (u_char *) &pid_port;
    lhq.proto = &lvlhsh_ports_proto;

    /* TODO lock ports */

    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;
}