1 // SPDX-License-Identifier: LGPL-2.1
2 /*
3 * Copyright (C) 2009, Steven Rostedt <srostedt@redhat.com>
4 * Copyright (C) 2018 VMware Inc, Steven Rostedt <rostedt@goodmis.org>
5 *
6 */
7 #include <stdio.h>
8 #include <stdlib.h>
9 #include <string.h>
10 #include <stdarg.h>
11 #include <assert.h>
12
13 #include "trace-filter-hash.h"
14
15 #define FILTER_HASH_BITS 8
16 #define FILTER_HASH_SIZE (1 << FILTER_HASH_BITS)
17
18 struct tracecmd_filter_id_item *
tracecmd_filter_id_find(struct tracecmd_filter_id * hash,int id)19 tracecmd_filter_id_find(struct tracecmd_filter_id *hash, int id)
20 {
21 int key = tracecmd_quick_hash(id, FILTER_HASH_BITS);
22 struct tracecmd_filter_id_item *item = hash->hash[key];
23
24 while (item) {
25 if (item->id == id)
26 break;
27 item = item->next;
28 }
29
30 return item;
31 }
32
tracecmd_filter_id_add(struct tracecmd_filter_id * hash,int id)33 void tracecmd_filter_id_add(struct tracecmd_filter_id *hash, int id)
34 {
35 int key = tracecmd_quick_hash(id, FILTER_HASH_BITS);
36 struct tracecmd_filter_id_item *item;
37
38 item = calloc(1, sizeof(*item));
39 assert(item);
40
41 item->id = id;
42 item->next = hash->hash[key];
43 hash->hash[key] = item;
44
45 hash->count++;
46 }
47
tracecmd_filter_id_remove(struct tracecmd_filter_id * hash,int id)48 void tracecmd_filter_id_remove(struct tracecmd_filter_id *hash, int id)
49 {
50 int key = tracecmd_quick_hash(id, FILTER_HASH_BITS);
51 struct tracecmd_filter_id_item **next = &hash->hash[key];
52 struct tracecmd_filter_id_item *item;
53
54 while (*next) {
55 if ((*next)->id == id)
56 break;
57 next = &(*next)->next;
58 }
59
60 if (!*next)
61 return;
62
63 assert(hash->count);
64 hash->count--;
65
66 item = *next;
67
68 *next = item->next;
69
70 free(item);
71 }
72
tracecmd_filter_id_clear(struct tracecmd_filter_id * hash)73 void tracecmd_filter_id_clear(struct tracecmd_filter_id *hash)
74 {
75 struct tracecmd_filter_id_item *item, *next;
76 int i;
77
78 for (i = 0; i < FILTER_HASH_SIZE; i++) {
79 next = hash->hash[i];
80 if (!next)
81 continue;
82
83 hash->hash[i] = NULL;
84 while (next) {
85 item = next;
86 next = item->next;
87 free(item);
88 }
89 }
90
91 hash->count = 0;
92 }
93
tracecmd_filter_id_hash_alloc(void)94 struct tracecmd_filter_id *tracecmd_filter_id_hash_alloc(void)
95 {
96 struct tracecmd_filter_id *hash;
97
98 hash = calloc(1, sizeof(*hash));
99 assert(hash);
100 hash->hash = calloc(FILTER_HASH_SIZE, sizeof(*hash->hash));
101 hash->count = 0;
102
103 return hash;
104 }
105
tracecmd_filter_id_hash_free(struct tracecmd_filter_id * hash)106 void tracecmd_filter_id_hash_free(struct tracecmd_filter_id *hash)
107 {
108 if (!hash)
109 return;
110
111 tracecmd_filter_id_clear(hash);
112 free(hash->hash);
113 free(hash);
114 }
115
116 struct tracecmd_filter_id *
tracecmd_filter_id_hash_copy(struct tracecmd_filter_id * hash)117 tracecmd_filter_id_hash_copy(struct tracecmd_filter_id *hash)
118 {
119 struct tracecmd_filter_id *new_hash;
120 struct tracecmd_filter_id_item *item, **pitem;
121 int i;
122
123 if (!hash)
124 return NULL;
125
126 new_hash = tracecmd_filter_id_hash_alloc();
127 assert(new_hash);
128
129 for (i = 0; i < FILTER_HASH_SIZE; i++) {
130 item = hash->hash[i];
131 if (!item)
132 continue;
133
134 pitem = &new_hash->hash[i];
135
136 while (item) {
137 *pitem = calloc(1, sizeof(*item));
138 assert(*pitem);
139 **pitem = *item;
140
141 pitem = &(*pitem)->next;
142 item = item->next;
143 }
144 }
145
146 new_hash->count = hash->count;
147 return new_hash;
148 }
149
tracecmd_filter_ids(struct tracecmd_filter_id * hash)150 int *tracecmd_filter_ids(struct tracecmd_filter_id *hash)
151 {
152 struct tracecmd_filter_id_item *item;
153 int *ids;
154 int count = 0;
155 int i;
156
157 if (!hash->count)
158 return NULL;
159
160 ids = malloc(sizeof(*ids) * (hash->count + 1));
161 if (!ids)
162 return NULL;
163
164 for (i = 0; i < FILTER_HASH_SIZE; i++) {
165 item = hash->hash[i];
166 while (item) {
167 ids[count++] = item->id;
168 item = item->next;
169 }
170 }
171
172 ids[count] = -1;
173 return ids;
174 }
175
176 /**
177 * filter_id_compare - compare two id hashes to see if they are equal
178 * @hash1: one hash to compare
179 * @hash2: another hash to compare to @hash1
180 *
181 * Returns 1 if the two hashes are the same, 0 otherwise.
182 */
tracecmd_filter_id_compare(struct tracecmd_filter_id * hash1,struct tracecmd_filter_id * hash2)183 int tracecmd_filter_id_compare(struct tracecmd_filter_id *hash1,
184 struct tracecmd_filter_id *hash2)
185 {
186 int *ids;
187 int ret = 0;
188 int i;
189
190 /* If counts don't match, then they obviously are not the same */
191 if (hash1->count != hash2->count)
192 return 0;
193
194 /* If both hashes are empty, they are the same */
195 if (!hash1->count && !hash2->count)
196 return 1;
197
198 /* Now compare the pids of one hash with the other */
199 ids = tracecmd_filter_ids(hash1);
200 for (i = 0; ids[i] >= 0; i++) {
201 if (!tracecmd_filter_id_find(hash2, ids[i]))
202 break;
203 }
204
205 if (ids[i] == -1)
206 ret = 1;
207
208 free(ids);
209
210 return ret;
211 }
212