XRootD
XrdCmsManTree.cc
Go to the documentation of this file.
1 /******************************************************************************/
2 /* */
3 /* X r d C m s M a n T r e e . c c */
4 /* */
5 /* (c) 2007 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 <cstdio>
32 
33 #include "XProtocol/YProtocol.hh"
34 
35 #include "XrdCms/XrdCmsManTree.hh"
36 #include "XrdCms/XrdCmsNode.hh"
37 #include "XrdCms/XrdCmsTrace.hh"
38 
39 using namespace XrdCms;
40 
41 /******************************************************************************/
42 /* C o n s t r u c t o r */
43 /******************************************************************************/
44 
45 XrdCmsManTree::XrdCmsManTree(int maxC) : maxTMI(0), numConn(0), maxConn(maxC),
46  atRoot(0), conLevel(0), conNID(-1),
47  numWaiting(0), myStatus(Active)
48 {
49  snprintf(buff, sizeof(buff), "%d", maxC);
50 }
51 
52 /******************************************************************************/
53 /* A b o r t */
54 /******************************************************************************/
55 
57 {
58  XrdSysMutexHelper Monitor(myMutex);
59 
60 // An abort may be issued to make sure no one is waiting to participate in
61 // tree construction. It's usually issued when the manager object has been
62 // permanently redirected.
63 //
64  if (myStatus != Aborted && numWaiting)
65  {for (int i = 0; i < maxTMI; i++)
66  if (tmInfo[i].Status == Waiting) {tmInfo[i].Level = 0; Redrive(i);}
67  }
68 
69 // Indicate we have aborted
70 //
71  myStatus = Aborted;
72 }
73 
74 /******************************************************************************/
75 /* C o n n e c t */
76 /******************************************************************************/
77 
79 {
80  static CmsDiscRequest discRequest = {{0, kYR_disc, 0, 0}};
81  XrdSysMutexHelper Monitor(myMutex);
82  char mybuff[16];
83  int i;
84 
85 // Rule 0: If we aborted tell the client to just stop doing this
86 //
87  if (myStatus == Aborted) return 0;
88 
89 // Rule 1: If we are already connected, thell the caller to disband the
90 // connection as we must have a connection to an interior node.
91 //
92  if (myStatus == Connected) return 0;
93  numConn++;
94  tmInfo[nID].nodeP = nP;
95 
96 // Rule 2: If we connected to a root node then consider ourselves connected
97 // only if all connections are to the root.
98 //
99  if (tmInfo[nID].Level == 0)
100  {if (numConn == maxConn)
101  {myStatus = Connected; conLevel = 0; atRoot = 1;
102  Say.Emsg("ManTree", "Now connected to", buff, "root node(s)");
103  }
104  tmInfo[nID].Status = Connected;
105  return 1;
106  }
107 
108 // Rule 3: We connected to an interior node. Disband all other existing
109 // connections (these should only be to root nodes) and consider
110 // ourselves connected.
111 //
112  for (i = 0; i < maxTMI; i++)
113  if (i != nID && tmInfo[i].Status == Connected)
114  {tmInfo[i].nodeP->Send((char *)&discRequest, sizeof(discRequest));
115  tmInfo[i].Status = Pending;
116  }
117  myStatus = Connected;
118  conLevel = tmInfo[nID].Level;
119  conNID = nID;
120  atRoot = 0;
121 
122 // Document our connection configuration
123 //
124  snprintf(mybuff, sizeof(mybuff), "%d", conLevel);
125  Say.Emsg("ManTree", "Now connected to supervisor at level", mybuff);
126  return 1;
127 }
128 
129 /******************************************************************************/
130 /* D i s c */
131 /******************************************************************************/
132 
133 void XrdCmsManTree::Disc(int nID)
134 {
135 
136 // A connected caller has lost it's connection.
137 //
138  myMutex.Lock();
139  if (tmInfo[nID].Status == Connected || tmInfo[nID].Status == Pending)
140  numConn--;
141  tmInfo[nID].Status = Active;
142  if (atRoot || (conLevel && conNID == nID)) myStatus = Active;
143  tmInfo[nID].nodeP = 0;
144  myMutex.UnLock();
145 }
146 
147 /******************************************************************************/
148 /* R e g i s t e r */
149 /******************************************************************************/
150 
152 {
153  int nID;
154 
155 // Add this server to the tree table. Register is called only once and there
156 // can be no more than MTMax connections to a manager. Hence, we dispense with
157 // error checking (how optimistic :-)
158 //
159  myMutex.Lock();
160  tmInfo[maxTMI].Status= Active;
161  nID = maxTMI; maxTMI++;
162  myMutex.UnLock();
163  return nID;
164 }
165 
166 /******************************************************************************/
167 /* T r y i n g */
168 /******************************************************************************/
169 
170 // This method arranges server connections to a manager to form a minimal B-Tree
171 // free of phantom arcs. The rule is simple, either all connections are to the
172 // root of tree or there is only one connection to an interior node. Because
173 // node discovery is non-determinstic, we must make sure that all root nodes
174 // are tried so as to discover the full set of supervisor nodes we can contact.
175 // This method returns True if the caller may continue at the indicated level
176 // and False if the caller should restart at the root node.
177 //
178 int XrdCmsManTree::Trying(int nID, int lvl)
179 {
180  int i;
181 
182 // Set the current status of the connection
183 //
184  myMutex.Lock();
185  tmInfo[nID].Level = lvl;
186 
187 // Rule 0: If we aborted tell the client to just stop doing this
188 //
189  if (myStatus == Aborted) return -1;
190 
191 // Rule 1: If we are already connected at level >0 then the caller must wait
192 //
193  if (myStatus == Connected && conLevel > 0)
194  {Pause(nID);
195  return (lvl == tmInfo[nID].Level);
196  }
197 
198 // Rule 2: If the caller is trying level 0 then any waiting threads must be
199 // allowed to continue but forced to level 0. This allows us to discover
200 // all the supervisors connected to the root.
201 //
202  if (!lvl)
203  {if (numWaiting)
204  {for (i = 0; i < maxTMI; i++)
205  if (i != nID && tmInfo[i].Status == Waiting)
206  {tmInfo[i].Level = 0; Redrive(i);}
207  }
208  myMutex.UnLock();
209  return 1;
210  }
211 
212 // Rule 3: If the caller is trying at a non-zero level (interior node) and
213 // someone else is trying at a non-zero level, then the caller must
214 // wait.
215 //
216  for (i = 0; i < maxTMI; i++)
217  if (i != nID && tmInfo[i].Status == Active && tmInfo[i].Level) break;
218  if (i < maxTMI) Pause(nID);
219  else myMutex.UnLock();
220 
221 // The caller may continue. Indicate whether the caller must restart at the
222 // root node. If the caller may continue trying to connect to an interior
223 // node then it's the only thread trying to do so.
224 //
225  return (lvl == tmInfo[nID].Level);
226 }
int Connect(int nID, XrdCmsNode *nP)
void Disc(int nID)
XrdCmsManTree(int maxC)
int Trying(int nID, int Lvl)
int Emsg(const char *esfx, int ecode, const char *text1, const char *text2=0)
Definition: XrdSysError.cc:95
XrdSysError Say
@ kYR_disc
Definition: YProtocol.hh:103