open_address_hash.c
Go to the documentation of this file.
1 /******************************************************************************/
41 /******************************************************************************/
42 
43 #include "open_address_hash.h"
44 
48  ion_hash_t (*hashing_function)(ion_hashmap_t *, ion_key_t, int),
49  ion_key_type_t key_type,
50  ion_key_size_t key_size,
51  ion_value_size_t value_size,
52  int size
53 ) {
54  int i;
55 
56  hashmap->write_concern = wc_insert_unique; /* By default allow unique inserts only */
57  hashmap->super.record.key_size = key_size;
58  hashmap->super.record.value_size = value_size;
59  hashmap->super.key_type = key_type;
60 
61 /* hashmap->compare = compare;*/
62 
63  /* The hash map is allocated as a single contiguous array*/
64  hashmap->map_size = size;
65  hashmap->entry = malloc((hashmap->super.record.key_size + hashmap->super.record.value_size + 1) * hashmap->map_size);
66  /* Allows for binding of different hash function depending on requirements. */
67  hashmap->compute_hash = (*hashing_function);
68 
69  if (NULL == hashmap->entry) {
70  return 1;
71  }
72 
73 #if ION_DEBUG
74  printf("Initializing hash table\n");
75 #endif
76 
77  /* Initialize hash table */
78  for (i = 0; i < size; i++) {
79  ((ion_hash_bucket_t *) (hashmap->entry + ((hashmap->super.record.key_size + hashmap->super.record.value_size + SIZEOF(STATUS)) * i)))->status = ION_EMPTY;
80  }
81 
82  return 0;
83 }
84 
85 int
87  ion_hash_t num,
88  int size
89 ) {
90  return num % size;
91 }
92 
95  ion_hashmap_t *hash_map
96 ) {
97  hash_map->compute_hash = NULL;
98  hash_map->map_size = 0;
99  hash_map->super.record.key_size = 0;
100  hash_map->super.record.value_size = 0;
101 
102  if (hash_map->entry != NULL) {
103  /* check to ensure that you are not freeing something already free */
104  free(hash_map->entry);
105  hash_map->entry = NULL; /* */
106  return err_ok;
107  }
108  else {
110  }
111 }
112 
115  ion_hashmap_t *hash_map,
116  ion_key_t key,
117  ion_value_t value
118 ) {
119  ion_write_concern_t current_write_concern = hash_map->write_concern;
120 
121  hash_map->write_concern = wc_update;/* change write concern to allow update */
122 
123  ion_status_t status = oah_insert(hash_map, key, value);
124 
125  hash_map->write_concern = current_write_concern;
126  return status;
127 }
128 
131  ion_hashmap_t *hash_map,
132  ion_key_t key,
133  ion_value_t value
134 ) {
135  ion_hash_t hash = hash_map->compute_hash(hash_map, key, hash_map->super.record.key_size); /* compute hash value for given key */
136 
137  int loc = oah_get_location(hash, hash_map->map_size);
138 
139  /* Scan until find an empty location - oah_insert if found */
140  int count = 0;
141 
142  ion_hash_bucket_t *item;
143 
144  while (count != hash_map->map_size) {
145  item = ((ion_hash_bucket_t *) ((hash_map->entry + (hash_map->super.record.key_size + hash_map->super.record.value_size + SIZEOF(STATUS)) * loc)));
146 
147  if (item->status == ION_IN_USE) {
148  /* if a cell is in use, need to key to */
149 
150  if (hash_map->super.compare(item->data, key, hash_map->super.record.key_size) == ION_IS_EQUAL) {
151  if (hash_map->write_concern == wc_insert_unique) {
152  /* allow unique entries only */
154  }
155  else if (hash_map->write_concern == wc_update) {
156  /* allows for values to be updated */
157  memcpy(item->data + hash_map->super.record.key_size, value, (hash_map->super.record.value_size));
158  return ION_STATUS_OK(1);
159  }
160  else {
161  return ION_STATUS_ERROR(err_file_write_error); /* there is a configuration issue with write concern */
162  }
163  }
164  }
165  else if ((item->status == ION_EMPTY) || (item->status == ION_DELETED)) {
166  /* problem is here with base types as it is just an array of data. Need better way */
167  item->status = ION_IN_USE;
168  memcpy(item->data, key, (hash_map->super.record.key_size));
169  memcpy(item->data + hash_map->super.record.key_size, value, (hash_map->super.record.value_size));
170  return ION_STATUS_OK(1);
171  }
172 
173  loc++;
174 
175  if (loc >= hash_map->map_size) {
176  /* Perform wrapping */
177  loc = 0;
178  }
179 
180 #if ION_DEBUG
181  printf("checking location %i\n", loc);
182 #endif
183  count++;
184  }
185 
186 #if ION_DEBUG
187  printf("Hash table full. Insert not done");
188 #endif
189 
191 }
192 
193 ion_err_t
195  ion_hashmap_t *hash_map,
196  ion_key_t key,
197  int *location
198 ) {
199  /* compute hash value for given key */
200  ion_hash_t hash = hash_map->compute_hash(hash_map, key, hash_map->super.record.key_size);
201 
202  int loc = oah_get_location(hash, hash_map->map_size);
203  /* determine bucket based on hash */
204 
205  int count = 0;
206 
207  while (count != hash_map->map_size) {
208  /* check to see if current item is a match based on key */
209  /* locate first item */
210  ion_hash_bucket_t *item = (((ion_hash_bucket_t *) ((hash_map->entry + (hash_map->super.record.key_size + hash_map->super.record.value_size + SIZEOF(STATUS)) * loc))));
211 
212  if (item->status == ION_EMPTY) {
213  return err_item_not_found; /* if you hit an empty cell, exit */
214  }
215  else {
216  /* calculate if there is a match */
217 
218  if (item->status != ION_DELETED) {
219  int key_is_equal = hash_map->super.compare(item->data, key, hash_map->super.record.key_size);
220 
221  if (ION_IS_EQUAL == key_is_equal) {
222  (*location) = loc;
223  return err_ok;
224  }
225  }
226 
227  count++;
228  loc++;
229 
230  if (loc >= hash_map->map_size) {
231  /* Perform wrapping */
232  loc = 0;
233  }
234  }
235  }
236 
237  return err_item_not_found; /* key have not been found */
238 }
239 
242  ion_hashmap_t *hash_map,
243  ion_key_t key
244 ) {
245  int loc = -1;
246 
247  if (oah_find_item_loc(hash_map, key, &loc) == err_item_not_found) {
248 #if ION_DEBUG
249  printf("Item not found when trying to oah_delete.\n");
250 #endif
252  }
253  else {
254  /* locate item */
255  ion_hash_bucket_t *item = (((ion_hash_bucket_t *) ((hash_map->entry + (hash_map->super.record.key_size + hash_map->super.record.value_size + SIZEOF(STATUS)) * loc))));
256 
257  item->status = ION_DELETED; /* delete item */
258 
259 #if ION_DEBUG
260  printf("Item deleted at location %d\n", loc);
261 #endif
262  return ION_STATUS_OK(1);
263  }
264 }
265 
268  ion_hashmap_t *hash_map,
269  ion_key_t key,
270  ion_value_t value
271 ) {
272  int loc;
273 
274  if (oah_find_item_loc(hash_map, key, &loc) == err_ok) {
275 #if ION_DEBUG
276  printf("Item found at location %d\n", loc);
277 #endif
278 
279  int data_length = hash_map->super.record.key_size + hash_map->super.record.value_size;
280  ion_hash_bucket_t *item = (((ion_hash_bucket_t *) ((hash_map->entry + (data_length + SIZEOF(STATUS)) * loc))));
281 
282  /* *value = malloc(sizeof(char) * (hash_map->super.record.value_size)); */
283  memcpy(value, (item->data + hash_map->super.record.key_size), hash_map->super.record.value_size);
284  return ION_STATUS_OK(1);
285  }
286  else {
287 #if ION_DEBUG
288  printf("Item not found in hash table.\n");
289 #endif
291  }
292 }
293 
307 void
309  ion_hashmap_t *hash_map,
310  int size,
311  ion_record_info_t *record
312 ) {
313  int i;
314 
315  printf("Printing map\n");
316 
317  for (i = 0; i < size; i++) {
318  printf("%d -- %i ", i, ((ion_hash_bucket_t *) ((hash_map->entry + (record->key_size + record->value_size + SIZEOF(STATUS)) * i)))->status);
319  {
320  if (((ion_hash_bucket_t *) ((hash_map->entry + (record->key_size + record->value_size + SIZEOF(STATUS)) * i)))->status == (ION_EMPTY | ION_DELETED)) {
321  printf("(null)");
322  }
323  else {
324  int j;
325 
326  for (j = 0; j < (record->key_size + record->value_size); j++) {
327  printf("%X ", *(ion_byte_t *) (((ion_hash_bucket_t *) ((hash_map->entry + (record->key_size + record->value_size + SIZEOF(STATUS)) * i)))->data + j));
328  }
329  }
330 
331  printf("\n");
332  }
333  }
334 }
335 
338  ion_hashmap_t *hashmap,
339  ion_key_t key,
340  int size_of_key
341 ) {
342  UNUSED(size_of_key);
343 
344  ion_hash_t hash = (ion_hash_t) (((*(int *) key) % hashmap->map_size) + hashmap->map_size) % hashmap->map_size;
345 
346  return hash;
347 }
int ion_hash_t
The position in the hashmap.
unsigned char ion_byte_t
A byte type.
Definition: kv_system.h:232
int(* compute_hash)(ion_hashmap_t *, ion_key_t, int)
#define ION_DELETED
#define ION_STATUS_ERROR(error)
Definition: kv_system.h:110
enum ION_KEY_TYPE ion_key_type_t
This is the available key types for ION_DB. All types will be based on system defines.
ion_record_info_t record
char * entry
Struct used to maintain an instance of an in memory hashmap.
#define ION_EMPTY
int ion_value_size_t
The size (length) of a dictionary value in bytes.
Definition: kv_system.h:256
A hash table using linear probing. Designed for in memory use.
ion_err_t oah_initialize(ion_hashmap_t *hashmap, ion_hash_t(*hashing_function)(ion_hashmap_t *, ion_key_t, int), ion_key_type_t key_type, ion_key_size_t key_size, ion_value_size_t value_size, int size)
This function initializes an open address in memory hash map.
ion_err_t oah_destroy(ion_hashmap_t *hash_map)
Destroys the map in memory.
ion_status_t oah_get(ion_hashmap_t *hash_map, ion_key_t key, ion_value_t value)
Locates the record if it exists.
ion_byte_t data[]
ion_dictionary_parent_t super
#define ION_STATUS_OK(count)
Definition: kv_system.h:113
#define key(k)
Definition: bpp_tree.c:75
ion_status_t oah_delete(ion_hashmap_t *hash_map, ion_key_t key)
Deletes item from map.
char ion_err_t
The error type used to store error codes.
Definition: kv_system.h:226
ion_hash_t oah_compute_simple_hash(ion_hashmap_t *hashmap, ion_key_t key, int size_of_key)
A simple hashing algorithm implementation.
#define printf(format,...)
ion_status_t oah_update(ion_hashmap_t *hash_map, ion_key_t key, ion_value_t value)
Updates a value in the map.
void * ion_key_t
A dictionary key.
Definition: kv_system.h:241
int oah_get_location(ion_hash_t num, int size)
Returns the theoretical location of item in hashmap.
void * ion_value_t
A dictionary value.
Definition: kv_system.h:246
Struct used to maintain individual records in the hashmap.
#define ION_IN_USE
ion_key_size_t key_size
Definition: kv_system.h:307
#define UNUSED(x)
Definition: kv_system.h:102
ion_err_t oah_find_item_loc(ion_hashmap_t *hash_map, ion_key_t key, int *location)
Locates item in map.
#define SIZEOF(STATUS)
ion_key_type_t key_type
ion_status_t oah_insert(ion_hashmap_t *hash_map, ion_key_t key, ion_value_t value)
Insert record into hashmap.
ion_dictionary_compare_t compare
char ion_write_concern_t
A type for write concern information used by hash table based dictionaries which limit insert/update ...
int ion_key_size_t
The size (length) of a dictionary key in bytes.
Definition: kv_system.h:251
ion_write_concern_t write_concern
void oah_print(ion_hashmap_t *hash_map, int size, ion_record_info_t *record)
Helper function to print out map.
Struct used to maintain information about size of key and value.
Definition: kv_system.h:306
ion_value_size_t value_size
Definition: kv_system.h:309
#define ION_IS_EQUAL
Definition: kv_system.h:64
A status object that describes the result of a dictionary operation.
Definition: kv_system.h:290