packets/packet_cache.c

Go to the documentation of this file.
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 //#define DEBUG
00017 #define DEBUGLOCKS
00018 
00019 extern GlobalVars       Globals;
00020 
00021 /*********************************
00022 * Get ready for some caching
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 * Calculate the hash of this key
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 * We no longer need this one
00063 * Assumes the caller locks and unlocks everything
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         /*Take it off the time chain*/
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         /*take it out of the bin*/
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         /*Mark it as free*/
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         /*return the packet into distribution*/
00113         Globals.Packets[Saves[SaveID].PacketSlot].SaveCount--;
00114         ReturnEmptyPacket(Saves[SaveID].PacketSlot);
00115 
00116         /*unlock the saved structs*/
00117         Globals.SavedCount--;
00118 }
00119 
00120 /**********************************************************
00121 * We no longer need these packets
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         /*lock the saved structs*/
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         /*unlock the saved structs*/
00141         hlbr_mutex_unlock(&SavedMutex);
00142 }
00143 
00144 /********************************************
00145 * timeout anybody that needs it
00146 * Assumes the caller locks everything
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         /*check to see if there is anything to time out*/
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 * Go and find a free saved record
00179 *
00180 * This is the absolutely slowest way to do 
00181 * this.
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 * Save a packet for later
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         /*Create a record to hold the new packet*/
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         /*push the packet onto the time list*/
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         /*put the SaveRec into the index*/
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                 /*TODO: free up everything*/
00242         }else{
00243                 SBins[KeyHash].Items[SBins[KeyHash].NumInBin]=SaveID;
00244                 SBins[KeyHash].NumInBin++;
00245         }
00246         
00247         /*increment the save count*/
00248         Globals.Packets[PacketSlot].SaveCount++;
00249         
00250         /*unlock the save structures*/
00251         hlbr_mutex_unlock(&Globals.Packets[PacketSlot].Mutex);
00252         hlbr_mutex_unlock(&SavedMutex);
00253         
00254         return TRUE;
00255 }
00256 
00257 /**********************************************************
00258 * Query for a particular key
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         /*Set up the query*/
00271         KeyHash=HashKey(Key, KeyLen);
00272         q=calloc(sizeof(SaveQuery),1);
00273         q->NumResults=0;
00274         
00275         /*Lock the saved structs*/
00276         hlbr_mutex_lock(&SavedMutex, GET_SAVED_1, &SaveLockID);
00277         
00278         /*perform the query*/
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         /*unlock the saved structs*/
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 * Unlock everything, but keep saving the packets
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         /*lock the saved structs*/
00323         hlbr_mutex_lock(&SavedMutex, UNLOCK_SAVED_1, &SaveLockID);
00324         
00325         /*iterate through and unlock*/
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         /*unlock the saved structs*/
00332         hlbr_mutex_unlock(&SavedMutex);
00333         
00334         free(q);
00335 }
00336 

Generated on Sat Jul 7 23:33:10 2007 for HLBR by  doxygen 1.5.2