Added pthread support for llookup and mlookup hash
[IRC.git] / Robust / src / Runtime / DSTM / interface / mlookup.c
1 #include "mlookup.h"
2
3 mhashtable_t mlookup;   //Global hash table
4
5 // Creates a machine lookup table with size =" size" 
6 unsigned int mhashCreate(unsigned int size, float loadfactor)  {
7         mhashlistnode_t *nodes;
8         int i;
9
10         // Allocate space for the hash table 
11         if((nodes = calloc(size, sizeof(mhashlistnode_t))) == NULL) {
12                 printf("Calloc error %s %d\n", __FILE__, __LINE__);
13                 return 1;
14         }
15         
16         mlookup.table = nodes;
17         mlookup.size = size;
18         mlookup.numelements = 0; // Initial number of elements in the hash
19         mlookup.loadfactor = loadfactor;
20         //Initialize the pthread_mutex variable         
21         pthread_mutex_init(&mlookup.locktable, NULL);
22         return 0;
23 }
24
25 // Assign to keys to bins inside hash table
26 unsigned int mhashFunction(unsigned int key) {
27         return( key % (mlookup.size));
28 }
29
30 // Insert value and key mapping into the hash table
31 unsigned int mhashInsert(unsigned int key, void *val) {
32         unsigned int newsize;
33         int index;
34         mhashlistnode_t *ptr, *node;
35         
36         if (mlookup.numelements > (mlookup.loadfactor * mlookup.size)) {
37                 //Resize Table
38                 newsize = 2 * mlookup.size + 1;         
39                 pthread_mutex_lock(&mlookup.locktable);
40                 mhashResize(newsize);
41                 pthread_mutex_unlock(&mlookup.locktable);
42         }
43         ptr = mlookup.table;
44         mlookup.numelements++;
45         
46         index = mhashFunction(key);
47 #ifdef DEBUG
48         printf("DEBUG -> index = %d, key = %d, val = %x\n", index, key, val);
49 #endif
50         pthread_mutex_lock(&mlookup.locktable);
51         if(ptr[index].next == NULL && ptr[index].key == 0) {    // Insert at the first position in the hashtable
52                 ptr[index].key = key;
53                 ptr[index].val = val;
54         } else {                        // Insert in the beginning of linked list
55                 if ((node = calloc(1, sizeof(mhashlistnode_t))) == NULL) {
56                         printf("Calloc error %s, %d\n", __FILE__, __LINE__);
57                         return 1;
58                 }
59                 node->key = key;
60                 node->val = val ;
61                 node->next = ptr[index].next;
62                 ptr[index].next = node;
63         }
64         pthread_mutex_unlock(&mlookup.locktable);
65         return 0;
66 }
67
68 // Return val for a given key in the hash table
69 void *mhashSearch(unsigned int key) {
70         int index;
71         mhashlistnode_t *ptr, *node;
72
73         ptr = mlookup.table;    // Address of the beginning of hash table       
74         index = mhashFunction(key);
75         node = &ptr[index];
76         pthread_mutex_lock(&mlookup.locktable);
77         while(node != NULL) {
78                 if(node->key == key) {
79                         return node->val;
80                 }
81                 node = node->next;
82         }
83         pthread_mutex_unlock(&mlookup.locktable);
84         return NULL;
85 }
86
87 // Remove an entry from the hash table
88 unsigned int mhashRemove(unsigned int key) {
89         int index;
90         mhashlistnode_t *curr, *prev;
91         mhashlistnode_t *ptr, *node;
92         
93         ptr = mlookup.table;
94         index = mhashFunction(key);
95         curr = &ptr[index];
96
97         pthread_mutex_lock(&mlookup.locktable);
98         for (; curr != NULL; curr = curr->next) {
99                 if (curr->key == key) {         // Find a match in the hash table
100                         mlookup.numelements--;  // Decrement the number of elements in the global hashtable
101                         if ((curr == &ptr[index]) && (curr->next == NULL))  { // Delete the first item inside the hashtable with no linked list of mhashlistnode_t 
102                                 curr->key = 0;
103                                 curr->val = NULL;
104                         } else if ((curr == &ptr[index]) && (curr->next != NULL)) { //Delete the first item with a linked list of mhashlistnode_t  connected 
105                                 curr->key = curr->next->key;
106                                 curr->val = curr->next->val;
107                                 node = curr->next;
108                                 curr->next = curr->next->next;
109                                 free(node);
110                         } else {                                                // Regular delete from linked listed    
111                                 prev->next = curr->next;
112                                 free(curr);
113                         }
114                         return 0;
115                 }       
116                 prev = curr; 
117         }
118         pthread_mutex_unlock(&mlookup.locktable);
119         return 1;
120 }
121
122 // Resize table
123 unsigned int mhashResize(unsigned int newsize) {
124         mhashlistnode_t *node, *ptr, *curr, *next;      // curr and next keep track of the current and the next mhashlistnodes in a linked list
125         unsigned int oldsize;
126         int isfirst;    // Keeps track of the first element in the mhashlistnode_t for each bin in hashtable
127         int i,index;    
128         mhashlistnode_t *newnode;               
129         
130         ptr = mlookup.table;
131         oldsize = mlookup.size;
132         
133         if((node = calloc(newsize, sizeof(mhashlistnode_t))) == NULL) {
134                 printf("Calloc error %s %d\n", __FILE__, __LINE__);
135                 return 1;
136         }
137
138         mlookup.table = node;           //Update the global hashtable upon resize()
139         mlookup.size = newsize;
140         mlookup.numelements = 0;
141
142         for(i = 0; i < oldsize; i++) {                  //Outer loop for each bin in hash table
143                 curr = &ptr[i];
144                 isfirst = 1;                    
145                 while (curr != NULL) {                  //Inner loop to go through linked lists
146                         if (curr->key == 0) {           //Exit inner loop if there the first element for a given bin/index is NULL
147                                 break;                  //key = val =0 for element if not present within the hash table
148                         }
149                         next = curr->next;
150
151                         index = mhashFunction(curr->key);
152 #ifdef DEBUG
153                         printf("DEBUG(resize) -> index = %d, key = %d, val = %x\n", index, curr->key, curr->val);
154 #endif
155                         // Insert into the new table
156                         if(mlookup.table[index].next == NULL && mlookup.table[index].key == 0) { 
157                                 mlookup.table[index].key = curr->key;
158                                 mlookup.table[index].val = curr->val;
159                                 mlookup.numelements++;
160                         }else { 
161                                 if((newnode = calloc(1, sizeof(mhashlistnode_t))) == NULL) { 
162                                         printf("Calloc error %s, %d\n", __FILE__, __LINE__);
163                                         return 1;
164                                 }       
165                                 newnode->key = curr->key;
166                                 newnode->val = curr->val;
167                                 newnode->next = mlookup.table[index].next;
168                                 mlookup.table[index].next = newnode;    
169                                 mlookup.numelements++;
170                         }       
171
172                         //free the linked list of mhashlistnode_t if not the first element in the hash table
173                         if (isfirst != 1) {
174                                 free(curr);
175                         } 
176                         
177                         isfirst = 0;
178                         curr = next;
179
180                 }
181         }
182
183         free(ptr);              //Free the memory of the old hash table 
184         return 0;
185 }
186
187 #if 0
188 // Hash Resize
189 vkey resize(obj_addr_table_t * table){
190         int newCapacity = 2*(table->size) + 1;
191         obj_listnode_t **old;
192         //if ((table->hash = (obj_listnode_t **) malloc(sizeof(obj_listnode_t *)*size)) == NULL) {
193 }
194
195 // Hashing for the Key
196 int hashKey(unsigned int key, obj_addr_table_t *table) {
197         // hash32shiftmult
198         int c2=0x27d4eb2d; // a prime or an odd constant
199         key = (key ^ 61) ^ (key >> 16);
200         key = key + (key << 3);
201         key = key ^ (key >> 4);
202         key = key * c2;
203         key = key ^ (key >> 15);
204         printf("The bucket number is %d\n", key % (table->size));
205         return (key % (table->size));
206 }
207
208 //Add key and its address to the new ob_listnode_t 
209 vkey addKey(unsigned int key, objheader_t *ptr, obj_addr_table_t *table) {
210         int index;
211         obj_listnode_t *node;
212         
213         table->numelements++;
214         if(table->numelements > (table->loadfactor * table->size)){
215         //TODO : check if table is nearly full and then resize
216         }
217
218         index = hashKey(key,table);
219         if ((node = (obj_listnode_t *) malloc(sizeof(obj_listnode_t))) == NULL) {
220                 printf("Malloc error %s %d\n", __FILE__, __LINE__);
221                 exit(-1);
222         }
223         node->key = key;
224         node->object = ptr; 
225         node->next = table->hash[index];
226         table->hash[index] = node;
227         return;
228 }
229 // Get the address of the object header for a given key
230 objheader_t *findKey(unsigned int key, obj_addr_table_t *table) {
231         int index;
232         obj_listnode_t *ptr;
233
234         index = hashKey(key,table);
235         ptr = table->hash[index];
236         while(ptr != NULL) {
237                 if (ptr->key == key) {
238                         return ptr->object;
239                 }
240                 ptr = ptr->next;
241         }
242         return NULL;
243 }
244 // Remove the pointer to the object header from a linked list of obj_listnode_t given an key
245 int removeKey(unsigned int key, obj_addr_table_t *table) {
246         int index;
247         obj_listnode_t *curr, *prev;            // prev points to previous node and curr points to the node to be deleted
248
249         index = hashKey(key,table);
250         prev = curr = table->hash[index];
251         for (; curr != NULL; curr = curr->next) {
252                 if (curr->key == key) {         // Find a match in the hash table
253                         table->numelements--;
254                         prev->next = curr->next;
255                         if (table->hash[index] == curr) { // Special case when there is one element pointed by  the hash table
256                                 table->hash[index] = NULL;
257                         }
258                         free(curr);
259                         return 0;
260                 } 
261                 prev = curr;
262         }
263         return -1;
264
265
266 #endif