#endif
do {
/* Look through all the objects in the transaction hash table */
- int finalResponse = traverseCache();
+ int finalResponse;
+ if (c_numelements<(c_size>>3))
+ finalResponse= alttraverseCache();
+ else
+ finalResponse= traverseCache();
if(finalResponse == TRANS_ABORT) {
#ifdef TRANSSTATS
numTransAbort++;
}
}
+/* ==================================================
+ * traverseCache
+ * - goes through the transaction cache and
+ * - decides if a transaction should commit or abort
+ * ==================================================
+ */
+int alttraverseCache() {
+ /* Create info to keep track of objects that can be locked */
+ int numoidrdlocked=0;
+ int numoidwrlocked=0;
+ void * rdlocked[200];
+ void * wrlocked[200];
+ int softabort=0;
+ int i;
+ void ** oidrdlocked;
+ void ** oidwrlocked;
+ if (c_numelements<200) {
+ oidrdlocked=rdlocked;
+ oidwrlocked=wrlocked;
+ } else {
+ int size=c_numelements*sizeof(void*);
+ oidrdlocked=malloc(size);
+ oidwrlocked=malloc(size);
+ }
+ chashlistnode_t *curr = c_list;
+ /* Inner loop to traverse the linked list of the cache lookupTable */
+ while(curr != NULL) {
+ //if the first bin in hash table is empty
+ objheader_t * headeraddr=&((objheader_t *) curr->val)[-1];
+
+ unsigned int version = headeraddr->version;
+ objheader_t *header=(objheader_t *) (((char *)curr->key)-sizeof(objheader_t));
+
+ if(STATUS(headeraddr) & DIRTY) {
+ /* Read from the main heap and compare versions */
+ if(write_trylock(&header->lock)) { //can aquire write lock
+ if (version == header->version) {/* versions match */
+ /* Keep track of objects locked */
+ oidwrlocked[numoidwrlocked++] = OID(header);
+ } else {
+ oidwrlocked[numoidwrlocked++] = OID(header);
+ transAbortProcess(oidrdlocked, &numoidrdlocked, oidwrlocked, &numoidwrlocked);
+ return TRANS_ABORT;
+ }
+ } else { /* cannot aquire lock */
+ if(version == header->version) /* versions match */
+ softabort=1;
+ else {
+ transAbortProcess(oidrdlocked, &numoidrdlocked, oidwrlocked, &numoidwrlocked);
+ return TRANS_ABORT;
+ }
+ }
+ } else {
+ /* Read from the main heap and compare versions */
+ if(read_trylock(&header->lock)) { //can further aquire read locks
+ if(version == header->version) {/* versions match */
+ oidrdlocked[numoidrdlocked++] = OID(header);
+ } else {
+ oidrdlocked[numoidrdlocked++] = OID(header);
+ transAbortProcess(oidrdlocked, &numoidrdlocked, oidwrlocked, &numoidwrlocked);
+ return TRANS_ABORT;
+ }
+ } else { /* cannot aquire lock */
+ if(version == header->version)
+ softabort=1;
+ else {
+ transAbortProcess(oidrdlocked, &numoidrdlocked, oidwrlocked, &numoidwrlocked);
+ return TRANS_ABORT;
+ }
+ }
+ }
+
+ curr = curr->lnext;
+ }
+
+ /* Decide the final response */
+ if (softabort) {
+ transAbortProcess(oidrdlocked, &numoidrdlocked, oidwrlocked, &numoidwrlocked);
+ return TRANS_SOFT_ABORT;
+ } else {
+ transCommitProcess(oidrdlocked, &numoidrdlocked, oidwrlocked, &numoidwrlocked);
+ return TRANS_COMMIT;
+ }
+}
+
/* ==================================
* transAbortProcess
#include "strings.h"
__thread chashlistnode_t *c_table;
+__thread chashlistnode_t *c_list;
__thread unsigned int c_size;
__thread unsigned INTPTR c_mask;
__thread unsigned int c_numelements;
c_threshold=size*loadfactor;
c_mask = (size << 3)-1;
c_numelements = 0; // Initial number of elements in the hash
+ c_list=NULL;
}
void t_chashreset() {
chashlistnode_t *ptr = c_table;
int i;
- for(i=0 ; i<c_size ; i++) {
- chashlistnode_t * curr = ptr[i].next;
- while(curr!=NULL) {
- chashlistnode_t * next = curr->next;
- free(curr);
- curr=next;
+ if (c_numelements<(c_size>>3)) {
+ chashlistnode_t *top=&ptr[c_size];
+ chashlistnode_t *tmpptr=c_list;
+ while(tmpptr!=NULL) {
+ chashlistnode_t *next=tmpptr->lnext;
+ if (tmpptr>=ptr&&tmpptr<top) {
+ //zero in list
+ tmpptr->key=0;
+ tmpptr->next=NULL;
+ } else {
+ free(tmpptr);
+ }
+ tmpptr=next;
+ }
+ } else {
+ for(i=0 ; i<c_size ; i++) {
+ chashlistnode_t * curr = ptr[i].next;
+ while(curr!=NULL) {
+ chashlistnode_t * next = curr->next;
+ free(curr);
+ curr=next;
+ }
}
+ bzero(c_table, sizeof(chashlistnode_t)*c_size);
}
c_numelements = 0;
- bzero(c_table, sizeof(chashlistnode_t)*c_size);
-}
-
-chashtable_t *chashCreate(unsigned int size, double loadfactor) {
- chashtable_t *ctable;
- chashlistnode_t *nodes;
- int i;
-
- if((ctable = calloc(1, sizeof(chashtable_t))) == NULL) {
- printf("Calloc error %s %d\n", __FILE__, __LINE__);
- return NULL;
- }
-
- // Allocate space for the hash table
- if((nodes = calloc(size, sizeof(chashlistnode_t))) == NULL) {
- printf("Calloc error %s %d\n", __FILE__, __LINE__);
- free(ctable);
- return NULL;
- }
-
- ctable->table = nodes;
- ctable->loadfactor = loadfactor;
- ctable->size = size;
- ctable->threshold=size*loadfactor;
- ctable->mask = (size << 3)-1;
- ctable->numelements = 0; // Initial number of elements in the hash
-
-
- return ctable;
-}
-
-//Finds the right bin in the hash table
-static INLINE unsigned int chashFunction(chashtable_t *table, void * key) {
- return (((unsigned INTPTR) key) & (table->mask))>>3; //throw away low order bit
-}
-
-//Store objects and their pointers into hash
-void chashInsert(chashtable_t *table, void * key, void *val) {
- chashlistnode_t *ptr;
-
- if(table->numelements > (table->threshold)) {
- //Resize
- unsigned int newsize = table->size << 1;
- chashResize(table,newsize);
- }
-
- ptr = &table->table[(((unsigned INTPTR)key)&table->mask)>>3];
- table->numelements++;
-
- if(ptr->key==0) {
- ptr->key=key;
- ptr->val=val;
- } else { // Insert in the beginning of linked list
- chashlistnode_t * node = calloc(1, sizeof(chashlistnode_t));
- node->key = key;
- node->val = val;
- node->next = ptr->next;
- ptr->next=node;
- }
-}
-
-// Search for an address for a given oid
-INLINE void * chashSearch(chashtable_t *table, void * key) {
- //REMOVE HASH FUNCTION CALL TO MAKE SURE IT IS INLINED HERE
- chashlistnode_t *node = &table->table[(((unsigned INTPTR)key) & table->mask)>>3];
-
- do {
- if(node->key == key) {
- return node->val;
- }
- node = node->next;
- } while(node != NULL);
-
- return NULL;
+ c_list=NULL;
}
//Store objects and their pointers into hash
if(ptr->key==0) {
ptr->key=key;
ptr->val=val;
+ ptr->lnext=c_list;
+ c_list=ptr;
} else { // Insert in the beginning of linked list
chashlistnode_t * node = calloc(1, sizeof(chashlistnode_t));
node->key = key;
node->val = val;
node->next = ptr->next;
ptr->next=node;
+ node->lnext=c_list;
+ c_list=node;
}
}
return NULL;
}
-
-unsigned int chashRemove(chashtable_t *table, void * key) {
- return chashRemove2(table, key)==NULL;
-
-}
-
-void * chashRemove2(chashtable_t *table, void * key) {
- int index;
- chashlistnode_t *curr, *prev;
- chashlistnode_t *ptr, *node;
- void *value;
-
- ptr = table->table;
- index = chashFunction(table,key);
- curr = &ptr[index];
-
- for (; curr != NULL; curr = curr->next) {
- if (curr->key == key) { // Find a match in the hash table
- table->numelements--; // Decrement the number of elements in the global hashtable
- if ((curr == &ptr[index]) && (curr->next == NULL)) { // Delete the first item inside the hashtable with no linked list of chashlistnode_t
- curr->key = 0;
- value=curr->val;
- curr->val = NULL;
- } else if ((curr == &ptr[index]) && (curr->next != NULL)) { //Delete the first item with a linked list of chashlistnode_t connected
- curr->key = curr->next->key;
- value=curr->val;
- curr->val = curr->next->val;
- node = curr->next;
- curr->next = curr->next->next;
- free(node);
- } else { // Regular delete from linked listed
- prev->next = curr->next;
- value=curr->val;
- free(curr);
- }
- return value;
- }
- prev = curr;
- }
- return NULL;
-}
-
-unsigned int chashResize(chashtable_t *table, unsigned int newsize) {
- chashlistnode_t *node, *ptr, *curr; // curr and next keep track of the current and the next chashlistnodes in a linked list
- unsigned int oldsize;
- int isfirst; // Keeps track of the first element in the chashlistnode_t for each bin in hashtable
- unsigned int i,index;
- unsigned int mask;
-
- ptr = table->table;
- oldsize = table->size;
-
- if((node = calloc(newsize, sizeof(chashlistnode_t))) == NULL) {
- printf("Calloc error %s %d\n", __FILE__, __LINE__);
- return 1;
- }
-
- table->table = node; //Update the global hashtable upon resize()
- table->size = newsize;
- table->threshold = newsize * table->loadfactor;
- mask=table->mask = (newsize << 3)-1;
-
- for(i = 0; i < oldsize; i++) { //Outer loop for each bin in hash table
- curr = &ptr[i];
- isfirst = 1;
- do { //Inner loop to go through linked lists
- void * key;
- chashlistnode_t *tmp,*next;
-
- if ((key=curr->key) == 0) { //Exit inner loop if there the first element is 0
- break; //key = val =0 for element if not present within the hash table
- }
- next = curr->next;
- index = (((unsigned INTPTR)key) & mask) >>3;
- tmp=&node[index];
- // Insert into the new table
- if(tmp->key == 0) {
- tmp->key = curr->key;
- tmp->val = curr->val;
- if (!isfirst) {
- free(curr);
- }
- }/*
- NOTE: Add this case if you change this...
- This case currently never happens because of the way things rehash....
- else if (isfirst) {
- chashlistnode_t *newnode= calloc(1, sizeof(chashlistnode_t));
- newnode->key = curr->key;
- newnode->val = curr->val;
- newnode->next = tmp->next;
- tmp->next=newnode;
- } */
- else {
- curr->next=tmp->next;
- tmp->next=curr;
- }
-
- isfirst = 0;
- curr = next;
- } while(curr!=NULL);
- }
-
- free(ptr); //Free the memory of the old hash table
- return 0;
-}
-
unsigned int t_chashResize(unsigned int newsize) {
chashlistnode_t *node, *ptr, *curr; // curr and next keep track of the current and the next chashlistnodes in a linked list
unsigned int oldsize;
ptr = c_table;
oldsize = c_size;
+ c_list=NULL;
if((node = calloc(newsize, sizeof(chashlistnode_t))) == NULL) {
printf("Calloc error %s %d\n", __FILE__, __LINE__);
if(tmp->key == 0) {
tmp->key = curr->key;
tmp->val = curr->val;
+ tmp->lnext=c_list;
+ c_list=tmp;
if (!isfirst) {
free(curr);
}
else {
curr->next=tmp->next;
tmp->next=curr;
+ curr->lnext=c_list;
+ c_list=curr;
}
isfirst = 0;
return 0;
}
-//Delete the entire hash table
-void chashDelete(chashtable_t *ctable) {
- int i;
- chashlistnode_t *ptr = ctable->table;
-
- for(i=0 ; i<ctable->size ; i++) {
- chashlistnode_t * curr = ptr[i].next;
- while(curr!=NULL) {
- chashlistnode_t * next = curr->next;
- free(curr);
- curr=next;
- }
- }
- free(ptr);
- free(ctable);
-}
-
//Delete the entire hash table
void t_chashDelete() {
int i;
}
free(ptr);
c_table=NULL;
+ c_list=NULL;
}