XRootD
XrdCmsCluster Class Reference

#include <XrdCmsCluster.hh>

+ Collaboration diagram for XrdCmsCluster:

Public Types

enum  CmsLSOpts {
  LS_NULL =0 ,
  LS_IPO =0x0100 ,
  LS_IDNT =0x0200 ,
  LS_ANY =0x0400 ,
  LS_IFMASK = 0x0f
}
 

Public Member Functions

 XrdCmsCluster ()
 
virtual ~XrdCmsCluster ()
 
XrdCmsNodeAdd (XrdLink *lp, int dport, int Status, int sport, const char *theNID, const char *theIF)
 
virtual void BlackList (XrdOucTList *blP)
 
SMask_t Broadcast (SMask_t smask, XrdCms::CmsRRHdr &Hdr, char *Data, int Dlen=0)
 
SMask_t Broadcast (SMask_t smask, XrdCms::CmsRRHdr &Hdr, void *Data, int Dlen)
 
SMask_t Broadcast (SMask_t, const struct iovec *, int, int tot=0)
 
int Broadsend (SMask_t smask, XrdCms::CmsRRHdr &Hdr, void *Data, int Dlen)
 
SMask_t getMask (const char *Cid)
 
SMask_t getMask (const XrdNetAddr *addr)
 
XrdCmsSelectedList (SMask_t mask, CmsLSOpts opts, bool &oksel)
 
int Locate (XrdCmsSelect &Sel)
 
void * MonPerf ()
 
void * MonRefs ()
 
long long Refs ()
 
void Remove (const char *reason, XrdCmsNode *theNode, int immed=0)
 
void Remove (XrdCmsNode *theNode)
 
void ResetRef (SMask_t smask, bool isLocked=false)
 
int Select (SMask_t pmask, int &port, char *hbuff, int &hlen, int isrw, int isMulti, int ifWant)
 
int Select (XrdCmsSelect &Sel)
 
void SLock (bool dolock, bool wrmode=true)
 
void Space (XrdCms::SpaceData &sData, SMask_t smask)
 
int Stats (char *bfr, int bln)
 
int Statt (char *bfr, int bln)
 

Public Attributes

int NodeCnt
 

Static Public Attributes

static const int EReplete = -4
 
static const int NotFound = -1
 
static const int RetryErr = -3
 
static const int Wait4CBk = -2
 

Friends

class XrdCmsDrop
 

Detailed Description

Definition at line 114 of file XrdCmsCluster.hh.

Member Enumeration Documentation

◆ CmsLSOpts

Enumerator
LS_NULL 
LS_IPO 
LS_IDNT 
LS_ANY 
LS_IFMASK 

Definition at line 155 of file XrdCmsCluster.hh.

155  {LS_NULL=0, LS_IPO=0x0100, LS_IDNT=0x0200,
156  LS_ANY =0x0400, LS_IFMASK = 0x0f};

Constructor & Destructor Documentation

◆ XrdCmsCluster()

XrdCmsCluster::XrdCmsCluster ( )

Definition at line 109 of file XrdCmsCluster.cc.

110 {
111  memset((void *)NodeTab, 0, sizeof(NodeTab));
112  memset((void *)AltMans, (int)' ', sizeof(AltMans));
113  AltMend = AltMans;
114  AltMent = -1;
115  NodeCnt = 0;
116  STHi = -1;
117  SelWtot = 0;
118  SelRtot = 0;
119  SelTcnt = 0;
120  peerHost = 0;
121  peerMask = ~peerHost;
122 }

◆ ~XrdCmsCluster()

virtual XrdCmsCluster::~XrdCmsCluster ( )
inlinevirtual

Definition at line 218 of file XrdCmsCluster.hh.

218 {} // This object should never be deleted

Member Function Documentation

◆ Add()

XrdCmsNode * XrdCmsCluster::Add ( XrdLink lp,
int  dport,
int  Status,
int  sport,
const char *  theNID,
const char *  theIF 
)

Definition at line 128 of file XrdCmsCluster.cc.

131 {
132  EPNAME("Add")
133  const char *act = "";
134  XrdCmsNode *nP = 0;
135  XrdCmsClustID *cidP = 0;
136  XrdSysRWLockHelper STMHelper(STMutex, false); // Need write lock!
137  int tmp, Slot, Free = -1, Bump1 = -1, Bump2 = -1, Bump3 = -1, aSet = 0;
138  bool Special = (Status & (CMS_isMan|CMS_isPeer));
139  bool SpecAlt = (Special && !(Status & CMS_isSuper));
140  bool Hidden = false;
141 
142 // Find available slot for this node. Here are the priorities:
143 // Slot = Reconnecting node
144 // Free = Available slot ( 1st in table)
145 // Bump1 = Disconnected server (last in table)
146 // Bump2 = Connected server (last in table) if new one is managr/peer
147 // Bump3 = Disconnected managr/peer ( 1st in table) if new one is managr/peer
148 //
149  for (Slot = 0; Slot < STMax; Slot++)
150  if (NodeTab[Slot])
151  {if (NodeTab[Slot]->isNode(lp, theNID, port)) break;
152 /*Conn*/ if (NodeTab[Slot]->isConn)
153  {if (!NodeTab[Slot]->isPerm && Special)
154  Bump2 = Slot; // Last conn Server
155 /*Disc*/ } else {
156  if ( NodeTab[Slot]->isPerm)
157  {if (Bump3 < 0 && Special) Bump3 = Slot;}// 1st disc Man/Pr
158  else Bump1 = Slot; // Last disc Server
159  }
160  } else if (Free < 0) Free = Slot; // 1st free slot
161 
162 // Check if node is already logged in or is a relogin
163 //
164  if (Slot < STMax)
165  {if (NodeTab[Slot] && NodeTab[Slot]->isBound)
166  {Say.Emsg("Cluster", lp->ID, "already logged in.");
167  return 0;
168  } else { // Rehook node to previous unconnected entry
169  nP = NodeTab[Slot];
170  nP->Link = lp;
171  nP->isOffline = 0;
172  nP->isBad &= ~XrdCmsNode::isSuspend;
173  nP->isConn = 1;
174  nP->Instance++;
175  nP->setName(lp, theIF, port); // Just in case it changed
176  act = "Reconnect ";
177  }
178  }
179 
180 // First see if this node may be an alternate
181 //
182  if (!nP && SpecAlt)
183  {if ((cidP = XrdCmsClustID::Find(theNID)) && !(cidP->IsEmpty()))
184  {if (!(nP = AddAlt(cidP, lp, port, Status, sport, theNID, theIF)))
185  return 0;
186  aSet = 1; Slot = nP->NodeID;
187  if (nP != NodeTab[Slot]) {Hidden = true; act = "Alternate ";}
188  }
189  }
190 
191 // Reuse an old ID if we must or redirect the incoming node
192 //
193  if (!nP)
194  {if (Free >= 0) Slot = Free;
195  else {if (Bump1 >= 0) Slot = Bump1;
196  else Slot = (Bump2 >= 0 ? Bump2 : Bump3);
197  if (Slot < 0)
198  {if (Status & CMS_isPeer) Say.Emsg("Cluster", "Add peer", lp->ID,
199  "failed; too many subscribers.");
200  else {sendAList(lp);
201  DEBUG(lp->ID <<" redirected; too many subscribers.");
202  }
203  return 0;
204  }
205 
206  if (Status & CMS_isMan) {setAltMan(Slot, lp, sport); aSet=1;}
207  if (NodeTab[Slot] && !(Status & CMS_isPeer))
208  sendAList(NodeTab[Slot]->Link);
209 
210  DEBUG(lp->ID << " bumps " << NodeTab[Slot]->Ident <<" #" <<Slot);
211  NodeTab[Slot]->Lock();
212  Remove("redirected", NodeTab[Slot], -1);
213  act = "Shoved ";
214  }
215  NodeTab[Slot] = nP = new XrdCmsNode(lp, theIF, theNID, port, 0, Slot);
216  if (!cidP) cidP = XrdCmsClustID::AddID(theNID);
217  if ((cidP->AddNode(nP, SpecAlt))) nP->cidP = cidP;
218  else {delete nP; NodeTab[Slot] = 0; return 0;} // OK to do delete!
219  }
220 
221 // Indicate whether this snode can be redirected
222 //
223  nP->isPerm = (Status & (CMS_isMan | CMS_isPeer)) ? 1 : 0;
224 
225 // Assign new server
226 //
227  if (!aSet && (Status & CMS_isSuper)) setAltMan(Slot, lp, sport);
228  if (Slot > STHi) STHi = Slot;
229  nP->isBound = 1;
230  nP->isConn = 1;
231  nP->isNoStage = 0 != (Status & CMS_noStage);
232  nP->isBad |= (Status & CMS_Suspend ? XrdCmsNode::isSuspend : 0);
233  nP->isMan = 0 != (Status & CMS_isMan);
234  nP->isPeer = 0 != (Status & CMS_isPeer);
236  nP->subsPort = sport;
237 
238 // If this is an actual non-hidden node, count it
239 //
240  if (!Hidden)
241  {NodeCnt++;
242  if (Config.SUPLevel
243  && (tmp = NodeCnt*Config.SUPLevel/100) > Config.SUPCount)
244  {Config.SUPCount=tmp; CmsState.Set(tmp);}
245  } else nP->isMan |= 0x02;
246 
247 // Compute new peer mask, as needed
248 //
249  if (nP->isPeer) peerHost |= nP->NodeMask;
250  else peerHost &= ~nP->NodeMask;
251  peerMask = ~peerHost;
252 
253 // Document login
254 //
255  if (QTRACE(Debug))
256  {DEBUG(act <<nP->Ident <<" to cluster " <<nP->myNID <<" slot "
257  <<Slot <<'.' <<nP->Instance <<" (nodecnt=" <<NodeCnt
258  <<" supn=" <<Config.SUPCount <<")");
259  }
260 
261 // Compute new state of all nodes if we are a reporting manager.
262 //
263  if (Config.asManager() && !Hidden)
265  nP->isBad & XrdCmsNode::isSuspend ? 0 : 1,
266  nP->isNoStage ? 0 : 1);
267 
268 // All done. Return the node locked.
269 //
270  nP->Lock();
271  return nP;
272 }
#define DEBUG(x)
Definition: XrdBwmTrace.hh:54
#define EPNAME(x)
Definition: XrdBwmTrace.hh:56
#define QTRACE(act)
Definition: XrdCmsTrace.hh:49
#define STMax
Definition: XrdCmsTypes.hh:39
if(Avsz)
static XrdCmsClustID * AddID(const char *cID)
static XrdCmsClustID * Find(const char *cID)
bool AddNode(XrdCmsNode *nP, bool isMan)
void Remove(XrdCmsNode *theNode)
char isPerm
Definition: XrdCmsNode.hh:73
char * Ident
Definition: XrdCmsNode.hh:61
char isConn
Definition: XrdCmsNode.hh:71
char isPeer
Definition: XrdCmsNode.hh:68
void Lock()
Definition: XrdCmsNode.hh:175
static const char isDisabled
Definition: XrdCmsNode.hh:80
char isBad
Definition: XrdCmsNode.hh:63
char isOffline
Definition: XrdCmsNode.hh:64
static const char isSuspend
Definition: XrdCmsNode.hh:81
char isNoStage
Definition: XrdCmsNode.hh:66
char isMan
Definition: XrdCmsNode.hh:67
void setName(XrdLink *lnkp, const char *theIF, int port)
Definition: XrdCmsNode.cc:145
char isBound
Definition: XrdCmsNode.hh:69
void Update(StateType StateT, int ActivVal, int StageVal=0)
Definition: XrdCmsState.cc:258
void Set(int ncount)
Definition: XrdCmsState.cc:182
int Emsg(const char *esfx, int ecode, const char *text1, const char *text2=0)
Definition: XrdSysError.cc:95
static const int CMS_isSuper
static const int CMS_noStage
XrdSysError Say
XrdCmsState CmsState
Definition: XrdCmsState.cc:55
static const int CMS_isMan
XrdCmsConfig Config
static const int CMS_isPeer
static const int CMS_Suspend

References XrdCmsClustID::AddID(), XrdCmsClustID::AddNode(), XrdCmsConfig::asManager(), XrdCms::CMS_isMan, XrdCms::CMS_isPeer, XrdCms::CMS_isSuper, XrdCms::CMS_noStage, XrdCms::CMS_Suspend, XrdCms::CmsState, XrdCms::Config, XrdCmsState::Counts, DEBUG, Macaroons::Debug, XrdSysError::Emsg(), EPNAME, XrdCmsClustID::Find(), XrdLink::ID, XrdCmsNode::Ident, XrdCmsNode::isBad, XrdCmsNode::isBound, XrdCmsNode::isConn, XrdCmsNode::isDisabled, XrdCmsClustID::IsEmpty(), XrdCmsNode::isMan, XrdCmsNode::isNoStage, XrdCmsNode::isOffline, XrdCmsNode::isPeer, XrdCmsNode::isPerm, XrdCmsNode::isSuspend, XrdCmsNode::Lock(), QTRACE, XrdCms::Say, XrdCmsState::Set(), XrdCmsNode::setName(), STMax, XrdCmsConfig::SUPCount, XrdCmsConfig::SUPLevel, and XrdCmsState::Update().

+ Here is the call graph for this function:

◆ BlackList()

void XrdCmsCluster::BlackList ( XrdOucTList blP)
virtual

Definition at line 330 of file XrdCmsCluster.cc.

331 {
332  static CmsDiscRequest discRequest = {{0, kYR_disc, 0, 0}};
333  XrdCmsNode *nP;
334  const char *etxt = "blacklisted.";
335  int i, blRD = 0;
336  bool inBL;
337 
338 // Obtain a lock on the table. We need this in write mode!
339 //
340  STMutex.WriteLock();
341 
342 // Run through the table looking to put or out of the blacklist
343 //
344  for (i = 0; i <= STHi; i++)
345  {if ((nP = NodeTab[i]))
346  {inBL = (blP && (blRD = XrdCmsBlackList::Present(nP->Name(), blP)));
347  if ((!inBL && !(nP->isBad & XrdCmsNode::isBlisted))
348  || ( inBL && (nP->isBad & XrdCmsNode::isBlisted))) continue;
349  nP->g2nLock(STMutex); // Downgrade to only node lock
350  if (inBL)
352  if (blRD < -1)
353  {if (kYR_Version > nP->myVersion)
354  etxt = "blacklisted; redirect unsupported.";
355  else etxt = "blacklisted with redirect.";
357  nP->Send((char *)&discRequest, sizeof(discRequest));
358  }
359  Say.Emsg("Manager", nP->Name(), etxt);
360  } else {
362  Say.Emsg("Manager", nP->Name(), "removed from blacklist.");
363  }
364  nP->n2gLock(STMutex);
365  }
366  }
367  STMutex.UnLock();
368 }
static int Present(const char *hName, XrdOucTList *bList=0, char *rbuff=0, int rblen=0)
void n2gLock(XrdSysRWLock &gMutex, bool rdlock=false)
Definition: XrdCmsNode.hh:168
int Send(const char *buff, int blen=0)
Definition: XrdCmsNode.hh:184
void g2nLock(XrdSysRWLock &gMutex)
Definition: XrdCmsNode.hh:162
static const char isDoomed
Definition: XrdCmsNode.hh:82
static const char isBlisted
Definition: XrdCmsNode.hh:79
char * Name()
Definition: XrdCmsNode.hh:158
static const unsigned char kYR_Version
Definition: YProtocol.hh:80
@ kYR_disc
Definition: YProtocol.hh:103

References XrdSysError::Emsg(), XrdCmsNode::g2nLock(), XrdCmsNode::isBad, XrdCmsNode::isBlisted, XrdCmsNode::isDoomed, XrdCms::kYR_disc, XrdCms::kYR_Version, XrdCmsNode::n2gLock(), XrdCmsNode::Name(), XrdCmsBlackList::Present(), XrdCms::Say, and XrdCmsNode::Send().

Referenced by XrdCmsBlackList::DoIt().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ Broadcast() [1/3]

SMask_t XrdCmsCluster::Broadcast ( SMask_t  smask,
XrdCms::CmsRRHdr Hdr,
char *  Data,
int  Dlen = 0 
)

Definition at line 411 of file XrdCmsCluster.cc.

413 {
414  struct iovec ioV[3], *iovP = &ioV[1];
415  unsigned short Temp;
416  int Blen;
417 
418 // Construct packed data for the character argument. If data is a string then
419 // Dlen must include the null byte if it is specified at all.
420 //
421  Blen = XrdOucPup::Pack(&iovP, Data, Temp, (Dlen ? strlen(Data)+1 : Dlen));
422  Hdr.datalen = htons(static_cast<unsigned short>(Blen));
423 
424 // Complete the iovec and send off the data
425 //
426  ioV[0].iov_base = (char *)&Hdr; ioV[0].iov_len = sizeof(Hdr);
427  return Broadcast(smask, ioV, 3, Blen+sizeof(Hdr));
428 }
SMask_t Broadcast(SMask_t, const struct iovec *, int, int tot=0)
static int Pack(struct iovec **, const char *, unsigned short &buff)
Definition: XrdOucPup.cc:52
kXR_unt16 datalen
Definition: YProtocol.hh:86

References XrdCms::CmsRRHdr::datalen, and XrdOucPup::Pack().

+ Here is the call graph for this function:

◆ Broadcast() [2/3]

SMask_t XrdCmsCluster::Broadcast ( SMask_t  smask,
XrdCms::CmsRRHdr Hdr,
void *  Data,
int  Dlen 
)

Definition at line 432 of file XrdCmsCluster.cc.

434 {
435  struct iovec ioV[2] = {{(char *)&Hdr, sizeof(Hdr)},
436  {(char *)Data, (size_t)Dlen}};
437 
438 // Send of the data as eveything was constructed properly
439 //
440  Hdr.datalen = htons(static_cast<unsigned short>(Dlen));
441  return Broadcast(smask, ioV, 2, Dlen+sizeof(Hdr));
442 }

References XrdCms::CmsRRHdr::datalen.

◆ Broadcast() [3/3]

SMask_t XrdCmsCluster::Broadcast ( SMask_t  smask,
const struct iovec *  iod,
int  iovcnt,
int  tot = 0 
)

Definition at line 374 of file XrdCmsCluster.cc.

376 {
377  EPNAME("Broadcast")
378  int i;
379  XrdCmsNode *nP;
380  SMask_t bmask, unQueried(0);
381 
382 // Obtain a lock on the table and screen out peer nodes
383 //
384  STMutex.ReadLock(); // Sufficient to prevent modifications
385  bmask = smask & peerMask;
386 
387 // Run through the table looking for nodes to send messages to. We don't need
388 // the node lock for this but we do need to up the reference count to keep the
389 // node pointer valid for the duration of the send() (may or may not block).
390 //
391  for (i = 0; i <= STHi; i++)
392  {if ((nP = NodeTab[i]) && nP->isNode(bmask))
393  {if (nP->isOffline) unQueried |= nP->Mask();
394  else {nP->Ref();
395  STMutex.UnLock();
396  if (nP->Send(iod, iovcnt, iotot) < 0)
397  {unQueried |= nP->Mask();
398  DEBUG(nP->Ident <<" is unreachable");
399  }
400  nP->unRef();
401  STMutex.ReadLock();
402  }
403  }
404  }
405  STMutex.UnLock();
406  return unQueried;
407 }
unsigned long long SMask_t
Definition: XrdCmsTypes.hh:33
void Ref()
Definition: XrdCmsNode.hh:179
void unRef()
Definition: XrdCmsNode.hh:180
int isNode(SMask_t smask)
Definition: XrdCmsNode.hh:145
SMask_t Mask()
Definition: XrdCmsNode.hh:160

References DEBUG, EPNAME, XrdCmsNode::Ident, XrdCmsNode::isNode(), XrdCmsNode::isOffline, XrdCmsNode::Mask(), XrdCmsNode::Ref(), XrdCmsNode::Send(), and XrdCmsNode::unRef().

Referenced by XrdCmsNode::do_StateFWD(), Locate(), and Select().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ Broadsend()

int XrdCmsCluster::Broadsend ( SMask_t  smask,
XrdCms::CmsRRHdr Hdr,
void *  Data,
int  Dlen 
)

Definition at line 450 of file XrdCmsCluster.cc.

452 {
453  EPNAME("Broadsend");
454  static int Start = 0;
455  XrdCmsNode *nP;
456  struct iovec ioV[2] = {{(char *)&Hdr, sizeof(Hdr)},
457  {(char *)Data, (size_t)Dlen}};
458  int i, Beg, Fin, ioTot = Dlen+sizeof(Hdr);
459 
460 // Send of the data as eveything was constructed properly
461 //
462  Hdr.datalen = htons(static_cast<unsigned short>(Dlen));
463 
464 // Obtain a lock on the table and get the starting and ending position. Note
465 // that the mechnism we use will necessarily skip newly added nodes.
466 //
467  STMutex.ReadLock(); // Sufficient to prevent modifications
468  Beg = Start = (Start <= STHi ? Start+1 : 0);
469  Fin = STHi;
470 
471 // Run through the table looking for a node to send a message to. We don't need
472 // the node lock for this but we do need to up the reference count to keep the
473 // node pointer valid for the duration of the send() (may or may not block).
474 //
475 do{for (i = Beg; i <= Fin; i++)
476  {if ((nP = NodeTab[i]) && nP->isNode(Who))
477  {if (nP->isOffline) continue;
478  nP->Ref();
479  STMutex.UnLock();
480  if (nP->Send(ioV, 2, ioTot) >= 0) {nP->unRef(); return 1;}
481  DEBUG(nP->Ident <<" is unreachable");
482  nP->unRef();
483  STMutex.ReadLock();
484  }
485  }
486  if (!Beg) break;
487  Fin = Beg-1; Beg = 0;
488  } while(1);
489 
490 // Did not send to anyone
491 //
492  STMutex.UnLock();
493  return 0;
494 }

References XrdCms::CmsRRHdr::datalen, DEBUG, EPNAME, XrdCmsNode::Ident, XrdCmsNode::isNode(), XrdCmsNode::isOffline, XrdCmsNode::Ref(), XrdCmsNode::Send(), and XrdCmsNode::unRef().

Referenced by XrdCmsNode::do_StateFWD().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ getMask() [1/2]

SMask_t XrdCmsCluster::getMask ( const char *  Cid)

Definition at line 524 of file XrdCmsCluster.cc.

525 {
526  return XrdCmsClustID::Mask(Cid);
527 }
static SMask_t Mask(const char *cID)

References XrdCmsClustID::Mask().

+ Here is the call graph for this function:

◆ getMask() [2/2]

SMask_t XrdCmsCluster::getMask ( const XrdNetAddr addr)

Definition at line 500 of file XrdCmsCluster.cc.

501 {
502  int i;
503  XrdCmsNode *nP;
504  SMask_t smask(0);
505 
506 // Obtain a lock on the table
507 //
508  STMutex.ReadLock();
509 
510 // Run through the table looking for a node with matching IP address
511 //
512  for (i = 0; i <= STHi; i++)
513  if ((nP = NodeTab[i]) && nP->isNode(addr))
514  {smask = nP->NodeMask; break;}
515 
516 // All done
517 //
518  STMutex.UnLock();
519  return smask;
520 }

References XrdCmsNode::isNode().

Referenced by XrdCmsNode::do_SelAvoid().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ List()

XrdCmsSelected * XrdCmsCluster::List ( SMask_t  mask,
CmsLSOpts  opts,
bool &  oksel 
)

Definition at line 533 of file XrdCmsCluster.cc.

534 {
535  static const int iSize = XrdCmsSelected::IdentSize;
536  XrdCmsNode *nP;
537  XrdCmsSelected *sipp = 0, *sip;
539  XrdNetIF::ifType ifGet = ifType;
540  int i, destLen;
541  bool retName = (opts & LS_IDNT) != 0;
542  bool retAny = (opts & LS_ANY ) != 0;
543  bool retDest = retName || (opts & LS_IPO);
544 
545 // If only one wanted, the select appropriately
546 //
547  oksel = false;
548  STMutex.ReadLock();
549  for (i = 0; i <= STHi; i++)
550  if ((nP=NodeTab[i]) && (nP->NodeMask & mask))
551  {oksel = true;
552  if (retDest)
553  { if (nP->netIF.HasDest(ifType)) ifGet = ifType;
554  else if (!retAny) continue;
555  else {ifGet = (XrdNetIF::ifType)(ifType ^ XrdNetIF::PrivateIF);
556  if (!nP->netIF.HasDest(ifGet)) continue;
557  }
558  }
559  sip = new XrdCmsSelected(sipp);
560  if (retDest) destLen = nP->netIF.GetPublicDest(sip->Ident, iSize);
561  else if (nP->myNlen >= XrdCmsSelected::IdentSize) destLen = 0;
562  else {strcpy(sip->Ident, nP->myName); destLen = nP->myNlen;}
563  if (!destLen) {delete sip; continue;}
564 
565  sip->IdentLen = destLen;
566  sip->Mask = nP->NodeMask;
567  sip->Id = nP->NodeID;
568  sip->Port = nP->netIF.Port();
569  sip->RefTotW = nP->RefTotW;
570  sip->RefTotR = nP->RefTotR;
571  sip->Shrin = nP->Shrin;
572  sip->Share = nP->Share;
573  sip->RoleID = nP->RoleID;
574  sip->Status = (nP->isOffline ? XrdCmsSelected::Offline : 0);
576  sip->Status |= XrdCmsSelected::Disable;
577  if (nP->isNoStage) sip->Status |= XrdCmsSelected::NoStage;
578  if (nP->isBad & XrdCmsNode::isSuspend)
579  sip->Status |= XrdCmsSelected::Suspend;
580  if (nP->isRW ) sip->Status |= XrdCmsSelected::isRW;
581  if (nP->isMan ) sip->Status |= XrdCmsSelected::isMangr;
582  sipp = sip;
583  }
584  STMutex.UnLock();
585 
586 // Return result
587 //
588  return sipp;
589 }
struct myOpts opts
char RoleID
Definition: XrdCmsNode.hh:75
static const int IdentSize
int Port()
Definition: XrdNetIF.hh:322
bool HasDest(ifType ifT=PublicV6)
Definition: XrdNetIF.hh:267
int GetPublicDest(char *dest, size_t dlen)
Definition: XrdNetIF.cc:412
ifType
The enum that is used to index into ifData to get appropriate interface.
Definition: XrdNetIF.hh:65
@ PrivateIF
Definition: XrdNetIF.hh:69

References XrdCmsSelected::Disable, XrdNetIF::GetPublicDest(), XrdNetIF::HasDest(), XrdCmsSelected::IdentSize, if(), XrdCmsNode::isBad, XrdCmsNode::isBlisted, XrdCmsNode::isDisabled, XrdCmsNode::isMan, XrdCmsSelected::isMangr, XrdCmsNode::isNoStage, XrdCmsNode::isOffline, XrdCmsNode::isRW, XrdCmsSelected::isRW, XrdCmsNode::isSuspend, XrdCmsSelected::NoStage, XrdCmsSelected::Offline, opts, XrdNetIF::Port(), XrdNetIF::PrivateIF, XrdCmsNode::RoleID, and XrdCmsSelected::Suspend.

Referenced by XrdCmsNode::do_Locate().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ Locate()

int XrdCmsCluster::Locate ( XrdCmsSelect Sel)

Definition at line 595 of file XrdCmsCluster.cc.

596 {
597  EPNAME("Locate");
598  XrdCmsPInfo pinfo;
599  SMask_t qfVec(0);
600  char *Path;
601  int retc = 0;
602 
603 // Check if this is a locate for all current servers
604 //
605  if (*Sel.Path.Val != '*') Path = Sel.Path.Val;
606  else {if (*(Sel.Path.Val+1) == '\0')
607  {Sel.Vec.hf = ~0LL; Sel.Vec.pf = Sel.Vec.wf = 0;
608  return 0;
609  }
610  Path = Sel.Path.Val+1;
611  }
612 
613 // Find out who serves this path
614 //
615  if (!Cache.Paths.Find(Path, pinfo) || !pinfo.rovec)
616  {Sel.Vec.hf = Sel.Vec.pf = Sel.Vec.wf = 0;
617  return NotFound;
618  } else Sel.Vec.wf = pinfo.rwvec;
619 
620 // Check if this was a non-lookup request
621 //
622  if (*Sel.Path.Val == '*')
623  {Sel.Vec.hf = pinfo.rovec; Sel.Vec.pf = 0;
624  Sel.Vec.wf = pinfo.rwvec;
625  return 0;
626  }
627 
628 // Complete the request info object if we have one
629 //
630  if (Sel.InfoP)
631  {Sel.InfoP->rwVec = pinfo.rwvec;
632  Sel.InfoP->isLU = 1;
633  }
634 
635 // If we are running a shared file system preform an optional restricted
636 // pre-selection and then do a standard selection.
637 //
638  if (baseFS.isDFS())
639  {SMask_t amask, smask, pmask;
640  amask = pmask = pinfo.rovec;
641  smask = (Sel.Opts & XrdCmsSelect::Online ? 0 : pinfo.ssvec & amask);
642  Sel.Resp.DLen = 0;
643  if (!(retc = SelDFS(Sel, amask, pmask, smask, 1)))
644  return (Sel.Opts & XrdCmsSelect::Asap && Sel.InfoP
645  ? Cache.WT4File(Sel,Sel.Vec.hf) : Config.LUPDelay);
646  if (retc < 0) return NotFound;
647  return 0;
648  }
649 
650 // First check if we have seen this file before. If so, get nodes that have it.
651 // A Refresh request kills this because it's as if we hadn't seen it before.
652 // If the file was found but either a query is in progress or we have a server
653 // bounce; the client must wait.
654 //
655  if (Sel.Opts & XrdCmsSelect::Refresh
656  || !(retc = Cache.GetFile(Sel, pinfo.rovec)))
657  {Cache.AddFile(Sel, 0);
658  qfVec = pinfo.rovec; Sel.Vec.hf = 0;
659  } else qfVec = Sel.Vec.bf;
660 
661 // Compute the delay, if any
662 //
663  if ((!qfVec && retc >= 0) || (Sel.Vec.hf && Sel.InfoP)) retc = 0;
664  else if (!(retc = Cache.WT4File(Sel, Sel.Vec.hf))) retc = Wait4CBk;
665 
666 // Check if we have to ask any nodes if they have the file
667 //
668  if (qfVec)
669  {CmsStateRequest QReq = {{Sel.Path.Hash, kYR_state, kYR_raw, 0}};
670  if (Sel.Opts & XrdCmsSelect::Refresh)
671  QReq.Hdr.modifier |= CmsStateRequest::kYR_refresh;
672  TRACE(Files, "seeking " <<Sel.Path.Val);
673  qfVec = Cluster.Broadcast(qfVec, QReq.Hdr,
674  (void *)Sel.Path.Val, Sel.Path.Len+1);
675  if (qfVec) Cache.UnkFile(Sel, qfVec);
676  }
677  return retc;
678 }
XrdOucString Path
#define TRACE(act, x)
Definition: XrdTrace.hh:63
int GetFile(XrdCmsSelect &Sel, SMask_t mask)
Definition: XrdCmsCache.cc:232
int AddFile(XrdCmsSelect &Sel, SMask_t mask)
Definition: XrdCmsCache.cc:117
XrdCmsPList_Anchor Paths
Definition: XrdCmsCache.hh:49
int UnkFile(XrdCmsSelect &Sel, SMask_t mask)
Definition: XrdCmsCache.cc:278
int WT4File(XrdCmsSelect &Sel, SMask_t mask)
Definition: XrdCmsCache.cc:306
static const int NotFound
static const int Wait4CBk
unsigned int Hash
Definition: XrdCmsKey.hh:53
char * Val
Definition: XrdCmsKey.hh:52
short Len
Definition: XrdCmsKey.hh:54
SMask_t ssvec
Definition: XrdCmsPList.hh:49
SMask_t rovec
Definition: XrdCmsPList.hh:47
SMask_t rwvec
Definition: XrdCmsPList.hh:48
int Find(const char *pname, XrdCmsPInfo &masks)
Definition: XrdCmsPList.cc:77
SMask_t rwVec
Definition: XrdCmsRRQ.hh:59
struct XrdCmsSelect::@93 Resp
struct XrdCmsSelect::@92 Vec
XrdCmsRRQInfo * InfoP
Definition: XrdCmsSelect.hh:47
XrdCmsKey Path
Definition: XrdCmsSelect.hh:46
XrdCmsCache Cache
Definition: XrdPfcFile.hh:204
kXR_char modifier
Definition: YProtocol.hh:85
XrdCmsCluster Cluster
XrdCmsBaseFS baseFS
@ kYR_raw
Definition: YProtocol.hh:132
@ kYR_state
Definition: YProtocol.hh:110

References XrdCmsCache::AddFile(), XrdCmsSelect::Asap, XrdCms::baseFS, Broadcast(), XrdCms::Cache, XrdCms::Cluster, XrdCms::Config, EPNAME, XrdCmsPList_Anchor::Find(), XrdCmsCache::GetFile(), XrdCmsKey::Hash, XrdCms::CmsStateRequest::Hdr, XrdCmsSelect::InfoP, XrdCmsBaseFS::isDFS(), XrdCmsRRQInfo::isLU, XrdCms::kYR_raw, XrdCms::CmsStateRequest::kYR_refresh, XrdCms::kYR_state, XrdCmsKey::Len, XrdCmsConfig::LUPDelay, XrdCms::CmsRRHdr::modifier, XrdCmsSelect::Online, XrdCmsSelect::Opts, XrdCmsSelect::Path, Path, XrdCmsCache::Paths, XrdCmsSelect::Refresh, XrdCmsSelect::Resp, XrdCmsPInfo::rovec, XrdCmsPInfo::rwvec, XrdCmsRRQInfo::rwVec, XrdCmsPInfo::ssvec, TRACE, XrdCmsCache::UnkFile(), XrdCmsKey::Val, XrdCmsSelect::Vec, and XrdCmsCache::WT4File().

Referenced by XrdCmsNode::do_Locate().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ MonPerf()

void * XrdCmsCluster::MonPerf ( )

Definition at line 684 of file XrdCmsCluster.cc.

685 {
686  CmsUsageRequest Usage = {{0, kYR_usage, 0, 0}};
687  struct iovec ioV[] = {{(char *)&Usage, sizeof(Usage)}};
688  int ioVnum = sizeof(ioV)/sizeof(struct iovec);
689  int ioVtot = sizeof(Usage);
690  SMask_t allNodes(~0);
691  int uInterval = Config.AskPing*Config.AskPerf;
692 
693 // Sleep for the indicated amount of time, then ask for load on each server
694 //
695  while(uInterval)
696  {XrdSysTimer::Snooze(uInterval);
697  Broadcast(allNodes, ioV, ioVnum, ioVtot);
698  }
699  return (void *)0;
700 }
void Usage(const char *msg)
Definition: XrdAccTest.cc:105
static void Snooze(int seconds)
Definition: XrdSysTimer.cc:168
@ kYR_usage
Definition: YProtocol.hh:116

References XrdCmsConfig::AskPerf, XrdCmsConfig::AskPing, XrdCms::Config, XrdCms::kYR_usage, XrdSysTimer::Snooze(), and Usage().

Referenced by XrdCmsStartMonPerf().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ MonRefs()

void * XrdCmsCluster::MonRefs ( )

Definition at line 706 of file XrdCmsCluster.cc.

707 {
708  XrdCmsNode *nP;
709  int snooze_interval = 60, snooze_total = 0;
710  int rCnt = 0, wCnt = 0;
711  bool resetW, resetR, resetRW;
712 
713 // Sleep for the snooze interval. If a reset was requested then do a selective
714 // reset unless we reached our snooze maximum and enough selections have gone
715 // by; in which case, do a global reset.
716 //
717  do {XrdSysTimer::Snooze(snooze_interval);
718  int totR = 0, totW = 0;
719 
720  STMutex.ReadLock();
721  for (int i = 0; i <= STHi; i++)
722  {if ((nP = NodeTab[i]))
723  {totR += nP->RefTotR;
724  totW += nP->RefTotW;
725  }
726  }
727  STMutex.UnLock();
728 
729  rCnt += (totR - SelRtot); SelRtot = totR;
730  wCnt += (totW - SelWtot); SelWtot = totW;
731  snooze_total += snooze_interval;
732 
733  resetR = (rCnt >= Config.RefTurn);
734  resetW = (wCnt >= Config.RefTurn);
735  resetRW = (snooze_total >= Config.RefReset && (resetW || resetR));
736  if (resetRW)
737  {ResetRef((SMask_t)0);
738  if (resetR) rCnt = 0;
739  if (resetW) wCnt = 0;
740  snooze_total = 0;
741  }
742  } while(1);
743 
744  return (void *)0;
745 }
void ResetRef(SMask_t smask, bool isLocked=false)

References XrdCms::Config, XrdCmsConfig::RefReset, XrdCmsConfig::RefTurn, and XrdSysTimer::Snooze().

Referenced by XrdCmsStartMonRefs().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ Refs()

long long XrdCmsCluster::Refs ( )
inline

Definition at line 174 of file XrdCmsCluster.hh.

174 {return SelWtot+SelRtot;}

Referenced by XrdCmsNode::do_Load().

+ Here is the caller graph for this function:

◆ Remove() [1/2]

void XrdCmsCluster::Remove ( const char *  reason,
XrdCmsNode theNode,
int  immed = 0 
)

Definition at line 765 of file XrdCmsCluster.cc.

766 {
767  EPNAME("Remove_Node")
768  struct theLocks
769  {XrdSysRWLock *myMutex;
770  XrdCmsNode *myNode;
771  int myNID;
772  int myInst;
773  bool hasLK;
774  bool doDrop;
775  char myIdent[510];
776 
777  theLocks(XrdSysRWLock *mtx, XrdCmsNode *node, int immed)
778  : myMutex(mtx), myNode(node), hasLK(immed < 0),
779  doDrop(false)
780  {strlcpy(myIdent, node->Ident, sizeof(myIdent));
781  myNID = node->ID(myInst);
782  if (!hasLK)
783  {myNode->Ref(); // Keep alive
784  myNode->UnLock();
785  myMutex->WriteLock(); // Get global lock
786  myNode->Lock();
787  myNode->unRef(); // Can't escape now
788  }
789  }
790  ~theLocks()
791  {if (myNode)
792  {if (doDrop)
793  {myNode->isBound = 0;
794  myNode->DropTime = 0;
795  myNode->DropJob = new XrdCmsDrop(myNode);
796  myNode->UnLock();
797  } else myNode->UnLock();
798  }
799  if (!hasLK) myMutex->UnLock();
800  }
801  } LockHandler(&STMutex, theNode, immed);
802 
803  XrdCmsNode *altNode = 0;
804  int Inst, NodeID = theNode->ID(Inst);
805 
806 // The LockHandler makes sure that the proper locks are obtained in a deadlock
807 // free order. However, this may require that the node lock be released and
808 // then re-aquired. We check if we are still dealing with same node at entry.
809 // If not, issue message and high-tail it out.
810 //
811  if (LockHandler.myNID != NodeID || LockHandler.myInst != Inst)
812  {Say.Emsg("Manager", LockHandler.myIdent, "removal aborted.");
813  DEBUG(LockHandler.myIdent <<" node " <<NodeID <<'.' <<Inst <<" != "
814  << LockHandler.myNID <<'.' <<LockHandler.myInst <<" at entry.");
815  }
816 
817 // Mark node as being offline and remove any drop job from it
818 //
819  theNode->isOffline = 1; // Global lock is held here
820 
821 // If the node is connected we simply close the connection. This will cause
822 // the connection handler to re-initiate the node removal. This condition
823 // exists only if one node is being displaced by another node. The Disc()
824 // may take a long time, but it's done async by default on the WAN and sync
825 // on the LAN (local connections are fast enough and error-free for this).
826 //
827  if (theNode->isConn)
828  {theNode->Disc(reason, 0);
829  theNode->isGone = 1; // Disc() sets the isOffline flag
830  return;
831  }
832 
833 // If we are not the primary node, then get rid of this node post-haste
834 //
835  if (!(NodeTab[NodeID] == theNode))
836  {const char *why = (theNode->isMan ? "dropped as alternate."
837  : "dropped and redirected.");
838  Say.Emsg("Remove_Node", theNode->Ident, why);
839  LockHandler.doDrop = true;
840  return;
841  }
842 
843 
844 // If the node is part of the cluster, do not count it anymore and
845 // indicate new state of this nodes if we are a reporting manager
846 //
847  if (theNode->isBound)
848  {theNode->isBound = 0;
849  NodeCnt--;
850  if (Config.asManager())
852  theNode->isBad & XrdCmsNode::isSuspend ? 0 : -1,
853  theNode->isNoStage ? 0 : -1);
854  }
855 
856 // If we have a working alternate, substitute it here and immediately drop
857 // the former primary. This allows the cache to remain warm.
858 //
859  if (theNode->isMan && theNode->cidP && !(theNode->cidP->IsSingle())
860  && (altNode = theNode->cidP->RemNode(theNode)))
861  {if (altNode->isBound) NodeCnt++;
862  NodeTab[NodeID] = altNode;
863  if (Config.asManager())
865  altNode->isBad & XrdCmsNode::isSuspend ? 0 : 1,
866  altNode->isNoStage ? 0 : 1);
867  setAltMan(altNode->NodeID, altNode->Link, altNode->subsPort);
868  Say.Emsg("Manager",altNode->Ident,"replacing dropped",theNode->Ident);
869  LockHandler.doDrop = true;
870  return;
871  }
872 
873 // If this is an immediate drop request, do so now. Drop() will delete
874 // the node object, so remove the node lock and tell LockHandler that.
875 //
876  if (immed || !Config.DRPDelay || theNode->isBad & XrdCmsNode::isDoomed)
877  {theNode->UnLock();
878  LockHandler.myNode = 0;
879  Drop(NodeID, Inst);
880  return;
881  }
882 
883 // If a drop job is already scheduled, update the instance field. Otherwise,
884 // Schedule a node drop at a future time.
885 //
886  theNode->DropTime = time(0)+Config.DRPDelay;
887  if (theNode->DropJob) theNode->DropJob->nodeInst = Inst;
888  else theNode->DropJob = new XrdCmsDrop(NodeID, Inst);
889 
890 // Document removal
891 //
892  if (reason)
893  Say.Emsg("Manager", theNode->Ident, "scheduled for removal;", reason);
894  else DEBUG(theNode->Ident <<" node " <<NodeID <<'.' <<Inst);
895 }
size_t strlcpy(char *dst, const char *src, size_t sz)
XrdCmsNode * RemNode(XrdCmsNode *nP)
friend class XrdCmsDrop
char isGone
Definition: XrdCmsNode.hh:72
int ID(int &INum)
Definition: XrdCmsNode.hh:139
void Disc(const char *reason=0, int needLock=1)
Definition: XrdCmsNode.cc:256
void UnLock()
Definition: XrdCmsNode.hh:177

References XrdCmsConfig::asManager(), XrdCms::CmsState, XrdCms::Config, XrdCmsState::Counts, DEBUG, XrdCmsNode::Disc(), XrdCmsConfig::DRPDelay, XrdSysError::Emsg(), EPNAME, XrdCmsNode::ID(), XrdCmsNode::Ident, XrdCmsNode::isBad, XrdCmsNode::isBound, XrdCmsNode::isConn, XrdCmsNode::isDoomed, XrdCmsNode::isGone, XrdCmsNode::isMan, XrdCmsNode::isNoStage, XrdCmsNode::isOffline, XrdCmsClustID::IsSingle(), XrdCmsNode::isSuspend, XrdCmsNode::Lock(), XrdCmsDrop::nodeInst, XrdCmsNode::Ref(), XrdCmsClustID::RemNode(), XrdCms::Say, strlcpy(), XrdCmsNode::UnLock(), XrdSysRWLock::UnLock(), XrdCmsNode::unRef(), XrdCmsState::Update(), and XrdSysRWLock::WriteLock().

+ Here is the call graph for this function:

◆ Remove() [2/2]

void XrdCmsCluster::Remove ( XrdCmsNode theNode)

Definition at line 754 of file XrdCmsCluster.cc.

755 {
756  theNode->DropJob = new XrdCmsDrop(theNode);
757 }

Referenced by XrdCmsProtocol::Process().

+ Here is the caller graph for this function:

◆ ResetRef()

void XrdCmsCluster::ResetRef ( SMask_t  smask,
bool  isLocked = false 
)

Definition at line 901 of file XrdCmsCluster.cc.

902 {
903  XrdCmsNode *nP;
904  bool doAll (nMask == 0);
905 
906 // Obtain a lock on the table if not already locked
907 //
908  if (!isLocked) STMutex.ReadLock();
909 
910 // Reset reference counts as needed. We can do this with a read lock as the
911 // reference counters are atomic.
912 //
913  for (int i = 0; i <= STHi; i++)
914  {if ((nP = NodeTab[i]) && (doAll || nP->isNode(nMask)))
915  {nP->RefW = 0;
916  nP->RefR = 0;
917  nP->Shrem = nP->Share;
918  }
919  }
920 
921 // Unlock table and exit
922 //
923  if (!isLocked) STMutex.UnLock();
924 }

References XrdCmsNode::isNode().

+ Here is the call graph for this function:

◆ Select() [1/2]

int XrdCmsCluster::Select ( SMask_t  pmask,
int &  port,
char *  hbuff,
int &  hlen,
int  isrw,
int  isMulti,
int  ifWant 
)

Definition at line 1086 of file XrdCmsCluster.cc.

1088 {
1089  static const SMask_t smLow(255);
1090  XrdCmsSelector selR;
1091  XrdCmsNode *nP = 0;
1092  SMask_t tmask;
1093  int Snum = 0;
1094  XrdNetIF::ifType nType = static_cast<XrdNetIF::ifType>(ifWant);
1095 
1096 // If there is nothing to select from, return failure
1097 //
1098  if (!pmask) return 0;
1099 
1100 // Obtain the network we need for the client
1101 //
1102  selR.needNet = XrdNetIF::Mask(nType);
1103 
1104 // Initialize
1105 //
1106  selR.needSpace = 0;
1107 
1108 // Packed selection can never occur in this code path so we turn it off
1109 //
1110  selR.selPack = 0;
1111 
1112 // If we are exporting a shared-everything system then the incoming mask
1113 // may have more than one server indicated. So, we need to do a full select.
1114 // This is forced when isMulti is true, indicating a choice may exist. Note
1115 // that the node, if any, is returned unlocked but we have the global mutex.
1116 //
1117  if (isMulti || baseFS.isDFS())
1118  {STMutex.ReadLock();
1119  nP = (Config.sched_RR ? SelbyRef(pmask,selR)
1120  : Config.sched_LoadR == 0 ? SelbyLoad(pmask,selR)
1121  : SelbyLoadR(pmask, selR));
1122 
1123  if (nP) hlen = nP->netIF.GetPublicName(hbuff, port) + 1;
1124  else hlen = 0;
1125  STMutex.UnLock();
1126  return hlen != 1;
1127  }
1128 
1129 // In shared-nothing systems the incoming mask will only have a single node.
1130 // Compute the a single node number that is contained in the mask.
1131 //
1132  do {if (!(tmask = pmask & smLow)) Snum += 8;
1133  else {while((tmask = tmask>>1)) Snum++; break;}
1134  } while((pmask = pmask >> 8));
1135 
1136 // See if the node passes muster
1137 //
1138  STMutex.ReadLock();
1139  if ((nP = NodeTab[Snum]))
1140  { if (nP->isBad) nP = 0;
1141  else if (!Config.sched_RR && (nP->myLoad > Config.MaxLoad)) nP = 0;
1142  else if (!(selR.needNet & nP->hasNet)) nP = 0;
1143  if (nP)
1144  {if (isrw)
1145  if (nP->isNoStage || nP->DiskFree < nP->DiskMinF) nP = 0;
1146  else {nP->RefTotW++; nP->RefW++;}
1147  else {nP->RefTotR++; nP->RefR++;}
1148  }
1149  }
1150 
1151 // At this point either we have a node or we do not
1152 //
1153  if (nP)
1154  {hlen = nP->netIF.GetPublicName(hbuff, port) + 1;
1155  nP->RefR++;
1156  STMutex.UnLock();
1157  return hlen != 1;
1158  }
1159  STMutex.UnLock();
1160  return 0;
1161 }
int DiskMinF
Definition: XrdCmsNode.hh:89
int DiskFree
Definition: XrdCmsNode.hh:90
char hasNet
Definition: XrdCmsNode.hh:62
char Mask()
Definition: XrdNetIF.hh:288
int GetPublicName(char *nbuff, int &nport)
Definition: XrdNetIF.hh:150

References XrdCms::baseFS, XrdCms::Config, XrdCmsNode::DiskFree, XrdCmsNode::DiskMinF, XrdNetIF::GetPublicName(), XrdCmsNode::hasNet, XrdCmsNode::isBad, XrdCmsBaseFS::isDFS(), XrdCmsNode::isNoStage, XrdNetIF::Mask(), XrdCmsConfig::MaxLoad, XrdCmsSelector::needNet, XrdCmsSelector::needSpace, XrdCmsConfig::sched_LoadR, XrdCmsConfig::sched_RR, and XrdCmsSelector::selPack.

+ Here is the call graph for this function:

◆ Select() [2/2]

int XrdCmsCluster::Select ( XrdCmsSelect Sel)

Definition at line 930 of file XrdCmsCluster.cc.

931 {
932  EPNAME("Select");
933  XrdCmsPInfo pinfo;
934  const char *Amode;
935  int dowt = 0, retc = 0, isRW, fRD, noSel = (Sel.Opts & XrdCmsSelect::Defer);
936  SMask_t amask, smask, pmask;
937 
938 // Establish some local options
939 //
940  if (Sel.Opts & XrdCmsSelect::Write)
941  {isRW = 1; Amode = "write";
942  if (Config.RWDelay)
943  if (Sel.Opts & XrdCmsSelect::Create && Config.RWDelay < 2) fRD = 1;
944  else fRD = 0;
945  else fRD = 1;
946  }
947  else {isRW = 0; Amode = "read"; fRD = 1;}
948 
949 // Find out who serves this path
950 //
951  if (!Cache.Paths.Find(Sel.Path.Val, pinfo)
952  || (amask = ((isRW ? pinfo.rwvec : pinfo.rovec) & ~Sel.nmask)) == 0)
953  {Sel.Resp.DLen = snprintf(Sel.Resp.Data, sizeof(Sel.Resp.Data)-1,
954  "No servers %s %s access to the file",
955  (isRW && Config.forceRO ? "allowed" : "have"), Amode)+1;
956  Sel.Resp.Port = kYR_ENOENT;
957  return EReplete;
958  }
959 
960 // If we are running a shared file system preform an optional restricted
961 // pre-selection and then do a standard selection. Since all nodes are equal,
962 // make sure the client is needlessly avoiding them as this signals an error.
963 //
964  if (baseFS.isDFS())
965  {if (Sel.nmask && !(Sel.Opts & XrdCmsSelect::NoTryLim))
966  {pmask = (isRW ? pinfo.rwvec : pinfo.rovec) & Sel.nmask;
967  if (!(Sel.Opts & XrdCmsSelect::Online))
968  pmask |= pinfo.ssvec & Sel.nmask;
969  if (pmask && maxBits(pmask, baseFS.dfsTries()))
970  {Sel.Resp.DLen = snprintf(Sel.Resp.Data, sizeof(Sel.Resp.Data)-1,
971  "Too many DFS %s attempts; operation terminated", Amode)+1;
972  return RetryErr;
973  }
974  }
975  pmask = amask;
976  smask = (Sel.Opts & XrdCmsSelect::Online ? 0 : pinfo.ssvec & amask);
977  if (baseFS.Trim())
978  {Sel.Resp.DLen = 0;
979  if (!(retc = SelDFS(Sel, amask, pmask, smask, isRW)))
980  return (fRD ? Cache.WT4File(Sel,Sel.Vec.hf) : Config.LUPDelay);
981  if (retc < 0) return retc;
982  } else if (noSel) return 0;
983  return SelNode(Sel, pmask, smask);
984  }
985 
986 // If either a refresh is wanted or we didn't find the file, re-prime the cache
987 // which will force the client to wait. Otherwise, compute the primary and
988 // secondary selections. If there are none, the client may have to wait if we
989 // have servers that we can query regarding the file. Note that for files being
990 // opened in write mode, only one writable copy may exist unless this is a
991 // meta-operation (e.g., remove) in which case the file itself remain unmodified
992 // or a replica request, in which case we select a new target server.
993 //
994  if (!(Sel.Opts & XrdCmsSelect::Refresh)
995  && (retc = Cache.GetFile(Sel, pinfo.rovec)))
996  {if (isRW)
997  { if (retc<0) return Config.LUPDelay;
998  else if (Sel.Opts & XrdCmsSelect::Replica)
999  {pmask = amask & ~(Sel.Vec.hf | Sel.Vec.bf); smask = 0;
1000  if (!pmask && !Sel.Vec.bf) return SelFail(Sel,eNoRep);
1001  }
1002  else if (Sel.Vec.bf) pmask = smask = 0;
1003  else if (Sel.Vec.hf)
1004  {if (Sel.Opts & XrdCmsSelect::NewFile) return SelFail(Sel,eExists);
1005  if (!(Sel.Opts & XrdCmsSelect::MWFiles))
1006  {if (!(Sel.Opts & XrdCmsSelect::isMeta)
1007  && maxBits(Sel.Vec.hf,2)) return SelFail(Sel,eDups);
1008  if ((Sel.Vec.hf & pinfo.rwvec)
1009  != (Sel.Vec.hf & pinfo.rovec)) return SelFail(Sel,eROfs);
1010  }
1011  if (!(pmask = Sel.Vec.hf & amask)) return SelFail(Sel,eNoSel);
1012  smask = 0;
1013  }
1014  else if (Sel.Opts & (XrdCmsSelect::Trunc | XrdCmsSelect::NewFile))
1015  {pmask = amask; smask = 0;}
1016  else if ((smask = pinfo.ssvec & amask)) pmask = 0;
1017  else pmask = smask = 0;
1018  } else {
1019  pmask = Sel.Vec.hf & amask;
1020  if (Sel.Opts & XrdCmsSelect::Online) {pmask &= ~Sel.Vec.pf; smask=0;}
1021  else smask = (retc < 0 ? 0 : pinfo.ssvec & amask);
1022  }
1023  if (Sel.Vec.hf & Sel.nmask) Cache.UnkFile(Sel, Sel.nmask);
1024  } else {
1025  Cache.AddFile(Sel, 0);
1026  Sel.Vec.bf = pinfo.rovec;
1027  Sel.Vec.hf = Sel.Vec.pf = pmask = smask = 0;
1028  retc = 0;
1029  }
1030 
1031 // A wait is required if we don't have any primary or seconday servers
1032 //
1033  dowt = (!pmask && !smask);
1034 
1035 // If we can query additional servers, do so now. The client will be placed
1036 // in the callback queue only if we have no possible selections
1037 //
1038  if (Sel.Vec.bf)
1039  {CmsStateRequest QReq = {{Sel.Path.Hash, kYR_state, kYR_raw, 0}};
1040  if (Sel.Opts & XrdCmsSelect::Refresh)
1041  QReq.Hdr.modifier |= CmsStateRequest::kYR_refresh;
1042  if (dowt) retc= (fRD ? Cache.WT4File(Sel,Sel.Vec.hf) : Config.LUPDelay);
1043  TRACE(Files, "seeking " <<Sel.Path.Val);
1044  amask = Cluster.Broadcast(Sel.Vec.bf, QReq.Hdr,
1045  (void *)Sel.Path.Val,Sel.Path.Len+1);
1046  if (amask) Cache.UnkFile(Sel, amask);
1047  if (dowt) return retc;
1048  } else if (dowt && retc < 0 && !noSel)
1049  return (fRD ? Cache.WT4File(Sel,Sel.Vec.hf) : Config.LUPDelay);
1050 
1051 // Broadcast a freshen up request if wanted
1052 //
1053  if ((Sel.Opts & XrdCmsSelect::Freshen) && (amask = pmask & ~Sel.Vec.bf))
1054  {CmsStateRequest Qupt={{0,kYR_state,kYR_raw|CmsStateRequest::kYR_noresp,0}};
1055  Cluster.Broadcast(amask, Qupt.Hdr,(void *)Sel.Path.Val,Sel.Path.Len+1);
1056  }
1057 
1058 // If we need to defer selection, simply return as this is a mindless prepare
1059 //
1060  if (noSel) return 0;
1061 
1062 // Check if we have no useable servers
1063 //
1064  if (dowt) return Unuseable(Sel);
1065 
1066 // Check if should eliminate staging servers. We may need to do this if the
1067 // client has been eliminating too many of them as they all should be equal.
1068 //
1069  if (Sel.nmask && pinfo.ssvec && !(Sel.Opts & XrdCmsSelect::NoTryLim)
1070  && maxBits(Sel.nmask & pinfo.ssvec, baseFS.stgTries()))
1071  {if (!pmask)
1072  {Sel.Resp.DLen = snprintf(Sel.Resp.Data, sizeof(Sel.Resp.Data)-1,
1073  "Too many attempts to stage %s access to the file", Amode)+1;
1074  return RetryErr;
1075  }
1076  smask = 0;
1077  }
1078 
1079 // Select a node
1080 //
1081  return SelNode(Sel, pmask, smask);
1082 }
static const int EReplete
static const int RetryErr
SMask_t nmask
Definition: XrdCmsSelect.hh:48
@ kYR_ENOENT
Definition: YProtocol.hh:150

References XrdCmsCache::AddFile(), XrdCms::baseFS, Broadcast(), XrdCms::Cache, XrdCms::Cluster, XrdCms::Config, XrdCmsSelect::Create, XrdCmsSelect::Defer, XrdCmsBaseFS::dfsTries(), EPNAME, XrdCmsPList_Anchor::Find(), XrdCmsConfig::forceRO, XrdCmsSelect::Freshen, XrdCmsCache::GetFile(), XrdCmsKey::Hash, XrdCms::CmsStateRequest::Hdr, if(), XrdCmsBaseFS::isDFS(), XrdCmsSelect::isMeta, XrdCms::kYR_ENOENT, XrdCms::CmsStateRequest::kYR_noresp, XrdCms::kYR_raw, XrdCms::CmsStateRequest::kYR_refresh, XrdCms::kYR_state, XrdCmsKey::Len, XrdCmsConfig::LUPDelay, XrdCms::CmsRRHdr::modifier, XrdCmsSelect::MWFiles, XrdCmsSelect::NewFile, XrdCmsSelect::nmask, XrdCmsSelect::NoTryLim, XrdCmsSelect::Online, XrdCmsSelect::Opts, XrdCmsSelect::Path, XrdCmsCache::Paths, XrdCmsSelect::Refresh, XrdCmsSelect::Replica, XrdCmsSelect::Resp, XrdCmsPInfo::rovec, XrdCmsConfig::RWDelay, XrdCmsPInfo::rwvec, XrdCmsPInfo::ssvec, XrdCmsBaseFS::stgTries(), TRACE, XrdCmsBaseFS::Trim(), XrdCmsSelect::Trunc, XrdCmsCache::UnkFile(), XrdCmsKey::Val, XrdCmsSelect::Vec, XrdCmsSelect::Write, and XrdCmsCache::WT4File().

Referenced by XrdCmsNode::do_Mv(), XrdCmsNode::do_Select(), and XrdCmsNode::do_SelPrep().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ SLock()

void XrdCmsCluster::SLock ( bool  dolock,
bool  wrmode = true 
)
inline

Definition at line 200 of file XrdCmsCluster.hh.

201  {if (dolock)
202  {if (wrmode) STMutex.WriteLock();
203  else STMutex.ReadLock();
204  }
205  else STMutex.UnLock();
206  }

References XrdSysRWLock::ReadLock(), XrdSysRWLock::UnLock(), and XrdSysRWLock::WriteLock().

Referenced by XrdCmsNode::do_Status(), and XrdCmsProtocol::Process().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ Space()

void XrdCmsCluster::Space ( XrdCms::SpaceData sData,
SMask_t  smask 
)

Definition at line 1215 of file XrdCmsCluster.cc.

1216 {
1217  XrdCmsNode *nP;
1218  SMask_t bmask;
1219  int i;
1220  bool doAll = !baseFS.isDFS();
1221 
1222 // Obtain a lock on the table and screen out peer nodes
1223 //
1224  STMutex.ReadLock();
1225  bmask = smask & peerMask;
1226 
1227 // Run through the table getting space information
1228 //
1229  for (i = 0; i <= STHi; i++)
1230  if ((nP = NodeTab[i]) && nP->isNode(bmask) && !(nP->isOffline))
1231  {if (doAll || !sData.Total)
1232  {sData.Total += nP->DiskTotal;
1233  sData.TotFr += nP->DiskFree;
1234  }
1235  if (nP->isRW & XrdCmsNode::allowsSS)
1236  {sData.sNum++;
1237  if (sData.sFree < nP->DiskFree)
1238  {sData.sFree = nP->DiskFree; sData.sUtil = nP->DiskUtil;}
1239  }
1240  if (nP->isRW & XrdCmsNode::allowsRW)
1241  {sData.wNum++;
1242  if (sData.wFree < nP->DiskFree)
1243  {sData.wFree = nP->DiskFree; sData.wUtil = nP->DiskUtil;
1244  sData.wMinF = nP->DiskMinF;
1245  }
1246  }
1247  }
1248  STMutex.UnLock();
1249 }
static const char allowsRW
Definition: XrdCmsNode.hh:84
static const char allowsSS
Definition: XrdCmsNode.hh:85
int DiskUtil
Definition: XrdCmsNode.hh:91
unsigned int DiskTotal
Definition: XrdCmsNode.hh:87

References XrdCmsNode::allowsRW, XrdCmsNode::allowsSS, XrdCms::baseFS, XrdCmsNode::DiskFree, XrdCmsNode::DiskMinF, XrdCmsNode::DiskTotal, XrdCmsNode::DiskUtil, XrdCmsBaseFS::isDFS(), XrdCmsNode::isNode(), XrdCmsNode::isOffline, XrdCmsNode::isRW, XrdCms::SpaceData::sFree, XrdCms::SpaceData::sNum, XrdCms::SpaceData::sUtil, XrdCms::SpaceData::Total, XrdCms::SpaceData::TotFr, XrdCms::SpaceData::wFree, XrdCms::SpaceData::wMinF, XrdCms::SpaceData::wNum, and XrdCms::SpaceData::wUtil.

Referenced by XrdCmsNode::do_StatFS().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ Stats()

int XrdCmsCluster::Stats ( char *  bfr,
int  bln 
)

Definition at line 1255 of file XrdCmsCluster.cc.

1256 {
1257  static const char statfmt1[] = "<stats id=\"cms\">"
1258  "<role>%s</role></stats>";
1259  int mlen;
1260 
1261 // Check if actual length wanted
1262 //
1263  if (!bfr) return sizeof(statfmt1) + 8;
1264 
1265 // Format the statistics (not much here for now)
1266 //
1267  mlen = snprintf(bfr, bln, statfmt1, Config.myRType);
1268 
1269  if ((bln -= mlen) <= 0) return 0;
1270  return mlen;
1271 }
char myRType[4]

References XrdCms::Config, and XrdCmsConfig::myRType.

Referenced by XrdCmsNode::do_Stats(), and XrdCmsProtocol::Stats().

+ Here is the caller graph for this function:

◆ Statt()

int XrdCmsCluster::Statt ( char *  bfr,
int  bln 
)

Definition at line 1277 of file XrdCmsCluster.cc.

1278 {
1279  static const char statfmt0[] = "</stats>";
1280  static const char statfmt1[] = "<stats id=\"cmsm\">"
1281  "<role>%s</role><sel><t>%lld</t><r>%lld</r><w>%lld</w></sel>"
1282  "<node>%d";
1283  static const char statfmt2[] = "<stats id=\"%d\">"
1284  "<host>%s</host><role>%s</role>"
1285  "<run>%s</run><ref><r>%d</r><w>%d</w></ref>%s</stats>";
1286  static const char statfmt3[] = "<shr>%d<use>%d</use></shr>";
1287  static const char statfmt4[] = "</node>";
1288  static const char statfmt5[] =
1289  "<frq><add>%lld<d>%lld</d></add><rsp>%lld<m>%lld</m></rsp>"
1290  "<lf>%lld</lf><ls>%lld</ls><rf>%lld</rf><rs>%lld</rs></frq>";
1291 
1292  static int AddFrq = (Config.RepStats & XrdCmsConfig::RepStat_frq);
1293  static int AddShr = (Config.RepStats & XrdCmsConfig::RepStat_shr)
1294  && Config.asMetaMan();
1295 
1296  XrdCmsRRQ::Info Frq;
1297  XrdCmsSelected *sp;
1298  int mlen, tlen, n = 0;
1299  char shrBuff[80], stat[6], *stp;
1300  bool oksel;
1301 
1302  class spmngr {
1303  public: XrdCmsSelected *sp;
1304 
1305  spmngr() {sp = 0;}
1306  ~spmngr() {XrdCmsSelected *xsp;
1307  while((xsp = sp)) {sp = sp->next; delete xsp;}
1308  }
1309  } mngrsp;
1310 
1311 // Check if actual length wanted
1312 //
1313  if (!bfr)
1314  {n = sizeof(statfmt0) +
1315  sizeof(statfmt1) + 12*3 + 3 + 3 +
1316  (sizeof(statfmt2) + 10*2 + 256 + 16) * STMax + sizeof(statfmt4);
1317  if (AddShr) n += sizeof(statfmt3) + 12;
1318  if (AddFrq) n += sizeof(statfmt4) + (10*8);
1319  return n;
1320  }
1321 
1322 // Get the statistics
1323 //
1324  if (AddFrq) RRQ.Statistics(Frq);
1325  mngrsp.sp = sp = List(FULLMASK, LS_NULL, oksel);
1326 
1327 // Count number of nodes we have
1328 //
1329  while(sp) {n++; sp = sp->next;}
1330  sp = mngrsp.sp;
1331 
1332 // Format the statistics
1333 //
1334  long long lclTcnt = SelTcnt, lclRtot = SelRtot, lclWtot = SelWtot;
1335  mlen = snprintf(bfr, bln, statfmt1,
1336  Config.myRType, lclTcnt, lclRtot, lclWtot, n);
1337 
1338  if ((bln -= mlen) <= 0) return 0;
1339  tlen = mlen; bfr += mlen; n = 0; *shrBuff = 0;
1340 
1341  while(sp && bln > 0)
1342  {stp = stat;
1343  if (sp->Status & XrdCmsSelected::Offline) *stp++ = 'o';
1344  else if (sp->Status & XrdCmsSelected::Suspend) *stp++ = 's';
1345  else if (sp->Status & XrdCmsSelected::Disable) *stp++ = 'd';
1346  else *stp++ = 'a';
1347  if (sp->Status & XrdCmsSelected::isRW) *stp++ = 'w';
1348  if (sp->Status & XrdCmsSelected::NoStage) *stp++ = 'n';
1349  *stp = 0;
1350  if (AddShr) snprintf(shrBuff, sizeof(shrBuff), statfmt3,
1351  (sp->Share ? sp->Share : 100), sp->Shrin);
1352  mlen = snprintf(bfr, bln, statfmt2, n, sp->Ident,
1353  XrdCmsRole::Type(static_cast<XrdCmsRole::RoleID>(sp->RoleID)),
1354  stat, sp->RefTotR, sp->RefTotW, shrBuff);
1355  bfr += mlen; bln -= mlen; tlen += mlen;
1356  sp = sp->next; n++;
1357  }
1358 
1359  if (bln <= (int)sizeof(statfmt4)) return 0;
1360  strcpy(bfr, statfmt4); mlen = sizeof(statfmt4) - 1;
1361  bfr += mlen; bln -= mlen; tlen += mlen;
1362 
1363  if (AddFrq && bln > 0)
1364  {mlen = snprintf(bfr, bln, statfmt5, Frq.Add2Q, Frq.PBack, Frq.Resp,
1365  Frq.Multi, Frq.luFast, Frq.luSlow, Frq.rdFast, Frq.rdSlow);
1366  bfr += mlen; bln -= mlen; tlen += mlen;
1367  }
1368 
1369 // See if we overflowed. otherwise finish up
1370 //
1371  if (sp || bln < (int)sizeof(statfmt0)) return 0;
1372  strcpy(bfr, statfmt0);
1373  return tlen + sizeof(statfmt0) - 1;
1374 }
#define FULLMASK
Definition: XrdCmsTypes.hh:35
int stat(const char *path, struct stat *buf)
XrdCmsSelected * List(SMask_t mask, CmsLSOpts opts, bool &oksel)
static const int RepStat_shr
static const int RepStat_frq
void Statistics(Info &Data)
Definition: XrdCmsRRQ.hh:144
static const char * Type(RoleID rid)
Definition: XrdCmsRole.hh:78
char Ident[IdentSize]
XrdCmsSelected * next
XrdCmsRRQ RRQ
Definition: XrdCmsRRQ.cc:55
long long luSlow
Definition: XrdCmsRRQ.hh:139
long long rdSlow
Definition: XrdCmsRRQ.hh:141
long long Resp
Definition: XrdCmsRRQ.hh:136
long long luFast
Definition: XrdCmsRRQ.hh:138
long long Add2Q
Definition: XrdCmsRRQ.hh:134
long long Multi
Definition: XrdCmsRRQ.hh:137
long long rdFast
Definition: XrdCmsRRQ.hh:140
long long PBack
Definition: XrdCmsRRQ.hh:135

References XrdCmsRRQ::Info::Add2Q, XrdCmsConfig::asMetaMan(), XrdCms::Config, XrdCmsSelected::Disable, FULLMASK, XrdCmsSelected::Ident, XrdCmsSelected::isRW, XrdCl::List(), XrdCmsRRQ::Info::luFast, XrdCmsRRQ::Info::luSlow, XrdCmsRRQ::Info::Multi, XrdCmsConfig::myRType, XrdCmsSelected::next, XrdCmsSelected::NoStage, XrdCmsSelected::Offline, XrdCmsRRQ::Info::PBack, XrdCmsRRQ::Info::rdFast, XrdCmsRRQ::Info::rdSlow, XrdCmsSelected::RefTotR, XrdCmsSelected::RefTotW, XrdCmsConfig::RepStat_frq, XrdCmsConfig::RepStat_shr, XrdCmsConfig::RepStats, XrdCmsRRQ::Info::Resp, XrdCmsSelected::RoleID, XrdCms::RRQ, XrdCmsSelected::Share, XrdCmsSelected::Shrin, stat(), XrdCmsRRQ::Statistics(), XrdCmsSelected::Status, STMax, XrdCmsSelected::Suspend, and XrdCmsRole::Type().

Referenced by XrdCmsProtocol::Stats().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

Friends And Related Function Documentation

◆ XrdCmsDrop

friend class XrdCmsDrop
friend

Definition at line 117 of file XrdCmsCluster.hh.

Member Data Documentation

◆ EReplete

const int XrdCmsCluster::EReplete = -4
static

Definition at line 191 of file XrdCmsCluster.hh.

Referenced by XrdCmsNode::do_SelAvoid(), and XrdCmsNode::do_Select().

◆ NodeCnt

int XrdCmsCluster::NodeCnt

Definition at line 119 of file XrdCmsCluster.hh.

Referenced by XrdCmsProtocol::Execute().

◆ NotFound

const int XrdCmsCluster::NotFound = -1
static

Definition at line 188 of file XrdCmsCluster.hh.

◆ RetryErr

const int XrdCmsCluster::RetryErr = -3
static

Definition at line 190 of file XrdCmsCluster.hh.

Referenced by XrdCmsNode::do_Select().

◆ Wait4CBk

const int XrdCmsCluster::Wait4CBk = -2
static

Definition at line 189 of file XrdCmsCluster.hh.

Referenced by XrdCmsNode::do_Locate().


The documentation for this class was generated from the following files: