XRootD
XrdFrmCns.cc
Go to the documentation of this file.
1 /******************************************************************************/
2 /* */
3 /* X r d F r m C n s . c c */
4 /* */
5 /* (c) 2011 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 <cerrno>
32 #include <poll.h>
33 #include <unistd.h>
34 #include <sys/param.h>
35 #include <sys/types.h>
36 #include <sys/stat.h>
37 #include <fcntl.h>
38 #include <cstdio>
39 
40 #include "XrdFrc/XrdFrcTrace.hh"
41 #include "XrdFrm/XrdFrmCns.hh"
42 #include "XrdFrm/XrdFrmConfig.hh"
43 #include "XrdOuc/XrdOucSxeq.hh"
44 #include "XrdOuc/XrdOucUtils.hh"
45 #include "XrdSys/XrdSysPlatform.hh"
46 #include "XrdSys/XrdSysPthread.hh"
47 #include "XrdSys/XrdSysTimer.hh"
48 
49 using namespace XrdFrc;
50 using namespace XrdFrm;
51 
52 /******************************************************************************/
53 /* S t a t i c V a r i a b l e s */
54 /******************************************************************************/
55 
56 char *XrdFrmCns::cnsPath = 0;
57 char *XrdFrmCns::cnsHdr[2] = {0, 0};
58 int XrdFrmCns::cnsHdrLen = 0;
59 int XrdFrmCns::cnsFD = -1;
60 int XrdFrmCns::cnsMode = XrdFrmCns::cnsIgnore;
61 int XrdFrmCns::cnsInit = 1;
62 
63 /******************************************************************************/
64 /* A d d */
65 /******************************************************************************/
66 
67 void XrdFrmCns::Add(const char *tID, const char *Path,
68  long long Size, mode_t Mode)
69 {
70  static const int mMask = S_IRWXU|S_IRWXG|S_IRWXO;
71  static char NewLine = '\n';
72  struct iovec iov[9];
73  char mBuff[8], sBuff[24];
74 
75 // Check if there is a cns here and we should initialize it
76 //
77  if (!cnsMode) return;
78  if (cnsInit && !Init())
79  {Say.Emsg("FrmCns", "Auto-ignore cnsd create", Path); return;}
80 
81 // Fill out the io vector
82 //
83  iov[0].iov_base = (char *)tID;
84  iov[0].iov_len = strlen(tID);
85  iov[1].iov_base = (char *)" create ";
86  iov[1].iov_len = 8;
87  iov[2].iov_base = mBuff;
88  iov[2].iov_len = sprintf(mBuff, "%3o ", Mode&mMask);
89  iov[3].iov_base = (char *)Path;
90  iov[3].iov_len = strlen(Path);
91  iov[4].iov_base = &NewLine;
92  iov[4].iov_len = 1;
93  iov[5] = iov[0];
94  iov[6].iov_base = (char *)" closew ";
95  iov[6].iov_len = 8;
96  iov[7] = iov[3];
97  iov[8].iov_base = sBuff;
98  iov[8].iov_len = sprintf(sBuff, " %lld\n", Size);
99 
100 // Send this off to the cnsd
101 //
102  if (!Send2Cnsd(iov, 9)) Say.Emsg("FrmCns", "Auto-ignore cnsd create", Path);
103 }
104 
105 /******************************************************************************/
106 /* D e l */
107 /******************************************************************************/
108 
109 void XrdFrmCns::Del(const char *Path, int HdrType, int islfn)
110 {
111  static char NewLine = '\n';
112  struct iovec iov[] = {{cnsHdr[HdrType],(size_t)cnsHdrLen},{0,0},{&NewLine,1}};
113  char buff[MAXPATHLEN];
114 
115 // Check if we should initialize
116 //
117  if (cnsInit && !Init())
118  {Say.Emsg("FrmCns", "Auto-ignore cnsd remove", Path); return;}
119 
120 // In most cases, del gets a pfn. We need to translate to an lfn.
121 //
122  if (islfn)
123  {iov[1].iov_base = (char *)Path;
124  iov[1].iov_len = strlen(Path);
125  } else if (!Config.LogicalPath(Path, buff, sizeof(buff))) return;
126  else {iov[1].iov_base = buff;
127  iov[1].iov_len = strlen(buff);
128  }
129 
130 // Send this off to the cnsd
131 //
132  if (!Send2Cnsd(iov, 3)) Say.Emsg("FrmCns", "Auto-ignore cnsd remove", Path);
133 }
134 
135 /******************************************************************************/
136 /* I n i t */
137 /******************************************************************************/
138 
139 int XrdFrmCns::Init()
140 {
141  static const int oMode= O_WRONLY | O_NONBLOCK | O_NDELAY;
142  static XrdSysMutex initMutex;
143  int rc, pMsg = 0;
144 
145 // Check if we really need to re-initialize
146 //
147  initMutex.Lock();
148  if (!cnsInit) {initMutex.UnLock(); return 1;}
149 
150 // Open the events FIFO. It might not exists or we might not be able to write
151 //
152  while((cnsFD = open(cnsPath, oMode)) < 0 && Retry(errno, pMsg)) {}
153 
154 // Check how we ended
155 //
156  cnsInit = (cnsFD < 0 ? 1 : 0);
157  rc = !cnsInit;
158 
159 // All done
160 //
161  initMutex.UnLock();
162  return rc;
163 }
164 
165 /******************************************************************************/
166 
167 int XrdFrmCns::Init(const char *aPath, int Opts)
168 {
169  int rc;
170 
171  if (aPath && (rc = setPath(aPath, 0))) return rc;
172  cnsMode = Opts;
173  return 0;
174 }
175 
176 /******************************************************************************/
177 
178 int XrdFrmCns::Init(const char *myID, const char *aPath, const char *iName)
179 {
180  char buff[2048];
181  int rc;
182 
183 // If we are ignoring the cns then don't bother with this
184 //
185  if (!cnsMode) return 0;
186 
187 // Construct the path to he cns events file (we know buff is large enough)
188 //
189  if (!cnsPath && (rc = setPath(aPath, iName))) return rc;
190 
191 // Create a static headers for deletes
192 //
193  cnsHdrLen = sprintf(buff, "%s.%d.0@localhost rmdir ", myID, getpid());
194  cnsHdr[HdrRmd] = strdup(buff);
195  sprintf(buff, "%s.%d.0@localhost rm ", myID, getpid());
196  cnsHdr[HdrRmf] = strdup(buff);
197 
198 // All done
199 //
200  return 0;
201 }
202 
203 /******************************************************************************/
204 /* R e t r y */
205 /******************************************************************************/
206 
207 int XrdFrmCns::Retry(int eNum, int &pMsg)
208 {
209  static const char *eAct = (cnsMode > 0 ? "Waiting for" : "Ignoring");
210  static const int Yawn = 10, Blurt = 6;
211 
212 // Always retry interrupted calls (these rarely happen, if ever)
213 //
214  if (eNum == EINTR) return 1;
215 
216 // Issue message as needed
217 //
218  if (eNum == ENOENT || eNum == EAGAIN || eNum == ENXIO || eNum == EPIPE)
219  {if (!(pMsg++%Blurt)) Say.Emsg("FrmCns", eAct, "cnsd on path", cnsPath);}
220  else Say.Emsg("FrmCns", errno, "notify cnsd via", cnsPath);
221 
222 // Check if we should sleep and retry or simply ignore this
223 //
224  if (cnsMode <= 0) return 0;
225  XrdSysTimer::Snooze(Yawn);
226  return 1;
227 }
228 
229 /******************************************************************************/
230 /* S e n d 2 C n s d */
231 /******************************************************************************/
232 
233 int XrdFrmCns::Send2Cnsd(struct iovec *iov, int iovn)
234 {
235  int rc, pMsg = 0;
236 
237 // Normally, writes will be atomic if we don't exceed PIPE_BUF, but this is
238 // not gauranteed when using vector writes. Plus, on some platforms, PIPE_BUF
239 // is way too small (i.e. 512 bytes). So, we just lock the file.
240 //
241  XrdOucSxeq::Serialize(cnsFD, 0);
242 
243 // Now write the data
244 //
245  while((rc = writev(cnsFD, iov, iovn)) < 0 && Retry(errno, pMsg)) {}
246 
247 // Unlock the file
248 //
249  XrdOucSxeq::Release(cnsFD);
250 
251 // All done
252 //
253  return rc > 0;
254 }
255 
256 /******************************************************************************/
257 /* s e t P a t h */
258 /******************************************************************************/
259 
260 int XrdFrmCns::setPath(const char *aPath, const char *iName)
261 {
262  static const char *sfx = "XrdCnsd.events";
263  struct stat Stat;
264  char buff[2048], *pP;
265 
266 // Release any cnspath we have
267 //
268  if (cnsPath) {free(cnsPath); cnsPath = 0;}
269 
270 // Generate a new one and make sure it is usable
271 //
272  pP = XrdOucUtils::genPath(aPath, iName, "cns");
273  if (strlen(pP) + strlen(sfx) >= (int)sizeof(buff))
274  {Say.Emsg("FrmCns", "Invalid cnsd apath", aPath); free(pP); return 1;}
275  strcpy(buff, pP); free(pP);
276  strcat(buff, "XrdCnsd.events");
277  if (stat(buff, &Stat) && errno != ENOENT)
278  {Say.Emsg("FrmCns", errno, "use cnsd file", buff); return 1;}
279  cnsPath = strdup(buff);
280  return 0;
281 }
struct stat Stat
Definition: XrdCks.cc:49
int stat(const char *path, struct stat *buf)
int open(const char *path, int oflag,...)
ssize_t writev(int fildes, const struct iovec *iov, int iovcnt)
int Mode
XrdOucString Path
static const int cnsIgnore
Definition: XrdFrmCns.hh:45
static int Init(const char *aPath, int Opts)
Definition: XrdFrmCns.cc:167
static void Add(const char *tID, const char *Path, long long Size, mode_t Mode)
Definition: XrdFrmCns.cc:67
int Release()
Definition: XrdOucSxeq.cc:106
int Serialize(int Opts=0)
Definition: XrdOucSxeq.cc:165
static char * genPath(const char *path, const char *inst, const char *psfx=0)
Definition: XrdOucUtils.cc:417
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
XrdCmsConfig Config
XrdSysError Say
int Opts
Definition: XrdMpxStats.cc:58