varnish-cache/bin/varnishd/hash/hash_simple_list.c
0
/*-
1
 * Copyright (c) 2006 Verdens Gang AS
2
 * Copyright (c) 2006-2011 Varnish Software AS
3
 * All rights reserved.
4
 *
5
 * Author: Poul-Henning Kamp <phk@phk.freebsd.dk>
6
 *
7
 * SPDX-License-Identifier: BSD-2-Clause
8
 *
9
 * Redistribution and use in source and binary forms, with or without
10
 * modification, are permitted provided that the following conditions
11
 * are met:
12
 * 1. Redistributions of source code must retain the above copyright
13
 *    notice, this list of conditions and the following disclaimer.
14
 * 2. Redistributions in binary form must reproduce the above copyright
15
 *    notice, this list of conditions and the following disclaimer in the
16
 *    documentation and/or other materials provided with the distribution.
17
 *
18
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
19
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21
 * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
22
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28
 * SUCH DAMAGE.
29
 *
30
 * This is the reference hash(/lookup) implementation
31
 */
32
33
#include "config.h"
34
35
#include "cache/cache_varnishd.h"
36
#include "cache/cache_objhead.h"
37
38
#include "hash/hash_slinger.h"
39
40
static struct VSC_lck *lck_hsl;
41
42
/*--------------------------------------------------------------------*/
43
44
static VTAILQ_HEAD(, objhead)   hsl_head = VTAILQ_HEAD_INITIALIZER(hsl_head);
45
static struct lock hsl_mtx;
46
47
/*--------------------------------------------------------------------
48
 * The ->init method is called during process start and allows
49
 * initialization to happen before the first lookup.
50
 */
51
52
static void v_matchproto_(hash_start_f)
53 40
hsl_start(void)
54
{
55
56 40
        lck_hsl = Lck_CreateClass(NULL, "hsl");
57 40
        Lck_New(&hsl_mtx, lck_hsl);
58 40
}
59
60
/*--------------------------------------------------------------------
61
 * Lookup and possibly insert element.
62
 * If nobj != NULL and the lookup does not find key, nobj is inserted.
63
 * If nobj == NULL and the lookup does not find key, NULL is returned.
64
 * A reference to the returned object is held.
65
 */
66
67
static struct objhead * v_matchproto_(hash_lookup_f)
68 80
hsl_lookup(struct worker *wrk, const void *digest, struct objhead **noh)
69
{
70
        struct objhead *oh;
71
        int i;
72
73 80
        CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
74 80
        AN(digest);
75 80
        if (noh != NULL)
76 80
                CHECK_OBJ_NOTNULL(*noh, OBJHEAD_MAGIC);
77
78 80
        Lck_Lock(&hsl_mtx);
79 80
        VTAILQ_FOREACH(oh, &hsl_head, hoh_list) {
80 40
                i = memcmp(oh->digest, digest, sizeof oh->digest);
81 40
                if (i < 0)
82 0
                        continue;
83 40
                if (i > 0)
84 0
                        break;
85 40
                oh->refcnt++;
86 40
                Lck_Unlock(&hsl_mtx);
87 40
                Lck_Lock(&oh->mtx);
88 40
                return (oh);
89
        }
90
91 40
        if (noh == NULL)
92 0
                return (NULL);
93
94 40
        if (oh != NULL)
95 0
                VTAILQ_INSERT_BEFORE(oh, *noh, hoh_list);
96
        else
97 40
                VTAILQ_INSERT_TAIL(&hsl_head, *noh, hoh_list);
98
99 40
        oh = *noh;
100 40
        *noh = NULL;
101 40
        memcpy(oh->digest, digest, sizeof oh->digest);
102 40
        Lck_Unlock(&hsl_mtx);
103 40
        Lck_Lock(&oh->mtx);
104 40
        return (oh);
105 80
}
106
107
/*--------------------------------------------------------------------
108
 * Dereference and if no references are left, free.
109
 */
110
111
static int v_matchproto_(hash_deref_f)
112 40
hsl_deref(struct worker *wrk, struct objhead *oh)
113
{
114
        int ret;
115
116 40
        CHECK_OBJ_NOTNULL(oh, OBJHEAD_MAGIC);
117 40
        Lck_AssertHeld(&oh->mtx);
118 40
        Lck_Unlock(&oh->mtx);
119
120 40
        Lck_Lock(&hsl_mtx);
121 40
        if (--oh->refcnt == 0) {
122 0
                VTAILQ_REMOVE(&hsl_head, oh, hoh_list);
123 0
                ret = 0;
124 0
        } else
125 40
                ret = 1;
126 40
        Lck_Unlock(&hsl_mtx);
127 40
        if (!ret)
128 0
                HSH_DeleteObjHead(wrk, oh);
129 40
        return (ret);
130
}
131
132
/*--------------------------------------------------------------------*/
133
134
const struct hash_slinger hsl_slinger = {
135
        .magic  =       SLINGER_MAGIC,
136
        .name   =       "simple",
137
        .start  =       hsl_start,
138
        .lookup =       hsl_lookup,
139
        .deref  =       hsl_deref,
140
};