XRootD
Loading...
Searching...
No Matches
XrdNetCache.cc
Go to the documentation of this file.
1/******************************************************************************/
2/* */
3/* X r d N e t C a c h e . c c */
4/* */
5/* (c) 2013 by the Board of Trustees of the Leland Stanford, Jr., University */
6/* All Rights Reserved */
7/* Produced by Andrew Hanushevsky for Stanford University under contract */
8/* DE-AC02-76-SFO0515 with the Department of Energy */
9/* */
10/* This file is part of the XRootD software suite. */
11/* */
12/* XRootD is free software: you can redistribute it and/or modify it under */
13/* the terms of the GNU Lesser General Public License as published by the */
14/* Free Software Foundation, either version 3 of the License, or (at your */
15/* option) any later version. */
16/* */
17/* XRootD is distributed in the hope that it will be useful, but WITHOUT */
18/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */
19/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public */
20/* License for more details. */
21/* */
22/* You should have received a copy of the GNU Lesser General Public License */
23/* along with XRootD in a file called COPYING.LESSER (LGPL license) and file */
24/* COPYING (GPL license). If not, see <http://www.gnu.org/licenses/>. */
25/* */
26/* The copyright holder's institutional names and contributor's names may not */
27/* be used to endorse or promote products derived from this software without */
28/* specific prior written permission of the institution or contributor. */
29/******************************************************************************/
30
31#include <cstdlib>
32#include <ctime>
33#include <sys/socket.h>
34#include <sys/types.h>
35
37#include "XrdNet/XrdNetCache.hh"
38
39/******************************************************************************/
40/* S t a t i c M e m b e r s */
41/******************************************************************************/
42
43int XrdNetCache::keepTime = 0;
44
45/******************************************************************************/
46/* C o n s t r u c t o r */
47/******************************************************************************/
48
49XrdNetCache::XrdNetCache(int psize, int csize)
50{
51 prevtablesize = psize;
52 nashtablesize = csize;
53 Threshold = (csize * LoadMax) / 100;
54 nashnum = 0;
55 nashtable = (anItem **)malloc( (size_t)(csize*sizeof(anItem *)) );
56 memset((void *)nashtable, 0, (size_t)(csize*sizeof(anItem *)));
57}
58
59/******************************************************************************/
60/* public A d d */
61/******************************************************************************/
62
63void XrdNetCache::Add(XrdNetAddrInfo *hAddr, const char *hName)
64{
65 anItem Item, *hip;
66 int kent;
67
68// Get the key and make sure this is a valid address (should be)
69//
70 if (!GenKey(Item, hAddr)) return;
71
72// We may be in a race condition, check we have this item
73//
74 myMutex.Lock();
75 if ((hip = Locate(Item)))
76 {if (hip->hName) free(hip->hName);
77 hip->hName = strdup(hName);
78 hip->expTime = time(0) + keepTime;
79 myMutex.UnLock();
80 return;
81 }
82
83// Check if we should expand the table
84//
85 if (++nashnum > Threshold) Expand();
86
87// Allocate a new entry
88//
89 hip = new anItem(Item, hName, keepTime);
90
91// Add the entry to the table
92//
93 kent = hip->aHash % nashtablesize;
94 hip->Next = nashtable[kent];
95 nashtable[kent] = hip;
96 myMutex.UnLock();
97}
98
99/******************************************************************************/
100/* private E x p a n d */
101/******************************************************************************/
102
103void XrdNetCache::Expand()
104{
105 int newsize, newent, i;
106 size_t memlen;
107 anItem **newtab, *nip, *nextnip;
108
109// Compute new size for table using a fibonacci series
110//
111 newsize = prevtablesize + nashtablesize;
112
113// Allocate the new table
114//
115 memlen = (size_t)(newsize*sizeof(anItem *));
116 if (!(newtab = (anItem **) malloc(memlen))) return;
117 memset((void *)newtab, 0, memlen);
118
119// Redistribute all of the current items
120//
121 for (i = 0; i < nashtablesize; i++)
122 {nip = nashtable[i];
123 while(nip)
124 {nextnip = nip->Next;
125 newent = nip->aHash % newsize;
126 nip->Next = newtab[newent];
127 newtab[newent] = nip;
128 nip = nextnip;
129 }
130 }
131
132// Free the old table and plug in the new table
133//
134 free((void *)nashtable);
135 nashtable = newtab;
136 prevtablesize = nashtablesize;
137 nashtablesize = newsize;
138
139// Compute new expansion threshold
140//
141 Threshold = static_cast<int>((static_cast<long long>(newsize)*LoadMax)/100);
142}
143
144/******************************************************************************/
145/* public F i n d */
146/******************************************************************************/
147
149{
150 anItem Item, *nip, *pip = 0;
151 int kent;
152
153// Get the hash for this address
154//
155 if (!GenKey(Item, hAddr)) return 0;
156
157// Compute position of the hash table entry
158//
159 myMutex.Lock();
160 kent = Item.aHash%nashtablesize;
161
162// Find the entry
163//
164 nip = nashtable[kent];
165 while(nip && *nip != Item) {pip = nip; nip = nip->Next;}
166 if (!nip) {myMutex.UnLock(); return 0;}
167
168// Make sure entry has not expired
169//
170 if (nip->expTime > time(0))
171 {char *hName = strdup(nip->hName);
172 myMutex.UnLock();
173 return hName;
174 }
175
176// Remove the entry and return not found
177//
178 if (pip) pip->Next = nip->Next;
179 else nashtable[kent] = nip->Next;
180 myMutex.UnLock();
181 delete nip;
182 return 0;
183}
184
185/******************************************************************************/
186/* G e n K e y */
187/******************************************************************************/
188
189int XrdNetCache::GenKey(XrdNetCache::anItem &Item, XrdNetAddrInfo *hAddr)
190{
191 union aPoint
192 {const sockaddr *sAddr;
193 const sockaddr_in *sAddr4;
194 const sockaddr_in6 *sAddr6;
195 } aP;
196 aP.sAddr = hAddr->SockAddr();
197 union{long long llVal; int intVal[2];} Temp;
198 int family = hAddr->Family();
199
200// Get the size, validate, and generate the key
201//
202 if (family == AF_INET)
203 {memcpy(Item.aVal, &(aP.sAddr4->sin_addr), 4);
204 Item.aHash = Item.aV4[0];
205 Item.aLen = 4;
206 return 1;
207 }
208
209 if (family == AF_INET6)
210 {memcpy(Item.aVal, &(aP.sAddr6->sin6_addr), 16);
211 Temp.llVal = Item.aV6[0] ^ Item.aV6[1];
212 Item.aHash = Temp.intVal[0] ^ Temp.intVal[1];
213 Item.aLen = 16;
214 return 1;
215 }
216
217 return 0;
218}
219
220/******************************************************************************/
221/* Private: L o c a t e */
222/******************************************************************************/
223
224XrdNetCache::anItem *XrdNetCache::Locate(XrdNetCache::anItem &Item)
225{
226 anItem *nip;
227 unsigned int kent;
228
229// Find the entry
230//
231 kent = Item.aHash%nashtablesize;
232 nip = nashtable[kent];
233 while(nip && *nip != Item) nip = nip->Next;
234 return nip;
235}
const sockaddr * SockAddr()
int Family() const
void Add(XrdNetAddrInfo *hAddr, const char *hName)
char * Find(XrdNetAddrInfo *hAddr)
XrdNetCache(int psize=987, int csize=1597)