1 /* LOCK THE ENTIRE HASH TABLE */
4 extern objstr_t *prefetchcache;
5 extern pthread_mutex_t prefetchcache_mutex; //Mutex to lock Prefetch Cache
6 extern prefetchNodeInfo_t pNodeInfo;
8 prehashtable_t pflookup; //Global prefetch cache table
10 unsigned int prehashCreate(unsigned int size, float loadfactor) {
11 prehashlistnode_t *nodes;
13 // Allocate space for the hash table
14 if((nodes = calloc(size, sizeof(prehashlistnode_t))) == NULL) {
15 printf("Calloc error %s %d\n", __FILE__, __LINE__);
18 pflookup.table = nodes;
20 pflookup.mask = (size << 1) -1;
21 pflookup.numelements = 0; // Initial number of elements in the hash
22 pflookup.loadfactor = loadfactor;
23 pflookup.threshold=loadfactor*size;
25 //Intiliaze and set prefetch table mutex attribute
26 pthread_mutexattr_init(&pflookup.prefetchmutexattr);
27 //NOTE:PTHREAD_MUTEX_RECURSIVE is currently inside a #if_def UNIX98 in the pthread.h file
28 //Therefore use PTHREAD_MUTEX_RECURSIVE_NP instead
29 pthread_mutexattr_settype(&pflookup.prefetchmutexattr, PTHREAD_MUTEX_RECURSIVE_NP);
31 //Initialize mutex var
32 pthread_mutex_init(&pflookup.lock, &pflookup.prefetchmutexattr);
33 //pthread_mutex_init(&pflookup.lock, NULL);
34 pthread_cond_init(&pflookup.cond, NULL);
38 //Assign keys to bins inside hash table
39 unsigned int prehashFunction(unsigned int key) {
40 return ( key & pflookup.mask) >> 1;
43 //Store oids and their pointers into hash
44 void prehashInsert(unsigned int key, void *val) {
45 prehashlistnode_t *ptr,*node,*tmp;
48 printf("Error: Trying to insert invalid key and value\n");
51 if(pflookup.numelements > (pflookup.threshold)) {
53 unsigned int newsize = pflookup.size << 1;
54 pthread_mutex_lock(&pflookup.lock);
55 prehashResize(newsize);
56 pthread_mutex_unlock(&pflookup.lock);
59 ptr = &pflookup.table[(key & pflookup.mask)>>1];
60 pthread_mutex_lock(&pflookup.lock);
61 if((ptr->key==0) && (ptr->next== NULL)) { //Insert at the first bin of the table
64 pflookup.numelements++;
70 tmp->val = val; //Replace value for an exsisting key
71 pthread_mutex_unlock(&pflookup.lock);
76 if(!isFound) { //Insert new key and value into the chain of linked list for the given bin
77 node = calloc(1, sizeof(prehashlistnode_t));
80 node->next = ptr->next;
82 pflookup.numelements++;
85 pthread_mutex_unlock(&pflookup.lock);
90 void prehashInsert(unsigned int key, void *val) {
91 prehashlistnode_t *ptr,*node;
92 pthread_mutex_lock(&pflookup.lock);
94 if(pflookup.numelements > (pflookup.threshold)) {
96 unsigned int newsize = pflookup.size << 1;
97 prehashResize(newsize);
101 ptr = &pflookup.table[(key & pflookup.mask)>>1];
102 pflookup.numelements++;
107 } else { // Insert in the beginning of linked list
108 node = calloc(1, sizeof(prehashlistnode_t));
111 node->next = ptr->next;
114 pthread_mutex_unlock(&pflookup.lock);
118 // Search for an address for a given oid
119 INLINE void *prehashSearch(unsigned int key) {
121 prehashlistnode_t *ptr, *node;
123 pthread_mutex_lock(&pflookup.lock);
124 node = &pflookup.table[(key & pflookup.mask)>>1];
126 if(node->key == key) {
127 void * tmp=node->val;
128 pthread_mutex_unlock(&pflookup.lock);
132 } while (node!=NULL);
133 pthread_mutex_unlock(&pflookup.lock);
137 unsigned int prehashRemove(unsigned int key) {
139 prehashlistnode_t *curr, *prev;
140 prehashlistnode_t *ptr, *node;
142 pthread_mutex_lock(&pflookup.lock);
143 ptr = pflookup.table;
144 index = prehashFunction(key);
147 for (; curr != NULL; curr = curr->next) {
148 if (curr->key == key) { // Find a match in the hash table
149 pflookup.numelements--; // Decrement the number of elements in the global hashtable
150 if ((curr == &ptr[index]) && (curr->next == NULL)) { // Delete the first item inside the hashtable with no linked list of prehashlistnode_t
153 } else if ((curr == &ptr[index]) && (curr->next != NULL)) { //Delete the first item with a linked list of prehashlistnode_t connected
154 curr->key = curr->next->key;
155 curr->val = curr->next->val;
157 curr->next = curr->next->next;
159 } else { // Regular delete from linked listed
160 prev->next = curr->next;
163 pthread_mutex_unlock(&pflookup.lock);
168 pthread_mutex_unlock(&pflookup.lock);
172 unsigned int prehashResize(unsigned int newsize) {
173 prehashlistnode_t *node, *ptr; // curr and next keep track of the current and the next chashlistnodes in a linked list
174 unsigned int oldsize;
177 ptr = pflookup.table;
178 oldsize = pflookup.size;
180 if((node = calloc(newsize, sizeof(prehashlistnode_t))) == NULL) {
181 printf("Calloc error %s %d\n", __FILE__, __LINE__);
185 pflookup.table = node; //Update the global hashtable upon resize()
186 pflookup.size = newsize;
187 pflookup.threshold=newsize*pflookup.loadfactor;
188 mask=pflookup.mask = (newsize << 1) -1;
190 for(i = 0; i < oldsize; i++) { //Outer loop for each bin in hash table
191 prehashlistnode_t * curr = &ptr[i];
192 prehashlistnode_t *tmp, *next;
196 if ((key=curr->key) == 0) { //Exit inner loop if there the first element for a given bin/index is NULL
197 break; //key = val =0 for element if not present within the hash table
200 index = (key & mask)>>1;
201 tmp=&pflookup.table[index];
202 // Insert into the new table
209 NOTE: Add this case if you change this...
210 This case currently never happens because of the way things rehash....
212 prehashlistnode_t * newnode = calloc(1, sizeof(prehashlistnode_t));
213 newnode->key = curr->key;
214 newnode->val = curr->val;
215 newnode->next = tmp->next;
219 curr->next=tmp->next;
228 free(ptr); //Free the memory of the old hash table
232 //Note: This is based on the implementation of the inserting a key in the first position of the hashtable
233 void prehashClear() {
236 prehashlistnode_t *ptr, *prev, *curr;
238 pthread_mutex_lock(&pflookup.lock);
239 ptr = pflookup.table;
240 for(i = 0; i < pflookup.size; i++) {
243 while(prev->next != NULL) {
246 prev->next = curr->next;
249 if(isFirstBin == 1) {
256 pthread_mutex_unlock(&pflookup.lock);
257 pthread_mutex_lock(&prefetchcache_mutex);
258 if (pNodeInfo.newstale==NULL) {
259 //transfer the list wholesale;
260 pNodeInfo.oldstale=pNodeInfo.oldptr;
261 pNodeInfo.newstale=pNodeInfo.newptr;
263 //merge the two lists
264 pNodeInfo.newstale->prev=pNodeInfo.oldptr;
265 pNodeInfo.newstale=pNodeInfo.newptr;
267 stale=STALL_THRESHOLD-pNodeInfo.stale_count;
269 if (stale>0&&stale>pNodeInfo.stall)
270 pNodeInfo.stall=stale;
272 pNodeInfo.stale_count+=pNodeInfo.os_count;
273 pNodeInfo.oldptr=getObjStr(DEFAULT_OBJ_STORE_SIZE);
274 pNodeInfo.newptr=pNodeInfo.oldptr;
275 pNodeInfo.os_count=1;
276 pthread_mutex_unlock(&prefetchcache_mutex);