xref: /dpdk/lib/member/rte_member_heap.h (revision 27226547965921171711b6f7a7e015f39f016487)
1db354bd2SLeyi Rong /* SPDX-License-Identifier: BSD-3-Clause
2db354bd2SLeyi Rong  * Copyright(c) 2020 Intel Corporation
3db354bd2SLeyi Rong  * Copyright(c) 2020, Alan Liu <zaoxingliu@gmail.com>
4db354bd2SLeyi Rong  */
5db354bd2SLeyi Rong 
6db354bd2SLeyi Rong #ifndef RTE_MEMBER_HEAP_H
7db354bd2SLeyi Rong #define RTE_MEMBER_HEAP_H
8db354bd2SLeyi Rong 
90e21c7c0SDavid Marchand #include "member.h"
10db354bd2SLeyi Rong #include <rte_ring_elem.h>
11db354bd2SLeyi Rong #include "rte_member.h"
12db354bd2SLeyi Rong 
13db354bd2SLeyi Rong #define LCHILD(x) (2 * x + 1)
14db354bd2SLeyi Rong #define RCHILD(x) (2 * x + 2)
15db354bd2SLeyi Rong #define PARENT(x) ((x - 1) / 2)
16db354bd2SLeyi Rong 
17db354bd2SLeyi Rong #define HASH_BKT_SIZE 16
18db354bd2SLeyi Rong #define HASH_HP_MULTI 4
19db354bd2SLeyi Rong #define HASH_RESIZE_MULTI 2
20db354bd2SLeyi Rong 
21db354bd2SLeyi Rong struct hash_bkt {
22db354bd2SLeyi Rong 	uint16_t sig[HASH_BKT_SIZE];
23db354bd2SLeyi Rong 	uint16_t idx[HASH_BKT_SIZE];
24db354bd2SLeyi Rong };
25db354bd2SLeyi Rong 
26db354bd2SLeyi Rong struct hash {
27db354bd2SLeyi Rong 	uint16_t bkt_cnt;
28db354bd2SLeyi Rong 	uint16_t num_item;
29db354bd2SLeyi Rong 	uint32_t seed;
30*27226547SStephen Hemminger 	struct hash_bkt buckets[];
31db354bd2SLeyi Rong };
32db354bd2SLeyi Rong 
33db354bd2SLeyi Rong struct node {
34db354bd2SLeyi Rong 	void *key;
35db354bd2SLeyi Rong 	uint64_t count;
36db354bd2SLeyi Rong };
37db354bd2SLeyi Rong 
38db354bd2SLeyi Rong struct minheap {
39db354bd2SLeyi Rong 	uint32_t key_len;
40db354bd2SLeyi Rong 	uint32_t size;
41db354bd2SLeyi Rong 	uint32_t socket;
42db354bd2SLeyi Rong 	struct hash *hashtable;
43db354bd2SLeyi Rong 	struct node *elem;
44db354bd2SLeyi Rong };
45db354bd2SLeyi Rong 
46db354bd2SLeyi Rong static int
hash_table_insert(const void * key,int value,int key_len,struct hash * table)47db354bd2SLeyi Rong hash_table_insert(const void *key, int value, int key_len, struct hash *table)
48db354bd2SLeyi Rong {
49db354bd2SLeyi Rong 	uint32_t hash = MEMBER_HASH_FUNC(key, key_len, table->seed);
50db354bd2SLeyi Rong 	uint16_t idx = hash % table->bkt_cnt;
51db354bd2SLeyi Rong 	uint16_t sig = hash >> 16;
52db354bd2SLeyi Rong 	int i;
53db354bd2SLeyi Rong 
54db354bd2SLeyi Rong 	for (i = 0; i < HASH_BKT_SIZE; i++) {
55db354bd2SLeyi Rong 		if (table->buckets[idx].idx[i] == 0) {
56db354bd2SLeyi Rong 			table->buckets[idx].idx[i] = value;
57db354bd2SLeyi Rong 			table->buckets[idx].sig[i] = sig;
58db354bd2SLeyi Rong 			table->num_item++;
59db354bd2SLeyi Rong 			return 0;
60db354bd2SLeyi Rong 		}
61db354bd2SLeyi Rong 	}
62db354bd2SLeyi Rong 
63db354bd2SLeyi Rong 	return -ENOMEM;
64db354bd2SLeyi Rong }
65db354bd2SLeyi Rong 
66db354bd2SLeyi Rong static int
hash_table_update(const void * key,int old_value,int value,int key_len,struct hash * table)67db354bd2SLeyi Rong hash_table_update(const void *key, int old_value, int value, int key_len, struct hash *table)
68db354bd2SLeyi Rong {
69db354bd2SLeyi Rong 	uint32_t hash = MEMBER_HASH_FUNC(key, key_len, table->seed);
70db354bd2SLeyi Rong 	uint16_t idx = hash % table->bkt_cnt;
71db354bd2SLeyi Rong 	uint16_t sig = hash >> 16;
72db354bd2SLeyi Rong 	int i;
73db354bd2SLeyi Rong 
74db354bd2SLeyi Rong 	for (i = 0; i < HASH_BKT_SIZE; i++) {
75db354bd2SLeyi Rong 		if (table->buckets[idx].sig[i] == sig && table->buckets[idx].idx[i] == old_value) {
76db354bd2SLeyi Rong 			table->buckets[idx].idx[i] = value;
77db354bd2SLeyi Rong 			return 0;
78db354bd2SLeyi Rong 		}
79db354bd2SLeyi Rong 	}
80db354bd2SLeyi Rong 
81db354bd2SLeyi Rong 	return -1;
82db354bd2SLeyi Rong }
83db354bd2SLeyi Rong 
84db354bd2SLeyi Rong static int
hash_table_del(const void * key,uint16_t value,int key_len,struct hash * table)85db354bd2SLeyi Rong hash_table_del(const void *key, uint16_t value, int key_len, struct hash *table)
86db354bd2SLeyi Rong {
87db354bd2SLeyi Rong 	uint32_t hash = MEMBER_HASH_FUNC(key, key_len, table->seed);
88db354bd2SLeyi Rong 	uint16_t idx = hash % table->bkt_cnt;
89db354bd2SLeyi Rong 	uint16_t sig = hash >> 16;
90db354bd2SLeyi Rong 	int i;
91db354bd2SLeyi Rong 
92db354bd2SLeyi Rong 	for (i = 0; i < HASH_BKT_SIZE; i++) {
93db354bd2SLeyi Rong 		if (table->buckets[idx].sig[i] == sig && table->buckets[idx].idx[i] == value) {
94db354bd2SLeyi Rong 			table->buckets[idx].idx[i] = 0;
95db354bd2SLeyi Rong 			table->num_item--;
96db354bd2SLeyi Rong 			return 0;
97db354bd2SLeyi Rong 		}
98db354bd2SLeyi Rong 	}
99db354bd2SLeyi Rong 
100db354bd2SLeyi Rong 	return -1;
101db354bd2SLeyi Rong }
102db354bd2SLeyi Rong 
103db354bd2SLeyi Rong static int
hash_table_lookup(const void * key,int key_len,struct minheap * hp)104db354bd2SLeyi Rong hash_table_lookup(const void *key, int key_len, struct minheap *hp)
105db354bd2SLeyi Rong {
106db354bd2SLeyi Rong 	struct hash *table = hp->hashtable;
107db354bd2SLeyi Rong 	uint32_t hash = MEMBER_HASH_FUNC(key, key_len, table->seed);
108db354bd2SLeyi Rong 	uint16_t idx = hash % table->bkt_cnt;
109db354bd2SLeyi Rong 	uint16_t sig = hash >> 16;
110db354bd2SLeyi Rong 	int i;
111db354bd2SLeyi Rong 
112db354bd2SLeyi Rong 	for (i = 0; i < HASH_BKT_SIZE; i++) {
113db354bd2SLeyi Rong 		if (table->buckets[idx].sig[i] == sig && table->buckets[idx].idx[i] != 0) {
114db354bd2SLeyi Rong 			uint32_t hp_idx = table->buckets[idx].idx[i] - 1;
115db354bd2SLeyi Rong 
116db354bd2SLeyi Rong 			if (memcmp(hp->elem[hp_idx].key, key, hp->key_len) == 0)
117db354bd2SLeyi Rong 				return hp_idx;
118db354bd2SLeyi Rong 		}
119db354bd2SLeyi Rong 	}
120db354bd2SLeyi Rong 
121db354bd2SLeyi Rong 	return -ENOENT; /* key doesn't exist */
122db354bd2SLeyi Rong }
123db354bd2SLeyi Rong 
124db354bd2SLeyi Rong static int
resize_hash_table(struct minheap * hp)125db354bd2SLeyi Rong resize_hash_table(struct minheap *hp)
126db354bd2SLeyi Rong {
127db354bd2SLeyi Rong 	uint32_t i;
128db354bd2SLeyi Rong 	uint32_t new_bkt_cnt;
129db354bd2SLeyi Rong 
130db354bd2SLeyi Rong 	while (1) {
131db354bd2SLeyi Rong 		new_bkt_cnt = hp->hashtable->bkt_cnt * HASH_RESIZE_MULTI;
132db354bd2SLeyi Rong 
1330e21c7c0SDavid Marchand 		MEMBER_LOG(ERR, "Sketch Minheap HT load factor is [%f]",
134db354bd2SLeyi Rong 			hp->hashtable->num_item / ((float)hp->hashtable->bkt_cnt * HASH_BKT_SIZE));
1350e21c7c0SDavid Marchand 		MEMBER_LOG(ERR, "Sketch Minheap HT resize happen!");
136db354bd2SLeyi Rong 		rte_free(hp->hashtable);
137db354bd2SLeyi Rong 		hp->hashtable = rte_zmalloc_socket(NULL, sizeof(struct hash) +
138db354bd2SLeyi Rong 						new_bkt_cnt * sizeof(struct hash_bkt),
139db354bd2SLeyi Rong 						RTE_CACHE_LINE_SIZE, hp->socket);
140db354bd2SLeyi Rong 
141db354bd2SLeyi Rong 		if (hp->hashtable == NULL) {
1420e21c7c0SDavid Marchand 			MEMBER_LOG(ERR, "Sketch Minheap HT allocation failed");
143db354bd2SLeyi Rong 			return -ENOMEM;
144db354bd2SLeyi Rong 		}
145db354bd2SLeyi Rong 
146db354bd2SLeyi Rong 		hp->hashtable->bkt_cnt = new_bkt_cnt;
147db354bd2SLeyi Rong 
148db354bd2SLeyi Rong 		for (i = 0; i < hp->size; ++i) {
149db354bd2SLeyi Rong 			if (hash_table_insert(hp->elem[i].key,
150db354bd2SLeyi Rong 				i + 1, hp->key_len, hp->hashtable) < 0) {
1510e21c7c0SDavid Marchand 				MEMBER_LOG(ERR,
1520e21c7c0SDavid Marchand 					"Sketch Minheap HT resize insert fail!");
153db354bd2SLeyi Rong 				break;
154db354bd2SLeyi Rong 			}
155db354bd2SLeyi Rong 		}
156db354bd2SLeyi Rong 		if (i == hp->size)
157db354bd2SLeyi Rong 			break;
158db354bd2SLeyi Rong 	}
159db354bd2SLeyi Rong 
160db354bd2SLeyi Rong 	return 0;
161db354bd2SLeyi Rong }
162db354bd2SLeyi Rong 
163db354bd2SLeyi Rong /* find the item in the given minheap */
164db354bd2SLeyi Rong static int
rte_member_minheap_find(struct minheap * hp,const void * key)165db354bd2SLeyi Rong rte_member_minheap_find(struct minheap *hp, const void *key)
166db354bd2SLeyi Rong {
167db354bd2SLeyi Rong 	int idx = hash_table_lookup(key, hp->key_len, hp);
168db354bd2SLeyi Rong 	return idx;
169db354bd2SLeyi Rong }
170db354bd2SLeyi Rong 
171db354bd2SLeyi Rong static int
rte_member_minheap_init(struct minheap * heap,int size,uint32_t socket,uint32_t seed)172db354bd2SLeyi Rong rte_member_minheap_init(struct minheap *heap, int size,
173db354bd2SLeyi Rong 			uint32_t socket, uint32_t seed)
174db354bd2SLeyi Rong {
175db354bd2SLeyi Rong 	heap->elem = rte_zmalloc_socket(NULL, sizeof(struct node) * size,
176db354bd2SLeyi Rong 				RTE_CACHE_LINE_SIZE, socket);
177db354bd2SLeyi Rong 	if (heap->elem == NULL) {
1780e21c7c0SDavid Marchand 		MEMBER_LOG(ERR, "Sketch Minheap elem allocation failed");
179db354bd2SLeyi Rong 		return -ENOMEM;
180db354bd2SLeyi Rong 	}
181db354bd2SLeyi Rong 
182db354bd2SLeyi Rong 	uint32_t hash_bkt_cnt = rte_align32pow2(size * HASH_HP_MULTI) / HASH_BKT_SIZE;
183db354bd2SLeyi Rong 
184db354bd2SLeyi Rong 	if (hash_bkt_cnt == 0)
185db354bd2SLeyi Rong 		hash_bkt_cnt = 1;
186db354bd2SLeyi Rong 
187db354bd2SLeyi Rong 	heap->hashtable = rte_zmalloc_socket(NULL, sizeof(struct hash) +
188db354bd2SLeyi Rong 					hash_bkt_cnt * sizeof(struct hash_bkt),
189db354bd2SLeyi Rong 					RTE_CACHE_LINE_SIZE, socket);
190db354bd2SLeyi Rong 
191db354bd2SLeyi Rong 	if (heap->hashtable == NULL) {
1920e21c7c0SDavid Marchand 		MEMBER_LOG(ERR, "Sketch Minheap HT allocation failed");
193db354bd2SLeyi Rong 		rte_free(heap->elem);
194db354bd2SLeyi Rong 		return -ENOMEM;
195db354bd2SLeyi Rong 	}
196db354bd2SLeyi Rong 
197db354bd2SLeyi Rong 	heap->hashtable->seed = seed;
198db354bd2SLeyi Rong 	heap->hashtable->bkt_cnt = hash_bkt_cnt;
199db354bd2SLeyi Rong 	heap->socket = socket;
200db354bd2SLeyi Rong 
201db354bd2SLeyi Rong 	return 0;
202db354bd2SLeyi Rong }
203db354bd2SLeyi Rong 
204db354bd2SLeyi Rong /* swap the minheap nodes */
205db354bd2SLeyi Rong static __rte_always_inline void
rte_member_heap_swap(struct node * n1,struct node * n2)206db354bd2SLeyi Rong rte_member_heap_swap(struct node *n1, struct node *n2)
207db354bd2SLeyi Rong {
208db354bd2SLeyi Rong 	struct node temp = *n1;
209db354bd2SLeyi Rong 	*n1 = *n2;
210db354bd2SLeyi Rong 	*n2 = temp;
211db354bd2SLeyi Rong }
212db354bd2SLeyi Rong 
213db354bd2SLeyi Rong /* heapify function */
214db354bd2SLeyi Rong static void
rte_member_heapify(struct minheap * hp,uint32_t idx,bool update_hash)215db354bd2SLeyi Rong rte_member_heapify(struct minheap *hp, uint32_t idx, bool update_hash)
216db354bd2SLeyi Rong {
217db354bd2SLeyi Rong 	uint32_t smallest;
218db354bd2SLeyi Rong 
219db354bd2SLeyi Rong 	if (LCHILD(idx) < hp->size &&
220db354bd2SLeyi Rong 			hp->elem[LCHILD(idx)].count < hp->elem[idx].count)
221db354bd2SLeyi Rong 		smallest = LCHILD(idx);
222db354bd2SLeyi Rong 	else
223db354bd2SLeyi Rong 		smallest = idx;
224db354bd2SLeyi Rong 
225db354bd2SLeyi Rong 	if (RCHILD(idx) < hp->size &&
226db354bd2SLeyi Rong 			hp->elem[RCHILD(idx)].count < hp->elem[smallest].count)
227db354bd2SLeyi Rong 		smallest = RCHILD(idx);
228db354bd2SLeyi Rong 
229db354bd2SLeyi Rong 	if (smallest != idx) {
230db354bd2SLeyi Rong 		rte_member_heap_swap(&(hp->elem[idx]), &(hp->elem[smallest]));
231db354bd2SLeyi Rong 
232db354bd2SLeyi Rong 		if (update_hash) {
233db354bd2SLeyi Rong 			if (hash_table_update(hp->elem[smallest].key, idx + 1, smallest + 1,
234db354bd2SLeyi Rong 					hp->key_len, hp->hashtable) < 0) {
2350e21c7c0SDavid Marchand 				MEMBER_LOG(ERR, "Minheap Hash Table update failed");
236db354bd2SLeyi Rong 				return;
237db354bd2SLeyi Rong 			}
238db354bd2SLeyi Rong 
239db354bd2SLeyi Rong 			if (hash_table_update(hp->elem[idx].key, smallest + 1, idx + 1,
240db354bd2SLeyi Rong 					hp->key_len, hp->hashtable) < 0) {
2410e21c7c0SDavid Marchand 				MEMBER_LOG(ERR, "Minheap Hash Table update failed");
242db354bd2SLeyi Rong 				return;
243db354bd2SLeyi Rong 			}
244db354bd2SLeyi Rong 		}
245db354bd2SLeyi Rong 		rte_member_heapify(hp, smallest, update_hash);
246db354bd2SLeyi Rong 	}
247db354bd2SLeyi Rong }
248db354bd2SLeyi Rong 
249db354bd2SLeyi Rong /* insert a node into the minheap */
250db354bd2SLeyi Rong static int
rte_member_minheap_insert_node(struct minheap * hp,const void * key,int counter,void * key_slot,struct rte_ring * free_key_slot)251db354bd2SLeyi Rong rte_member_minheap_insert_node(struct minheap *hp, const void *key,
252db354bd2SLeyi Rong 			       int counter, void *key_slot,
253db354bd2SLeyi Rong 			       struct rte_ring *free_key_slot)
254db354bd2SLeyi Rong {
255db354bd2SLeyi Rong 	struct node nd;
256db354bd2SLeyi Rong 	uint32_t slot_id;
257db354bd2SLeyi Rong 
258db354bd2SLeyi Rong 	if (rte_ring_sc_dequeue_elem(free_key_slot, &slot_id, sizeof(uint32_t)) != 0) {
2590e21c7c0SDavid Marchand 		MEMBER_LOG(ERR, "Minheap get empty keyslot failed");
260db354bd2SLeyi Rong 		return -1;
261db354bd2SLeyi Rong 	}
262db354bd2SLeyi Rong 
263db354bd2SLeyi Rong 	nd.count = counter;
264db354bd2SLeyi Rong 	nd.key = RTE_PTR_ADD(key_slot, slot_id * hp->key_len);
265db354bd2SLeyi Rong 
266db354bd2SLeyi Rong 	memcpy(nd.key, key, hp->key_len);
267db354bd2SLeyi Rong 
268db354bd2SLeyi Rong 	uint32_t i = (hp->size)++;
269db354bd2SLeyi Rong 
270db354bd2SLeyi Rong 	while (i && nd.count < hp->elem[PARENT(i)].count) {
271db354bd2SLeyi Rong 		hp->elem[i] = hp->elem[PARENT(i)];
272db354bd2SLeyi Rong 		if (hash_table_update(hp->elem[i].key, PARENT(i) + 1, i + 1,
273db354bd2SLeyi Rong 				hp->key_len, hp->hashtable) < 0) {
2740e21c7c0SDavid Marchand 			MEMBER_LOG(ERR, "Minheap Hash Table update failed");
275db354bd2SLeyi Rong 			return -1;
276db354bd2SLeyi Rong 		}
277db354bd2SLeyi Rong 		i = PARENT(i);
278db354bd2SLeyi Rong 	}
279db354bd2SLeyi Rong 	hp->elem[i] = nd;
280db354bd2SLeyi Rong 
281db354bd2SLeyi Rong 	if (hash_table_insert(key, i + 1, hp->key_len, hp->hashtable) < 0) {
282db354bd2SLeyi Rong 		if (resize_hash_table(hp) < 0) {
2830e21c7c0SDavid Marchand 			MEMBER_LOG(ERR, "Minheap Hash Table resize failed");
284db354bd2SLeyi Rong 			return -1;
285db354bd2SLeyi Rong 		}
286db354bd2SLeyi Rong 	}
287db354bd2SLeyi Rong 
288db354bd2SLeyi Rong 	return 0;
289db354bd2SLeyi Rong }
290db354bd2SLeyi Rong 
291db354bd2SLeyi Rong /* delete a key from the minheap */
292db354bd2SLeyi Rong static int
rte_member_minheap_delete_node(struct minheap * hp,const void * key,void * key_slot,struct rte_ring * free_key_slot)293db354bd2SLeyi Rong rte_member_minheap_delete_node(struct minheap *hp, const void *key,
294db354bd2SLeyi Rong 			       void *key_slot, struct rte_ring *free_key_slot)
295db354bd2SLeyi Rong {
296db354bd2SLeyi Rong 	int idx = rte_member_minheap_find(hp, key);
297db354bd2SLeyi Rong 	uint32_t offset = RTE_PTR_DIFF(hp->elem[idx].key, key_slot) / hp->key_len;
298db354bd2SLeyi Rong 
299db354bd2SLeyi Rong 	if (hash_table_del(key, idx + 1, hp->key_len, hp->hashtable) < 0) {
3000e21c7c0SDavid Marchand 		MEMBER_LOG(ERR, "Minheap Hash Table delete failed");
301db354bd2SLeyi Rong 		return -1;
302db354bd2SLeyi Rong 	}
303db354bd2SLeyi Rong 
304db354bd2SLeyi Rong 	rte_ring_sp_enqueue_elem(free_key_slot, &offset, sizeof(uint32_t));
305db354bd2SLeyi Rong 
306db354bd2SLeyi Rong 	if (idx == (int)(hp->size - 1)) {
307db354bd2SLeyi Rong 		hp->size--;
308db354bd2SLeyi Rong 		return 0;
309db354bd2SLeyi Rong 	}
310db354bd2SLeyi Rong 
311db354bd2SLeyi Rong 	hp->elem[idx] = hp->elem[hp->size - 1];
312db354bd2SLeyi Rong 
313db354bd2SLeyi Rong 	if (hash_table_update(hp->elem[idx].key, hp->size, idx + 1,
314db354bd2SLeyi Rong 				hp->key_len, hp->hashtable) < 0) {
3150e21c7c0SDavid Marchand 		MEMBER_LOG(ERR, "Minheap Hash Table update failed");
316db354bd2SLeyi Rong 		return -1;
317db354bd2SLeyi Rong 	}
318db354bd2SLeyi Rong 	hp->size--;
319db354bd2SLeyi Rong 	rte_member_heapify(hp, idx, true);
320db354bd2SLeyi Rong 
321db354bd2SLeyi Rong 	return 0;
322db354bd2SLeyi Rong }
323db354bd2SLeyi Rong 
324db354bd2SLeyi Rong /* replace a min node with a new key. */
325db354bd2SLeyi Rong static int
rte_member_minheap_replace_node(struct minheap * hp,const void * new_key,int new_counter)326db354bd2SLeyi Rong rte_member_minheap_replace_node(struct minheap *hp,
327db354bd2SLeyi Rong 				const void *new_key,
328db354bd2SLeyi Rong 				int new_counter)
329db354bd2SLeyi Rong {
330db354bd2SLeyi Rong 	struct node nd;
331db354bd2SLeyi Rong 	void *recycle_key = NULL;
332db354bd2SLeyi Rong 
333db354bd2SLeyi Rong 	recycle_key = hp->elem[0].key;
334db354bd2SLeyi Rong 
335db354bd2SLeyi Rong 	if (hash_table_del(recycle_key, 1, hp->key_len, hp->hashtable) < 0) {
3360e21c7c0SDavid Marchand 		MEMBER_LOG(ERR, "Minheap Hash Table delete failed");
337db354bd2SLeyi Rong 		return -1;
338db354bd2SLeyi Rong 	}
339db354bd2SLeyi Rong 
340db354bd2SLeyi Rong 	hp->elem[0] = hp->elem[hp->size - 1];
341db354bd2SLeyi Rong 
342db354bd2SLeyi Rong 	if (hash_table_update(hp->elem[0].key, hp->size, 1,
343db354bd2SLeyi Rong 				hp->key_len, hp->hashtable) < 0) {
3440e21c7c0SDavid Marchand 		MEMBER_LOG(ERR, "Minheap Hash Table update failed");
345db354bd2SLeyi Rong 		return -1;
346db354bd2SLeyi Rong 	}
347db354bd2SLeyi Rong 	hp->size--;
348db354bd2SLeyi Rong 
349db354bd2SLeyi Rong 	rte_member_heapify(hp, 0, true);
350db354bd2SLeyi Rong 
351db354bd2SLeyi Rong 	nd.count = new_counter;
352db354bd2SLeyi Rong 	nd.key = recycle_key;
353db354bd2SLeyi Rong 
354db354bd2SLeyi Rong 	memcpy(nd.key, new_key, hp->key_len);
355db354bd2SLeyi Rong 
356db354bd2SLeyi Rong 	uint32_t i = (hp->size)++;
357db354bd2SLeyi Rong 
358db354bd2SLeyi Rong 	while (i && nd.count < hp->elem[PARENT(i)].count) {
359db354bd2SLeyi Rong 		hp->elem[i] = hp->elem[PARENT(i)];
360db354bd2SLeyi Rong 		if (hash_table_update(hp->elem[i].key, PARENT(i) + 1, i + 1,
361db354bd2SLeyi Rong 				hp->key_len, hp->hashtable) < 0) {
3620e21c7c0SDavid Marchand 			MEMBER_LOG(ERR, "Minheap Hash Table update failed");
363db354bd2SLeyi Rong 			return -1;
364db354bd2SLeyi Rong 		}
365db354bd2SLeyi Rong 		i = PARENT(i);
366db354bd2SLeyi Rong 	}
367db354bd2SLeyi Rong 
368db354bd2SLeyi Rong 	hp->elem[i] = nd;
369db354bd2SLeyi Rong 
370db354bd2SLeyi Rong 	if (hash_table_insert(new_key, i + 1, hp->key_len, hp->hashtable) < 0) {
3710e21c7c0SDavid Marchand 		MEMBER_LOG(ERR, "Minheap Hash Table replace insert failed");
372db354bd2SLeyi Rong 		if (resize_hash_table(hp) < 0) {
3730e21c7c0SDavid Marchand 			MEMBER_LOG(ERR, "Minheap Hash Table replace resize failed");
374db354bd2SLeyi Rong 			return -1;
375db354bd2SLeyi Rong 		}
376db354bd2SLeyi Rong 	}
377db354bd2SLeyi Rong 
378db354bd2SLeyi Rong 	return 0;
379db354bd2SLeyi Rong }
380db354bd2SLeyi Rong 
381db354bd2SLeyi Rong /* sort the heap into a descending array */
382db354bd2SLeyi Rong static void
rte_member_heapsort(struct minheap * hp,struct node * result_array)383db354bd2SLeyi Rong rte_member_heapsort(struct minheap *hp, struct node *result_array)
384db354bd2SLeyi Rong {
385db354bd2SLeyi Rong 	struct minheap new_hp;
386db354bd2SLeyi Rong 
387db354bd2SLeyi Rong 	/* build a new heap for using the given array */
388db354bd2SLeyi Rong 	new_hp.size = hp->size;
389db354bd2SLeyi Rong 	new_hp.key_len = hp->key_len;
390db354bd2SLeyi Rong 	new_hp.elem = result_array;
391db354bd2SLeyi Rong 	memcpy(result_array, hp->elem, hp->size * sizeof(struct node));
392db354bd2SLeyi Rong 
393db354bd2SLeyi Rong 	/* sort the new heap */
394db354bd2SLeyi Rong 	while (new_hp.size > 1) {
395db354bd2SLeyi Rong 		rte_member_heap_swap(&(new_hp.elem[0]), &(new_hp.elem[new_hp.size - 1]));
396db354bd2SLeyi Rong 		new_hp.size--;
397db354bd2SLeyi Rong 		rte_member_heapify(&new_hp, 0, false);
398db354bd2SLeyi Rong 	}
399db354bd2SLeyi Rong }
400db354bd2SLeyi Rong 
401db354bd2SLeyi Rong static void
rte_member_minheap_free(struct minheap * hp)402db354bd2SLeyi Rong rte_member_minheap_free(struct minheap *hp)
403db354bd2SLeyi Rong {
404db354bd2SLeyi Rong 	if (hp == NULL)
405db354bd2SLeyi Rong 		return;
406db354bd2SLeyi Rong 
407db354bd2SLeyi Rong 	rte_free(hp->elem);
408db354bd2SLeyi Rong 	rte_free(hp->hashtable);
409db354bd2SLeyi Rong }
410db354bd2SLeyi Rong 
411db354bd2SLeyi Rong static void
rte_member_minheap_reset(struct minheap * hp)412db354bd2SLeyi Rong rte_member_minheap_reset(struct minheap *hp)
413db354bd2SLeyi Rong {
414db354bd2SLeyi Rong 	if (hp == NULL)
415db354bd2SLeyi Rong 		return;
416db354bd2SLeyi Rong 
417db354bd2SLeyi Rong 	memset(hp->elem, 0, sizeof(struct node) * hp->size);
418db354bd2SLeyi Rong 	hp->size = 0;
419db354bd2SLeyi Rong 
420db354bd2SLeyi Rong 	memset((char *)hp->hashtable + sizeof(struct hash), 0,
421db354bd2SLeyi Rong 			hp->hashtable->bkt_cnt * sizeof(struct hash_bkt));
422db354bd2SLeyi Rong 	hp->hashtable->num_item = 0;
423db354bd2SLeyi Rong }
424db354bd2SLeyi Rong 
425db354bd2SLeyi Rong #endif /* RTE_MEMBER_HEAP_H */
426