Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygennbnamecache.c
Go to the documentation of this file.
00001 /* Copyright (c) 2003 Juan Lang 00002 * 00003 * This library is free software; you can redistribute it and/or 00004 * modify it under the terms of the GNU Lesser General Public 00005 * License as published by the Free Software Foundation; either 00006 * version 2.1 of the License, or (at your option) any later version. 00007 * 00008 * This library is distributed in the hope that it will be useful, 00009 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00010 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00011 * Lesser General Public License for more details. 00012 * 00013 * You should have received a copy of the GNU Lesser General Public 00014 * License along with this library; if not, write to the Free Software 00015 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 00016 * 00017 * This implementation uses a linked list, because I don't have a decent 00018 * hash table implementation handy. This is somewhat inefficient, but it's 00019 * rather more efficient than not having a name cache at all. 00020 */ 00021 00022 #include "config.h" 00023 #include "wine/port.h" 00024 00025 #include "nbnamecache.h" 00026 00027 typedef struct _NBNameCacheNode 00028 { 00029 DWORD expireTime; 00030 NBNameCacheEntry *entry; 00031 struct _NBNameCacheNode *next; 00032 } NBNameCacheNode; 00033 00034 struct NBNameCache 00035 { 00036 HANDLE heap; 00037 CRITICAL_SECTION cs; 00038 DWORD entryExpireTimeMS; 00039 NBNameCacheNode *head; 00040 }; 00041 00042 /* Unlinks the node pointed to by *prev, and frees any associated memory. 00043 * If that node's next pointed to another node, *prev now points to it. 00044 * Assumes the caller owns cache's lock. 00045 */ 00046 static void NBNameCacheUnlinkNode(struct NBNameCache *cache, 00047 NBNameCacheNode **prev) 00048 { 00049 if (cache && prev && *prev) 00050 { 00051 NBNameCacheNode *next = (*prev)->next; 00052 00053 HeapFree(cache->heap, 0, (*prev)->entry); 00054 HeapFree(cache->heap, 0, *prev); 00055 *prev = next; 00056 } 00057 } 00058 00059 /* Walks the list beginning with cache->head looking for the node with name 00060 * name. If the node is found, returns a pointer to the next pointer of the 00061 * node _prior_ to the found node (or head if head points to it). Thus, if the 00062 * node's all you want, dereference the return value twice. If you want to 00063 * modify the list, modify the referent of the return value. 00064 * While it's at it, deletes nodes whose time has expired (except the node 00065 * you're looking for, of course). 00066 * Returns NULL if the node isn't found. 00067 * Assumes the caller owns cache's lock. 00068 */ 00069 static NBNameCacheNode **NBNameCacheWalk(struct NBNameCache *cache, 00070 const char name[NCBNAMSZ]) 00071 { 00072 NBNameCacheNode **ret = NULL; 00073 00074 if (cache && cache->head) 00075 { 00076 NBNameCacheNode **ptr; 00077 00078 ptr = &cache->head; 00079 while (ptr && *ptr && (*ptr)->entry) 00080 { 00081 if (!memcmp((*ptr)->entry->name, name, NCBNAMSZ - 1)) 00082 ret = ptr; 00083 else 00084 { 00085 if (GetTickCount() > (*ptr)->expireTime) 00086 NBNameCacheUnlinkNode(cache, ptr); 00087 } 00088 if (*ptr) 00089 ptr = &(*ptr)->next; 00090 } 00091 } 00092 return ret; 00093 } 00094 00095 struct NBNameCache *NBNameCacheCreate(HANDLE heap, DWORD entryExpireTimeMS) 00096 { 00097 struct NBNameCache *cache; 00098 00099 00100 if (!heap) 00101 heap = GetProcessHeap(); 00102 cache = HeapAlloc(heap, 0, sizeof(struct NBNameCache)); 00103 if (cache) 00104 { 00105 cache->heap = heap; 00106 InitializeCriticalSection(&cache->cs); 00107 cache->cs.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": NBNameCache.cs"); 00108 cache->entryExpireTimeMS = entryExpireTimeMS; 00109 cache->head = NULL; 00110 } 00111 return cache; 00112 } 00113 00114 BOOL NBNameCacheAddEntry(struct NBNameCache *cache, NBNameCacheEntry *entry) 00115 { 00116 BOOL ret; 00117 00118 if (cache && entry) 00119 { 00120 NBNameCacheNode **node; 00121 00122 EnterCriticalSection(&cache->cs); 00123 node = NBNameCacheWalk(cache, (char*)entry->name); 00124 if (node) 00125 { 00126 (*node)->expireTime = GetTickCount() + 00127 cache->entryExpireTimeMS; 00128 HeapFree(cache->heap, 0, (*node)->entry); 00129 (*node)->entry = entry; 00130 ret = TRUE; 00131 } 00132 else 00133 { 00134 NBNameCacheNode *newNode = HeapAlloc(cache->heap, 0, sizeof(NBNameCacheNode)); 00135 if (newNode) 00136 { 00137 newNode->expireTime = GetTickCount() + 00138 cache->entryExpireTimeMS; 00139 newNode->entry = entry; 00140 newNode->next = cache->head; 00141 cache->head = newNode; 00142 ret = TRUE; 00143 } 00144 else 00145 ret = FALSE; 00146 } 00147 LeaveCriticalSection(&cache->cs); 00148 } 00149 else 00150 ret = FALSE; 00151 return ret; 00152 } 00153 00154 const NBNameCacheEntry *NBNameCacheFindEntry(struct NBNameCache *cache, 00155 const UCHAR name[NCBNAMSZ]) 00156 { 00157 const NBNameCacheEntry *ret; 00158 UCHAR printName[NCBNAMSZ]; 00159 00160 memcpy(printName, name, NCBNAMSZ - 1); 00161 printName[NCBNAMSZ - 1] = '\0'; 00162 if (cache) 00163 { 00164 NBNameCacheNode **node; 00165 00166 EnterCriticalSection(&cache->cs); 00167 node = NBNameCacheWalk(cache, (const char *)name); 00168 if (node) 00169 ret = (*node)->entry; 00170 else 00171 ret = NULL; 00172 LeaveCriticalSection(&cache->cs); 00173 } 00174 else 00175 ret = NULL; 00176 return ret; 00177 } 00178 00179 void NBNameCacheDestroy(struct NBNameCache *cache) 00180 { 00181 if (cache) 00182 { 00183 cache->cs.DebugInfo->Spare[0] = 0; 00184 DeleteCriticalSection(&cache->cs); 00185 while (cache->head) 00186 NBNameCacheUnlinkNode(cache, &cache->head); 00187 HeapFree(cache->heap, 0, cache); 00188 } 00189 } Generated on Sun May 27 2012 04:25:27 for ReactOS by
1.7.6.1
|