This commit was manufactured by cvs2svn to create tag 'buildscript'.
[IRC.git] /
1 /************************************************************************************************
2    IMP NOTE:
3    All llookup hash function prototypes returns 0 on sucess and 1 otherwise
4    llookup hash is an array of lhashlistnode_t
5    oid = mid = 0 in a given lhashlistnode_t for each bin in the hash table ONLY if the entry is empty =>
6    the OID's can be any unsigned int except 0
7
8    Uses pthreads. compile using -lpthread option
9  ***************************************************************************************************/
10 #include "llookup.h"
11
12 #ifdef SIMPLE_LLOOKUP
13
14 extern unsigned int *hostIpAddrs;
15 extern unsigned int oidsPerBlock;
16
17 unsigned int lhashCreate(unsigned int size, float loadfactor) {
18   return 0;
19 }
20
21 unsigned int lhashInsert(unsigned int oid, unsigned int mid) {
22   return 0;
23 }
24
25 unsigned int lhashSearch(unsigned int oid) {
26   if (oidsPerBlock == 0)
27     return hostIpAddrs[0];
28   else
29     return hostIpAddrs[oid / oidsPerBlock];
30 }
31
32 unsigned int lhashRemove(unsigned int oid) {
33   return 0;
34 }
35
36 #else
37
38 lhashtable_t llookup;           //Global Hash table
39
40 // Creates a hash table with size and an array of lhashlistnode_t
41 unsigned int lhashCreate(unsigned int size, float loadfactor) {
42   lhashlistnode_t *nodes;
43   int i;
44
45   // Allocate space for the hash table
46   if((nodes = calloc(size, sizeof(lhashlistnode_t))) == NULL) {
47     printf("Calloc error %s %d\n", __FILE__, __LINE__);
48     return 1;
49   }
50
51   llookup.table = nodes;
52   llookup.size = size;
53   llookup.numelements = 0;       // Initial number of elements in the hash
54   llookup.loadfactor = loadfactor;
55   //Initialize the pthread_mutex variable
56   pthread_mutex_init(&llookup.locktable, NULL);
57   return 0;
58 }
59
60 // Assign to oids to bins inside hash table
61 unsigned int lhashFunction(unsigned int oid) {
62   return( oid % (llookup.size));
63 }
64
65 // Insert oid and mid mapping into the hash table
66 unsigned int lhashInsert(unsigned int oid, unsigned int mid) {
67   unsigned int newsize;
68   int index;
69   lhashlistnode_t *ptr, *node;
70
71   if (llookup.numelements > (llookup.loadfactor * llookup.size)) {
72     //Resize Table
73     newsize = 2 * llookup.size + 1;
74     pthread_mutex_lock(&llookup.locktable);
75     lhashResize(newsize);
76     pthread_mutex_unlock(&llookup.locktable);
77   }
78
79   ptr = llookup.table;
80   llookup.numelements++;
81
82   index = lhashFunction(oid);
83 #ifdef DEBUG
84   printf("DEBUG(insert) oid = %d, mid =%d, index =%d\n",oid,mid, index);
85 #endif
86   pthread_mutex_lock(&llookup.locktable);
87   if(ptr[index].next == NULL && ptr[index].oid == 0) {          // Insert at the first position in the hashtable
88     ptr[index].oid = oid;
89     ptr[index].mid = mid;
90   } else {                              // Insert in the linked list
91     if ((node = calloc(1, sizeof(lhashlistnode_t))) == NULL) {
92       printf("Calloc error %s, %d\n", __FILE__, __LINE__);
93       pthread_mutex_unlock(&llookup.locktable);
94       return 1;
95     }
96     node->oid = oid;
97     node->mid = mid;
98     node->next = ptr[index].next;
99     ptr[index].next = node;
100   }
101
102   pthread_mutex_unlock(&llookup.locktable);
103   return 0;
104 }
105
106 // Return mid for a given oid in the hash table
107 unsigned int lhashSearch(unsigned int oid) {
108   int index;
109   lhashlistnode_t *ptr, *node;
110
111   ptr = llookup.table;          // Address of the beginning of hash table
112   index = lhashFunction(oid);
113   node = &ptr[index];
114   pthread_mutex_lock(&llookup.locktable);
115   while(node != NULL) {
116     if(node->oid == oid) {
117       pthread_mutex_unlock(&llookup.locktable);
118       return node->mid;
119     }
120     node = node->next;
121   }
122   pthread_mutex_unlock(&llookup.locktable);
123   return 0;
124 }
125
126 // Remove an entry from the hash table
127 unsigned int lhashRemove(unsigned int oid) {
128   int index;
129   lhashlistnode_t *curr, *prev;
130   lhashlistnode_t *ptr, *node;
131
132   ptr = llookup.table;
133   index = lhashFunction(oid);
134   curr = &ptr[index];
135
136   pthread_mutex_lock(&llookup.locktable);
137   for (; curr != NULL; curr = curr->next) {
138     if (curr->oid == oid) {                     // Find a match in the hash table
139       llookup.numelements--;                    // Decrement the number of elements in the global hashtable
140       if ((curr == &ptr[index]) && (curr->next == NULL)) {                    // Delete the first item inside the hashtable with no linked list of lhashlistnode_t
141         curr->oid = 0;
142         curr->mid = 0;
143       } else if ((curr == &ptr[index]) && (curr->next != NULL)) {                   //Delete the first item with a linked list of lhashlistnode_t  connected
144         curr->oid = curr->next->oid;
145         curr->mid = curr->next->mid;
146         node = curr->next;
147         curr->next = curr->next->next;
148         free(node);
149       } else {                                                                  // Regular delete from linked listed
150         prev->next = curr->next;
151         free(curr);
152       }
153       pthread_mutex_unlock(&llookup.locktable);
154       return 0;
155     }
156     prev = curr;
157   }
158   pthread_mutex_unlock(&llookup.locktable);
159   return 1;
160 }
161
162 // Resize table
163 unsigned int lhashResize(unsigned int newsize) {
164   lhashlistnode_t *node, *ptr, *curr, *next;            // curr and next keep track of the current and the next lhashlistnodes in a linked list
165   unsigned int oldsize;
166   int isfirst;          // Keeps track of the first element in the lhashlistnode_t for each bin in hashtable
167   int i,index;
168   lhashlistnode_t *newnode;
169
170   ptr = llookup.table;
171   oldsize = llookup.size;
172
173   if((node = calloc(newsize, sizeof(lhashlistnode_t))) == NULL) {
174     printf("Calloc error %s %d\n", __FILE__, __LINE__);
175     return 1;
176   }
177
178   llookup.table = node;                 //Update the global hashtable upon resize()
179   llookup.size = newsize;
180   llookup.numelements = 0;
181
182   for(i = 0; i < oldsize; i++) {                        //Outer loop for each bin in hash table
183     curr = &ptr[i];
184     isfirst = 1;
185     while (curr != NULL) {                              //Inner loop to go through linked lists
186       if (curr->oid == 0) {                             //Exit inner loop if there the first element for a given bin/index is NULL
187         break;                                          //oid = mid =0 for element if not present within the hash table
188       }
189       next = curr->next;
190       index = lhashFunction(curr->oid);
191       // Insert into the new table
192       if(llookup.table[index].next == NULL && llookup.table[index].oid == 0) {
193         llookup.table[index].oid = curr->oid;
194         llookup.table[index].mid = curr->mid;
195         llookup.numelements++;
196       } else {
197         if((newnode = calloc(1, sizeof(lhashlistnode_t))) == NULL) {
198           printf("Calloc error %s, %d\n", __FILE__, __LINE__);
199           return 1;
200         }
201         newnode->oid = curr->oid;
202         newnode->mid = curr->mid;
203         newnode->next = llookup.table[index].next;
204         llookup.table[index].next = newnode;
205         llookup.numelements++;
206       }
207
208       //free the linked list of lhashlistnode_t if not the first element in the hash table
209       if (isfirst != 1) {
210         free(curr);
211       }
212
213       isfirst = 0;
214       curr = next;
215
216     }
217   }
218
219   free(ptr);                    //Free the memory of the old hash table
220   return 0;
221 }
222
223 #endif
224