XRootD
Loading...
Searching...
No Matches
XrdPrep.cc
Go to the documentation of this file.
1/******************************************************************************/
2/* */
3/* X r d P r e p . c c */
4/* */
5/* (c) 2021 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 <iostream>
32#include <vector>
33#include <string>
34
35#include <ctype.h>
36#include <errno.h>
37#include <limits.h>
38#include <stdlib.h>
39#include <stdio.h>
40#include <sys/param.h>
41#include <sys/types.h>
42
43#include "XrdOuc/XrdOucEnv.hh"
44#include "XrdSys/XrdSysE2T.hh"
47
48using namespace XrdCl;
49
50/******************************************************************************/
51/* L o c a l D e f i n e s */
52/******************************************************************************/
53
54#define EMSG(x) std::cerr <<"xrdprep: "<<x<<std::endl
55
56/******************************************************************************/
57/* G e t N u m */
58/******************************************************************************/
59
60namespace
61{
62bool GetNum(const char *emsg, const char *item, int *val, int minv, int maxv=-1)
63{
64 char *eP;
65
66 if (!item || !*item)
67 {EMSG(emsg<<" value not specified"); return false;}
68
69 errno = 0;
70 *val = strtol(item, &eP, 10);
71 if (errno || *eP)
72 {EMSG(emsg<<" '"<<item<<"' is not a number");
73 return false;
74 }
75
76 if (*val < minv)
77 {EMSG(emsg<<" may not be less than "<<minv); return false;}
78 if (maxv >= 0 && *val > maxv)
79 {EMSG(emsg<<" may not be greater than "<<maxv); return false;}
80
81 return true;
82}
83}
84
85/******************************************************************************/
86/* U s a g e */
87/******************************************************************************/
88
89namespace
90{
91void Usage(int rc)
92{
93std::cerr<<"\nUsage: xrdprep [opts1] [prepare] host[:port] [path [...]]\n";
94std::cerr<<"\n xrdprep [opts2] {cancel | query} host[:port] handle [path [...]]\n";
95std::cerr<<"\nOpts1: [-E] [-p prty] [-s] [-S] [-w] [opts2]\n";
96std::cerr<<"\nOpts2: [-d n] [-f fn]" <<std::endl;
97exit(rc);
98}
99}
100
101/******************************************************************************/
102/* m a i n */
103/******************************************************************************/
104
105int main(int argc, char **argv)
106{
107 extern char *optarg;
108 extern int optind, opterr;
109
110 static const int MaxPathLen = MAXPATHLEN+1;
111 static const PrepareFlags::Flags mPrep = PrepareFlags::Cancel |
114
115 std::vector<std::string> fList;
116 FILE *Stream = 0;
117 const char *msgArgs[] = {"execute", "prepare"};
118 char Target[512];
119 char *inFile = 0;
121 int rc, Prty = 0, Debug = 0;
122 char c, lastOpt = 0;
123 bool isQuery = false, needHandle = false;
124
125// See simple help is needed
126//
127 if (argc <= 1) Usage(0);
128
129// Process the options
130//
131 opterr = 0;
132 if (argc > 1 && '-' == *argv[1])
133 while ((c = getopt(argc,argv,"d:Ef:p:sStw")) && ((unsigned char)c != 0xff))
134 { switch(c)
135 {
136 case 'd': if (!GetNum("debug level", optarg, &Debug, 0, 5)) exit(1);
137 break;
138 case 'E': lastOpt = c;
139 Opts |= PrepareFlags::Evict;
140 break;
141 case 'f': inFile = optarg;
142 break;
143 case 'p': lastOpt = c;
144 if (!GetNum("priority", optarg, &Prty, 0, 3)) exit(1);
145 break;
146 case 's': lastOpt = c; Opts |= PrepareFlags::Stage;
147 break;
148 case 'S': lastOpt = c; Opts |=(PrepareFlags::Stage|PrepareFlags::Colocate);
149 break;
150 case 't': lastOpt = c; Opts |= PrepareFlags::Fresh;
151 break;
152 case 'w': lastOpt = c; Opts |= PrepareFlags::WriteMode;
153 break;
154 default: EMSG("Invalid option '-"<<argv[optind-1]<<"'");
155 Usage(1);
156 }
157 }
158
159// The next argument is either a keyword or the hostname
160//
161 while(optind < argc)
162 { if (!strcmp(argv[optind], "cancel")) Opts = PrepareFlags::Cancel;
163 else if (!strcmp(argv[optind], "query")) isQuery = true;
164 else if (!strcmp(argv[optind], "prepare")){optind++; break;}
165 else break;
166 if (lastOpt)
167 {EMSG('-'<<lastOpt<<"' option is invalid for '"<<argv[optind]<<"'");
168 Usage(1);
169 }
170 needHandle = true;
171 msgArgs[0] = argv[optind++];
172 break;
173 }
174
175// Make sure a host has been specified
176//
177 if (optind >= argc || !isalnum(*argv[optind]))
178 {EMSG("target host name not specified");
179 Usage(1);
180 }
181
182// Grab the host name or address
183//
184 strcpy(Target, "root://");
185 strcat(Target, argv[optind]);
186 optind++;
187
188// If we need a handle then make sure we have one
189//
190 if (needHandle)
191 {if (optind >= argc || *argv[optind] == '/')
192 {EMSG(msgArgs[0]<<" prepare request handle not specified");
193 Usage(1);
194 }
195 }
196
197// Pre-process any command line paths at this point
198//
199 std::string strArg;
200 int totArgLen = 0;
201 for (int i = optind; i < argc; i++)
202 {strArg = argv[i];
203 totArgLen += strArg.size() + 1;
204 fList.push_back(strArg);
205 }
206
207// If an infile was specified, make sure we can open it
208//
209 if (inFile)
210 {if (!(Stream = fopen(inFile, "r")))
211 {EMSG("Unable to open "<<inFile<<"; "<<XrdSysE2T(errno));
212 exit(4);
213 }
214 char *sP, fBuff[MaxPathLen];
215 do {if (!(sP = fgets(fBuff, MaxPathLen, Stream))) break;
216 while(*sP && *sP == ' ') sP++;
217 if (*sP && *sP != '\n')
218 {strArg = sP;
219 if (strArg.size() && strArg.back() == '\n') strArg.pop_back();
220 while(strArg.size() && strArg.back() == ' ') strArg.pop_back();
221 totArgLen += strArg.size() + 1;
222 fList.push_back(strArg);
223 }
224 } while(!feof(Stream) && !ferror(Stream));
225 if ((rc = ferror(Stream)))
226 {EMSG("unable to read "<<inFile<<"; "<<XrdSysE2T(rc));
227 exit(4);
228 }
229 fclose(Stream);
230 }
231
232// If this is a prepare request then we need at least one path
233//
234 if (!needHandle && fList.size() == 0)
235 {EMSG("No files specified for 'prepare'");
236 Usage(1);
237 }
238
239// Cleanup options if eviction is wanted
240//
241 if (Opts & PrepareFlags::Evict) Opts &= ~mPrep;
242
243// Establish debugging level
244//
245 if (Debug > 0)
246 {const char *dbg[] = {"Info","Warning","Error","Debug","Dump"};
247 if (Debug > 5) Debug = 5;
248 XrdOucEnv::Export("XRD_LOGLEVEL", dbg[Debug-1]);
249 }
250
251// Get an instance of the file system
252//
253 FileSystem Admin(Target);
254
255// Issue the relevant operation
256//
257 Buffer *response = 0;
258 XRootDStatus st;
259 if (!isQuery) st = Admin.Prepare(fList, Opts, uint8_t(Prty), response);
260 else {Buffer qryArgs(totArgLen);
261 char *bP = qryArgs.GetBuffer();
262 for (int i = 0; i < (int)fList.size(); i++)
263 {strcpy(bP, fList[i].c_str());
264 bP += fList[i].size();
265 *bP++ = '\n';
266 }
267 *(bP-1) = 0;
268 st = Admin.Query(QueryCode::Prepare, qryArgs, response);
269 }
270
271// Check if all went well
272//
273 if (!st.IsOK())
274 {std::string estr = st.ToStr();
275 const char *einfo, *etxt = estr.c_str();
276 if (!(einfo = rindex(etxt, ']'))) einfo = etxt;
277 else {einfo++;
278 while(*einfo && *einfo == ' ') einfo++;
279 }
280 EMSG("Unable to "<<msgArgs[0]<<' '<<msgArgs[1]<<"; "
281 <<(char)tolower(*einfo)<<einfo+1);
282 exit(8);
283 }
284
285// Display the result
286//
287 std::string rstr = response->ToString();
288 const char *xx = rstr.c_str();
289 if (*xx) std::cout << xx << std::endl;
290 delete response;
291
292// All done
293//
294 exit(0);
295}
void Usage(const char *msg)
int optind
int fclose(FILE *stream)
#define fopen(a, b)
Definition XrdPosix.hh:54
int main(int argc, char **argv)
Definition XrdPrep.cc:105
#define EMSG(x)
Definition XrdPrep.cc:54
bool Debug
int emsg(int rc, char *msg)
const char * XrdSysE2T(int errcode)
Definition XrdSysE2T.cc:104
Binary blob representation.
const char * GetBuffer(uint32_t offset=0) const
Get the message buffer.
std::string ToString() const
Convert the buffer to a string.
Send file/filesystem queries to an XRootD cluster.
std::string ToStr() const
Convert to string.
static int Export(const char *Var, const char *Val)
Definition XrdOucEnv.cc:170
@ Cancel
cancel staging request
@ Colocate
co-locate staged files, if possible
@ Prepare
Query prepare status.
bool IsOK() const
We're fine.