-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcapreqidx.c
195 lines (151 loc) · 5.13 KB
/
capreqidx.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
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
/*
Copyright (C) 2000 - 2008 Pawel A. Gajda <[email protected]>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License published by
the Free Software Foundation (see file COPYING for details).
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include <stdlib.h>
#include <string.h>
#include <trurl/nassert.h>
#include <trurl/nmalloc.h>
#include "compiler.h"
#include "i18n.h"
#include "pkg.h"
#include "capreqidx.h"
#include "capreq.h"
#include "log.h"
static void capreq_ent_free(struct capreq_idx_ent *ent)
{
DBGF("ent %p, %p %d, %d\n", ent, ent->crent_pkgs, ent->_size, ent->items);
if (ent->_size > 1)
free(ent->crent_pkgs);
}
int capreq_idx_init(struct capreq_idx *idx, unsigned type, int nelem)
{
idx->flags = type;
MEMINF("START");
idx->na = n_alloc_new(4, TN_ALLOC_OBSTACK);
idx->ht = n_hash_new_na(idx->na, nelem, (tn_fn_free)capreq_ent_free);
n_hash_ctl(idx->ht, TN_HASH_NOCPKEY);
MEMINF("END");
return 1;
}
void capreq_idx_destroy(struct capreq_idx *idx)
{
n_hash_free(idx->ht);
n_alloc_free(idx->na);
memset(idx, 0, sizeof(*idx));
}
static int capreq_idx_ent_transform_to_array(struct capreq_idx_ent *ent)
{
struct pkg *tmp;
n_assert(ent->_size == 1); /* crent_pkgs is NOT allocated */
tmp = ent->crent_pkg;
ent->crent_pkgs = n_malloc(2 * sizeof(*ent->crent_pkgs));
ent->crent_pkgs[0] = tmp;
ent->_size = 2;
return 1;
}
int capreq_idx_add(struct capreq_idx *idx, const char *capname,
struct pkg *pkg)
{
struct capreq_idx_ent *ent;
unsigned khash = 0;
int klen = 0;
if ((ent = n_hash_get_ex(idx->ht, capname, &klen, &khash)) == NULL) {
const char *hcapname = capreq__alloc_name(capname);
ent = idx->na->na_malloc(idx->na, sizeof(*ent));
ent->_size = 1;
ent->items = 1;
ent->crent_pkg = pkg;
n_hash_insert_ex(idx->ht, hcapname, klen, khash, ent);
#if ENABLE_TRACE
if ((n_hash_size(idx->ht) % 1000) == 0)
n_hash_stats(idx->ht);
#endif
} else {
if (ent->_size == 1) /* crent_pkgs is NOT allocated */
capreq_idx_ent_transform_to_array(ent);
/*
* Sometimes, there are duplicates, especially in dotnet-* packages
* which provides multiple versions of one cap. For example dotnet-mono-zeroconf
* provides: mono(Mono.Zeroconf) = 1.0.0.0, mono(Mono.Zeroconf) = 2.0.0.0, etc.
*/
if (idx->flags & CAPREQ_IDX_CAP) { /* check for duplicates */
register int i;
for (i=0; i < ent->items; i++) {
if (pkg == ent->crent_pkgs[i])
return 1;
}
}
if (ent->items == ent->_size) {
ent->_size *= 2;
ent->crent_pkgs = n_realloc(ent->crent_pkgs,
ent->_size * sizeof(*ent->crent_pkgs));
}
ent->crent_pkgs[ent->items++] = pkg;
}
return 1;
}
void capreq_idx_remove(struct capreq_idx *idx, const char *capname,
struct pkg *pkg)
{
struct capreq_idx_ent *ent;
int i;
if ((ent = n_hash_get(idx->ht, capname)) == NULL)
return;
if (ent->_size == 1) { /* no crent_pkgs */
if (pkg_cmp_name_evr(pkg, ent->crent_pkg) == 0) {
ent->items = 0;
ent->crent_pkg = NULL;
}
return;
}
for (i=0; i < ent->items; i++) {
if (pkg_cmp_name_evr(pkg, ent->crent_pkgs[i]) == 0) {
if (i == ent->items - 1)
ent->crent_pkgs[i] = NULL;
else
memmove(&ent->crent_pkgs[i], &ent->crent_pkgs[i + 1],
(ent->_size - 1 - i) * sizeof(*ent->crent_pkgs));
ent->crent_pkgs[ent->_size - 1] = NULL;
ent->items--;
}
}
}
void capreq_idx_stats(const char *prefix, struct capreq_idx *idx)
{
tn_array *keys = n_hash_keys(idx->ht);
int i, stats[100000];
memset(stats, 0, sizeof(stats));
for (i=0; i < n_array_size(keys); i++) {
struct capreq_idx_ent *ent;
ent = n_hash_get(idx->ht, n_array_nth(keys, i));
stats[ent->items]++;
}
n_array_free(keys);
printf("CAPREQ_IDX %s %d\n", prefix, n_hash_size(idx->ht));
for (i=0; i < 100000; i++) {
if (stats[i])
printf("%s: %d: %d\n", prefix, i, stats[i]);
}
}
const
struct capreq_idx_ent *capreq_idx_lookup(struct capreq_idx *idx,
const char *capname)
{
struct capreq_idx_ent *ent;
if ((ent = n_hash_get(idx->ht, capname)) == NULL)
return NULL;
if (ent->items == 0)
return NULL;
if (ent->_size == 1) /* return only transformed ents */
capreq_idx_ent_transform_to_array(ent);
return ent;
}