XRootD
XrdCmsNode.cc
Go to the documentation of this file.
1 /***********************************************************************************************/
2 /* */
3 /* X r d C m s N o d e . c c */
4 /* */
5 /* (c) 2007 by the Board of Trustees of the Leland Stanford, Jr., University */
6 /* All Rights Reserved */
7 /* Produced by Andrew Hanushevsky for Stanford University under contract */
8 /* DE-AC02-76-SFO0515 with the Department of Energy */
9 /* */
10 /* This file is part of the XRootD software suite. */
11 /* */
12 /* XRootD is free software: you can redistribute it and/or modify it under */
13 /* the terms of the GNU Lesser General Public License as published by the */
14 /* Free Software Foundation, either version 3 of the License, or (at your */
15 /* option) any later version. */
16 /* */
17 /* XRootD is distributed in the hope that it will be useful, but WITHOUT */
18 /* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */
19 /* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public */
20 /* License for more details. */
21 /* */
22 /* You should have received a copy of the GNU Lesser General Public License */
23 /* along with XRootD in a file called COPYING.LESSER (LGPL license) and file */
24 /* COPYING (GPL license). If not, see <http://www.gnu.org/licenses/>. */
25 /* */
26 /* The copyright holder's institutional names and contributor's names may not */
27 /* be used to endorse or promote products derived from this software without */
28 /* specific prior written permission of the institution or contributor. */
29 /******************************************************************************/
30 
31 #include <limits.h>
32 #include <cstdio>
33 #include <ctime>
34 #include <netinet/in.h>
35 #include <sys/types.h>
36 #include <sys/stat.h>
37 
38 #include "Xrd/XrdJob.hh"
39 #include "Xrd/XrdLink.hh"
40 
41 #include "XProtocol/YProtocol.hh"
42 
43 #include "XrdCms/XrdCmsBaseFS.hh"
44 #include "XrdCms/XrdCmsCache.hh"
45 #include "XrdCms/XrdCmsCluster.hh"
46 #include "XrdCms/XrdCmsClustID.hh"
47 #include "XrdCms/XrdCmsConfig.hh"
48 #include "XrdCms/XrdCmsManager.hh"
49 #include "XrdCms/XrdCmsManList.hh"
50 #include "XrdCms/XrdCmsMeter.hh"
51 #include "XrdCms/XrdCmsPList.hh"
52 #include "XrdCms/XrdCmsPrepare.hh"
53 #include "XrdCms/XrdCmsRRData.hh"
54 #include "XrdCms/XrdCmsNode.hh"
55 #include "XrdCms/XrdCmsSelect.hh"
56 #include "XrdCms/XrdCmsState.hh"
57 #include "XrdCms/XrdCmsTrace.hh"
58 
59 #include "XrdOss/XrdOss.hh"
60 
61 #include "XrdOuc/XrdOucCRC.hh"
63 #include "XrdOuc/XrdOucProg.hh"
64 #include "XrdOuc/XrdOucPup.hh"
65 #include "XrdOuc/XrdOucUtils.hh"
66 
67 #include "XrdNet/XrdNetUtils.hh"
68 
69 #include "XrdSys/XrdSysE2T.hh"
70 #include "XrdSys/XrdSysPlatform.hh"
71 #include "XrdSys/XrdSysTimer.hh"
72 
73 using namespace XrdCms;
74 
75 /******************************************************************************/
76 /* S t a t i c O b j e c t s */
77 /******************************************************************************/
78 
79 XrdSysMutex XrdCmsNode::mlMutex;
80 
81 int XrdCmsNode::LastFree = 0;
82 
83 namespace
84 {
87 
88 const char *msrcmsg = "Cluster does not support multi-source access.";
89 int msrclen = strlen(msrcmsg)+1;
90 const char *mtrymsg = "Cluster retry limit exceeded.";
91 int mtrylen = strlen(mtrymsg)+1;
92 };
93 
94 /******************************************************************************/
95 /* C o n s t r u c t o r */
96 /******************************************************************************/
97 
98 XrdCmsNode::XrdCmsNode(XrdLink *lnkp, const char *theIF, const char *nid,
99  int port, int lvl, int id)
100 {
101  static XrdSysMutex iMutex;
102  static const SMask_t smask_1(1);
103  static int iNum = 1;
104 
105  Link = lnkp;
106  NodeMask = (id < 0 ? 0 : smask_1 << id);
107  NodeID = id;
108  isOffline= (lnkp == 0);
109  logload = Config.LogPerf;
110  myNID = strdup(nid ? nid : "?");
111  if ((myCID = index(myNID, ' '))) myCID++;
112  else myCID = myNID;
113  myLevel = lvl;
115 
116 // setName() will set the node identification information
117 //
118  setName(lnkp, theIF, (nid ? port : 0));
119 
120  iMutex.Lock();
121  Instance = iNum++;
122  iMutex.UnLock();
123 }
124 
125 /******************************************************************************/
126 /* D e s t r u c t o r */
127 /******************************************************************************/
128 
130 {
131  isOffline = 1; // STMutex not needed here
132 
133 // Delete other appendages
134 //
135  if (cidP) {cidP->RemNode(this); cidP = 0;}
136  if (Ident) free(Ident);
137  if (myNID) free(myNID);
138  if (myName)free(myName);
139 }
140 
141 /******************************************************************************/
142 /* s e t N a m e */
143 /******************************************************************************/
144 
145 void XrdCmsNode::setName(XrdLink *lnkp, const char *theIF, int port)
146 {
147  char buff[512];
148  const char *hname = lnkp->Host();
149 
150 // Check if this is a duplicate. Note that we check for strict equivalence.
151 //
152  if (myName)
153  {if (!strcmp(myName,hname) && port == netIF.Port()
154  && netID.Same(lnkp->NetAddr())) return;
155  free(myName);
156  }
157 
158 // Get our address information but substitute data port for actual port
159 //
160  netID = *(lnkp->NetAddr());
161 
162 // Set the network interface. Note that out of domain nodes are not allowed
163 // to specify interface addresses as this does not make global sense.
164 //
165  if (theIF && !netIF.InDomain(&netID)) theIF = 0;
166  netIF.SetIF(&netID, theIF, port);
167  hasNet = netIF.Mask();
168 
169  netIF.SetPublicName(hname);
170 
171 // Construct our identification
172 //
173  myName = strdup(hname);
174  myNlen = strlen(hname);
175 
176  if (!port) strcpy(buff, lnkp->ID);
177  else sprintf(buff, "%s:%d", lnkp->ID, port);
178  if (Ident) free(Ident);
179  Ident = strdup(buff);
180 }
181 
182 /******************************************************************************/
183 /* D e l e t e */
184 /******************************************************************************/
185 
187 {
188  EPNAME("Delete");
189  static const int warnIntvl = 60;
190  int totWait = 0, tmoWarn = 60;
191  int tmoWait (Config.DELDelay < 3 ? Config.DELDelay : 3);
192  bool doDel = true;
193 
194 // We need to make sure there are no references to this object. This is true
195 // when the refCnt is zero but only when we hold a global write lock that has
196 // been passed to us. As this node has been removed from all global tables
197 // at this point, we just need to make sure than no threads are poised to
198 // increase it. That can't happen if we obrtain a write lock. To start,
199 // get the node lock and do some debugging. Set the isGone flag even though it
200 // should be set. Note that we need to serialize with the refCnt as some
201 // threads may still be holding a reference to the node.
202 //
203  nodeMutex.Lock();
204  isGone = 1;
205  nodeMutex.UnLock();
206  DEBUG(Ident <<" refs=" <<refCnt);
207 
208 // Now wait for things to simmer down. We wait for an appropriate time because
209 // we don't want to occupy this thread forever.
210 //
211  gMutex.WriteLock();
212  while(refCnt)
213  {if (totWait >= Config.DELDelay) {doDel = false; break;}
214  gMutex.UnLock();
215  if (totWait >= tmoWarn)
216  {unsigned int theCnt = refCnt;
217  DeleteWarn(theCnt);
218  tmoWarn += warnIntvl;
219  }
220  XrdSysTimer::Snooze(tmoWait);
221  totWait += tmoWait;
222  gMutex.WriteLock();
223  }
224  gMutex.UnLock();
225 
226 // We can now safely delete this node
227 //
228  if (doDel) delete this;
229  else {char eBuff[256];
230  snprintf(eBuff, sizeof(eBuff),
231  " (%p) delete timeout; node object lost!", this);
232  Say.Emsg("Delete", Ident, eBuff);
233  }
234 }
235 
236 /******************************************************************************/
237 /* Private: D e l e t e W a r n */
238 /******************************************************************************/
239 
240 void XrdCmsNode::DeleteWarn(unsigned int lkVal)
241 {
242 
243 // Print warning
244 //
245  if (lkVal)
246  {char eBuff[256];
247  snprintf(eBuff, sizeof(eBuff), "delete sync stall; refs = %u", lkVal);
248  Say.Emsg("Delete", Ident, eBuff);
249  }
250 }
251 
252 /******************************************************************************/
253 /* D i s c */
254 /******************************************************************************/
255 
256 void XrdCmsNode::Disc(const char *reason, int needLock)
257 {
258 // Indicate we are offline. If a lock is not need then we only need to set the
259 // offline flag as it's already properly protected. Otherwise, set the flag
260 // after we get the lock. This is indeed messy.
261 //
262  if (needLock) nodeMutex.Lock();
263  isOffline = 1; // STMutex is already held if needed
264 
265 // If we are still connected, initiate a teardown. This may be done async as
266 // we are asking for a deferred close which will be followed by a full close.
267 //
268  if (isConn)
269  {Link->setEtext(reason);
270  Link->Close(1);
271  isConn = 0;
272  }
273 
274 // Unlock ourselves if we locked ourselves
275 //
276  if (needLock) nodeMutex.UnLock();
277 }
278 
279 /******************************************************************************/
280 /* d o _ A v a i l */
281 /******************************************************************************/
282 
283 // Node responses to space usage requests from a manager are localized to the
284 // cell and need not be propopagated in any direction.
285 //
287 {
288  EPNAME("do_Avail")
289 
290 // Process: avail <fsdsk> <util>
291 //
292  DiskFree = Arg.dskFree;
293  DiskUtil = static_cast<int>(Arg.dskUtil);
294 
295 // Do some debugging
296 //
297  DEBUGR(DiskFree <<"MB free; " <<DiskUtil <<"% util");
298  return 0;
299 }
300 
301 /******************************************************************************/
302 /* d o _ C h m o d */
303 /******************************************************************************/
304 
305 // Chmod requests are forwarded to all subscribers
306 //
308 {
309  EPNAME("do_Chmod")
310  mode_t mode = 0;
311  int rc;
312 
313 // Do some debugging
314 //
315  DEBUGR("mode " <<Arg.Mode <<' ' <<Arg.Path);
316 
317 // We are don here if we have no data; otherwise convert the mode if we
318 // haven't done so already.
319 //
320  if (!Config.DiskOK) return 0;
321  if (!mode && !getMode(Arg.Mode, mode)) return "invalid mode";
322 
323 // Attempt to change the mode either via call-out or the oss plug-in
324 //
325  if (Config.ProgCH) rc = fsExec(Config.ProgCH, Arg.Mode, Arg.Path);
326  else rc = Config.ossFS->Chmod(Arg.Path, mode);
327 
328 // Return appropriate result
329 //
330  return (rc ? fsFail(Arg.Ident, "chmod", Arg.Path, rc) : 0);
331 }
332 
333 /******************************************************************************/
334 /* d o _ D i s c */
335 /******************************************************************************/
336 
337 // When a manager receives a disc response from a node it sends a disc request
338 // and then closes the connection.
339 // When a node receives a disc request it simply closes the connection.
340 
342 {
343 
344 // Indicate we have received a disconnect
345 //
346  Say.Emsg("Node", Link->Name(), "requested a disconnect");
347 
348 // If we must send a disc request, do so now
349 //
350  if (Config.asManager()) Link->Send((char *)&Arg.Request,sizeof(Arg.Request));
351 
352 // Close the link and return an error
353 //
354  isOffline = 1; // STMutex not needed here
355  Link->Close(1);
356  return "."; // Signal disconnect
357 }
358 
359 /******************************************************************************/
360 /* d o _ G o n e */
361 /******************************************************************************/
362 
363 // When a manager receives a gone request it is propogated if we are subscribed
364 // and we have not sent a gone request in the immediate past.
365 //
367 {
368  EPNAME("do_Gone")
369  static const SMask_t allNodes(~0);
370  int newgone;
371 
372 // Do some debugging
373 //
374  TRACER(Files,Arg.Path);
375 
376 // Update path information and delete this from the prep queue if we are a
377 // staging node. We can also be called via the admin end-point interface
378 // In this case, we have no cache and simply forward up the request.
379 //
380  if (Config.asManager())
382  newgone = Cache.DelFile(Sel, baseFS.isDFS() ? allNodes : NodeMask);
383  } else {
384  newgone = 1;
385  if (Config.DiskSS) PrepQ.Gone(Arg.Path);
386  }
387 
388 // If we have no managers and we still have the file or never had it, return
389 //
390  if (!XrdCmsManager::Present() || !newgone) return 0;
391 
392 // Back-propogate the gone to all of our managers
393 //
394  XrdCmsManager::Inform(Arg.Request, Arg.Buff, Arg.Dlen);
395 
396 // All done
397 //
398  return 0;
399 }
400 
401 /******************************************************************************/
402 /* d o _ H a v e */
403 /******************************************************************************/
404 
405 // When a manager receives a have request it is propogated if we are subscribed
406 // and we have not sent a have request in the immediate past.
407 //
409 {
410  EPNAME("do_Have")
411  static const SMask_t allNodes(~0);
412  XrdCmsPInfo pinfo;
413  int isnew, Opts;
414 
415 // Do some debugging
416 //
417  TRACER(Files, (Arg.Request.modifier&CmsHaveRequest::Pending ? "P ":"")
418  <<Arg.Path);
419 
420 // Find if we can handle the file in r/w mode and if staging is present
421 //
422  Opts = (Cache.Paths.Find(Arg.Path, pinfo) && (pinfo.rwvec & NodeMask)
423  ? XrdCmsSelect::Write : 0);
426 
427 // Update path information. If we are exporting a shared-everything file system
428 // then we need to also provide the cache the current list of nodes and how
429 // they export the path in question for fast redispatch processing.
430 //
431  if (!Config.asManager()) isnew = 1;
432  else {XrdCmsSelect Sel(XrdCmsSelect::Advisory|Opts,Arg.Path,Arg.PathLen-1);
433  Sel.Path.Hash = Arg.Request.streamid;
434  if (baseFS.isDFS())
435  {Sel.Vec.hf = pinfo.rovec; Sel.Vec.wf = pinfo.rwvec;
436  isnew = Cache.AddFile(Sel, allNodes);
437  } else isnew = Cache.AddFile(Sel, NodeMask);
438  }
439 
440 // Return if we have no managers or we already informed the managers
441 //
442  if (!XrdCmsManager::Present() || !isnew) return 0;
443 
444 // Back-propogate the have to all of our managers
445 //
446  XrdCmsManager::Inform(Arg.Request, Arg.Buff, Arg.Dlen);
447 
448 // All done
449 //
450  return 0;
451 }
452 
453 /******************************************************************************/
454 /* d o _ L o a d */
455 /******************************************************************************/
456 
457 // Responses to usage requests are local to the cell and never propagated.
458 //
460 {
461  EPNAME("do_Load")
462  uint32_t pcpu, pnet, pxeq, pmem, ppag, pdsk;
463  int temp;
464 
465 // Process: load <cpu> <io> <load> <mem> <pag> <util> <rsvd> <dskFree>
466 // 0 1 2 3 4 5 6
467  pcpu = static_cast<uint32_t>(Arg.Opaque[CmsLoadRequest::cpuLoad]);
468  pnet = static_cast<uint32_t>(Arg.Opaque[CmsLoadRequest::netLoad]);
469  pxeq = static_cast<uint32_t>(Arg.Opaque[CmsLoadRequest::xeqLoad]);
470  pmem = static_cast<uint32_t>(Arg.Opaque[CmsLoadRequest::memLoad]);
471  ppag = static_cast<uint32_t>(Arg.Opaque[CmsLoadRequest::pagLoad]);
472  pdsk = static_cast<uint32_t>(Arg.Opaque[CmsLoadRequest::dskLoad]);
473 
474 // Compute actual load value. Note that the update is not thread-kosher as we
475 // do not obtain a write lock. However, the values below use the single writer
476 // principal so other threads will eventually see a coherent picture. This is
477 // good enough for what these values are used for.
478 //
479  myLoad = Meter.calcLoad(pcpu, pnet, pxeq, pmem, ppag);
480  myMass = Meter.calcLoad(myLoad, pdsk);
481  DiskFree = Arg.dskFree;
482  DiskUtil = pdsk;
483 
484 // Do some debugging
485 //
486  DEBUGR("cpu=" <<pcpu <<" net=" <<pnet <<" xeq=" <<pxeq
487  <<" mem=" <<pmem <<" pag=" <<ppag <<" dsk=" <<pdsk
488  <<"% " <<DiskFree <<"MB load=" <<myLoad <<" mass=" <<myMass);
489 
490 // If we are also a manager then use this load figure to come up with
491 // an overall load to report when asked. If we get free space, then we
492 // must report that now so that we can be selected for allocation.
493 //
494  if (Config.asManager())
495  {Meter.Record(pcpu, pnet, pxeq, pmem, ppag, pdsk);
496  if (isRW && DiskFree != LastFree)
497  {mlMutex.Lock();
498  temp = LastFree; LastFree = DiskFree; Meter.setVirtUpdt();
499  if (!temp && DiskFree >= Config.DiskMin) do_Space(Arg);
500  mlMutex.UnLock();
501  }
502  }
503 
504 // Report new load if need be
505 //
506  if (Config.LogPerf && !logload)
507  {char buff[1024];
508  long long tRefs = Cluster.Refs();
509  long long nRefs = static_cast<long long>(RefTotW + RefTotR)*100;
510  long long sRefs = static_cast<long long>(Share) * Shrin * 100;
511  int myShr = (Share ? Share : 100);
512  if (tRefs) {nRefs /= tRefs; sRefs /= tRefs;}
513  else nRefs = sRefs = 0;
514  snprintf(buff, sizeof(buff)-1,
515  "load=%d; cpu=%d net=%d inq=%d mem=%d pag=%d dsk=%d utl=%d "
516  "shr=[%d %lld %lld] ref=[%d %d]",
517  myLoad, pcpu, pnet, pxeq, pmem, ppag, Arg.dskFree, pdsk,
518  myShr, nRefs, sRefs, RefTotR+RefR, RefTotW+RefW);
519  Say.Emsg("Node", Name(), buff);
520  logload = Config.LogPerf;
521  } else logload--;
522 
523 // Return as if we had gotten a pong
524 //
525  return do_Pong(Arg);
526 }
527 
528 
529 /******************************************************************************/
530 /* d o _ L o c a t e */
531 /******************************************************************************/
532 
534 {
535  EPNAME("do_Locate";)
536  XrdCmsRRQInfo reqInfo(Instance,RSlot,Arg.Request.streamid,Config.QryMinum);
537  XrdCmsSelect Sel(0, Arg.Path, Arg.PathLen-1);
538  XrdCmsSelected *sP = 0;
539  struct {kXR_unt32 Val;
540  char outbuff[CmsLocateRequest::RHLen*STMax];} Resp;
541  struct iovec ioV[2] = {{(char *)&Arg.Request, sizeof(Arg.Request)},
542  {(char *)&Resp, 0}};
543  const char *Why;
544  char eBuff[128], theopts[8], *toP = theopts;
546  XrdNetIF::ifType ifType;
547  int rc, bytes;
548  bool lsuniq = false, oksel = false, lsall = (*Arg.Path == '*');
549 
550 // Get the right interface selection options
551 //
552  ifType = ifVec[(Arg.Opts & CmsLocateRequest::kYR_retipmsk)
554 
555 // Indicate whether we want a name or an actual address
556 //
557  lsopts = (Arg.Opts & CmsLocateRequest::kYR_retname
559 
560 // Indicate if only a single server entry should be listed
561 //
563  {lsuniq = true; *toP++='u';}
564 
565 // Indicate whether we can ignore network restrictions
566 //
568  lsopts |= XrdCmsCluster::LS_ANY;
569 
570 // Indicate whether we ony want to list a single entry
571 //
572 
573 // Handle private networks here
574 //
576  {XrdNetIF::Privatize(ifType);
577  *toP++='P';
578  }
579 
580 // Encode if type into the options
581 //
582  Sel.Opts = static_cast<int>(ifType) & XrdCmsSelect::ifWant;
583  lsopts = static_cast<XrdCmsCluster::CmsLSOpts>(lsopts | ifType);
584 
585 // Grab various options
586 //
588  {Sel.Opts = XrdCmsSelect::Refresh; *toP++='s';}
590  {Sel.Opts |= XrdCmsSelect::Asap; *toP++='i'; Sel.InfoP = &reqInfo;
591  reqInfo.lsLU = static_cast<char>(lsopts);
592  }
593  else Sel.InfoP = 0;
594 
595 // Do some debugging
596 //
597  *toP = '\0';
598  DEBUGR(theopts <<' ' <<Arg.Path);
599 
600 // Perform location
601 //
602  if ((rc = Cluster.Locate(Sel)))
603  {if (rc > 0)
604  {Arg.Request.rrCode = kYR_wait;
605  bytes = sizeof(Resp.Val); Why = "delay ";
606  } else {
607  if (rc == XrdCmsCluster::Wait4CBk) return 0;
608  Arg.Request.rrCode = kYR_error;
609  rc = kYR_ENOENT; Why = "miss ";
610  bytes = strlcpy(Resp.outbuff, "No servers have access to the file",
611  sizeof(Resp.outbuff)) + sizeof(Resp.Val) + 1;
612  }
613  } else {Why = "?"; bytes = 0;}
614 
615 // List the servers
616 //
617  if (!rc)
618  {if (!Sel.Vec.hf || !(sP=Cluster.List(Sel.Vec.hf, lsopts, oksel)))
619  {const char *eTxt;
620  Arg.Request.rrCode = kYR_error;
621  if (oksel)
622  {rc = kYR_ENETUNREACH; Why = "unreachable ";
623  sprintf(eBuff, "No servers are reachable via %s network",
624  XrdNetIF::Name(ifType));
625  eTxt = eBuff;
626  } else {
627  rc = kYR_ENOENT; Why = "none ";
628  eTxt = "No servers have the file";
629  }
630  bytes = strlcpy(Resp.outbuff, eTxt,
631  sizeof(Resp.outbuff)) + sizeof(Resp.Val) + 1;
632  } else rc = 0;
633  }
634 
635 // Either prepare to send an error or format the result
636 //
637  if (rc)
638  {Resp.Val = htonl(rc);
639  DEBUGR(Why <<Arg.Path);
640  } else {
641  bytes = do_LocFmt(Resp.outbuff, sP, Sel.Vec.pf, Sel.Vec.wf, lsall,lsuniq)
642  + sizeof(Resp.Val) + 1;
643  Resp.Val = 0;
644  Arg.Request.rrCode = kYR_data;
645  }
646 
647 // Send off the response
648 //
649  Arg.Request.datalen = htons(bytes);
650  ioV[1].iov_len = bytes;
651  Link->Send(ioV, 2, bytes+sizeof(Arg.Request));
652  return 0;
653 }
654 
655 /******************************************************************************/
656 /* Static d o _ L o c F m t */
657 /******************************************************************************/
658 
660  SMask_t pfVec, SMask_t wfVec, bool lsall, bool lsuniq)
661 {
662  static const int Skip = (XrdCmsSelected::Disable | XrdCmsSelected::Offline);
663  static const int Hung = (XrdCmsSelected::Disable | XrdCmsSelected::Offline
665  XrdCmsSelected *pP;
666  char *oP = buff;
667 
668 // If only unique entries are wanted then we need to only let through
669 // all non-servers and one server (prefereably a r/w one)
670 //
671 if (!lsall && lsuniq)
672  {XrdCmsSelected *xP = 0;
673  bool haverw = false;
674  pP = sP;
675  while(pP)
676  {if (!(pP->Status & (XrdCmsSelected::isMangr | Skip)))
677  {if (haverw) pP->Status |= Skip;
678  else {if (xP) xP->Status |= Skip;
679  xP = pP;
680  haverw = (pP->Mask & wfVec) != 0;
681  }
682  }
683  pP = pP->next;
684  }
685  }
686 
687 // format out the request as follows:
688 // 01234567810123456789212345678
689 // xy[::123.123.123.123]:123456
690 //
691 if (lsall)
692  while(sP)
693  {*oP = (sP->Status & XrdCmsSelected::isMangr ? 'M' : 'S');
694  if (sP->Status & Hung) *oP = tolower(*oP);
695  *(oP+1) = (sP->Mask & wfVec ? 'w' : 'r');
696  strcpy(oP+2, sP->Ident); oP += sP->IdentLen + 2;
697  if (sP->next) *oP++ = ' ';
698  pP = sP; sP = sP->next; delete pP;
699  }
700  else
701  while(sP)
702  {if (!(sP->Status & Skip))
703  {*oP = (sP->Status & XrdCmsSelected::isMangr ? 'M' : 'S');
704  if (sP->Mask & pfVec) *oP = tolower(*oP);
705  *(oP+1) = (sP->Mask & wfVec ? 'w' : 'r');
706  strcpy(oP+2, sP->Ident); oP += sP->IdentLen + 2;
707  if (sP->next) *oP++ = ' ';
708  }
709  pP = sP; sP = sP->next; delete pP;
710  }
711 
712 // Send of the result
713 //
714  *oP = '\0';
715  return (oP - buff);
716 }
717 
718 /******************************************************************************/
719 /* d o _ M k d i r */
720 /******************************************************************************/
721 
722 // Mkdir requests are forwarded to all subscribers
723 //
725 {
726  EPNAME("do_Mkdir")
727  mode_t mode = 0;
728  int rc;
729 
730 // Do some debugging
731 //
732  DEBUGR("mode " <<Arg.Mode <<' ' <<Arg.Path);
733 
734 // We are don here if we have no data; otherwise convert the mode if we
735 // haven't done so already.
736 //
737  if (!Config.DiskOK) return 0;
738  if (!mode && !getMode(Arg.Mode, mode)) return "invalid mode";
739 
740 // Attempt to create the directory either via call-out of oss plug-in
741 //
742  if (Config.ProgMD) rc = fsExec(Config.ProgMD, Arg.Mode, Arg.Path);
743  else rc = Config.ossFS->Mkdir(Arg.Path, mode);
744 
745 // Return appropriate result
746 //
747  return (rc ? fsFail(Arg.Ident, "mkdir", Arg.Path, rc) : 0);
748 }
749 
750 /******************************************************************************/
751 /* d o _ M k p a t h */
752 /******************************************************************************/
753 
754 // Mkpath requests are forwarded to all subscribers
755 //
757 {
758  EPNAME("do_Mkpath")
759  mode_t mode = 0;
760  int rc;
761 
762 // Do some debugging
763 //
764  DEBUGR("mode " <<Arg.Mode <<' ' <<Arg.Path);
765 
766 // We are don here if we have no data; otherwise convert the mode if we
767 // haven't done so already.
768 //
769  if (!Config.DiskOK) return 0;
770  if (!mode && !getMode(Arg.Mode, mode)) return "invalid mode";
771 
772 // Attempt to create the directory path via call-out or oss plugin
773 //
774  if (Config.ProgMP) rc = fsExec(Config.ProgMP, Arg.Mode, Arg.Path);
775  else rc = Config.ossFS->Mkdir(Arg.Path, mode, 1);
776 
777 // Return appropriate result
778 //
779  return (rc ? fsFail(Arg.Ident, "mkpath", Arg.Path, rc) : 0);
780 }
781 
782 /******************************************************************************/
783 /* d o _ M v */
784 /******************************************************************************/
785 
786 // Mv requests are forwarded to all subscribers
787 //
789 {
790  EPNAME("do_Mv")
791  static const SMask_t allNodes(~0);
792  int rc;
793 
794 // Do some debugging
795 //
796  DEBUGR(Arg.Path <<" to " <<Arg.Path2);
797 
798 // If we are not a server, if must remove references to the old and new names
799 // from our cache. This is independent of how the raname is handled. We need
800 // not back percolate the mv since it was hanled top down in the first place.
801 // Note that we will scuttle the mv if the target file exists somewhere.
802 //
803  if (!Config.DiskOK)
804  {XrdCmsSelect Sel1(XrdCmsSelect::Defer, Arg.Path, strlen(Arg.Path ));
805  XrdCmsSelect Sel2(XrdCmsSelect::Defer, Arg.Path2,strlen(Arg.Path2));
806 
807  // Setup select data (note that mv does not allow fast redirect)
808  //
809  Sel2.iovP = 0; Sel2.iovN = 0;
810  Sel2.InfoP = 0; // No fast redirects
811  Sel2.nmask = SMask_t(0);
812 
813  // Perform selection
814  //
815  if ((rc = Cluster.Select(Sel2)))
816  {if (rc > 0) {Arg.waitVal = rc; return "!mv";}
817  else if (Sel2.Vec.hf)
818  {Say.Emsg("do_Mv",Arg.Path2,"exists; mv failed for",Arg.Path);
819  return "target file exists";
820  }
821  }
822  Cache.DelFile(Sel2, allNodes);
823  Cache.DelFile(Sel1, allNodes);
824  return 0;
825  }
826 
827 // Rename the file via call-out or oss plug-in (we used to do this via a requeue
828 // to the local xrootd but it's no longer necessary).
829 //
830  if (Config.ProgMV) rc = fsExec(Config.ProgMV, Arg.Path, Arg.Path2);
831  else rc = Config.ossFS->Rename(Arg.Path, Arg.Path2);
832 
833 // Return appropriate result
834 //
835  return (rc ? fsFail(Arg.Ident, "mv", Arg.Path, rc) : 0);
836 }
837 
838 /******************************************************************************/
839 /* d o _ P i n g */
840 /******************************************************************************/
841 
842 // Ping requests from a manager are local to the cell and never propagated.
843 //
845 {
846  static CmsPongRequest pongIt = {{0, kYR_pong, 0, 0}};
847 
848 // Process: ping
849 // Respond: pong
850 //
851  if (isBad & isDoomed) return ".redirected";
852  Link->Send((char *)&pongIt, sizeof(pongIt));
853  return 0;
854 }
855 
856 /******************************************************************************/
857 /* d o _ P o n g */
858 /******************************************************************************/
859 
860 // Responses to a ping are local to the cell and never propagated.
861 //
863 {
864 // Process: pong
865 // Reponds: n/a
866 
867  return 0;
868 }
869 
870 /******************************************************************************/
871 /* d o _ P r e p A d d */
872 /******************************************************************************/
873 
875 {
876  EPNAME("do_PrepAdd")
877 
878 // Do some debugging
879 //
880  DEBUGR("parms: " <<Arg.Reqid <<' ' <<Arg.Notify <<' ' <<Arg.Prty <<' '
881  <<Arg.Mode <<' ' <<Arg.Path);
882 
883 // Queue this request for async processing
884 //
885  (new XrdCmsPrepArgs(Arg))->Queue();
886  return 0;
887 }
888 
889 /******************************************************************************/
890 /* d o _ P r e p D e l */
891 /******************************************************************************/
892 
894 {
895  EPNAME("do_PrepDel")
896 
897 // Do some debugging
898 //
899  DEBUGR("reqid " <<Arg.Reqid);
900 
901 // Cancel the request if applicable.
902 //
903  if (Config.DiskOK)
904  {if (!Config.DiskSS) {DEBUGR("ignoring cancel prepare " <<Arg.Reqid);}
905  else {DEBUGR("canceling prepare " <<Arg.Reqid);
906  PrepQ.Del(Arg.Reqid);
907  }
908  }
909  return 0;
910 }
911 
912 /******************************************************************************/
913 /* d o _ R m */
914 /******************************************************************************/
915 
916 // Rm requests are forwarded to all subscribers
917 //
919 {
920  EPNAME("do_Rm")
921  static const SMask_t allNodes(~0);
922  int rc;
923 
924 // Do some debugging
925 //
926  DEBUGR(Arg.Path);
927 
928 // If we have no data then we should remove this file from our cache
929 //
930  if (!Config.DiskOK)
931  {XrdCmsSelect Sel(0, Arg.Path, strlen(Arg.Path));
932  Cache.DelFile(Sel, allNodes);
933  return 0;
934  }
935 
936 // Remove the file either via call-out or the oss plugin. We used to requeue
937 // the request to the local xrootd but this is no longer needed.
938 //
939  if (Config.ProgRM) rc = fsExec(Config.ProgRM, Arg.Path);
940  else rc = Config.ossFS->Unlink(Arg.Path);
941 
942 // Return appropriate result
943 //
944  return (rc ? fsFail(Arg.Ident, "rm", Arg.Path, rc) : 0);
945 }
946 
947 /******************************************************************************/
948 /* d o _ R m d i r */
949 /******************************************************************************/
950 
951 // Rmdir requests are forwarded to all subscribers
952 //
954 {
955  EPNAME("do_Rmdir")
956  static const SMask_t allNodes(~0);
957  int rc;
958 
959 // Do some debugging
960 //
961  DEBUGR(Arg.Path);
962 
963 // If we have no data then we should remove this directory from our cache
964 //
965  if (!Config.DiskOK)
966  {XrdCmsSelect Sel(0, Arg.Path, strlen(Arg.Path));
967  Cache.DelFile(Sel, allNodes);
968  return 0;
969  }
970 
971 // Remove the directory either via call-out or the oss plug-in (we used to
972 // do this by requeing the request to the local xrootd; no longer needed).
973 //
974  if (Config.ProgRD) rc = fsExec(Config.ProgRD, Arg.Path);
975  else rc = Config.ossFS->Remdir(Arg.Path);
976 
977 // Return appropriate result
978 //
979  return (rc ? fsFail(Arg.Ident, "rmdir", Arg.Path, rc) : 0);
980 }
981 
982 /******************************************************************************/
983 /* d o _ S e l A v o i d */
984 /******************************************************************************/
985 
987  char *Avoid, bool &doRedir)
988 {
989  XrdNetAddr avoidAddr;
990  char *Comma;
991  int avNum = 0;
992 
993 // Process the avoid list
994 //
995  Sel.InfoP = 0;
996  do {if ((Comma = index(Avoid,','))) *Comma = '\0';
997  if (*Avoid == '+') Sel.nmask |= Cluster.getMask(Avoid+1);
998  else if (!avoidAddr.Set(Avoid,0))
999  Sel.nmask |= Cluster.getMask(&avoidAddr);
1000  Avoid = Comma+1; avNum++;
1001  } while(Comma && *Avoid);
1002 
1003 // Check why we have an avoid list. For dfs style clusters, the limits on
1004 // selections are handled by the basefs object.
1005 //
1006  if (baseFS.isDFS())
1009  return 0;
1010  }
1011 
1012 // This is a standard cluster, check if client is expanding the server base
1013 // and whether or not this is allowed in this cluster.
1014 //
1016  {if (Config.msRdrHost)
1017  {strcpy(Sel.Resp.Data, Config.msRdrHost); // Gauranteed to fit!
1018  Sel.Resp.DLen = Config.msRdrHLen;
1019  Sel.Resp.Port = Config.msRdrPort;
1020  doRedir = true;
1021  return -1;
1022  }
1023  strncpy(Sel.Resp.Data, msrcmsg, sizeof(Sel.Resp.Data));
1024  Sel.Resp.DLen = msrclen;
1025  if (Arg.Opts & CmsSelectRequest::kYR_tryRSEL) Sel.Resp.Port = kYR_EPERM;
1026  else Sel.Resp.Port = kYR_ENOENT;
1027  return XrdCmsCluster::EReplete;
1028  }
1029 
1030 // Check if we exceeded the retry count
1031 //
1032  if (avNum > Config.MaxRetries)
1033  {if (Config.mrRdrHost)
1034  {strcpy(Sel.Resp.Data, Config.mrRdrHost); // Gauranteed to fit!
1035  Sel.Resp.DLen = Config.mrRdrHLen;
1036  Sel.Resp.Port = Config.mrRdrPort;
1037  doRedir = true;
1038  } else {
1039  strncpy(Sel.Resp.Data, mtrymsg, sizeof(Sel.Resp.Data));
1040  Sel.Resp.DLen = mtrylen;
1041  }
1042  return -1;
1043  }
1044 
1045 // We suceeded, indicate selection can proceed.
1046 //
1047  return 0;
1048 }
1049 
1050 /******************************************************************************/
1051 /* d o _ S e l e c t */
1052 /******************************************************************************/
1053 
1054 // A select request comes from a redirector and is handled locally within the
1055 // cell. This may cause "state" requests to be broadcast to subscribers.
1056 //
1058 {
1059  EPNAME("do_Select")
1060 // kXR_NotFound kXR_IOError kXR_FSError kXR_ServerError
1061  static int rtEC[] = {kYR_ENOENT, kYR_EIO, kYR_FSError, kYR_SrvError};
1062  XrdCmsRRQInfo reqInfo(Instance,RSlot,Arg.Request.streamid,Config.QryMinum);
1063  XrdCmsSelect Sel(XrdCmsSelect::Peers, Arg.Path, Arg.PathLen-1);
1064  struct iovec ioV[2];
1065  char theopts[16], *toP = theopts;
1066  XrdNetIF::ifType ifType;
1067  int rc, bytes;
1068 
1069 // Init select data (note that refresh supresses fast redirects)
1070 //
1071  Sel.iovP = 0; Sel.iovN = 0; Sel.InfoP = &reqInfo;
1072 
1073 // Determine what interface to return to the client
1074 //
1075  ifType = ifVec[(Arg.Opts & CmsSelectRequest::kYR_retipmsk)
1078  {XrdNetIF::Privatize(ifType); *toP++='P';}
1079  Sel.Opts |= static_cast<int>(ifType) & XrdCmsSelect::ifWant;
1080 
1081 // Complete the arguments to select
1082 //
1084  {Sel.Opts |= XrdCmsSelect::Refresh; *toP++='s';}
1086  {Sel.Opts |= XrdCmsSelect::Online; *toP++='o';}
1087  if (Arg.Opts & CmsSelectRequest::kYR_stat)
1088  {Sel.Opts |= XrdCmsSelect::noBind; *toP++='x';}
1089  else {if (Arg.Opts & CmsSelectRequest::kYR_trunc)
1090  {Sel.Opts |= XrdCmsSelect::Write | XrdCmsSelect::Trunc; *toP++='t';}
1091  if (Arg.Opts & CmsSelectRequest::kYR_write)
1092  {Sel.Opts |= XrdCmsSelect::Write; *toP++='w';
1094  {Sel.Opts |= XrdCmsSelect::MWFiles; *(toP-1)='W';}
1095  }
1097  {Sel.Opts |= XrdCmsSelect::isMeta; *toP++='m';
1098  if (!(Arg.Opts & CmsSelectRequest::kYR_write))
1099  {Sel.Opts |= XrdCmsSelect::isDir; *toP++='D';}
1100  }
1102  {Sel.Opts |= XrdCmsSelect::Write|XrdCmsSelect::NewFile; *toP++='c';
1104  {Sel.Opts |= XrdCmsSelect::Replica; *toP++='+';}
1105  }
1106  }
1107  *toP = '\0';
1108 
1109 // If the client can override selection mode, check if this has been done. Note
1110 // that true packed selection turns off fast redirect.
1111 //
1113  {if (Config.sched_Pack)
1114  {Sel.Opts |= XrdCmsSelect::Pack;
1115  if (Config.sched_Pack > 1) Sel.InfoP = 0;
1117  }
1118  } else {
1120  {Sel.Opts |= XrdCmsSelect::Pack;
1121  if (Arg.Opts & CmsSelectRequest::kYR_aWait) Sel.InfoP = 0;
1122  if ((Arg.Opts & CmsSelectRequest::kYR_aPack) ==
1124  Sel.Opts |= XrdCmsSelect::UseRef;
1125  }
1126  }
1127 
1128 // Compute alternate hash.
1129 //
1131  && Sel.Path.Len > 3) setHash(Sel, Config.sched_AffPC);
1132 
1133 // Check if an avoid node present. If so, this is ineligible for fast redirect.
1134 //
1135  bool doRedir = false;
1136  Sel.nmask = SMask_t(0);
1137  if (Arg.Avoid) rc = do_SelAvoid(Arg, Sel, Arg.Avoid, doRedir);
1138  else rc = 0;
1139 
1140 // Perform selection
1141 //
1142  if (!doRedir && (rc || (rc = Cluster.Select(Sel))))
1143  {if (rc > 0)
1144  {Arg.Request.rrCode = kYR_wait;
1145  Sel.Resp.Port = rc;
1146  Sel.Resp.DLen = 0;
1147  DEBUGR("delay " <<rc <<' ' <<Arg.Path);
1148  } else {
1149  Arg.Request.rrCode = kYR_error;
1150  if (rc != XrdCmsCluster::EReplete) // if error info has not been set
1151  {if (rc == XrdCmsCluster::RetryErr)
1152  {int rtRC = (Arg.Opts & CmsSelectRequest::kYR_tryMASK)
1154  Sel.Resp.Port = rtEC[rtRC];
1155  } else {
1156  Sel.Resp.Port = kYR_ENOENT; // This should never happen!
1157  Sel.Resp.DLen = sprintf(Sel.Resp.Data,"%s","Item not found.")+1;
1158  }
1159  }
1160  DEBUGR("failed; " <<Sel.Resp.Data << ' ' <<Arg.Path);
1161  }
1162  } else if (!Sel.Resp.DLen) return 0;
1163  else {Arg.Request.rrCode = kYR_redirect;
1164  DEBUGR("Redirect -> " <<Sel.Resp.Data <<':'
1165  <<Sel.Resp.Port <<" for " <<Arg.Path);
1166  }
1167 
1168 // Format the response
1169 //
1170  bytes = Sel.Resp.DLen+sizeof(Sel.Resp.Port);
1171  Arg.Request.datalen = htons(bytes);
1172  Sel.Resp.Port = htonl(Sel.Resp.Port);
1173 
1174 // Fill out the I/O vector
1175 //
1176  ioV[0].iov_base = (char *)&Arg.Request;
1177  ioV[0].iov_len = sizeof(Arg.Request);
1178  ioV[1].iov_base = (char *)&Sel.Resp;
1179  ioV[1].iov_len = bytes;
1180 
1181 // Send back the response
1182 //
1183  Link->Send(ioV, 2, bytes+sizeof(Arg.Request));
1184  return 0;
1185 }
1186 
1187 /******************************************************************************/
1188 /* d o _ S e l P r e p */
1189 /******************************************************************************/
1190 
1192 {
1193  EPNAME("do_SelPrep")
1194  XrdCmsSelect Sel(XrdCmsSelect::Peers, Arg.path, Arg.pathlen-1);
1195  int rc;
1196 
1197 // Complete the arguments to select
1198 //
1200  Sel.Opts |= XrdCmsSelect::Freshen;
1202  Sel.Opts |= XrdCmsSelect::Write;
1204  {Sel.iovP = Arg.ioV; Sel.iovN = Arg.iovNum;}
1205  else {Sel.iovP = 0; Sel.iovN = 0;
1206  Sel.Opts |= XrdCmsSelect::Defer;
1207  }
1208 
1209 // Setup select data (note that prepare does not allow fast redirect)
1210 //
1211  Sel.InfoP = 0; // No fast redirects
1212  Sel.nmask = SMask_t(0);
1213 
1214 // We do not care what interface is being used. This may conflict with a
1215 // staging prepare but it's too complicated to handle at this point.
1216 //
1217  Sel.Opts |= static_cast<char>(XrdNetIF::ifAny);
1218 
1219 // Check if co-location wanted relevant only when staging wanted
1220 //
1221  if (Arg.clPath && Sel.iovP)
1222  {XrdCmsSelect Scl(XrdCmsSelect::Peers, Arg.clPath, strlen(Arg.clPath));
1223  Scl.iovP = 0; Scl.iovN = 0; Scl.InfoP = 0; Scl.nmask = SMask_t(0);
1224  DEBUGR("colocating " <<Arg.path <<" w.r.t. " <<Arg.clPath);
1225  rc = Cluster.Select(Scl);
1226  if (rc > 0) {Sched->Schedule((XrdJob *)&Arg, rc+time(0));
1227  DEBUGR("coloc to " <<Arg.clPath <<" delayed " <<rc <<" seconds");
1228  return 1;
1229  }
1230  if (rc < 0) Say.Emsg("SelPrep", Arg.path, "failed;", Sel.Resp.Data);
1231  else Sel.nmask = ~Scl.smask;
1232  }
1233 
1234 // Perform selection
1235 //
1236  if ((rc = Cluster.Select(Sel)))
1237  {if (rc > 0)
1238  {if (!(Arg.options & CmsPrepAddRequest::kYR_stage)) return 0;
1239  Sched->Schedule((XrdJob *)&Arg, rc+time(0));
1240  DEBUGR("prep delayed " <<rc <<" seconds");
1241  return 1;
1242  }
1243  Say.Emsg("SelPrep", Arg.path, "failed;", Sel.Resp.Data);
1244  PrepQ.Inform("unavail", &Arg);
1245  }
1246 
1247 // All done
1248 //
1249  return 0;
1250 }
1251 
1252 /******************************************************************************/
1253 /* d o _ S p a c e */
1254 /******************************************************************************/
1255 
1256 // Manager space requests are local to the cell and never propagated.
1257 //
1259 {
1260  EPNAME("do_Space")
1261  struct iovec xmsg[2];
1262  CmsAvailRequest mySpace = {{0, kYR_avail, 0, 0}};
1263  char buff[sizeof(int)*2+2], *bp = buff;
1264  int blen, maxfr, tutil;
1265 
1266 // Process: <id> space
1267 // Respond: <id> avail <numkb> <dskutil>
1268 //
1269  maxfr = Meter.FreeSpace(tutil);
1270 
1271 // Do some debugging
1272 //
1273  DEBUGR(maxfr <<"MB free; " <<tutil <<"% util");
1274 
1275 // Construct a message to be sent to the manager.
1276 //
1277  blen = XrdOucPup::Pack(&bp, maxfr);
1278  blen += XrdOucPup::Pack(&bp, tutil);
1279  mySpace.Hdr.datalen = htons(static_cast<unsigned short>(blen));
1280 
1281 // Send the response
1282 //
1283  if (Arg.Request.rrCode != kYR_space)
1284  XrdCmsManager::Inform(mySpace.Hdr, buff, blen);
1285  else {xmsg[0].iov_base = (char *)&mySpace;
1286  xmsg[0].iov_len = sizeof(mySpace);
1287  xmsg[1].iov_base = buff;
1288  xmsg[1].iov_len = blen;
1289  mySpace.Hdr.datalen = htons(static_cast<unsigned short>(blen));
1290  Link->Send(xmsg, 2);
1291  }
1292  return 0;
1293 }
1294 
1295 /******************************************************************************/
1296 /* d o _ S t a t e */
1297 /******************************************************************************/
1298 
1299 // State requests from a manager are rebroadcast to all relevant subscribers.
1300 //
1302 {
1303  EPNAME("do_State")
1304  struct iovec xmsg[2];
1305  int rc, noResp = Arg.Request.modifier & CmsStateRequest::kYR_noresp;
1306 
1307 // Do some debugging
1308 //
1309  TRACER(Files,Arg.Path);
1310 
1311 // Process: state <path>
1312 // Respond: have <path>
1313 //
1314  isKnown = 1;
1315 
1316 // If we are a manager then check for the file in the local cache. Otherwise,
1317 // ask the underlying filesystem whether it has the file.
1318 //
1319  if (isMan) {if(!(Arg.Request.modifier = do_StateFWD(Arg))) return 0;}
1320  else if (!Config.DiskOK && !Config.asProxy()) return 0;
1322  {XrdCmsPInfo pinfo;
1323  pinfo.rovec = NodeMask;
1324  if ((rc = baseFS.Exists(Arg,pinfo)) > 0) Arg.Request.modifier = rc;
1325  else return 0;
1326  }
1327  else if ((rc = baseFS.Exists(Arg.Path, -(Arg.PathLen-1))) > 0)
1328  Arg.Request.modifier = rc;
1329  else return 0;
1330 
1331 // Respond appropriately
1332 //
1333  if (Arg.Request.modifier && !noResp)
1334  {TRACER(Files,Arg.Path <<" responding have!");
1335  xmsg[0].iov_base = (char *)&Arg.Request;
1336  xmsg[0].iov_len = sizeof(Arg.Request);
1337  xmsg[1].iov_base = Arg.Buff;
1338  xmsg[1].iov_len = Arg.Dlen;
1339  Arg.Request.rrCode = kYR_have;
1340  Arg.Request.modifier |= kYR_raw;
1341  Link->Send(xmsg, 2);
1342  }
1343  return 0;
1344 }
1345 
1346 /******************************************************************************/
1347 /* d o _ S t a t e D F S */
1348 /******************************************************************************/
1349 
1350 void XrdCmsNode::do_StateDFS(XrdCmsBaseFR *rP, int rc)
1351 {
1352  EPNAME("StateDFs");
1353  static const SMask_t allNodes(~0);
1354  CmsRRHdr Request = {rP->Sid, 0, (kXR_char)(rP->Mod | kYR_raw), 0};
1355  XrdCmsSelect Sel(0, rP->Path, rP->PathLen);
1356  int isNew;
1357 
1358 // Do some debugging and record the hash code.
1359 //
1360  DEBUG((rP->Mod & CmsStateRequest::kYR_metaman ? "met " : "man ") <<Xrd::hex1
1361  <<int(rP->Mod) <<" rc=" <<rc <<" path=" <<rP->Path);
1362  Sel.Path.Hash = rP->Sid;
1363 
1364 // If the return code is negative then the file does not exist. If it is zero
1365 // then we should forward the request to another node. Either way we must be
1366 // a manager to do so as servers only worry about existing files.
1367 //
1368  if (rc <= 0)
1369  {if (Config.asManager())
1370  {Cache.AddFile(Sel, 0);
1371  if (!rc)
1372  {Request.rrCode = kYR_state;
1373  Cluster.Broadsend(rP->Route, Request, rP->Path, rP->PathLen+1);
1374  }
1375  }
1376  return;
1377  }
1378 
1379 // The file exists but it could be pending
1380 //
1381  if (rc == CmsHaveRequest::Pending)
1382  {Sel.Opts = XrdCmsSelect::Pending;
1383  Request.modifier |= CmsHaveRequest::Pending;
1384  }
1385  Sel.Vec.hf = rP->Route; Sel.Vec.wf = rP->RouteW;
1386  isNew = (Config.asManager() ? Cache.AddFile(Sel, allNodes) : 1);
1387 
1388 // Now inform our managers only if we haven't informed them before. At some
1389 // point we will only inform the manager that actually wants to know. This
1390 // is encoded to the route passed to us.
1391 //
1392  if (XrdCmsManager::Present() && isNew
1393  && !(rP->Mod & CmsStateRequest::kYR_noresp))
1394  {Request.rrCode = kYR_have;
1395  XrdCmsManager::Inform(Request, rP->Path, rP->PathLen+1);
1396  }
1397 }
1398 
1399 /******************************************************************************/
1400 /* d o _ S t a t e F W D */
1401 /******************************************************************************/
1402 
1404 {
1405  EPNAME("do_StateFWD");
1406  static const SMask_t allNodes(~0);
1407  XrdCmsSelect Sel(0, Arg.Path, Arg.PathLen-1);
1408  XrdCmsPInfo pinfo;
1409  int retc;
1410 
1411 // Find out who could serve this file
1412 //
1413  if (!Cache.Paths.Find(Arg.Path, pinfo) || pinfo.rovec == 0)
1414  {DEBUGR("Path find failed for state " <<Arg.Path);
1415  return 0;
1416  }
1417 
1418 // Get the primary locations for this file
1419 //
1420  Sel.Vec.hf = Sel.Vec.pf = Sel.Vec.bf = 0;
1421  if (Arg.Request.modifier & CmsStateRequest::kYR_refresh) retc = 0;
1422  else retc = Cache.GetFile(Sel, pinfo.rovec);
1423 
1424 // If we will possibly be forwarding this request we indicate here whether this
1425 // is a request from a meta-manager. Making the decision in the manager node
1426 // prevents the requestor from lying about its status.
1427 //
1428  if (!retc && !Config.asServer())
1430 
1431 // Here we process the case where we need to discover whether the file exists.
1432 // For distributed file systems, we either ask the underlying file system here
1433 // or forward the request to some arbitrary node in a callback via the baseFS.
1434 // If cached information exists, pending status takes precedence (more below).
1435 // Additionally, if a query is alrady in progress, deep-six this attempt.
1436 //
1437  if (baseFS.isDFS())
1438  {if (retc < 0) return 0;
1439  if (!retc)
1440  {if (baseFS.Traverse())
1441  {Cache.AddFile(Sel, 0);
1442  Cluster.Broadsend(pinfo.rovec, Arg.Request, Arg.Buff, Arg.Dlen);
1443  return 0;
1444  }
1445  if ((retc = baseFS.Exists(Arg, pinfo)) <= 0)
1446  {if (retc < 0) Cache.AddFile(Sel, 0);
1447  return 0;
1448  }
1450  Sel.Vec.hf = pinfo.rovec; Sel.Vec.wf = pinfo.rwvec;
1451  Cache.AddFile(Sel, allNodes);
1452  return retc;
1453  }
1454  if (Sel.Vec.pf != 0) return CmsHaveRequest::Pending;
1455  if (Sel.Vec.hf != 0) return CmsHaveRequest::Online;
1456  return 0;
1457  }
1458 
1459 // For shared-nothing setups, first check if we need to ask any unasked nodes
1460 // whether they have the file.
1461 //
1462  if (!retc || Sel.Vec.bf != 0)
1463  {if (!retc) Cache.AddFile(Sel, 0);
1464  Cluster.Broadcast((retc ? Sel.Vec.bf : pinfo.rovec), Arg.Request,
1465  (void *)Arg.Buff, Arg.Dlen);
1466  }
1467 
1468 // Return true if anyone has the file at this point. In shared-nothing systems
1469 // we are interested in some node has the file in non-pending status. This
1470 // differs from shared-everything because pending status applies to all nodes.
1471 //
1472  if (Sel.Vec.hf != 0) return CmsHaveRequest::Online;
1473  if (Sel.Vec.pf != 0){return CmsHaveRequest::Pending;}
1474  return 0;
1475 }
1476 
1477 /******************************************************************************/
1478 /* d o _ S t a t F S */
1479 /******************************************************************************/
1480 
1482 {
1483  static kXR_unt32 Zero = 0;
1484  char buff[256];
1485  struct iovec ioV[3] = {{(char *)&Arg.Request, sizeof(Arg.Request)},
1486  {(char *)&Zero, sizeof(Zero)},
1487  {(char *)&buff, 0}};
1488  XrdCmsPInfo pinfo;
1489  int bytes;
1490  SpaceData theSpace;
1491 
1492 // Find out who serves this path and get space relative to it
1493 //
1494  if (Cache.Paths.Find(Arg.Path, pinfo) && pinfo.rovec)
1495  {Cluster.Space(theSpace, pinfo.rovec);
1497  {bytes = sprintf(buff, "A %lld %lld %d",
1498  theSpace.Total, theSpace.TotFr,
1499  (theSpace.wFree < theSpace.sFree ? theSpace.sFree
1500  : theSpace.wFree)) + 1;
1501  } else {
1502  bytes = sprintf(buff, "%d %d %d %d %d %d",
1503  theSpace.wNum, theSpace.wFree, theSpace.wUtil,
1504  theSpace.sNum, theSpace.sFree, theSpace.sUtil) + 1;
1505  }
1506  } else bytes = strlcpy(buff, "-1 -1 -1 -1 -1 -1", sizeof(buff)) + 1;
1507 
1508 // Send the response
1509 //
1510  ioV[2].iov_len = bytes;
1511  bytes += sizeof(Zero);
1512  Arg.Request.rrCode = kYR_data;
1513  Arg.Request.datalen = htons(bytes);
1514  Link->Send(ioV, 3, bytes+sizeof(Arg.Request));
1515  return 0;
1516 }
1517 
1518 /******************************************************************************/
1519 /* d o _ S t a t s */
1520 /******************************************************************************/
1521 
1522 // We punt on stats requests as we have no way to export them anyway.
1523 //
1525 {
1526  static const unsigned short szLen = sizeof(kXR_unt32);
1527  static XrdSysMutex StatsData;
1528  static int statsz = 0;
1529  static int statln = 0;
1530  static char *statbuff = 0;
1531  static time_t statlast = 0;
1532  static kXR_unt32 theSize;
1533 
1534  struct iovec ioV[3] = {{(char *)&Arg.Request, sizeof(Arg.Request)},
1535  {(char *)&theSize, sizeof(theSize)},
1536  {0, 0}
1537  };
1538  time_t tNow;
1539 
1540 // Allocate buffer if we do not have one
1541 //
1542  StatsData.Lock();
1543  if (!statsz || !statbuff)
1544  {statsz = Cluster.Stats(0,0);
1545  statbuff = (char *)malloc(statsz);
1546  theSize = htonl(statsz);
1547  }
1548 
1549 // Check if only the size is wanted
1550 //
1552  {ioV[1].iov_len = sizeof(theSize);
1553  Arg.Request.datalen = htons(szLen);
1554  Arg.Request.rrCode = kYR_data;
1555  Link->Send(ioV, 2);
1556  StatsData.UnLock();
1557  return 0;
1558  }
1559 
1560 // Get full statistics if enough time has passed
1561 //
1562  tNow = time(0);
1563  if (statlast+9 >= tNow)
1564  {statln = Cluster.Stats(statbuff, statsz); statlast = tNow;}
1565 
1566 // Format result and send response
1567 //
1568  ioV[2].iov_base = statbuff;
1569  ioV[2].iov_len = statln;
1570  Arg.Request.datalen = htons(static_cast<unsigned short>(szLen+statln));
1571  Arg.Request.rrCode = kYR_data;
1572  Link->Send(ioV, 3);
1573 
1574 // All done
1575 //
1576  StatsData.UnLock();
1577  return 0;
1578 }
1579 
1580 /******************************************************************************/
1581 /* d o _ S t a t u s */
1582 /******************************************************************************/
1583 
1584 // the reset request is propagated to all of our managers. A special reset case
1585 // is sent when a subscribed supervisor adds a new node. This causes all cache
1586 // lines for the supervisor to be marked suspect. Status change requests are
1587 // propagated to upper-level managers only if the summary state has changed.
1588 //
1590 {
1591  EPNAME("do_Status")
1592  const char *srvMsg, *stgMsg;
1593  int Stage = Arg.Request.modifier & CmsStatusRequest::kYR_Stage;
1594  int noStage = Arg.Request.modifier & CmsStatusRequest::kYR_noStage;
1595  int Resume = Arg.Request.modifier & CmsStatusRequest::kYR_Resume;
1596  int Suspend = Arg.Request.modifier & CmsStatusRequest::kYR_Suspend;
1597  int Reset = Arg.Request.modifier & CmsStatusRequest::kYR_Reset;
1598  int add2Activ, add2Stage, port;
1599 
1600 // Do some debugging
1601 //
1602  DEBUGR( (Reset ? "reset " : "")
1603  <<(Resume ? "resume " : (Suspend ? "suspend " : ""))
1604  <<(Stage ? "stage " : (noStage ? "nostage " : "")));
1605 
1606 // Process reset requests. These are exclsuive to any other request
1607 //
1608  if (Reset)
1609  {XrdCmsManager::Reset(); // Propagate the reset to our managers
1610  Cache.Bounce(NodeMask, NodeID); // Now invalidate our cache lines
1611  }
1612 
1613 // Process stage/nostage
1614 //
1615  if ((Stage && isNoStage) || (noStage && !isNoStage))
1616  if (noStage) {add2Stage = -1; isNoStage = 1; stgMsg="staging suspended";}
1617  else {add2Stage = 1; isNoStage = 0; stgMsg="staging resumed";}
1618  else {add2Stage = 0; stgMsg = 0;}
1619 
1620 // Process suspend/resume. We mmerely need a read lock to alter isBad here.
1621 //
1622  if ((Resume && (isBad & isSuspend)) || (Suspend && !(isBad & isSuspend)))
1623  if (Suspend) {add2Activ = -1;
1624  Cluster.SLock(true, false);
1625  isBad |= isSuspend; // Keep coherency with black listing
1626  Cluster.SLock(false);
1627  srvMsg="service suspended";
1628  stgMsg = 0;
1629  }
1630  else {add2Activ = 1;
1631  Cluster.SLock(true, false);
1632  isBad &= ~isSuspend; // Keep coherency with black listing
1633  Cluster.SLock(false);
1634  srvMsg="service resumed";
1635  stgMsg = (isNoStage ? "(no staging)" : "(staging)");
1636  port = ntohl(Arg.Request.streamid);
1637  if (port && port != netIF.Port())
1638  {Lock(); netIF.Port(port); UnLock();
1639  DEBUGR("set data port to " <<port);
1640  }
1641  }
1642  else {add2Activ = 0; srvMsg = 0;}
1643 
1644 // Get the most important message out (advisory isOffline doen't need STMutex)
1645 //
1646  if (isOffline) {srvMsg = "service offline"; stgMsg = 0;}
1647  else if (isBad & isDisabled) {srvMsg = "service disabled"; stgMsg = 0;}
1648  else if (isBad & isBlisted ) {srvMsg = "service blacklisted"; stgMsg = 0;}
1649 
1650 // Now see if we need to change anything
1651 //
1652  if (add2Activ || add2Stage)
1653  {CmsState.Update(XrdCmsState::Counts, add2Activ, add2Stage);
1654  Say.Emsg("Node", Name(), srvMsg, stgMsg);
1655  }
1656 
1657  return 0;
1658 }
1659 
1660 /******************************************************************************/
1661 /* d o _ T r u n c */
1662 /******************************************************************************/
1663 
1664 // Trunc requests are forwarded to all subscribers
1665 //
1667 {
1668  EPNAME("do_Trunc")
1669  long long Size = -1;
1670  int rc;
1671 
1672 // Do some debugging
1673 //
1674  DEBUGR("size " <<Arg.Mode <<' ' <<Arg.Path);
1675 
1676 // We are don here if we have no data; otherwise convert the mode if we
1677 // haven't done so already.
1678 //
1679  if (!Config.DiskOK) return 0;
1680  if (Size < 0 && !getSize(Arg.Mode, Size)) return "invalid size";
1681 
1682 // Attempt to change the size either via call-out or the oss plug-in
1683 //
1684  if (Config.ProgTR) rc = fsExec(Config.ProgTR, Arg.Mode, Arg.Path);
1685  else rc = Config.ossFS->Truncate(Arg.Path, Size);
1686 
1687 // Return appropriate result
1688 //
1689  return (rc ? fsFail(Arg.Ident, "trunc", Arg.Path, rc) : 0);
1690 }
1691 
1692 /******************************************************************************/
1693 /* d o _ T r y */
1694 /******************************************************************************/
1695 
1696 // Try requests from a manager indicate that we are being displaced and should
1697 // hunt for another manager. The request provides hints as to where to try.
1698 // Note that this method is no longer called but handled in XrdCmsProtocol!
1699 //
1701 {
1702  EPNAME("do_Try")
1703 
1704 // Do somde debugging
1705 //
1706  DEBUGR(Arg.Path);
1707 
1708 // Add all the alternates to our alternate list
1709 //
1710  if (Manager) Manager->myMans->Add(&netID, Arg.Path, Config.PortTCP, myLevel);
1711 
1712 // Close the link and return an error
1713 //
1714 // Disc("redirected.");
1715  return ".redirected";
1716 }
1717 
1718 /******************************************************************************/
1719 /* d o _ U p d a t e */
1720 /******************************************************************************/
1721 
1723 {
1724 
1725 // Process: <id> update
1726 // Respond: <id> status
1727 //
1728  CmsState.sendState(Link);
1729  return 0;
1730 }
1731 
1732 /******************************************************************************/
1733 /* d o _ U s a g e */
1734 /******************************************************************************/
1735 
1736 // Usage requests from a manager are local to the cell and never propagated.
1737 //
1739 {
1740 
1741 // Process: <id> usage
1742 // Respond: <id> load <cpu> <io> <load> <mem> <pag> <dskfree> <dskutil>
1743 //
1744  Report_Usage(Link);
1745  return 0;
1746 }
1747 
1748 /******************************************************************************/
1749 /* R e p o r t _ U s a g e */
1750 /******************************************************************************/
1751 
1752 void XrdCmsNode::Report_Usage(XrdLink *lp) // Static!
1753 {
1754  EPNAME("Report_Usage")
1755  CmsLoadRequest myLoad = {{0, kYR_load, 0, 0}};
1756  struct iovec xmsg[2];
1757  char loadbuff[CmsLoadRequest::numLoad];
1758  char respbuff[sizeof(loadbuff)+2+sizeof(int)+2], *bp = respbuff;
1759  int blen, maxfr, pcpu, pnet, pxeq, pmem, ppag, pdsk;
1760 
1761 // Respond: <id> load <cpu> <io> <load> <mem> <pag> <dskfree> <dskutil>
1762 //
1763  maxfr = Meter.Report(pcpu, pnet, pxeq, pmem, ppag, pdsk);
1764 
1765  loadbuff[CmsLoadRequest::cpuLoad] = static_cast<char>(pcpu);
1766  loadbuff[CmsLoadRequest::netLoad] = static_cast<char>(pnet);
1767  loadbuff[CmsLoadRequest::xeqLoad] = static_cast<char>(pxeq);
1768  loadbuff[CmsLoadRequest::memLoad] = static_cast<char>(pmem);
1769  loadbuff[CmsLoadRequest::pagLoad] = static_cast<char>(ppag);
1770  loadbuff[CmsLoadRequest::dskLoad] = static_cast<char>(pdsk);
1771 
1772  blen = XrdOucPup::Pack(&bp, loadbuff, sizeof(loadbuff));
1773  blen += XrdOucPup::Pack(&bp, maxfr);
1774  myLoad.Hdr.datalen = htons(static_cast<unsigned short>(blen));
1775 
1776  xmsg[0].iov_base = (char *)&myLoad;
1777  xmsg[0].iov_len = sizeof(myLoad);
1778  xmsg[1].iov_base = respbuff;
1779  xmsg[1].iov_len = blen;
1780  if (lp) lp->Send(xmsg, 2);
1781  else XrdCmsManager::Inform("usage", xmsg, 2);
1782 
1783 // Do some debugging
1784 //
1785  DEBUG("cpu=" <<pcpu <<" net=" <<pnet <<" xeq=" <<pxeq
1786  <<" mem=" <<pmem <<" pag=" <<ppag <<" dsk=" <<pdsk <<' ' <<maxfr);
1787 }
1788 
1789 /******************************************************************************/
1790 /* S y n c S p a c e */
1791 /******************************************************************************/
1792 
1794 {
1795  XrdCmsRRData Arg;
1796  int old_free = 0;
1797 
1798 // For newly logged in nodes, we need to sync the free space stats
1799 //
1800  mlMutex.Lock();
1801  if (isRW && DiskFree > LastFree)
1802  {old_free = LastFree; LastFree = DiskFree;}
1803  mlMutex.UnLock();
1804 
1805 // Tell our manager if we now have more space, if need be.
1806 //
1807  if (!old_free)
1808  {Arg.Request.rrCode = kYR_login;
1809  Arg.Ident = Ident;
1810  Arg.dskFree = DiskFree;
1811  Arg.dskUtil = DiskUtil;
1812  do_Space(Arg);
1813  }
1814 }
1815 
1816 /******************************************************************************/
1817 /* P r i v a t e M e t h o d s */
1818 /******************************************************************************/
1819 /******************************************************************************/
1820 /* f s E x e c */
1821 /******************************************************************************/
1822 
1823 int XrdCmsNode::fsExec(XrdOucProg *Prog, char *Arg1, char *Arg2)
1824 {
1825  static const int PfnSZ = XrdCmsMAX_PATH_LEN+1;
1826  char Pfn1[PfnSZ], Pfn2[PfnSZ];
1827 
1828 // The first argument may or may not be a path. The second, if present is always
1829 // a path. If we have a name mapper then we need to substitute remapped paths.
1830 //
1831  if (Config.lcl_N2N)
1832  {if (*Arg1 == '/')
1833  {if (Config.lcl_N2N->lfn2pfn(Arg1,Pfn1,PfnSZ-1)) return fsL2PFail1;
1834  Arg1 = Pfn1;
1835  }
1836  if ( Arg2)
1837  {if (Config.lcl_N2N->lfn2pfn(Arg2,Pfn2,PfnSZ-1)) return fsL2PFail2;
1838  Arg2 = Pfn2;
1839  }
1840  }
1841 
1842 // Return results of the call-out
1843 //
1844  return Prog->Run(Arg1, Arg2);
1845 }
1846 
1847 /******************************************************************************/
1848 /* f s F a i l */
1849 /******************************************************************************/
1850 
1851 const char *XrdCmsNode::fsFail(const char *Who, const char *What,
1852  const char *Path, int rc)
1853 {
1854  EPNAME("fsFail")
1855 
1856 // Immediately return on the two most unlikely failures; o/w issue message
1857 //
1858  rc = abs(rc);
1859  if (rc == fsL2PFail1) return "lfn2pfn path1 failed";
1860  if (rc == fsL2PFail2) return "lfn2pfn path2 failed";
1861  if (rc != ENOENT) Say.Emsg("Node", rc, What, Path);
1862  else {struct {const char *Ident;} Arg = {Who};
1863  DEBUGR("rc=" <<rc <<' ' <<What <<' ' <<Path);
1864  }
1865  return rc ? XrdSysE2T(rc) : 0;
1866 }
1867 
1868 /******************************************************************************/
1869 /* g e t M o d e */
1870 /******************************************************************************/
1871 
1872 int XrdCmsNode::getMode(const char *theMode, mode_t &Mode)
1873 {
1874  char *eP;
1875 
1876 // Convert the mode argument
1877 //
1878  if (!(Mode = strtol(theMode, &eP, 8)) || *eP || (Mode >> 9)) return 0;
1879  return 1;
1880 }
1881 
1882 /******************************************************************************/
1883 /* g e t S i z e */
1884 /******************************************************************************/
1885 
1886 int XrdCmsNode::getSize(const char *theSize, long long &Size)
1887 {
1888  char *eP;
1889 
1890 // Convert the size argument
1891 //
1892  if (!(Size = strtoll(theSize, &eP, 10)) || *eP) return 0;
1893  return 1;
1894 }
1895 
1896 /******************************************************************************/
1897 /* s e t H a s h */
1898 /******************************************************************************/
1899 
1900 void XrdCmsNode::setHash(XrdCmsSelect &Sel, int acount)
1901 {
1902 
1903 // Process postive count
1904 //
1905  if (acount > 0)
1906  {char *spos = (*Sel.Path.Val == '/' ? Sel.Path.Val+1 : Sel.Path.Val);
1907  char *slash;
1908  while(acount)
1909  {if (!(slash = index(spos, '/'))) return;
1910  acount--; spos = slash+1;
1911  }
1912  *slash = 0;
1913  Sel.AltHash = XrdOucCRC::Calc32C(Sel.Path.Val, slash - Sel.Path.Val);
1914  *slash = '/';
1915  Sel.Opts |= XrdCmsSelect::UseAH;
1916  return;
1917  }
1918 
1919 // Process negative count
1920 //
1921  if (acount < 0)
1922  {int i = Sel.Path.Len-1;
1923  if (Sel.Path.Val[i] == '/') i--;
1924 
1925  for(; i > 0; i--)
1926  {if (Sel.Path.Val[i] == '/' && !(++acount)) break;}
1927 
1928  if (i)
1929  {Sel.AltHash = XrdOucCRC::Calc32C(Sel.Path.Val+i, Sel.Path.Len-i);
1930  Sel.Opts |= XrdCmsSelect::UseAH;
1931  }
1932  }
1933 }
unsigned int kXR_unt32
Definition: XPtypes.hh:90
unsigned char kXR_char
Definition: XPtypes.hh:65
#define DEBUG(x)
Definition: XrdBwmTrace.hh:54
#define EPNAME(x)
Definition: XrdBwmTrace.hh:56
#define DEBUGR(y)
Definition: XrdCmsTrace.hh:51
#define TRACER(x, y)
Definition: XrdCmsTrace.hh:58
#define STMax
Definition: XrdCmsTypes.hh:39
unsigned long long SMask_t
Definition: XrdCmsTypes.hh:33
#define XrdCmsMAX_PATH_LEN
Definition: XrdCmsTypes.hh:46
int Mode
XrdOucString Path
const char * XrdSysE2T(int errcode)
Definition: XrdSysE2T.cc:104
if(Avsz)
size_t strlcpy(char *dst, const char *src, size_t sz)
kXR_char Mod
Definition: XrdCmsBaseFS.hh:60
kXR_unt32 Sid
Definition: XrdCmsBaseFS.hh:59
SMask_t RouteW
Definition: XrdCmsBaseFS.hh:53
SMask_t Route
Definition: XrdCmsBaseFS.hh:52
int Exists(XrdCmsRRData &Arg, XrdCmsPInfo &Who, int noLim=0)
void Bounce(SMask_t smask, int SNum)
Definition: XrdCmsCache.cc:343
int GetFile(XrdCmsSelect &Sel, SMask_t mask)
Definition: XrdCmsCache.cc:232
int DelFile(XrdCmsSelect &Sel, SMask_t mask)
Definition: XrdCmsCache.cc:191
int AddFile(XrdCmsSelect &Sel, SMask_t mask)
Definition: XrdCmsCache.cc:117
XrdCmsPList_Anchor Paths
Definition: XrdCmsCache.hh:49
SMask_t getMask(const XrdNetAddr *addr)
void SLock(bool dolock, bool wrmode=true)
void Space(XrdCms::SpaceData &sData, SMask_t smask)
int Broadsend(SMask_t smask, XrdCms::CmsRRHdr &Hdr, void *Data, int Dlen)
long long Refs()
int Select(XrdCmsSelect &Sel)
int Locate(XrdCmsSelect &Sel)
static const int EReplete
SMask_t Broadcast(SMask_t, const struct iovec *, int, int tot=0)
XrdCmsSelected * List(SMask_t mask, CmsLSOpts opts, bool &oksel)
static const int RetryErr
static const int Wait4CBk
int Stats(char *bfr, int bln)
XrdOucProg * ProgMP
XrdOucProg * ProgRM
XrdOss * ossFS
char * mrRdrHost
XrdOucProg * ProgRD
XrdOucProg * ProgCH
char * msRdrHost
XrdOucProg * ProgMV
XrdOucProg * ProgMD
XrdOucName2Name * lcl_N2N
XrdOucProg * ProgTR
unsigned int Hash
Definition: XrdCmsKey.hh:53
char * Val
Definition: XrdCmsKey.hh:52
short Len
Definition: XrdCmsKey.hh:54
static void Inform(const char *What, const char *Data, int Dlen)
static bool Present()
static void Reset()
void Record(int pcpu, int pnet, int pxeq, int pmem, int ppag, int pdsk)
Definition: XrdCmsMeter.cc:351
int Report(int &pcpu, int &pnet, int &pxeq, int &pmem, int &ppag, int &pdsk)
Definition: XrdCmsMeter.cc:374
int FreeSpace(int &tutil)
Definition: XrdCmsMeter.cc:158
int calcLoad(uint32_t pcpu, uint32_t pio, uint32_t pload, uint32_t pmem, uint32_t ppag)
Definition: XrdCmsMeter.cc:130
void setVirtUpdt()
Definition: XrdCmsMeter.hh:78
const char * do_PrepDel(XrdCmsRRData &Arg)
Definition: XrdCmsNode.cc:893
int do_StateFWD(XrdCmsRRData &Arg)
Definition: XrdCmsNode.cc:1403
const char * do_Gone(XrdCmsRRData &Arg)
Definition: XrdCmsNode.cc:366
const char * do_Locate(XrdCmsRRData &Arg)
Definition: XrdCmsNode.cc:533
const char * do_Update(XrdCmsRRData &Arg)
Definition: XrdCmsNode.cc:1722
const char * do_Try(XrdCmsRRData &Arg)
Definition: XrdCmsNode.cc:1700
const char * do_State(XrdCmsRRData &Arg)
Definition: XrdCmsNode.cc:1301
void Delete(XrdSysRWLock &gMutex)
Definition: XrdCmsNode.hh:129
static void do_StateDFS(XrdCmsBaseFR *rP, int rc)
const char * do_Space(XrdCmsRRData &Arg)
Definition: XrdCmsNode.cc:1258
int do_SelAvoid(XrdCmsRRData &Arg, XrdCmsSelect &Sel, char *Avoid, bool &doRedir)
Definition: XrdCmsNode.cc:986
const char * do_Select(XrdCmsRRData &Arg)
Definition: XrdCmsNode.cc:1057
const char * do_Mv(XrdCmsRRData &Arg)
Definition: XrdCmsNode.cc:788
const char * do_Trunc(XrdCmsRRData &Arg)
Definition: XrdCmsNode.cc:1666
static void Report_Usage(XrdLink *lp)
Definition: XrdCmsNode.cc:1752
const char * do_Usage(XrdCmsRRData &Arg)
Definition: XrdCmsNode.cc:1738
const char * do_Chmod(XrdCmsRRData &Arg)
Definition: XrdCmsNode.cc:307
void SyncSpace()
Definition: XrdCmsNode.cc:1793
const char * do_Load(XrdCmsRRData &Arg)
Definition: XrdCmsNode.cc:459
static int do_SelPrep(XrdCmsPrepArgs &Arg)
Definition: XrdCmsNode.cc:1191
const char * do_Rm(XrdCmsRRData &Arg)
Definition: XrdCmsNode.cc:918
const char * do_PrepAdd(XrdCmsRRData &Arg)
Definition: XrdCmsNode.cc:874
const char * do_Ping(XrdCmsRRData &Arg)
Definition: XrdCmsNode.cc:844
const char * do_Have(XrdCmsRRData &Arg)
Definition: XrdCmsNode.cc:408
const char * do_Stats(XrdCmsRRData &Arg)
Definition: XrdCmsNode.cc:1524
const char * do_Disc(XrdCmsRRData &Arg)
Definition: XrdCmsNode.cc:341
const char * do_Avail(XrdCmsRRData &Arg)
Definition: XrdCmsNode.cc:286
static int do_LocFmt(char *buff, XrdCmsSelected *sP, SMask_t pf, SMask_t wf, bool lsall=false, bool lsuniq=false)
Definition: XrdCmsNode.cc:659
void Disc(const char *reason=0, int needLock=1)
Definition: XrdCmsNode.cc:256
const char * do_Mkpath(XrdCmsRRData &Arg)
Definition: XrdCmsNode.cc:756
XrdCmsNode(XrdLink *lnkp, const char *theIF=0, const char *sid=0, int port=0, int lvl=0, int id=-1)
Definition: XrdCmsNode.cc:98
const char * do_Pong(XrdCmsRRData &Arg)
Definition: XrdCmsNode.cc:862
void setName(XrdLink *lnkp, const char *theIF, int port)
Definition: XrdCmsNode.cc:145
const char * do_Mkdir(XrdCmsRRData &Arg)
Definition: XrdCmsNode.cc:724
const char * do_StatFS(XrdCmsRRData &Arg)
Definition: XrdCmsNode.cc:1481
const char * do_Rmdir(XrdCmsRRData &Arg)
Definition: XrdCmsNode.cc:953
const char * do_Status(XrdCmsRRData &Arg)
Definition: XrdCmsNode.cc:1589
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
struct iovec ioV[iovNum]
static const int iovNum
void Gone(char *path)
void Inform(const char *cmd, XrdCmsPrepArgs *pargs)
int Del(char *reqid)
unsigned int Opts
Definition: XrdCmsRRData.hh:65
unsigned int dskFree
Definition: XrdCmsRRData.hh:67
XrdCms::CmsRRHdr Request
Definition: XrdCmsRRData.hh:54
SMask_t smask
Definition: XrdCmsSelect.hh:49
struct iovec * iovP
Definition: XrdCmsSelect.hh:50
struct XrdCmsSelect::@93 Resp
struct XrdCmsSelect::@92 Vec
XrdCmsRRQInfo * InfoP
Definition: XrdCmsSelect.hh:47
XrdCmsKey Path
Definition: XrdCmsSelect.hh:46
unsigned int AltHash
Definition: XrdCmsSelect.hh:53
SMask_t nmask
Definition: XrdCmsSelect.hh:48
char Ident[IdentSize]
XrdCmsSelected * next
void Update(StateType StateT, int ActivVal, int StageVal=0)
Definition: XrdCmsState.cc:258
void sendState(XrdLink *Link)
Definition: XrdCmsState.cc:161
Definition: XrdJob.hh:43
const char * Set(const char *hSpec, int pNum=PortInSpec)
Definition: XrdNetAddr.cc:216
static const char * Name(ifType ifT)
Definition: XrdNetIF.hh:312
ifType
The enum that is used to index into ifData to get appropriate interface.
Definition: XrdNetIF.hh:65
@ Public46
Definition: XrdNetIF.hh:71
@ PublicV4
Definition: XrdNetIF.hh:65
@ Public64
Definition: XrdNetIF.hh:73
@ PublicV6
Definition: XrdNetIF.hh:67
static void Privatize(ifType &x)
Definition: XrdNetIF.hh:330
virtual int Mkdir(const char *path, mode_t mode, int mkpath=0, XrdOucEnv *envP=0)=0
virtual int Chmod(const char *path, mode_t mode, XrdOucEnv *envP=0)=0
virtual int Remdir(const char *path, int Opts=0, XrdOucEnv *envP=0)=0
virtual int Rename(const char *oPath, const char *nPath, XrdOucEnv *oEnvP=0, XrdOucEnv *nEnvP=0)=0
virtual int Truncate(const char *path, unsigned long long fsize, XrdOucEnv *envP=0)=0
virtual int Unlink(const char *path, int Opts=0, XrdOucEnv *envP=0)=0
static uint32_t Calc32C(const void *data, size_t count, uint32_t prevcs=0)
Definition: XrdOucCRC.cc:190
virtual int lfn2pfn(const char *lfn, char *buff, int blen)=0
int Run(XrdOucStream *Sp, const char *argV[], int argc=0, const char *envV[]=0) const
Definition: XrdOucProg.cc:108
static int Pack(struct iovec **, const char *, unsigned short &buff)
Definition: XrdOucPup.cc:52
void Schedule(XrdJob *jp)
int Emsg(const char *esfx, int ecode, const char *text1, const char *text2=0)
Definition: XrdSysError.cc:95
static void Snooze(int seconds)
Definition: XrdSysTimer.cc:168
XrdCmsMeter Meter
Definition: XrdCmsMeter.hh:131
XrdCmsCache Cache
Definition: XrdPfcFile.hh:204
XrdVersionInfo myVersion
static const unsigned char kYR_Version
Definition: YProtocol.hh:80
kXR_unt16 datalen
Definition: YProtocol.hh:86
@ kYR_FSError
Definition: YProtocol.hh:161
@ kYR_ENETUNREACH
Definition: YProtocol.hh:158
@ kYR_EIO
Definition: YProtocol.hh:154
@ kYR_ENOENT
Definition: YProtocol.hh:150
@ kYR_SrvError
Definition: YProtocol.hh:162
@ kYR_EPERM
Definition: YProtocol.hh:151
kXR_char modifier
Definition: YProtocol.hh:85
XrdScheduler * Sched
XrdCmsCluster Cluster
XrdCmsBaseFS baseFS
@ kYR_data
Definition: YProtocol.hh:141
@ kYR_redirect
Definition: YProtocol.hh:143
@ kYR_wait
Definition: YProtocol.hh:144
@ kYR_error
Definition: YProtocol.hh:142
XrdSysError Say
kXR_char rrCode
Definition: YProtocol.hh:84
XrdCmsState CmsState
Definition: XrdCmsState.cc:55
XrdCmsPrepare PrepQ
kXR_unt32 streamid
Definition: YProtocol.hh:83
XrdCmsConfig Config
@ kYR_raw
Definition: YProtocol.hh:132
@ kYR_space
Definition: YProtocol.hh:109
@ kYR_login
Definition: YProtocol.hh:90
@ kYR_state
Definition: YProtocol.hh:110
@ kYR_have
Definition: YProtocol.hh:105
@ kYR_pong
Definition: YProtocol.hh:108
@ kYR_load
Definition: YProtocol.hh:106
@ kYR_avail
Definition: YProtocol.hh:102
int Opts
Definition: XrdMpxStats.cc:58
@ hex1
Definition: XrdSysTrace.hh:42
static const int RHLen
Definition: YProtocol.hh:264