This commit was manufactured by cvs2svn to create tag 'buildscript'.
[IRC.git] /
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         // Allocate space for the hash table 
9         if((nodes = calloc(size, sizeof(mhashlistnode_t))) == NULL) {
10                 printf("Calloc error %s %d\n", __FILE__, __LINE__);
11                 return 1;
12         }
13         
14         mlookup.table = nodes;
15         mlookup.size = size;
16         mlookup.numelements = 0; // Initial number of elements in the hash
17         mlookup.loadfactor = loadfactor;
18         //Initialize the pthread_mutex variable         
19         pthread_mutex_init(&mlookup.locktable, NULL);
20         return 0;
21 }
22
23 // Assign to keys to bins inside hash table
24 unsigned int mhashFunction(unsigned int key) {
25         return( key % (mlookup.size));
26 }
27
28 // Insert value and key mapping into the hash table
29 unsigned int mhashInsert(unsigned int key, void *val) {
30         unsigned int newsize;
31         int index;
32         mhashlistnode_t *ptr, *node;
33         
34         if (mlookup.numelements > (mlookup.loadfactor * mlookup.size)) {
35                 //Resize Table
36                 newsize = 2 * mlookup.size + 1;         
37                 pthread_mutex_lock(&mlookup.locktable);
38                 mhashResize(newsize);
39                 pthread_mutex_unlock(&mlookup.locktable);
40         }
41         ptr = mlookup.table;
42         mlookup.numelements++;
43         
44         index = mhashFunction(key);
45 #ifdef DEBUG
46         printf("DEBUG -> index = %d, key = %d, val = %x\n", index, key, val);
47 #endif
48         pthread_mutex_lock(&mlookup.locktable);
49         if(ptr[index].next == NULL && ptr[index].key == 0) {    // Insert at the first position in the hashtable
50                 ptr[index].key = key;
51                 ptr[index].val = val;
52         } else {                        // Insert in the beginning of linked list
53                 if ((node = calloc(1, sizeof(mhashlistnode_t))) == NULL) {
54                         printf("Calloc error %s, %d\n", __FILE__, __LINE__);
55                         pthread_mutex_unlock(&mlookup.locktable);
56                         return 1;
57                 }
58                 node->key = key;
59                 node->val = val;
60                 node->next = ptr[index].next;
61                 ptr[index].next = node;
62         }
63         pthread_mutex_unlock(&mlookup.locktable);
64         return 0;
65 }
66
67 // Return val for a given key in the hash table
68 void *mhashSearch(unsigned int key) {
69         int index;
70         mhashlistnode_t *ptr, *node;
71
72         ptr = mlookup.table;    // Address of the beginning of hash table       
73         index = mhashFunction(key);
74         node = &ptr[index];
75         pthread_mutex_lock(&mlookup.locktable);
76         while(node != NULL) {
77                 if(node->key == key) {
78                         pthread_mutex_unlock(&mlookup.locktable);
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                         pthread_mutex_unlock(&mlookup.locktable);
115                         return 0;
116                 }       
117                 prev = curr; 
118         }
119         pthread_mutex_unlock(&mlookup.locktable);
120         return 1;
121 }
122
123 // Resize table
124 unsigned int mhashResize(unsigned int newsize) {
125         mhashlistnode_t *node, *ptr, *curr, *next;      // curr and next keep track of the current and the next mhashlistnodes in a linked list
126         unsigned int oldsize;
127         int isfirst;    // Keeps track of the first element in the mhashlistnode_t for each bin in hashtable
128         int i,index;    
129         mhashlistnode_t *newnode;               
130         
131         ptr = mlookup.table;
132         oldsize = mlookup.size;
133         
134         if((node = calloc(newsize, sizeof(mhashlistnode_t))) == NULL) {
135                 printf("Calloc error %s %d\n", __FILE__, __LINE__);
136                 return 1;
137         }
138
139         mlookup.table = node;           //Update the global hashtable upon resize()
140         mlookup.size = newsize;
141         mlookup.numelements = 0;
142
143         for(i = 0; i < oldsize; i++) {                  //Outer loop for each bin in hash table
144                 curr = &ptr[i];
145                 isfirst = 1;                    
146                 while (curr != NULL) {                  //Inner loop to go through linked lists
147                         if (curr->key == 0) {           //Exit inner loop if there the first element for a given bin/index is NULL
148                                 break;                  //key = val =0 for element if not present within the hash table
149                         }
150                         next = curr->next;
151
152                         index = mhashFunction(curr->key);
153 #ifdef DEBUG
154                         printf("DEBUG(resize) -> index = %d, key = %d, val = %x\n", index, curr->key, curr->val);
155 #endif
156                         // Insert into the new table
157                         if(mlookup.table[index].next == NULL && mlookup.table[index].key == 0) { 
158                                 mlookup.table[index].key = curr->key;
159                                 mlookup.table[index].val = curr->val;
160                                 mlookup.numelements++;
161                         }else { 
162                                 if((newnode = calloc(1, sizeof(mhashlistnode_t))) == NULL) { 
163                                         printf("Calloc error %s, %d\n", __FILE__, __LINE__);
164                                         return 1;
165                                 }       
166                                 newnode->key = curr->key;
167                                 newnode->val = curr->val;
168                                 newnode->next = mlookup.table[index].next;
169                                 mlookup.table[index].next = newnode;    
170                                 mlookup.numelements++;
171                         }       
172
173                         //free the linked list of mhashlistnode_t if not the first element in the hash table
174                         if (isfirst != 1) {
175                                 free(curr);
176                         } 
177                         
178                         isfirst = 0;
179                         curr = next;
180
181                 }
182         }
183
184         free(ptr);              //Free the memory of the old hash table 
185         return 0;
186 }
187
188 unsigned int *mhashGetKeys(unsigned int *numKeys)
189 {
190         unsigned int *keys;
191         int i, keyindex;
192         mhashlistnode_t *curr;
193
194         pthread_mutex_lock(&mlookup.locktable);
195
196         *numKeys = mlookup.numelements;
197         keys = calloc(*numKeys, sizeof(unsigned int));
198
199         keyindex = 0;
200         for (i = 0; i < mlookup.size; i++)
201         {
202                 if (mlookup.table[i].key != 0)
203                 {
204                         curr = &mlookup.table[i];
205                         while (curr != NULL)
206                         {
207                                 keys[keyindex++] = curr->key;
208                                 curr = curr->next;
209                         }
210                 }
211         }
212
213         if (keyindex != *numKeys)
214                 printf("mhashGetKeys(): WARNING: incorrect mlookup.numelements value!\n");
215
216         pthread_mutex_unlock(&mlookup.locktable);
217         return keys;
218 }
219