00001 #include "packet_cache.h"
00002 #include "packet.h"
00003 #include <stdio.h>
00004 #include <string.h>
00005 #include <unistd.h>
00006 #include <stdlib.h>
00007
00008 pthread_mutex_t SavedMutex;
00009 int SaveLockID;
00010 SaveRec Saves[MAX_SAVES];
00011 SaveBin SBins[65536];
00012
00013 int SaveTimeHead;
00014 int SaveTimeTail;
00015
00016
00017 #define DEBUGLOCKS
00018
00019 extern GlobalVars Globals;
00020
00021
00022
00023
00024 int InitCache(){
00025 #ifdef DEBUGPATH
00026 printf("In InitCache\n");
00027 #endif
00028
00029 bzero(Saves, sizeof(SaveRec)*MAX_SAVES);
00030 bzero(SBins, sizeof(SaveBin)*65536);
00031
00032 return TRUE;
00033 }
00034
00035
00036
00037
00038
00039 unsigned short HashKey(char* Key, int KeyLen){
00040 unsigned short KeyHash;
00041 int i;
00042
00043 #ifdef DEBUGPATH
00044 printf("In HashKey\n");
00045 #endif
00046
00047 if (!Key){
00048 printf("Internal Error: Key was Null in HashKey\n");
00049 return 0;
00050 }
00051
00052 KeyHash=0;
00053 for (i=0;i<KeyLen/2;i++){
00054 KeyHash=KeyHash^((unsigned short*)Key)[i];
00055 }
00056 if (KeyLen%2) KeyHash=KeyHash+Key[KeyLen-1];
00057
00058 return KeyHash;
00059 }
00060
00061
00062
00063
00064
00065 void FreeSaved(int SaveID){
00066 unsigned short KeyHash;
00067 SaveRec* s;
00068 int i,j;
00069
00070 #ifdef DEBUGPATH
00071 printf("in FreeSaved\n");
00072 #endif
00073
00074 #ifdef DEBUG
00075 printf("Removing a packet\n");
00076 #endif
00077
00078 s=&Saves[SaveID];
00079
00080
00081 if (SaveTimeHead==SaveID) SaveTimeHead=Saves[SaveID].NextTime;
00082 if (SaveTimeTail==SaveID) SaveTimeTail=Saves[SaveID].PrevTime;
00083
00084 if (s->PrevTime != -1){
00085 Saves[s->PrevTime].NextTime=s->NextTime;
00086 }
00087 if (s->NextTime != -1){
00088 Saves[s->NextTime].PrevTime=s->PrevTime;
00089 }
00090
00091
00092 KeyHash=HashKey(s->Key,s->KeyLen);
00093 for (i=0;i<SBins[KeyHash].NumInBin;i++){
00094 if (SBins[KeyHash].Items[i]==SaveID){
00095 for (j=i;j<SBins[KeyHash].NumInBin-1;j++){
00096 SBins[KeyHash].Items[j]=SBins[KeyHash].Items[j+1];
00097 SBins[KeyHash].NumInBin--;
00098 }
00099 }
00100 }
00101
00102
00103 Saves[SaveID].InUse=FALSE;
00104 free(Saves[SaveID].Key);
00105 Saves[SaveID].Key=NULL;
00106 Saves[SaveID].KeyLen=0;
00107 Saves[SaveID].NextTime=-1;
00108 Saves[SaveID].PrevTime=-1;
00109 hlbr_mutex_unlock(&Globals.Packets[Saves[SaveID].PacketSlot].Mutex);
00110 hlbr_mutex_unlock(&Saves[SaveID].Mutex);
00111
00112
00113 Globals.Packets[Saves[SaveID].PacketSlot].SaveCount--;
00114 ReturnEmptyPacket(Saves[SaveID].PacketSlot);
00115
00116
00117 Globals.SavedCount--;
00118 }
00119
00120
00121
00122
00123 void FreeSaveQuery(SaveQuery* q){
00124 int i;
00125 #ifdef DEBUGPATH
00126 printf("In FreeSaveQuery\n");
00127 #endif
00128
00129 if (!q) return;
00130
00131
00132 hlbr_mutex_lock(&SavedMutex, FREE_SAVED_1, &SaveLockID);
00133
00134 for (i=0;i<q->NumResults;i++){
00135 FreeSaved(q->Saves[i]);
00136 }
00137
00138 free(q);
00139
00140
00141 hlbr_mutex_unlock(&SavedMutex);
00142 }
00143
00144
00145
00146
00147
00148 void TimeoutSavedPackets(long CurTime){
00149 int This;
00150 int DelPacket;
00151
00152 #ifdef DEBUGPATH
00153 printf("In TimeoutSavedPackets\n");
00154 #endif
00155
00156
00157 if (Globals.SavedCount==0) return;
00158
00159 DelPacket=-1;
00160 This=SaveTimeHead;
00161 while (This!=-1){
00162 hlbr_mutex_lock(&Saves[This].Mutex, TIMEOUT_SAVED_1, &Saves[This].LockID);
00163 if (CurTime > Saves[This].Timeout){
00164 FreeSaved(This);
00165 hlbr_mutex_unlock(&Saves[This].Mutex);
00166 This=SaveTimeHead;
00167 }else{
00168 #ifdef DEBUG
00169 printf("Didn't need to be timed out\n");
00170 #endif
00171 hlbr_mutex_unlock(&Saves[This].Mutex);
00172 return;
00173 }
00174 }
00175 }
00176
00177
00178
00179
00180
00181
00182
00183 int GetFreeSaved(){
00184 int i;
00185 #ifdef DEBUGPATH
00186 printf("in GetFreeSaved\n");
00187 #endif
00188 for (i=0;i<MAX_SAVES;i++){
00189 if (!Saves[i].InUse) return i;
00190 }
00191
00192 return -1;
00193 }
00194
00195
00196
00197
00198 int SavePacket(int PacketSlot, char* Key, int KeyLen, int Timeout){
00199 unsigned short KeyHash;
00200 int SaveID;
00201
00202 #ifdef DEBUGPATH
00203 printf("In SavePacket\n");
00204 #endif
00205
00206 hlbr_mutex_lock(&SavedMutex, SAVE_PACKET_1, &SaveLockID);
00207 TimeoutSavedPackets(Globals.Packets[PacketSlot].tv.tv_sec);
00208 hlbr_mutex_lock(&Globals.Packets[PacketSlot].Mutex, SAVE_PACKET_2, &Globals.Packets[PacketSlot].LockID);
00209
00210
00211 if ( (SaveID=GetFreeSaved())==-1){
00212 printf("There are no free save records\n");
00213 hlbr_mutex_unlock(&SavedMutex);
00214 return FALSE;
00215 }
00216
00217 Saves[SaveID].InUse=TRUE;
00218 Saves[SaveID].Key=malloc(KeyLen+1);
00219 memcpy(Saves[SaveID].Key, Key, KeyLen);
00220 Saves[SaveID].KeyLen=KeyLen;
00221 Saves[SaveID].PacketSlot=PacketSlot;
00222 Saves[SaveID].Timeout=Globals.Packets[PacketSlot].tv.tv_sec+Timeout;
00223
00224
00225 if (SaveTimeHead==-1){
00226 #ifdef DEBUG
00227 printf("First Packet into the cache\n");
00228 #endif
00229 SaveTimeHead=SaveID;
00230 SaveTimeTail=SaveID;
00231 }else{
00232 Saves[SaveTimeTail].NextTime=SaveID;
00233 SaveTimeTail=SaveID;
00234 }
00235
00236
00237 KeyHash=HashKey(Key, KeyLen);
00238
00239 if (SBins[KeyHash].NumInBin==MAX_SAVES_PER_BIN){
00240 printf("No more room in this bin\n");
00241
00242 }else{
00243 SBins[KeyHash].Items[SBins[KeyHash].NumInBin]=SaveID;
00244 SBins[KeyHash].NumInBin++;
00245 }
00246
00247
00248 Globals.Packets[PacketSlot].SaveCount++;
00249
00250
00251 hlbr_mutex_unlock(&Globals.Packets[PacketSlot].Mutex);
00252 hlbr_mutex_unlock(&SavedMutex);
00253
00254 return TRUE;
00255 }
00256
00257
00258
00259
00260 SaveQuery* GetAndLockSavedPackets(char* Key, int KeyLen){
00261 unsigned short KeyHash;
00262 SaveQuery* q;
00263 int i;
00264 SaveRec* s;
00265
00266 #ifdef DEBUGPATH
00267 printf("In GetAndLockSavedPackets\n");
00268 #endif
00269
00270
00271 KeyHash=HashKey(Key, KeyLen);
00272 q=calloc(sizeof(SaveQuery),1);
00273 q->NumResults=0;
00274
00275
00276 hlbr_mutex_lock(&SavedMutex, GET_SAVED_1, &SaveLockID);
00277
00278
00279 for (i=0;i<SBins[KeyHash].NumInBin;i++){
00280 s=&Saves[SBins[KeyHash].Items[i]];
00281
00282 if (s->KeyLen==KeyLen)
00283 if (memcmp(s->Key, Key, KeyLen)==0){
00284 hlbr_mutex_lock(&s->Mutex, GET_SAVED_2, &s->LockID);
00285 hlbr_mutex_lock(&Globals.Packets[s->PacketSlot].Mutex, GET_SAVED_3, &Globals.Packets[s->PacketSlot].LockID);
00286
00287 q->Saves[q->NumResults]=SBins[KeyHash].Items[i];
00288 q->Packets[q->NumResults]=s->PacketSlot;
00289 q->NumResults++;
00290
00291 if (q->NumResults==MAX_QUERY_RESULTS){
00292 #ifdef DEBUG
00293 printf("Too Many results to fit in struct\n");
00294 #endif
00295 hlbr_mutex_unlock(&SavedMutex);
00296 return q;
00297 }
00298 }
00299 }
00300
00301
00302 hlbr_mutex_unlock(&SavedMutex);
00303
00304 #ifdef DEBUG
00305 printf("Query Returned %i results\n",q->NumResults);
00306 #endif
00307
00308 return q;
00309 }
00310
00311
00312
00313
00314 void UnlockSavedQuery(SaveQuery* q){
00315 int i;
00316 #ifdef DEBUGPATH
00317 printf("in UnlockSavedQuery\n");
00318 #endif
00319
00320 if (!q) return;
00321
00322
00323 hlbr_mutex_lock(&SavedMutex, UNLOCK_SAVED_1, &SaveLockID);
00324
00325
00326 for (i=0;i<q->NumResults;i++){
00327 hlbr_mutex_unlock(&Globals.Packets[Saves[q->Saves[i]].PacketSlot].Mutex);
00328 hlbr_mutex_unlock(&Saves[q->Saves[i]].Mutex);
00329 }
00330
00331
00332 hlbr_mutex_unlock(&SavedMutex);
00333
00334 free(q);
00335 }
00336