XRootD
Loading...
Searching...
No Matches
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.

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}

References NodeCnt.

◆ ~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)
#define EPNAME(x)
#define QTRACE(act)
#define STMax
bool Debug
if(ec< 0) ec
static XrdCmsClustID * AddID(const char *cID)
static XrdCmsClustID * Find(const char *cID)
bool AddNode(XrdCmsNode *nP, bool isMan)
void Remove(XrdCmsNode *theNode)
char * Ident
Definition XrdCmsNode.hh:61
void Lock()
static const char isDisabled
Definition XrdCmsNode.hh:80
char isOffline
Definition XrdCmsNode.hh:64
static const char isSuspend
Definition XrdCmsNode.hh:81
char isNoStage
Definition XrdCmsNode.hh:66
void setName(XrdLink *lnkp, const char *theIF, int port)
void Update(StateType StateT, int ActivVal, int StageVal=0)
void Set(int ncount)
int Emsg(const char *esfx, int ecode, const char *text1, const char *text2=0)
static const int CMS_isSuper
static const int CMS_noStage
XrdSysError Say
XrdCmsState CmsState
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, 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(), NodeCnt, QTRACE, Remove(), 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)
int Send(const char *buff, int blen=0)
char * Name()
void g2nLock(XrdSysRWLock &gMutex)
static const char isDoomed
Definition XrdCmsNode.hh:82
static const char isBlisted
Definition XrdCmsNode.hh:79
static const unsigned char kYR_Version
Definition YProtocol.hh:80

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, XrdCmsNode::Send(), XrdSysRWLock::UnLock(), and XrdSysRWLock::WriteLock().

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 Broadcast(), 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 Broadcast(), and XrdCms::CmsRRHdr::datalen.

+ Here is the call graph for this function:

◆ 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
void unRef()
int isNode(SMask_t smask)
SMask_t Mask()

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

Referenced by Broadcast(), Broadcast(), XrdCmsNode::do_StateFWD(), Locate(), MonPerf(), 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//
475do{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, XrdSysRWLock::ReadLock(), XrdCmsNode::Ref(), XrdCmsNode::Send(), XrdSysRWLock::UnLock(), 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(), XrdSysRWLock::ReadLock(), and XrdSysRWLock::UnLock().

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.GetDest(sip->Ident, iSize,
561 ifGet, retName);
562 else if (nP->myNlen >= XrdCmsSelected::IdentSize) destLen = 0;
563 else {strcpy(sip->Ident, nP->myName); destLen = nP->myNlen;}
564 if (!destLen) {delete sip; continue;}
565
566 sip->IdentLen = destLen;
567 sip->Mask = nP->NodeMask;
568 sip->Id = nP->NodeID;
569 sip->Port = nP->netIF.Port();
570 sip->RefTotW = nP->RefTotW;
571 sip->RefTotR = nP->RefTotR;
572 sip->Shrin = nP->Shrin;
573 sip->Share = nP->Share;
574 sip->RoleID = nP->RoleID;
575 sip->Status = (nP->isOffline ? XrdCmsSelected::Offline : 0);
577 sip->Status |= XrdCmsSelected::Disable;
578 if (nP->isNoStage) sip->Status |= XrdCmsSelected::NoStage;
580 sip->Status |= XrdCmsSelected::Suspend;
581 if (nP->isRW ) sip->Status |= XrdCmsSelected::isRW;
582 if (nP->isMan ) sip->Status |= XrdCmsSelected::isMangr;
583 sipp = sip;
584 }
585 STMutex.UnLock();
586
587// Return result
588//
589 return sipp;
590}
struct myOpts opts
static const int IdentSize
int Port()
Definition XrdNetIF.hh:276
bool HasDest(ifType ifT=PublicV6)
Definition XrdNetIF.hh:221
int GetDest(char *dest, int dlen, ifType ifT=PublicV6, bool prefn=false)
Definition XrdNetIF.cc:389
ifType
The enum that is used to index into ifData to get appropriate interface.
Definition XrdNetIF.hh:64
@ PrivateIF
Definition XrdNetIF.hh:68

References XrdCmsSelected::Disable, XrdNetIF::GetDest(), XrdNetIF::HasDest(), XrdCmsSelected::IdentSize, XrdCmsNode::isBad, XrdCmsNode::isBlisted, XrdCmsNode::isDisabled, XrdCmsNode::isMan, XrdCmsSelected::isMangr, XrdCmsNode::isNoStage, XrdCmsNode::isOffline, XrdCmsNode::isRW, XrdCmsSelected::isRW, XrdCmsNode::isSuspend, LS_ANY, LS_IDNT, LS_IFMASK, LS_IPO, XrdCmsSelected::NoStage, XrdCmsSelected::Offline, opts, XrdNetIF::Port(), XrdNetIF::PrivateIF, XrdSysRWLock::ReadLock(), XrdCmsNode::RoleID, XrdCmsSelected::Suspend, and XrdSysRWLock::UnLock().

Referenced by XrdCmsNode::do_Locate(), and Statt().

+ 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 596 of file XrdCmsCluster.cc.

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

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

References XrdCmsConfig::AskPerf, XrdCmsConfig::AskPing, Broadcast(), 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 707 of file XrdCmsCluster.cc.

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

References XrdCms::Config, XrdSysRWLock::ReadLock(), XrdCmsConfig::RefReset, XrdCmsConfig::RefTurn, ResetRef(), XrdSysTimer::Snooze(), and XrdSysRWLock::UnLock().

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 766 of file XrdCmsCluster.cc.

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

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(), NodeCnt, XrdCmsDrop::nodeInst, XrdCmsNode::Ref(), XrdCmsClustID::RemNode(), XrdCms::Say, strlcpy(), XrdCmsNode::UnLock(), XrdSysRWLock::UnLock(), XrdCmsNode::unRef(), XrdCmsState::Update(), XrdSysRWLock::WriteLock(), and XrdCmsDrop.

+ Here is the call graph for this function:

◆ Remove() [2/2]

void XrdCmsCluster::Remove ( XrdCmsNode theNode)

Definition at line 755 of file XrdCmsCluster.cc.

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

References XrdCmsDrop.

Referenced by Add(), and XrdCmsProtocol::Process().

+ Here is the caller graph for this function:

◆ ResetRef()

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

Definition at line 902 of file XrdCmsCluster.cc.

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

References XrdCmsNode::isNode(), XrdSysRWLock::ReadLock(), and XrdSysRWLock::UnLock().

Referenced by MonRefs().

+ Here is the call graph for this function:
+ Here is the caller 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 1087 of file XrdCmsCluster.cc.

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

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

+ Here is the call graph for this function:

◆ Select() [2/2]

int XrdCmsCluster::Select ( XrdCmsSelect Sel)

Definition at line 931 of file XrdCmsCluster.cc.

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

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

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

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 1278 of file XrdCmsCluster.cc.

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

◆ XrdCmsDrop

friend class XrdCmsDrop
friend

Definition at line 117 of file XrdCmsCluster.hh.

Referenced by Remove(), and Remove().

Member Data Documentation

◆ EReplete

const int XrdCmsCluster::EReplete = -4
static

Definition at line 191 of file XrdCmsCluster.hh.

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

◆ NodeCnt

int XrdCmsCluster::NodeCnt

Definition at line 119 of file XrdCmsCluster.hh.

Referenced by XrdCmsCluster(), Add(), XrdCmsProtocol::Execute(), and Remove().

◆ NotFound

const int XrdCmsCluster::NotFound = -1
static

Definition at line 188 of file XrdCmsCluster.hh.

Referenced by Locate().

◆ RetryErr

const int XrdCmsCluster::RetryErr = -3
static

Definition at line 190 of file XrdCmsCluster.hh.

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

◆ Wait4CBk

const int XrdCmsCluster::Wait4CBk = -2
static

Definition at line 189 of file XrdCmsCluster.hh.

Referenced by XrdCmsNode::do_Locate(), and Locate().


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