• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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