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 #ifdef DEBUG
45         printf("DEBUG -> index = %d, key = %d, val = %x\n", index, key, val);
46 #endif
47         pthread_mutex_lock(&mlookup.locktable);
48         index = mhashFunction(key);
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         pthread_mutex_lock(&mlookup.locktable);
73         ptr = mlookup.table;    // Address of the beginning of hash table       
74         index = mhashFunction(key);
75         node = &ptr[index];
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         pthread_mutex_lock(&mlookup.locktable);
94         ptr = mlookup.table;
95         index = mhashFunction(key);
96         curr = &ptr[index];
97         for (; curr != NULL; curr = curr->next) {
98                 if (curr->key == key) {         // Find a match in the hash table
99                         mlookup.numelements--;  // Decrement the number of elements in the global hashtable
100                         if ((curr == &ptr[index]) && (curr->next == NULL))  { // Delete the first item inside the hashtable with no linked list of mhashlistnode_t 
101                                 curr->key = 0;
102                                 curr->val = NULL;
103                         } else if ((curr == &ptr[index]) && (curr->next != NULL)) { //Delete the first item with a linked list of mhashlistnode_t  connected 
104                                 curr->key = curr->next->key;
105                                 curr->val = curr->next->val;
106                                 node = curr->next;
107                                 curr->next = curr->next->next;
108                                 free(node);
109                         } else {                                                // Regular delete from linked listed    
110                                 prev->next = curr->next;
111                                 free(curr);
112                         }
113                         pthread_mutex_unlock(&mlookup.locktable);
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 unsigned int *mhashGetKeys(unsigned int *numKeys)
188 {
189         unsigned int *keys;
190         int i, keyindex;
191         mhashlistnode_t *curr;
192
193         pthread_mutex_lock(&mlookup.locktable);
194
195         *numKeys = mlookup.numelements;
196         keys = calloc(*numKeys, sizeof(unsigned int));
197
198         keyindex = 0;
199         for (i = 0; i < mlookup.size; i++)
200         {
201                 if (mlookup.table[i].key != 0)
202                 {
203                         curr = &mlookup.table[i];
204                         while (curr != NULL)
205                         {
206                                 keys[keyindex++] = curr->key;
207                                 curr = curr->next;
208                         }
209                 }
210         }
211
212         if (keyindex != *numKeys)
213                 printf("mhashGetKeys(): WARNING: incorrect mlookup.numelements value!\n");
214
215         pthread_mutex_unlock(&mlookup.locktable);
216         return keys;
217 }
218