1 /*
2  * Copyright (C) 2021 Jakub Kruszona-Zawadzki, Core Technology Sp. z o.o.
3  *
4  * This file is part of MooseFS.
5  *
6  * MooseFS is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation, version 2 (only).
9  *
10  * MooseFS is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with MooseFS; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02111-1301, USA
18  * or visit http://www.gnu.org/licenses/gpl-2.0.html
19  */
20 
21 #ifdef HAVE_CONFIG_H
22 #include "config.h"
23 #endif
24 
25 #include <stdlib.h>
26 #include <string.h>
27 #include <stddef.h>
28 #include <inttypes.h>
29 #ifdef HAVE_SYS_MMAN_H
30 #include <sys/mman.h>
31 #endif
32 
33 #include "massert.h"
34 
35 #include "glue.h"
36 
37 typedef struct _dictentry {
38 	struct _dictentry *next;
39 	uint32_t hashval;
40 	uint32_t refcnt;
41 	uint32_t leng;
42 	const uint8_t data[1];
43 } dictentry;
44 
45 #define LOHASH_BITS 20
46 #define ENTRY_TYPE dictentry
47 #define GLUE_FN_NAME_PREFIX(Y) GLUE(dict,Y)
48 #define HASH_ARGS_TYPE_LIST const uint8_t *data,uint32_t leng
49 #define HASH_ARGS_LIST data,leng
50 #define GLUE_HASH_TAB_PREFIX(Y) GLUE(dict,Y)
51 #define HASH_VALUE_FIELD hashval
52 
GLUE_FN_NAME_PREFIX(_cmp)53 static inline int GLUE_FN_NAME_PREFIX(_cmp)(ENTRY_TYPE *e,HASH_ARGS_TYPE_LIST) {
54 	return (e->leng==leng && memcmp((char*)(e->data),(char*)data,leng)==0);
55 }
56 
GLUE_FN_NAME_PREFIX(_hash)57 static inline uint32_t GLUE_FN_NAME_PREFIX(_hash)(HASH_ARGS_TYPE_LIST) {
58 	uint32_t hash,i;
59 	hash = leng;
60 	for (i=0 ; i<leng ; i++) {
61 		hash = hash*33+data[i];
62 	}
63 	return hash;
64 }
65 
66 // GLUE_FN_NAME_PREFIX(_ehash) is needed only if HASH_VALUE_FIELD is not defined !!!
67 
68 #include "hash_begin.h"
69 
70 /* externals */
71 
dict_init(void)72 int dict_init(void) {
73 	dict_hash_init();
74 	return 0;
75 }
76 
dict_cleanup(void)77 void dict_cleanup(void) {
78 	dict_hash_cleanup();
79 }
80 
dict_search(const uint8_t * data,uint32_t leng)81 void* dict_search(const uint8_t *data,uint32_t leng) {
82 	return dict_find(data,leng);
83 }
84 
dict_insert(const uint8_t * data,uint32_t leng)85 void* dict_insert(const uint8_t *data,uint32_t leng) {
86 	dictentry *de;
87 	de = dict_find(data,leng);
88 	if (de) {
89 		de->refcnt++;
90 		return de;
91 	}
92 	de = malloc(offsetof(dictentry,data)+leng);
93 	passert(de);
94 	de->refcnt = 1;
95 	de->leng = leng;
96 	memcpy((uint8_t*)(de->data),data,leng);
97 	dict_add(de);
98 	return de;
99 }
100 
dict_get_ptr(void * dptr)101 const uint8_t* dict_get_ptr(void *dptr) {
102 	dictentry *de = (dictentry*)dptr;
103 
104 	return de->data;
105 }
106 
dict_get_leng(void * dptr)107 uint32_t dict_get_leng(void *dptr) {
108 	dictentry *de = (dictentry*)dptr;
109 
110 	return de->leng;
111 }
112 
dict_get_hash(void * dptr)113 uint32_t dict_get_hash(void *dptr) {
114 	dictentry *de = (dictentry*)dptr;
115 
116 	return de->hashval;
117 }
118 
dict_dec_ref(void * dptr)119 void dict_dec_ref(void *dptr) {
120 	dictentry *de = (dictentry*)dptr;
121 	massert(de->refcnt>0,"dictionary reference counter is zero");
122 	de->refcnt--;
123 	if (de->refcnt==0) {
124 		dict_delete(de);
125 		free(de);
126 	}
127 }
128 
dict_inc_ref(void * dptr)129 void dict_inc_ref(void *dptr) {
130 	dictentry *de = (dictentry*)dptr;
131 	massert(de->refcnt>0,"dictionary reference counter is zero");
132 	de->refcnt++;
133 }
134 
135 #include "hash_end.h"
136 
137 #undef LOHASH_BITS
138 #undef ENTRY_TYPE
139 #undef GLUE_FN_NAME_PREFIX
140 #undef HASH_ARGS_TYPE_LIST
141 #undef HASH_ARGS_LIST
142 #undef GLUE_HASH_TAB_PREFIX
143