Fix tabbing.... Please fix your editors so they do tabbing correctly!!! (Spaces...
[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, double 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.threshold=size*loadfactor;
17   mlookup.mask = (size << 1) -1;
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.mask) >>1;
28 }
29
30 // Insert value and key mapping into the hash table
31 void mhashInsert(unsigned int key, void *val) {
32   mhashlistnode_t *ptr, *node;
33
34   pthread_mutex_lock(&mlookup.locktable);
35   if (mlookup.numelements > mlookup.threshold) {
36     //Resize Table
37     unsigned int newsize = mlookup.size << 1;
38     mhashResize(newsize);
39   }
40
41   ptr = &mlookup.table[(key & mlookup.mask) >>1];
42   mlookup.numelements++;
43
44
45   if(ptr->key ==0) {
46     ptr->key=key;
47     ptr->val=val;
48   } else {                              // Insert in the beginning of linked list
49     node = calloc(1, sizeof(mhashlistnode_t));
50     node->key = key;
51     node->val = val;
52     node->next = ptr->next;
53     ptr->next=node;
54   }
55   pthread_mutex_unlock(&mlookup.locktable);
56 }
57
58 // Return val for a given key in the hash table
59 void *mhashSearch(unsigned int key) {
60   int index;
61   mhashlistnode_t *node;
62   pthread_mutex_lock(&mlookup.locktable);
63   node = &mlookup.table[(key & mlookup.mask)>>1];
64   do {
65     if(node->key == key) {
66       void * tmp=node->val;
67       pthread_mutex_unlock(&mlookup.locktable);
68       return tmp;
69     }
70     node = node->next;
71   } while (node!=NULL);
72
73   pthread_mutex_unlock(&mlookup.locktable);
74   return NULL;
75 }
76
77 // Remove an entry from the hash table
78 unsigned int mhashRemove(unsigned int key) {
79   int index;
80   mhashlistnode_t *curr, *prev;
81   mhashlistnode_t *ptr, *node;
82
83   pthread_mutex_lock(&mlookup.locktable);
84   ptr = mlookup.table;
85   index = mhashFunction(key);
86   curr = &ptr[index];
87   for (; curr != NULL; curr = curr->next) {
88     if (curr->key == key) {                     // Find a match in the hash table
89       mlookup.numelements--;                    // Decrement the number of elements in the global hashtable
90       if ((curr == &ptr[index]) && (curr->next == NULL)) {                    // Delete the first item inside the hashtable with no linked list of mhashlistnode_t
91         curr->key = 0;
92         curr->val = NULL;
93       } else if ((curr == &ptr[index]) && (curr->next != NULL)) {                   //Delete the first item with a linked list of mhashlistnode_t  connected
94         curr->key = curr->next->key;
95         curr->val = curr->next->val;
96         node = curr->next;
97         curr->next = curr->next->next;
98         free(node);
99       } else {                                                                  // Regular delete from linked listed
100         prev->next = curr->next;
101         free(curr);
102       }
103       pthread_mutex_unlock(&mlookup.locktable);
104       return 0;
105     }
106     prev = curr;
107   }
108   pthread_mutex_unlock(&mlookup.locktable);
109   return 1;
110 }
111
112
113
114 // Resize table
115 unsigned int mhashResize(unsigned int newsize) {
116   mhashlistnode_t *node, *ptr, *curr;            // curr and next keep track of the current and the next mhashlistnodes in a linked list
117   unsigned int oldsize;
118   int isfirst;          // Keeps track of the first element in the mhashlistnode_t for each bin in hashtable
119   unsigned int i,index;
120   unsigned int mask;
121
122   ptr = mlookup.table;
123   oldsize = mlookup.size;
124
125   if((node = calloc(newsize, sizeof(mhashlistnode_t))) == NULL) {
126     printf("Calloc error %s %d\n", __FILE__, __LINE__);
127     return 1;
128   }
129
130   mlookup.table = node;                 //Update the global hashtable upon resize()
131   mlookup.size = newsize;
132   mlookup.threshold=newsize*mlookup.loadfactor;
133   mask=mlookup.mask = (newsize << 1)-1;
134
135   for(i = 0; i < oldsize; i++) {                        //Outer loop for each bin in hash table
136     curr = &ptr[i];
137     isfirst = 1;
138     do {
139       unsigned int key;
140       mhashlistnode_t *tmp,*next;
141
142       if ((key=curr->key) == 0) {                             //Exit inner loop if there the first element for a given bin/index is NULL
143         break;                                          //key = val =0 for element if not present within the hash table
144       }
145       next = curr->next;
146       index = (key & mask) >>1;
147       tmp=&mlookup.table[index];
148
149       // Insert into the new table
150       if(tmp->key ==0) {
151         tmp->key=curr->key;
152         tmp->val=curr->val;
153         if (!isfirst)
154           free(curr);
155       } /*
156
157            NOTE:  Add this case if you change this...
158            This case currently never happens because of the way things rehash....
159            else if (isfirst) {
160            mhashlistnode_t *newnode = calloc(1, sizeof(mhashlistnode_t));
161            newnode->key = curr->key;
162            newnode->val = curr->val;
163            newnode->next = tmp->next;
164            tmp->next=newnode;
165            } */
166       else {
167         curr->next=tmp->next;
168         tmp->next=curr;
169       }
170       isfirst = 0;
171       curr = next;
172     } while(curr!=NULL);
173   }
174
175   free(ptr);                    //Free the memory of the old hash table
176   return 0;
177 }
178
179 unsigned int *mhashGetKeys(unsigned int *numKeys) {
180   unsigned int *keys;
181   int i, keyindex;
182   mhashlistnode_t *curr;
183
184   pthread_mutex_lock(&mlookup.locktable);
185
186   *numKeys = mlookup.numelements;
187   keys = calloc(*numKeys, sizeof(unsigned int));
188
189   keyindex = 0;
190   for (i = 0; i < mlookup.size; i++) {
191     if (mlookup.table[i].key != 0) {
192       curr = &mlookup.table[i];
193       while (curr != NULL) {
194         keys[keyindex++] = curr->key;
195         curr = curr->next;
196       }
197     }
198   }
199
200   if (keyindex != *numKeys)
201     printf("mhashGetKeys(): WARNING: incorrect mlookup.numelements value!\n");
202
203   pthread_mutex_unlock(&mlookup.locktable);
204   return keys;
205 }
206