-
Notifications
You must be signed in to change notification settings - Fork 2
/
store.c
134 lines (98 loc) · 2.64 KB
/
store.c
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
#include <stdlib.h>
#include <stdio.h>
#include <stdbool.h>
#include <inttypes.h>
#include "utils.h"
#include "chunk.h"
#include "store.h"
struct substore {
struct store *s;
bool active;
uint32_t hits;
};
struct store_chain {
struct store s;
struct substore *stores;
size_t n_stores, stores_space;
uint32_t queries;
};
static ssize_t store_chain_get_chunk(struct store *s, uint8_t *id, uint8_t *out, size_t out_max)
{
struct store_chain *sc = (struct store_chain*) s;
char chunk_name[CHUNK_ID_STRLEN];
chunk_format_id(chunk_name, id);
sc->queries++;
for (size_t i = 0; i < sc->n_stores; i++) {
struct substore *substore = &sc->stores[i];
if (!substore->active)
continue;
ssize_t ret;
ret = store_get_chunk(substore->s, id, out, out_max);
if (ret < 0) {
u_log(DEBUG, "store '%s' has failed, deactivating it",
store_get_name(substore->s));
substore->active = false;
continue;
} else if (ret > 0) {
substore->hits++;
u_log(DEBUG, "chunk %s found in store '%s'",
chunk_name, store_get_name(substore->s));
return ret;
}
}
u_log(WARN, "chunk %s not found in any store", chunk_name);
return 0;
}
static void store_chain_free(struct store *s)
{
struct store_chain *sc = (struct store_chain*) s;
u_log(INFO, "%"PRIu32" queries received by %s",
sc->queries, store_get_name(s));
for (size_t i = 0; i < sc->n_stores; i++)
u_log(INFO, " %"PRIu32" answered by store %s",
sc->stores[i].hits,
store_get_name(sc->stores[i].s));
for (size_t i = 0; i < sc->n_stores; i++)
store_free(sc->stores[i].s);
free(sc->stores);
free(sc);
}
struct store_chain *store_chain_new(size_t size_hint)
{
static int chain_ctr = 0;
struct store_chain *sc;
sc = calloc(1, sizeof(*sc));
u_notnull(sc, return NULL);
sc->n_stores = 0;
if (size_hint)
sc->stores_space = size_hint;
else
sc->stores_space = 1;
sc->stores = calloc(sc->stores_space, sizeof(*sc->stores));
u_notnull(sc->stores, goto err_sc);
snprintf(sc->s.name, sizeof(sc->s.name), "chain%d", chain_ctr);
sc->s.get_chunk = store_chain_get_chunk;
sc->s.free = store_chain_free;
chain_ctr++;
return sc;
err_sc:
free(sc);
return NULL;
}
int store_chain_append(struct store_chain *sc, struct store *s)
{
if (sc->n_stores >= sc->stores_space) {
struct substore *new_stores;
size_t new_space;
new_space = sc->stores_space * 2;
new_stores = realloc(sc->stores, new_space * sizeof(*sc->stores));
u_notnull(new_stores, return -1);
sc->stores = new_stores;
sc->stores_space = new_space;
}
struct substore *substore = &sc->stores[sc->n_stores];
substore->s = s;
substore->active = true;
sc->n_stores++;
return 0;
}