XRootD
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 
36 #include "XrdNet/XrdNetAddrInfo.hh"
37 #include "XrdNet/XrdNetCache.hh"
38 
39 /******************************************************************************/
40 /* S t a t i c M e m b e r s */
41 /******************************************************************************/
42 
43 int XrdNetCache::keepTime = 0;
44 
45 /******************************************************************************/
46 /* C o n s t r u c t o r */
47 /******************************************************************************/
48 
49 XrdNetCache::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 
63 void 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 
103 void 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 
189 int 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 
224 XrdNetCache::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)
Definition: XrdNetCache.cc:63
char * Find(XrdNetAddrInfo *hAddr)
Definition: XrdNetCache.cc:148
XrdNetCache(int psize=987, int csize=1597)
Definition: XrdNetCache.cc:49