XRootD
XrdCmsManList.cc
Go to the documentation of this file.
1 /******************************************************************************/
2 /* */
3 /* X r d C m s M a n L i s t . c c */
4 /* */
5 /* (c) 2011 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 <cctype>
32 #include <cstdio>
33 #include <unistd.h>
34 
35 #include "XrdCms/XrdCmsManList.hh"
36 #include "XrdNet/XrdNetAddr.hh"
37 #include "XrdOuc/XrdOucTList.hh"
39 #include "XrdSys/XrdSysPlatform.hh"
40 
41 /******************************************************************************/
42 /* L o c a l C l a s s e s */
43 /******************************************************************************/
44 
46 {
47 public:
48 
50 char *Manager;
51 unsigned int ManRef;
52 int ManPort;
53 int ManLvl;
54 
55  XrdCmsManRef(unsigned int ref, char *name, int port, int lvl)
56  : Next(0), Manager(name), ManRef(ref),
57  ManPort(port), ManLvl(lvl) {};
58 
59  ~XrdCmsManRef() {if (Manager) free(Manager);}
60 };
61 
62 /******************************************************************************/
63 /* D e s t r u c t o r */
64 /******************************************************************************/
65 
67 {
68  XrdCmsManRef *prp, *mrp = allMans;
69 
70  while(mrp) {prp = mrp; mrp = mrp->Next; delete prp;}
71 }
72 
73 
74 /******************************************************************************/
75 /* A d d */
76 /******************************************************************************/
77 
78 void XrdCmsManList::Add(const XrdNetAddr *netAddr, char *redList,
79  int manPort, int lvl)
80 {
81  XrdOucTokenizer hList((char *)redList);
82  char *hP;
83  int theRef;
84 
85 // Get the manager's reference number and if exists, delete existing entries
86 //
87  if ((theRef = getRef(netAddr)) >= 0) Del(theRef);
88  else theRef = -theRef;
89 
90 // Add eeach redirect target in the list
91 //
92  hP = hList.GetLine();
93  while((hP = hList.GetToken())) Add(theRef, hP, manPort, lvl);
94 }
95 
96 /******************************************************************************/
97 
98 void XrdCmsManList::Add(int ref, char *manp, int manport, int lvl)
99 {
100  XrdCmsManRef *prp = 0, *mrp;
101  char *cp, *ipname;
102  int port;
103 
104 // Find the colon in the host name
105 //
106  if (*manp != '[') cp = index(manp, int(':'));
107  else if ((cp = index(manp+1, ']'))) cp = index(cp+1, int(':'));
108  if (!cp) port = manport;
109  else {if (!(port=atoi(cp+1)) || port > 0xffff) port=manport;
110  *cp = '\0';
111  }
112 
113 // Get the full name of the host target unless it is an actual address
114 //
115  if (XrdNetAddrInfo::isHostName(manp)) ipname = strdup(manp);
116  else {XrdNetAddr redAddr;
117  const char *redName;
118  if (redAddr.Set(manp,0) || !(redName = redAddr.Name())) return;
119  ipname = strdup(redName);
120  }
121  if (cp) *cp = ':';
122 
123 // Start up
124 //
125  mlMutex.Lock();
126  mrp = allMans;
127 
128 // Chck if this is a duplicate
129 //
130  while(mrp)
131  {if (!strcmp(mrp->Manager, ipname) && mrp->ManPort == port)
132  {mlMutex.UnLock(); free(ipname); return;}
133  if (mrp->Next)
134  {if (mrp->Next->ManLvl > lvl) prp = mrp;}
135  else if (!prp) prp = mrp;
136  mrp = mrp->Next;
137  }
138 
139 // Create new entry
140 //
141  mrp = new XrdCmsManRef(ref, ipname, port, lvl);
142  if (!prp) nextMan = allMans = mrp;
143  else {mrp->Next = prp->Next; prp->Next = mrp;
144  if (nextMan->ManLvl > lvl) nextMan = mrp;
145  }
146  mlMutex.UnLock();
147 }
148 
149 /******************************************************************************/
150 /* D e l */
151 /******************************************************************************/
152 
153 void XrdCmsManList::Del(int ref)
154 {
155  XrdCmsManRef *nrp, *prp = 0, *mrp;
156 
157 // If mistakingly called for a newly added reference, do nothing
158 //
159  if (ref < 0) return;
160 
161 // Start up
162 //
163  mlMutex.Lock();
164  mrp = allMans;
165 
166 // Delete all ref entries
167 //
168  while(mrp)
169  {if (mrp->ManRef == (unsigned int)ref)
170  {nrp = mrp->Next;
171  if (!prp) allMans = nrp;
172  else {prp->Next = nrp;
173  if (mrp == allMans) allMans = nrp;
174  }
175  if (mrp == nextMan) nextMan = nrp;
176  delete mrp;
177  mrp = nrp;
178  } else {prp = mrp; mrp = mrp->Next;}
179  }
180 
181 // All done
182 //
183  mlMutex.UnLock();
184 }
185 
186 /******************************************************************************/
187 /* g e t R e f */
188 /******************************************************************************/
189 
191 {
192  static int refNum = 1;
193  XrdNetAddr theAddr = *netAddr;
194  XrdOucTList *tP;
195  char buff[128];
196  int theNum;
197 
198 // Convert address to text
199 //
200  theAddr.Format(buff,sizeof(buff),XrdNetAddr::fmtAdv6,XrdNetAddr::old6Map4);
201 
202 // Find the entry in this list
203 //
204  refMutex.Lock();
205  tP = refList;
206  while(tP && strcmp(buff, tP->text)) tP = tP->next;
207 
208 // If we didn't find one, add it
209 //
210  if (tP) theNum = tP->val;
211  else {refList = new XrdOucTList(buff, refNum, refList);
212  theNum = -refNum++;
213  }
214 
215 // Return the number
216 //
217  refMutex.UnLock();
218  return theNum;
219 }
220 
221 /******************************************************************************/
222 /* N e x t */
223 /******************************************************************************/
224 
225 int XrdCmsManList::Next(int &port, char *buff, int bsz)
226 {
227  XrdCmsManRef *np;
228  int lvl;
229 
230  mlMutex.Lock();
231  if (!(np = nextMan)) nextMan = allMans;
232  else {strlcpy(buff, np->Manager, bsz);
233  port = np->ManPort;
234  nextMan = np->Next;
235  }
236  lvl = (np ? np->ManLvl : 0);
237  mlMutex.UnLock();
238  return lvl;
239 }
size_t strlcpy(char *dst, const char *src, size_t sz)
void Del(const XrdNetAddr *refP)
void Add(const XrdNetAddr *netAddr, char *redList, int manport, int lvl)
int getRef(const XrdNetAddr *refP)
int Next(int &port, char *buff, int bsz)
XrdCmsManRef * Next
unsigned int ManRef
XrdCmsManRef(unsigned int ref, char *name, int port, int lvl)
static const int old6Map4
Use deprecated IPV6 mapped format.
static bool isHostName(const char *name)
int Format(char *bAddr, int bLen, fmtUse fmtType=fmtAuto, int fmtOpts=0)
const char * Name(const char *eName=0, const char **eText=0)
const char * Set(const char *hSpec, int pNum=PortInSpec)
Definition: XrdNetAddr.cc:216
XrdOucTList * next
Definition: XrdOucTList.hh:45
char * text
Definition: XrdOucTList.hh:46
char * GetToken(char **rest=0, int lowcase=0)