SIONlib  1.6.2
Scalable I/O library for parallel access to task-local files
sion_keyvalue_table.c
Go to the documentation of this file.
1 /****************************************************************************
2 ** SIONLIB http://www.fz-juelich.de/jsc/sionlib **
3 *****************************************************************************
4 ** Copyright (c) 2008-2016 **
5 ** Forschungszentrum Juelich, Juelich Supercomputing Centre **
6 ** **
7 ** See the file COPYRIGHT in the package base directory for details **
8 ****************************************************************************/
9 
14 #include <stdlib.h>
15 #include <stdio.h>
16 #include <string.h>
17 #include <time.h>
18 
19 #include <sys/types.h>
20 #include <sys/stat.h>
21 #include <fcntl.h>
22 #include <unistd.h>
23 #include <assert.h>
24 
25 
26 #include "sion.h"
27 #include "sion_debug.h"
28 #include "sion_internal.h"
29 #include "sion_printts.h"
30 #include "sion_keyvalue_table.h"
31 
32 typedef enum {
33  KEYVALUE_TABLE_ENTRY_STATE_USED,
34  KEYVALUE_TABLE_ENTRY_STATE_FREE,
35  KEYVALUE_TABLE_ENTRY_STATE_UNKNOWN
36 } sion_keyvalue_table_entry_state_t;
37 
39 
41  int used;
42  int size;
43  int num_added_entries;
44 
45  /* for iterator by index */
46  int iterator_lastreadindex;
47  _sion_keyvalue_table_entry* iterator_lastreadentry;
48 
49  /* for iterator by store orde */
50  _sion_keyvalue_table_entry* iterator_next;
51  _sion_keyvalue_table_entry* iterator_head;
52  _sion_keyvalue_table_entry* iterator_tail;
53 
55 };
56 
58  sion_keyvalue_table_entry_state_t state;
59  sion_table_key_t key;
60  _sion_keyvalue_table_entry *iterator_next;
62  void *data;
63 };
64 
65 #define HASH_FCT_SIMPLE_not
66 #define HASH_FCT_SPLIT
67 
68 #define DFUNCTION "_sion_keyvalue_table_hash_fct"
69 unsigned int _sion_keyvalue_table_hash_fct(sion_table_key_t key, int tab_size) {
70  unsigned int index=0;
71 
72 #if defined(HASH_FCT_SIMPLE)
73  /* simple modulo */
74  {
75  index = (unsigned int) key % tab_size;
76  }
77 #elif defined(HASH_FCT_SPLIT)
78  {
79  /* split modulo */
80  uint32_t upper =( uint32_t) (key >> 32);
81  uint32_t lower =( uint32_t) (key & 0xffffffff);
82  DPRINTFP((2, DFUNCTION, -1, "key %ld -> %d %d \n",(long) key, (int) upper, (int) lower));
83  index = (unsigned int) (
84  (unsigned int) upper % tab_size
85  + (unsigned int) lower % tab_size
86  ) % tab_size;
87  }
88 #endif
89 
90  return(index);
91 }
92 #undef DFUNCTION
93 
94 #define DFUNCTION "_sion_keyvalue_table_init"
95 _sion_keyvalue_table* _sion_keyvalue_table_init(int size) {
96  _sion_keyvalue_table* table=NULL;
97  _sion_keyvalue_table_entry* entries=NULL;
98  int i;
99 
100  DPRINTFP((2, DFUNCTION, -1, "enter init size=%d\n",size));
101 
102  table = malloc(sizeof(_sion_keyvalue_table));
103  if (table == NULL) {
104  _sion_errorprint(0,_SION_ERROR_RETURN,"cannot allocate internal keyvalue table of size %lu , aborting ...\n", (unsigned long) sizeof(_sion_keyvalue_table));
105  return(NULL);
106  }
107 
108  entries = malloc(size * sizeof(_sion_keyvalue_table_entry));
109  if (entries == NULL) {
110  _sion_errorprint(0,_SION_ERROR_RETURN,"cannot allocate internal keyvalue table entries of size %lu , aborting ...\n", (unsigned long) size);
111  free(table);
112  return(NULL);
113  }
114  table->entries=entries;
115 
116  table->size=size;
117  table->used=0;
118  table->num_added_entries=0;
119  table->iterator_lastreadindex=-1;
120  table->iterator_lastreadentry=NULL;
121  table->iterator_next=NULL;
122  table->iterator_head=NULL;
123  table->iterator_tail=NULL;
124  for(i=0;i<table->size;i++) {
125  table->entries[i].state=KEYVALUE_TABLE_ENTRY_STATE_FREE;
126  table->entries[i].key=0;
127  table->entries[i].iterator_next=NULL;
128  table->entries[i].next=NULL;
129  table->entries[i].data=NULL;
130  }
131 
132 
133  DPRINTFP((2, DFUNCTION, -1, "leave\n"));
134  return (table);
135 }
136 #undef DFUNCTION
137 
138 #define DFUNCTION "_sion_keyvalue_table_destroy"
139 int _sion_keyvalue_table_destroy(_sion_keyvalue_table* table) {
140  size_t rc=SION_SUCCESS;
141  int i;
142  _sion_keyvalue_table_entry *entry,*next_entry;
143 
144  DPRINTFP((2, DFUNCTION, -1, "enter\n"));
145  if(table->entries) {
146 
147 
148  for(i=0;i<table->size;i++) {
149  /* free entry data */
150  if((table->entries[i].state!=KEYVALUE_TABLE_ENTRY_STATE_FREE) && (table->entries[i].data!=NULL)) {
151  _SION_SAFE_FREE(table->entries[i].data, NULL);
152  }
153  /* free linked list */
154  entry=table->entries[i].next;
155  while (entry != NULL) {
156  if((entry->state!=KEYVALUE_TABLE_ENTRY_STATE_FREE) && (entry->data!=NULL)) {
157  _SION_SAFE_FREE(entry->data, NULL);
158  }
159  next_entry=entry->next;
160  _SION_SAFE_FREE(entry, NULL);
161  entry = next_entry;
162  }
163  }
164 
165  free(table->entries);
166  table->entries=NULL;
167  }
168  free(table);
169  table = NULL;
170 
171 
172  DPRINTFP((2, DFUNCTION, -1, "leave rc=%d\n",rc));
173  return (rc);
174 }
175 #undef DFUNCTION
176 
177 #define DFUNCTION "_sion_keyvalue_table_store"
178 int _sion_keyvalue_table_store(_sion_keyvalue_table* table, sion_table_key_t key, void *data) {
179  size_t rc=SION_SUCCESS;
180  unsigned int index;
181  _sion_keyvalue_table_entry *new_entry;
182 
183  DPRINTFP((2, DFUNCTION, -1, "enter\n"));
184 
185  index = _sion_keyvalue_table_hash_fct(key,table->size);
186  DPRINTFP((2, DFUNCTION, -1, "store entry with key %ld index=%d\n", (long) key, index));
187 
188  new_entry = &table->entries[index];
189  if (new_entry->state != KEYVALUE_TABLE_ENTRY_STATE_FREE) {
190  while (new_entry->next != NULL) {
191  new_entry = new_entry->next;
192  }
193  new_entry->next = (_sion_keyvalue_table_entry*) malloc(sizeof(_sion_keyvalue_table_entry));
194  if (new_entry->next == NULL) {
195  return(_sion_errorprint(SION_NOT_SUCCESS,_SION_ERROR_RETURN,"cannot allocate internal keyvalue table entry, aborting ...\n"));
196  }
197  DPRINTFP((2, DFUNCTION, -1, "add new entry to next list\n"));
198  table->num_added_entries++;
199  new_entry = new_entry->next;
200  }
201  table->used++;
202 
203  new_entry->state= KEYVALUE_TABLE_ENTRY_STATE_USED;
204  new_entry->key = key;
205  new_entry->data = data;
206  new_entry->next = NULL;
207  new_entry->iterator_next = NULL;
208 
209  if ( (table->iterator_head==NULL) && (table->iterator_tail==NULL) ) {
210  /* first entry */
211  table->iterator_next=table->iterator_head=table->iterator_tail=new_entry;
212  } else {
213  table->iterator_tail->iterator_next=new_entry;
214  table->iterator_tail=table->iterator_tail->iterator_next; /* advance tail */
215  }
216 
217 
218  DPRINTFP((2, DFUNCTION, -1, "new entry successfully added (key %ld index=%d)\n", (long) key, index));
219  DPRINTFP((2, DFUNCTION, -1, "TABLE[slots %d of %d, +%d, total %d] \n", table->used - table->num_added_entries,table->size,table->num_added_entries,table->used));
220 
221  DPRINTFP((2, DFUNCTION, -1, "leave rc=%d\n",rc));
222  return (rc);
223 }
224 #undef DFUNCTION
225 
226 #define DFUNCTION "_sion_keyvalue_table_lookup"
227 void * _sion_keyvalue_table_lookup(_sion_keyvalue_table* table, sion_table_key_t key) {
228  unsigned int index;
230 
231  DPRINTFP((2, DFUNCTION, -1, "enter\n"));
232 
233  index = _sion_keyvalue_table_hash_fct(key,table->size);
234  DPRINTFP((2, DFUNCTION, -1, "lookup entry with key %ld index=%d\n", (long) key, index));
235 
236  entry = &(table->entries[index]);
237  while (entry != NULL) {
238 
239  DPRINTFP((2, DFUNCTION, -1, "search: state=%ld\n",(long) entry->state ));
240 
241  if (entry->state == KEYVALUE_TABLE_ENTRY_STATE_USED) {
242  if(entry->key == key) {
243  DPRINTFP((2, DFUNCTION, -1, "key found %ld in key list\n",(long) entry->key ));
244  return(entry->data);
245  } else {
246  DPRINTFP((2, DFUNCTION, -1, "skip this key another key found %ld in list\n",(long) entry->key ));
247  entry = entry->next;
248  }
249  } else {
250  /* slot is empty */
251  return(NULL);
252  }
253  }
254  DPRINTFP((2, DFUNCTION, -1, "leave:entry not found\n"));
255  return(NULL);
256 
257 }
258 #undef DFUNCTION
259 
260 #define DFUNCTION "_sion_keyvalue_table_iterator_reset"
261 int _sion_keyvalue_table_iterator_reset(_sion_keyvalue_table* table) {
262 
263  int rc=SION_SUCCESS;
264 
265  DPRINTFP((2, DFUNCTION, -1, "enter\n"));
266  table->iterator_lastreadindex=-1;
267  table->iterator_lastreadentry=NULL;
268  table->iterator_next=table->iterator_head;
269  DPRINTFP((2, DFUNCTION, -1, "leave\n"));
270 
271  return(rc);
272 }
273 #undef DFUNCTION
274 
275 #define DFUNCTION "_sion_keyvalue_table_iterator_next_in_store_order"
276 int _sion_keyvalue_table_iterator_next_in_store_order(_sion_keyvalue_table* table, sion_table_key_t *key, void **data) {
278 
279  DPRINTFP((2, DFUNCTION, -1, "enter\n"));
280  if(table->used==0) {
281  return(SION_NOT_SUCCESS);
282  }
283  entry=table->iterator_next;
284 
285  if(entry != NULL) {
286  *key=entry->key;
287  *data=entry->data;
288  DPRINTFP((2, DFUNCTION, -1, "found entry with key %ld\n",(long) *key));
289  table->iterator_next=entry->iterator_next; /* move forward in iterator list */
290  return(SION_SUCCESS);
291  } else {
292  return(SION_NOT_SUCCESS);
293  }
294 }
295 #undef DFUNCTION
296 
297 #define DFUNCTION "_sion_keyvalue_table_iterator_next"
298 int _sion_keyvalue_table_iterator_next(_sion_keyvalue_table* table, sion_table_key_t *key, void **data) {
299 
300  DPRINTFP((2, DFUNCTION, -1, "enter\n"));
301  if(table->used==0) {
302  return(SION_NOT_SUCCESS);
303  }
304  if(table->iterator_lastreadindex==-1) {
305  /* search first entry which must be there (used>0) */
306  DPRINTFP((2, DFUNCTION, -1, "start first\n"));
307  table->iterator_lastreadindex++;
308  while(table->iterator_lastreadindex < table->size) {
309  if (table->entries[table->iterator_lastreadindex].state == KEYVALUE_TABLE_ENTRY_STATE_USED) {
310  table->iterator_lastreadentry = &table->entries[table->iterator_lastreadindex];
311  break;
312  }
313  table->iterator_lastreadindex++;
314  }
315  DPRINTFP((2, DFUNCTION, -1, "start first, found entry at index %d\n",table->iterator_lastreadindex));
316 
317  } else {
318 
319  /* another entry in list? */
320  if(table->iterator_lastreadentry->next != NULL) {
321  table->iterator_lastreadentry=table->iterator_lastreadentry->next;
322  DPRINTFP((2, DFUNCTION, -1, "found another entry in list at index %d\n",table->iterator_lastreadindex));
323  } else {
324  /* search forward */
325  table->iterator_lastreadindex++;
326  while(table->iterator_lastreadindex < table->size) {
327  if (table->entries[table->iterator_lastreadindex].state == KEYVALUE_TABLE_ENTRY_STATE_USED) {
328  table->iterator_lastreadentry = &table->entries[table->iterator_lastreadindex];
329  DPRINTFP((2, DFUNCTION, -1, "found entry at another index %d\n",table->iterator_lastreadindex));
330  break;
331  }
332  table->iterator_lastreadindex++;
333  }
334  }
335  }
336  if(table->iterator_lastreadindex < table->size) {
337  *key=table->iterator_lastreadentry->key;
338  *data=table->iterator_lastreadentry->data;
339  DPRINTFP((2, DFUNCTION, -1, "leave: entry found\n"));
340  return(SION_SUCCESS);
341  } else {
342  DPRINTFP((2, DFUNCTION, -1, "leave: next entry not found\n"));
343  return(SION_NOT_SUCCESS);
344  }
345 }
346 #undef DFUNCTION
347 
348 #define DFUNCTION "_sion_keyvalue_table_get_size"
349 int _sion_keyvalue_table_get_size(_sion_keyvalue_table* table) {
350  size_t help_bytes, bytes=0;
351  int i;
353 
354  DPRINTFP((2, DFUNCTION, -1, "enter\n"));
355 
356  help_bytes= sizeof(_sion_keyvalue_table);
357  DPRINTFP((2, DFUNCTION, -1, " sizeof key_table= %5d\n", help_bytes));
358  bytes+=help_bytes;
359 
360  if(table->entries) {
361 
362  help_bytes= table->size*sizeof(_sion_keyvalue_table_entry);
363  DPRINTFP((2, DFUNCTION, -1, " sizeof key_entries= %5d\n", help_bytes));
364  bytes+=help_bytes;
365 
366  help_bytes=0;
367  for(i=0;i<table->size;i++) {
368  entry=table->entries[i].next;
369  while (entry != NULL) {
370  help_bytes+=sizeof(_sion_keyvalue_table_entry);
371  entry = entry->next;
372  }
373  }
374 
375  DPRINTFP((2, DFUNCTION, -1, " sizeof key_addentries= %5d\n", help_bytes));
376  bytes+=help_bytes;
377 
378  }
379 
380  DPRINTFP((2, DFUNCTION, -1, "leave bytes=%d\n",bytes));
381  return (bytes);
382 }
383 #undef DFUNCTION
int _sion_errorprint(int rc, int level, const char *format,...)
Internal SION error.
Sion Time Stamp Header.