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