start of new file
[IRC.git] / Robust / src / Runtime / DSTM / interface / prelookup.c
1 /* LOCK THE ENTIRE HASH TABLE */
2 #include "prelookup.h"
3 extern objstr_t *prefetchcache;
4
5 prehashtable_t pflookup; //Global prefetch cache table
6
7 unsigned int prehashCreate(unsigned int size, float loadfactor) {
8   prehashlistnode_t *nodes; 
9   int i; 
10   
11   // Allocate space for the hash table 
12   if((nodes = calloc(size, sizeof(prehashlistnode_t))) == NULL) { 
13     printf("Calloc error %s %d\n", __FILE__, __LINE__);
14     return 1;
15   }
16   pflookup.hack=NULL;
17   pflookup.hack2=NULL;
18   pflookup.table = nodes;
19   pflookup.size = size; 
20   pflookup.numelements = 0; // Initial number of elements in the hash
21   pflookup.loadfactor = loadfactor;
22   
23   //Intiliaze and set prefetch table mutex attribute
24   pthread_mutexattr_init(&pflookup.prefetchmutexattr);
25   //NOTE:PTHREAD_MUTEX_RECURSIVE is currently inside a #if_def UNIX98 in the pthread.h file
26   //Therefore use PTHREAD_MUTEX_RECURSIVE_NP instead
27   pthread_mutexattr_settype(&pflookup.prefetchmutexattr, PTHREAD_MUTEX_RECURSIVE_NP);
28   
29   //Initialize mutex var
30   pthread_mutex_init(&pflookup.lock, &pflookup.prefetchmutexattr);
31   //pthread_mutex_init(&pflookup.lock, NULL);
32   pthread_cond_init(&pflookup.cond, NULL); 
33   return 0;
34 }
35
36 //Assign keys to bins inside hash table
37 unsigned int prehashFunction(unsigned int key) {
38   return ( key % (pflookup.size));
39 }
40
41 //Store oids and their pointers into hash
42 unsigned int prehashInsert(unsigned int key, void *val) {
43   unsigned int newsize;
44   int index;
45   prehashlistnode_t *ptr, *node;
46   
47   if(pflookup.numelements > (pflookup.loadfactor * pflookup.size)) {
48     //Resize
49     newsize = 2 * pflookup.size + 1;
50     pthread_mutex_lock(&pflookup.lock);
51     prehashResize(newsize);
52     pthread_mutex_unlock(&pflookup.lock);
53   }
54   
55   ptr = pflookup.table;
56   pflookup.numelements++;
57   
58   pthread_mutex_lock(&pflookup.lock);
59   index = prehashFunction(key);
60   if(ptr[index].next == NULL && ptr[index].key == 0) {  // Insert at the first position in the hashtable
61     ptr[index].key = key;
62     ptr[index].val = val;
63   } else {                      // Insert in the beginning of linked list
64     if ((node = calloc(1, sizeof(prehashlistnode_t))) == NULL) {
65       printf("Calloc error %s, %d\n", __FILE__, __LINE__);
66       pthread_mutex_unlock(&pflookup.lock);
67       return 1;
68     }
69     node->key = key;
70     node->val = val ;
71     node->next = ptr[index].next;
72     ptr[index].next = node;
73   }
74   pthread_mutex_unlock(&pflookup.lock);
75   return 0;
76 }
77
78 // Search for an address for a given oid
79 void *prehashSearch(unsigned int key) {
80   int index;
81   prehashlistnode_t *ptr, *node;
82   
83   pthread_mutex_lock(&pflookup.lock);
84   ptr = pflookup.table;
85   index = prehashFunction(key);
86   node = &ptr[index];
87   while(node != NULL) {
88     if(node->key == key) {
89       pthread_mutex_unlock(&pflookup.lock);
90       return node->val;
91     }
92     node = node->next;
93   }
94   pthread_mutex_unlock(&pflookup.lock);
95   return NULL;
96 }
97
98 unsigned int prehashRemove(unsigned int key) {
99   int index;
100   prehashlistnode_t *curr, *prev;
101   prehashlistnode_t *ptr, *node;
102
103   pthread_mutex_lock(&pflookup.lock);
104     ptr = pflookup.table;
105   index = prehashFunction(key);
106   curr = &ptr[index];
107   
108   for (; curr != NULL; curr = curr->next) {
109     if (curr->key == key) {         // Find a match in the hash table
110       pflookup.numelements--;  // Decrement the number of elements in the global hashtable
111       if ((curr == &ptr[index]) && (curr->next == NULL))  { // Delete the first item inside the hashtable with no linked list of prehashlistnode_t 
112         curr->key = 0;
113         curr->val = NULL;
114       } else if ((curr == &ptr[index]) && (curr->next != NULL)) { //Delete the first item with a linked list of prehashlistnode_t  connected 
115         curr->key = curr->next->key;
116         curr->val = curr->next->val;
117         node = curr->next;
118         curr->next = curr->next->next;
119         free(node);
120       } else {                                          // Regular delete from linked listed    
121         prev->next = curr->next;
122         free(curr);
123       }
124       pthread_mutex_unlock(&pflookup.lock);
125       return 0;
126     }       
127     prev = curr; 
128   }
129   pthread_mutex_unlock(&pflookup.lock);
130   return 1;
131 }
132
133 unsigned int prehashResize(unsigned int newsize) {
134   prehashlistnode_t *node, *ptr, *curr, *next;  // curr and next keep track of the current and the next chashlistnodes in a linked list
135   unsigned int oldsize;
136   int isfirst;    // Keeps track of the first element in the prehashlistnode_t for each bin in hashtable
137   int i,index;          
138   prehashlistnode_t *newnode;           
139   
140   ptr = pflookup.table;
141   oldsize = pflookup.size;
142   
143   if((node = calloc(newsize, sizeof(prehashlistnode_t))) == NULL) {
144     printf("Calloc error %s %d\n", __FILE__, __LINE__);
145     return 1;
146   }
147   
148   pflookup.table = node;                //Update the global hashtable upon resize()
149   pflookup.size = newsize;
150   pflookup.numelements = 0;
151   
152   for(i = 0; i < oldsize; i++) {                        //Outer loop for each bin in hash table
153     curr = &ptr[i];
154     isfirst = 1;                        
155     while (curr != NULL) {                      //Inner loop to go through linked lists
156       if (curr->key == 0) {             //Exit inner loop if there the first element for a given bin/index is NULL
157         break;                  //key = val =0 for element if not present within the hash table
158       }
159       next = curr->next;
160       index = prehashFunction(curr->key);
161       // Insert into the new table
162       if(pflookup.table[index].next == NULL && pflookup.table[index].key == 0) { 
163         pflookup.table[index].key = curr->key;
164         pflookup.table[index].val = curr->val;
165         pflookup.numelements++;
166       }else { 
167         if((newnode = calloc(1, sizeof(prehashlistnode_t))) == NULL) { 
168           printf("Calloc error %s, %d\n", __FILE__, __LINE__);
169           return 1;
170         }       
171         newnode->key = curr->key;
172         newnode->val = curr->val;
173         newnode->next = pflookup.table[index].next;
174         pflookup.table[index].next = newnode;    
175         pflookup.numelements++;
176       }       
177       
178       //free the linked list of prehashlistnode_t if not the first element in the hash table
179       if (isfirst != 1) {
180         free(curr);
181       } 
182       
183       isfirst = 0;
184       curr = next;
185     }
186   }
187   
188   free(ptr);            //Free the memory of the old hash table 
189   return 0;
190 }
191
192 //Note: This is based on the implementation of the inserting a key in the first position of the hashtable 
193 void prehashClear() {
194   int i, isFirstBin;
195   prehashlistnode_t *ptr, *prev, *curr;
196   
197   objstr_t *oldcache=prefetchcache;
198   prefetchcache=objstrCreate(prefetchcache->size);
199
200   pthread_mutex_lock(&pflookup.lock);
201   ptr = pflookup.table; 
202   for(i = 0; i < pflookup.size; i++) {
203     prev = &ptr[i];
204     isFirstBin = 1;
205     while(prev->next != NULL) {
206       isFirstBin = 0;
207       curr = prev->next;
208       prev->next = curr->next;
209       free(curr);
210     }
211     if(isFirstBin == 1) {
212       prev->key = 0;
213       prev->next = NULL;
214     }
215   }
216   pthread_mutex_unlock(&pflookup.lock);
217
218   if (pflookup.hack2!=NULL) {
219     objstrDelete(pflookup.hack2);
220   }
221   pflookup.hack2=pflookup.hack;
222   pflookup.hack=oldcache;
223 }
224