XRootD
XrdFrcUtils.cc
Go to the documentation of this file.
1 /******************************************************************************/
2 /* */
3 /* X r d F r c U t i l s . c c */
4 /* */
5 /* (c) 2009 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 <fcntl.h>
33 #include <unistd.h>
34 #include <utime.h>
35 #include <sys/stat.h>
36 #include <sys/types.h>
37 
38 #include "XrdFrc/XrdFrcTrace.hh"
39 #include "XrdFrc/XrdFrcUtils.hh"
40 #include "XrdFrc/XrdFrcXAttr.hh"
41 
42 #include "XrdOuc/XrdOucSxeq.hh"
43 #include "XrdOuc/XrdOucUtils.hh"
44 #include "XrdOuc/XrdOucXAttr.hh"
45 
46 #include "XrdSys/XrdSysError.hh"
47 #include "XrdSys/XrdSysHeaders.hh"
48 #include "XrdSys/XrdSysPlatform.hh"
49 
50 using namespace XrdFrc;
51 
52 /******************************************************************************/
53 /* A s k */
54 /******************************************************************************/
55 
56 char XrdFrcUtils::Ask(char dflt, const char *Msg1, const char *Msg2,
57  const char *Msg3)
58 {
59  const char *Hint;
60  char Answer[8];
61  int n;
62 
63  Hint = (dflt == 'y' ? " (y | n | a): " : " (n | y | a): ");
64 
65  do {std::cerr <<"frm_admin: " <<Msg1 <<Msg2 <<Msg3 <<Hint;
66  std::cin.getline(Answer, sizeof(Answer));
67  if (!*Answer) return dflt;
68 
69  n = strlen(Answer);
70  if (!strncmp("yes", Answer, n)) return 'y';
71  if (!strncmp("no", Answer, n)) return 'n';
72  if (!strncmp("abort",Answer, n)) return 'a';
73  } while(1);
74  return 'a';
75 }
76 
77 /******************************************************************************/
78 /* c h k U R L */
79 /******************************************************************************/
80 
81 int XrdFrcUtils::chkURL(const char *Url)
82 {
83  const char *Elem;
84 
85 // Verify that this is a valid url and return offset to the lfn
86 //
87  if (!(Elem = index(Url, ':'))) return 0;
88  if (Elem[1] != '/' || Elem[2] != '/') return 0;
89  if (!(Elem = index(Elem+3, '/')) || Elem[1] != '/') return 0;
90  Elem++;
91 
92 // At this point ignore all leading slashes but one
93 //
94  while(Elem[1] == '/') Elem++;
95  return Elem - Url;
96 }
97 
98 /******************************************************************************/
99 /* m a k e P a t h */
100 /******************************************************************************/
101 
102 char *XrdFrcUtils::makePath(const char *iName, const char *Path, int Mode)
103 {
104  char *bPath;
105  int rc;
106 
107 // Generate an frm-specific admin path
108 //
109  bPath = XrdOucUtils::genPath(Path, iName, "frm");
110 
111 // Create the admin directory if it does not exists and a mode supplied
112 //
113  if (Mode > 0 && (rc = XrdOucUtils::makePath(bPath, Mode)))
114  {Say.Emsg("makePath", rc, "create directory", bPath);
115  return 0;
116  }
117 
118 // Return the actual adminpath we are to use (this has been strduped).
119 //
120  return bPath;
121 }
122 
123 /******************************************************************************/
124 /* m a k e Q D i r */
125 /******************************************************************************/
126 
127 char *XrdFrcUtils::makeQDir(const char *Path, int Mode)
128 {
129  char qPath[1040], qLink[1032];
130  int n, lksz, rc;
131 
132 // Generate an frm-specific queue path
133 //
134  strcpy(qPath, Path);
135  n = strlen(qPath);
136  if (qPath[n-1] != '/') qPath[n++] = '/';
137  strcpy(qPath+n, "Queues/");
138 
139 // If the target is a symlink, optimize the path
140 //
141  if ((lksz = readlink(qPath, qLink, sizeof(qLink)-1)) > 0)
142  {qLink[lksz] = '\0';
143  if (qLink[lksz-1] != '/') {qLink[lksz++] = '/'; qLink[lksz++] = '\0';}
144  if (*qLink == '/') strcpy(qPath, qLink);
145  else strcpy(qPath+n, qLink);
146  }
147 
148 // Create the queue directory if it does not exists
149 //
150  if (Mode > 0 && (rc = XrdOucUtils::makePath(qPath, Mode)))
151  {Say.Emsg("makeQDir", rc, "create directory", qPath);
152  return 0;
153  }
154 
155 // Return the actual adminpath we are to use
156 //
157  return strdup(qPath);
158 }
159 
160 /******************************************************************************/
161 /* M a p M 2 O */
162 /******************************************************************************/
163 
164 int XrdFrcUtils::MapM2O(const char *Nop, const char *Pop)
165 {
166  int Options = 0;
167 
168 // Map processing options to request options
169 //
170  if (index(Pop, 'w')) Options |= XrdFrcRequest::makeRW;
171  if (*Nop != '-')
172  {if (index(Pop, 's') || index(Pop, 'n'))
173  Options |= XrdFrcRequest::msgSucc;
174  if (index(Pop, 'f') || !index(Pop, 'q'))
175  Options |= XrdFrcRequest::msgFail;
176  }
177 
178 // All done
179 //
180  return Options;
181 }
182 
183 /******************************************************************************/
184 /* M a p R 2 Q */
185 /******************************************************************************/
186 
187 int XrdFrcUtils::MapR2Q(char Opc, int *Flags)
188 {
189 
190 // Simply map the request code to the relevant queue
191 //
192  switch(Opc)
193  {case 0 :
194  case '+': return XrdFrcRequest::stgQ;
195  case '^': if (Flags) *Flags = XrdFrcRequest::Purge;
196  return XrdFrcRequest::migQ;
197  case '&': return XrdFrcRequest::migQ;
198  case '<': return XrdFrcRequest::getQ;
199  case '=': if (Flags) *Flags |= XrdFrcRequest::Purge;
200  return XrdFrcRequest::putQ;
201  case '>': return XrdFrcRequest::putQ;
202  default: break;
203  }
204  return XrdFrcRequest::nilQ;
205 }
206 
207 /******************************************************************************/
208 /* M a p V 2 I */
209 /******************************************************************************/
210 
211 int XrdFrcUtils::MapV2I(const char *vName, XrdFrcRequest::Item &ICode)
212 {
213  static struct ITypes {const char *IName; XrdFrcRequest::Item ICode;}
214  ITList[] = {{"lfn", XrdFrcRequest::getLFN},
215  {"lfncgi", XrdFrcRequest::getLFNCGI},
216  {"mode", XrdFrcRequest::getMODE},
217  {"obj", XrdFrcRequest::getOBJ},
218  {"objcgi", XrdFrcRequest::getOBJCGI},
219  {"op", XrdFrcRequest::getOP},
220  {"prty", XrdFrcRequest::getPRTY},
221  {"qwt", XrdFrcRequest::getQWT},
222  {"rid", XrdFrcRequest::getRID},
223  {"tod", XrdFrcRequest::getTOD},
224  {"note", XrdFrcRequest::getNOTE},
225  {"tid", XrdFrcRequest::getUSER}};
226  static const int ITNum = sizeof(ITList)/sizeof(struct ITypes);
227  int i;
228 
229 // Simply map the variable name to the item code
230 //
231  for (i = 0; i < ITNum; i++)
232  if (!strcmp(vName, ITList[i].IName))
233  {ICode = ITList[i].ICode; return 1;}
234  return 0;
235 }
236 
237 /******************************************************************************/
238 /* U n i q u e */
239 /******************************************************************************/
240 
241 int XrdFrcUtils::Unique(const char *lkfn, const char *myProg)
242 {
243  static const int Mode = S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH;
244  FLOCK_t lock_args;
245  int myFD, rc;
246 
247 // Open the lock file first in r/w mode
248 //
249  if ((myFD = open(lkfn, O_RDWR|O_CREAT, Mode)) < 0)
250  {Say.Emsg("Unique",errno,"open",lkfn); return 0;}
251 
252 // Establish locking options
253 //
254  bzero(&lock_args, sizeof(lock_args));
255  lock_args.l_type = F_WRLCK;
256 
257 // Perform action.
258 //
259  do {rc = fcntl(myFD,F_SETLK,&lock_args);}
260  while(rc < 0 && errno == EINTR);
261  if (rc < 0)
262  {Say.Emsg("Unique", errno, "obtain the run lock on", lkfn);
263  Say.Emsg("Unique", "Another", myProg, "may already be running!");
264  close(myFD);
265  return 0;
266  }
267 
268 // All done
269 //
270  return 1;
271 }
272 
273 /******************************************************************************/
274 /* u p d t C p y */
275 /******************************************************************************/
276 
277 int XrdFrcUtils::updtCpy(const char *Pfn, int Adj)
278 {
280  struct stat Stat;
281 
282 // Make sure the base file exists
283 //
284  if (stat(Pfn, &Stat)) {Say.Emsg("updCpy", errno,"stat pfn ",Pfn); return 0;}
285 
286 // Set correct copy time based on need
287 //
288  cpyInfo.Attr.cpyTime = static_cast<long long>(Stat.st_mtime + Adj);
289  return cpyInfo.Set(Pfn) == 0;
290 }
291 
292 /******************************************************************************/
293 /* U t i m e */
294 /******************************************************************************/
295 
296 int XrdFrcUtils::Utime(const char *Path, time_t tVal)
297 {
298  struct utimbuf tbuf = {tVal, tVal};
299  int rc;
300 
301 // Set the time
302 //
303  do {rc = utime(Path, &tbuf);} while(rc && errno == EINTR);
304  if (rc) Say.Emsg("Utils", errno, "set utime for pfn", Path);
305 
306 // All done
307 //
308  return rc == 0;
309 }
struct stat Stat
Definition: XrdCks.cc:49
int stat(const char *path, struct stat *buf)
int open(const char *path, int oflag,...)
int fcntl(int fd, int cmd,...)
#define close(a)
Definition: XrdPosix.hh:43
int Mode
XrdOucString Path
#define FLOCK_t
static const int stgQ
static const int getQ
static const int migQ
static const int putQ
static const int Purge
static const int msgFail
static const int makeRW
static const int msgSucc
static const int nilQ
static int chkURL(const char *Url)
Definition: XrdFrcUtils.cc:81
static char Ask(char dflt, const char *Msg1, const char *Msg2="", const char *Msg3="")
Definition: XrdFrcUtils.cc:56
static int MapR2Q(char Opc, int *Flags=0)
Definition: XrdFrcUtils.cc:187
static int Unique(const char *lkfn, const char *myProg)
Definition: XrdFrcUtils.cc:241
static char * makePath(const char *iName, const char *Path, int Mode)
Definition: XrdFrcUtils.cc:102
static int MapV2I(const char *Opc, XrdFrcRequest::Item &ICode)
Definition: XrdFrcUtils.cc:211
static int Utime(const char *Path, time_t tVal)
Definition: XrdFrcUtils.cc:296
static char * makeQDir(const char *Path, int Mode)
Definition: XrdFrcUtils.cc:127
static int MapM2O(const char *Nop, const char *Pop)
Definition: XrdFrcUtils.cc:164
static int updtCpy(const char *Pfn, int Adj)
Definition: XrdFrcUtils.cc:277
long long cpyTime
Definition: XrdFrcXAttr.hh:55
static char * genPath(const char *path, const char *inst, const char *psfx=0)
Definition: XrdOucUtils.cc:417
static int makePath(char *path, mode_t mode, bool reset=false)
Definition: XrdOucUtils.cc:917
int Set(const char *Path, int fd=-1)
Definition: XrdOucXAttr.hh:139
int Emsg(const char *esfx, int ecode, const char *text1, const char *text2=0)
Definition: XrdSysError.cc:95
XrdSysError Say