XRootD
Loading...
Searching...
No Matches
XrdNetRegistry.cc
Go to the documentation of this file.
1/******************************************************************************/
2/* */
3/* X r d N e t R e g i s t r y . c c */
4/* */
5/* (c) 2020 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 <string>
32#include <vector>
33
34#include "XrdNet/XrdNetAddr.hh"
37
38/******************************************************************************/
39/* L o c a l C l a s s e s */
40/******************************************************************************/
41
42namespace
43{
44class regEntry
45{
46public:
47
48static regEntry *first;
49regEntry *next;
50regEntry *parent;
51std::string hName;
52std::vector<std::string> hVec;
53uint8_t refs;
54bool rotate;
55
56static void Add(regEntry *rP) {rP->next = first; first = rP;}
57
58static
59regEntry *Find(const char *hName)
60 {regEntry *rP = first;
61 while(rP && (hName != rP->hName)) rP = rP->next;
62 if (rP && rP->parent) return rP->parent;
63 return rP;
64 }
65
66 void Hold(bool want)
67 {if (want) myLock.ReadLock();
68 else myLock.UnLock();
69 }
70
71 void Update(const char **hlist, int hlnum, bool rot)
72 {myLock.WriteLock();
73 hVec.assign(hlist, hlist+hlnum);
74 rotate = rot;
75 myLock.UnLock();
76 }
77
78 regEntry(const char *hname, regEntry *pP)
79 : next(0), parent(pP), hName(hname), refs(0),
80 rotate(false) {}
81
82 regEntry(const char *hname, const char *hlist[], int hlnum, bool rot)
83 : next(0), parent(0), hName(hname), refs(0), rotate(rot)
84 {hVec.assign(hlist, hlist+hlnum);}
85
86 ~regEntry() {}
87
88private:
89
90XrdSysRWLock myLock;
91};
92
93regEntry *regEntry::first = 0;
94
95}
96
97/******************************************************************************/
98/* L o c a l S t a t i c O b j e c t s */
99/******************************************************************************/
100
101namespace
102{
103XrdSysMutex regMutex;
104}
105
106/******************************************************************************/
107/* G e t A d d r s */
108/******************************************************************************/
109
110const char *XrdNetRegistry::GetAddrs(const std::string &hSpec,
111 std::vector<XrdNetAddr> &aVec, int *ordn,
112 XrdNetUtils::AddrOpts opts, int pNum)
113{
114 regEntry *reP;
115 unsigned int refs;
116
117// Find the entry
118//
119 XrdSysMutexHelper mHelp(regMutex);
120 if (!(reP = regEntry::Find(hSpec.c_str())))
121 {aVec.clear();
122 return "pseudo host not registered";
123 }
124
125// Hold this entry as we don't want to hold the global lock doing DNS lookups.
126//
127 if (reP->rotate) refs = reP->refs++;
128 else refs = 0;
129 reP->Hold(true);
130 mHelp.UnLock();
131
132// Resolve the the host specification (at least one must be resolvable)
133//
134 XrdNetUtils::GetAddrs(reP->hVec, aVec, ordn, opts, refs, true);
135
136// Drop the hold on the entry and return result
137//
138 reP->Hold(false);
139 if (aVec.size() == 0) return "registry entry unresolvable";
140 return 0;
141}
142
143/******************************************************************************/
144/* R e g i s t e r */
145/******************************************************************************/
146
147bool XrdNetRegistry::Register(const char *hName,
148 const char *hList[], int hLNum,
149 std::string *eText, bool rotate)
150{
151 regEntry *reP;
152
153// Make sure we have valid parameters
154//
155 if (!hName || *hName != pfx || !hList || hLNum <= 0)
156 {if (eText) *eText = "invalid calling arguments";
157 return false;
158 }
159
160// Run through the list resolving all of the addresses. When registering, all
161// of them must be resolvable. When running at least one must be resolvable.
162//
163 for (int i = 0; i < hLNum; i++) if (!Resolve(hList[i], eText)) return false;
164
165// Do replacement or addition
166//
167 regMutex.Lock();
168 if ((reP = regEntry::Find(hName))) reP->Update(hList, hLNum, rotate);
169 else regEntry::Add(new regEntry(hName, hList, hLNum, rotate));
170 regMutex.UnLock();
171
172// All done
173//
174 return true;
175}
176
177/******************************************************************************/
178
179bool XrdNetRegistry::Register(const char *hName, const char *hList,
180 std::string *eText, bool rotate)
181{
182 char *comma, *hosts = strdup(hList);
183 std::vector<const char*> hVec;
184
185// Make sure we have valid parameters
186//
187 if (!hName || *hName != pfx || !hList)
188 {if (eText) *eText = "invalid calling arguments";
189 return 0;
190 }
191
192// Check for alias creation
193//
194 if (*hList == pfx) return SetAlias(hName, hList, eText);
195
196// Construct a vector of contacts
197//
198 hVec.reserve(16);
199 hVec.push_back(hosts);
200 comma = hosts;
201 while((comma = index(comma, ',')))
202 {*comma++ = 0;
203 hVec.push_back(comma);
204 }
205
206// Verify that each element has a colon in it
207//
208 for (int i = 0; i < (int)hVec.size(); i++)
209 {if (!index(hVec[i], ':'))
210 {if (eText)
211 {*eText = "port missing for '";
212 *eText += hVec[i]; *eText += "'";
213 }
214 free(hosts);
215 return false;
216 }
217 }
218
219// Register this contact
220//
221 bool aOK = Register(hName, hVec.data(), (int)hVec.size(), eText, rotate);
222
223// Cleanup and return result
224//
225 free(hosts);
226 return aOK;
227}
228
229/******************************************************************************/
230/* Private: R e s o l v e */
231/******************************************************************************/
232
233bool XrdNetRegistry::Resolve(const char *hSpec, std::string *eText)
234{
235 XrdNetAddr netAddr;
236 const char *emsg;
237
238// Validate the specification.
239//
240 emsg = netAddr.Set(hSpec);
241
242// Check for errors
243//
244 if (emsg && strncmp(emsg, "Dynamic ", 8))
245 {if (eText)
246 {*eText = "unable to resolve '"; *eText += hSpec;
247 *eText += "'; "; *eText += emsg;
248 }
249 return false;
250 }
251
252
253// All done
254//
255 return true;
256}
257
258/******************************************************************************/
259/* Private: S e t A l i a s */
260/******************************************************************************/
261
262bool XrdNetRegistry::SetAlias(const char *hAlias, const char *hName,
263 std::string *eText)
264{
265 regEntry *reP;
266 const char *eWhy = 0;
267
268// Verify that the source does not exist and the target does
269//
270 regMutex.Lock();
271 if (regEntry::Find(hAlias)) eWhy = "source already exists";
272 else if (!(reP = regEntry::Find(hName))) eWhy = "target does not exist";
273 if (eWhy)
274 {regMutex.UnLock();
275 if (eText)
276 {*eText = "alias "; *eText += hAlias; *eText += " not created; ";
277 *eText += eWhy;
278 }
279 return false;
280 }
281
282// Add the alias
283//
284 regEntry::Add(new regEntry(hAlias,reP));
285 regMutex.UnLock();
286 return true;
287}
struct myOpts opts
int emsg(int rc, char *msg)
const char * Set(const char *hSpec, int pNum=PortInSpec)
static bool Register(const char *hName, const char *hList[], int hLNum, std::string *eText=0, bool rotate=false)
static const char * GetAddrs(const std::string &hSpec, std::vector< XrdNetAddr > &aVec, int *ordn=0, XrdNetUtils::AddrOpts opts=XrdNetUtils::allIPMap, int pNum=XrdNetUtils::PortInSpec)
static const char pfx
Registry names must start with this character.
static const char * GetAddrs(const char *hSpec, XrdNetAddr *aListP[], int &aListN, AddrOpts opts=allIPMap, int pNum=PortInSpec)