XRootD
Loading...
Searching...
No Matches
XrdThrottleConfig.cc
Go to the documentation of this file.
1/******************************************************************************/
2/* */
3/* (c) 2025 by the Morgridge Institute for Research */
4/* */
5/* This file is part of the XRootD software suite. */
6/* */
7/* XRootD is free software: you can redistribute it and/or modify it under */
8/* the terms of the GNU Lesser General Public License as published by the */
9/* Free Software Foundation, either version 3 of the License, or (at your */
10/* option) any later version. */
11/* */
12/* XRootD is distributed in the hope that it will be useful, but WITHOUT */
13/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */
14/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public */
15/* License for more details. */
16/* */
17/* You should have received a copy of the GNU Lesser General Public License */
18/* along with XRootD in a file called COPYING.LESSER (LGPL license) and file */
19/* COPYING (GPL license). If not, see <http://www.gnu.org/licenses/>. */
20/* */
21/* The copyright holder's institutional names and contributor's names may not */
22/* be used to endorse or promote products derived from this software without */
23/* specific prior written permission of the institution or contributor. */
24/******************************************************************************/
25
26#include "XrdOuc/XrdOuca2x.hh"
27#include "XrdOuc/XrdOucEnv.hh"
29#include "XrdSys/XrdSysError.hh"
32
33#include <cstring>
34#include <string>
35#include <fcntl.h>
36
37using namespace XrdThrottle;
38
39#define TS_Xeq(key, func) NoGo = (strcmp(key, var) == 0) ? func(Config) : 0
40int
41Configuration::Configure(const std::string &config_file)
42{
43 XrdOucEnv myEnv;
44 XrdOucStream Config(&m_log, getenv("XRDINSTANCE"), &myEnv, "(Throttle Config)> ");
45 int cfgFD;
46 if (config_file.empty()) {
47 m_log.Say("No filename specified.");
48 return 1;
49 }
50 if ((cfgFD = open(config_file.c_str(), O_RDONLY)) < 0) {
51 m_log.Emsg("Config", errno, "Unable to open configuration file", config_file.c_str());
52 return 1;
53 }
54 Config.Attach(cfgFD);
55 static const char *cvec[] = { "*** throttle (ofs) plugin config:", 0 };
56 Config.Capture(cvec);
57
58 char *var, *val;
59 int NoGo = 0;
60 while( (var = Config.GetMyFirstWord()) )
61 {
62 if (!strcmp("throttle.fslib", var)) {
63 val = Config.GetWord();
64 if (!val || !val[0]) {m_log.Emsg("Config", "fslib not specified."); continue;}
65 m_fslib = val;
66 }
67 TS_Xeq("throttle.max_open_files", xmaxopen);
68 TS_Xeq("throttle.max_active_connections", xmaxconn);
69 TS_Xeq("throttle.throttle", xthrottle);
70 TS_Xeq("throttle.loadshed", xloadshed);
71 TS_Xeq("throttle.max_wait_time", xmaxwait);
72 TS_Xeq("throttle.trace", xtrace);
73 TS_Xeq("throttle.userconfig", xuserconfig);
74 if (NoGo)
75 {
76 m_log.Emsg("Config", "Throttle configuration failed.");
77 return 1;
78 }
79 }
80 return 0;
81}
82
83/******************************************************************************/
84/* x m a x o p e n */
85/******************************************************************************/
86
87/* Function: xmaxopen
88
89 Purpose: Parse the directive: throttle.max_open_files <limit>
90
91 <limit> maximum number of open file handles for a unique entity.
92
93 Output: 0 upon success or !0 upon failure.
94*/
95int
96Configuration::xmaxopen(XrdOucStream &Config)
97{
98 auto val = Config.GetWord();
99 if (!val || val[0] == '\0')
100 {m_log.Emsg("Config", "Max open files not specified! Example usage: throttle.max_open_files 16000");}
101 long long max_open = -1;
102 if (XrdOuca2x::a2sz(m_log, "max open files value", val, &max_open, 1)) return 1;
103
104 m_max_open = max_open;
105 return 0;
106}
107
108
109/******************************************************************************/
110/* x m a x c o n n */
111/******************************************************************************/
112
113/* Function: xmaxconn
114
115 Purpose: Parse the directive: throttle.max_active_connections <limit>
116
117 <limit> maximum number of connections with at least one open file for a given entity
118
119 Output: 0 upon success or !0 upon failure.
120*/
121int
122Configuration::xmaxconn(XrdOucStream &Config)
123{
124 auto val = Config.GetWord();
125 if (!val || val[0] == '\0')
126 {m_log.Emsg("Config", "Max active connections not specified! Example usage: throttle.max_active_connections 4000");}
127 long long max_conn = -1;
128 if (XrdOuca2x::a2sz(m_log, "max active connections value", val, &max_conn, 1)) return 1;
129
130 m_max_conn = max_conn;
131 return 0;
132}
133
134/******************************************************************************/
135/* x m a x w a i t */
136/******************************************************************************/
137
138/* Function: xmaxwait
139
140 Purpose: Parse the directive: throttle.max_wait_time <limit>
141
142 <limit> maximum wait time, in seconds, before an operation should fail
143
144 If the directive is not provided, the default is 30 seconds.
145
146 Output: 0 upon success or !0 upon failure.
147*/
148int
149Configuration::xmaxwait(XrdOucStream &Config)
150{
151 auto val = Config.GetWord();
152 if (!val || val[0] == '\0')
153 {m_log.Emsg("Config", "Max waiting time not specified (must be in seconds)! Example usage: throttle.max_wait_time 20");}
154 long long max_wait = -1;
155 if (XrdOuca2x::a2sz(m_log, "max waiting time value", val, &max_wait, 1)) return 1;
156
157 m_max_wait = max_wait;
158
159 return 0;
160}
161
162/******************************************************************************/
163/* x t h r o t t l e */
164/******************************************************************************/
165
166/* Function: xthrottle
167
168 Purpose: To parse the directive: throttle [data <drate>] [iops <irate>] [concurrency <climit>] [interval <rint>]
169
170 <drate> maximum bytes per second through the server.
171 <irate> maximum IOPS per second through the server.
172 <climit> maximum number of concurrent IO connections.
173 <rint> minimum interval in milliseconds between throttle re-computing.
174
175 Output: 0 upon success or !0 upon failure.
176*/
177int
178Configuration::xthrottle(XrdOucStream &Config)
179{
180 long long drate = -1, irate = -1, rint = 1000, climit = -1;
181 char *val;
182
183 while ((val = Config.GetWord()))
184 {
185 if (strcmp("data", val) == 0)
186 {
187 if (!(val = Config.GetWord()))
188 {m_log.Emsg("Config", "data throttle limit not specified."); return 1;}
189 if (XrdOuca2x::a2sz(m_log,"data throttle value",val,&drate,1)) return 1;
190 }
191 else if (strcmp("iops", val) == 0)
192 {
193 if (!(val = Config.GetWord()))
194 {m_log.Emsg("Config", "IOPS throttle limit not specified."); return 1;}
195 if (XrdOuca2x::a2sz(m_log,"IOPS throttle value",val,&irate,1)) return 1;
196 }
197 else if (strcmp("rint", val) == 0)
198 {
199 if (!(val = Config.GetWord()))
200 {m_log.Emsg("Config", "recompute interval not specified (in ms)."); return 1;}
201 if (XrdOuca2x::a2sp(m_log,"recompute interval value (in ms)",val,&rint,10)) return 1;
202 }
203 else if (strcmp("concurrency", val) == 0)
204 {
205 if (!(val = Config.GetWord()))
206 {m_log.Emsg("Config", "Concurrency limit not specified."); return 1;}
207 if (XrdOuca2x::a2sz(m_log,"Concurrency limit value",val,&climit,1)) return 1;
208 }
209 else
210 {
211 m_log.Emsg("Config", "Warning - unknown throttle option specified", val, ".");
212 }
213 }
214
215 m_throttle_data_rate = drate;
216 m_throttle_iops_rate = irate;
217 m_throttle_concurrency_limit = climit;
218 m_throttle_recompute_interval_ms = rint;
219
220 return 0;
221}
222
223/******************************************************************************/
224/* x l o a d s h e d */
225/******************************************************************************/
226
227/* Function: xloadshed
228
229 Purpose: To parse the directive: loadshed host <hostname> [port <port>] [frequency <freq>]
230
231 <hostname> hostname of server to shed load to. Required
232 <port> port of server to shed load to. Defaults to 1094
233 <freq> A value from 1 to 100 specifying how often to shed load
234 (1 = 1% chance; 100 = 100% chance; defaults to 10).
235
236 Output: 0 upon success or !0 upon failure.
237*/
238int Configuration::xloadshed(XrdOucStream &Config)
239{
240 long long port = 0, freq = 0;
241 char *val;
242 std::string hostname;
243
244 while ((val = Config.GetWord()))
245 {
246 if (strcmp("host", val) == 0)
247 {
248 if (!(val = Config.GetWord()))
249 {m_log.Emsg("Config", "loadshed hostname not specified."); return 1;}
250 hostname = val;
251 }
252 else if (strcmp("port", val) == 0)
253 {
254 if (!(val = Config.GetWord()))
255 {m_log.Emsg("Config", "Port number not specified."); return 1;}
256 if (XrdOuca2x::a2sz(m_log,"Port number",val,&port,1, 65536)) return 1;
257 }
258 else if (strcmp("frequency", val) == 0)
259 {
260 if (!(val = Config.GetWord()))
261 {m_log.Emsg("Config", "Loadshed frequency not specified."); return 1;}
262 if (XrdOuca2x::a2sz(m_log,"Loadshed frequency",val,&freq,1,100)) return 1;
263 }
264 else
265 {
266 m_log.Emsg("Config", "Warning - unknown loadshed option specified", val, ".");
267 }
268 }
269
270 if (hostname.empty())
271 {
272 m_log.Emsg("Config", "must specify hostname for loadshed parameter.");
273 return 1;
274 }
275
276 m_loadshed_freq = freq;
277 m_loadshed_hostname = hostname;
278 m_loadshed_port = port;
279
280 return 0;
281}
282
283/******************************************************************************/
284/* x t r a c e */
285/******************************************************************************/
286
287/* Function: xtrace
288
289 Purpose: To parse the directive: trace <events>
290
291 <events> the blank separated list of events to trace. Trace
292 directives are cummalative.
293
294 Output: 0 upon success or 1 upon failure.
295*/
296
297int Configuration::xtrace(XrdOucStream &Config)
298{
299 char *val;
300 static const struct traceopts {const char *opname; int opval;} tropts[] =
301 {
302 {"all", TRACE_ALL},
303 {"off", TRACE_NONE},
304 {"none", TRACE_NONE},
305 {"debug", TRACE_DEBUG},
306 {"iops", TRACE_IOPS},
307 {"bandwidth", TRACE_BANDWIDTH},
308 {"ioload", TRACE_IOLOAD},
309 {"files", TRACE_FILES},
310 {"connections",TRACE_CONNS},
311 };
312 int i, neg, trval = 0, numopts = sizeof(tropts)/sizeof(struct traceopts);
313
314 if (!(val = Config.GetWord()))
315 {
316 m_log.Emsg("Config", "trace option not specified");
317 return 1;
318 }
319 while (val)
320 {
321 if (!strcmp(val, "off"))
322 {
323 trval = 0;
324 }
325 else
326 {
327 if ((neg = (val[0] == '-' && val[1])))
328 {
329 val++;
330 }
331 for (i = 0; i < numopts; i++)
332 {
333 if (!strcmp(val, tropts[i].opname))
334 {
335 if (neg)
336 {
337 if (tropts[i].opval) trval &= ~tropts[i].opval;
338 else trval = TRACE_ALL;
339 }
340 else if (tropts[i].opval) trval |= tropts[i].opval;
341 else trval = TRACE_NONE;
342 break;
343 }
344 }
345 if (i >= numopts)
346 {
347 m_log.Say("Config warning: ignoring invalid trace option '", val, "'.");
348 }
349 }
350 val = Config.GetWord();
351 }
352 m_trace_levels = trval;
353 return 0;
354}
355
356/******************************************************************************/
357/* x u s e r c o n f i g */
358/******************************************************************************/
359
360/* Function: xuserconfig
361
362 Purpose: Parse the directive: throttle.userconfig <filepath>
363
364 <filepath> path to the per-user configuration file in INI format
365
366 Output: 0 upon success or !0 upon failure.
367*/
368int Configuration::xuserconfig(XrdOucStream &Config)
369{
370 auto val = Config.GetWord();
371 if (!val || val[0] == '\0')
372 {
373 m_log.Emsg("Config", "User config file path not specified! Example usage: throttle.userconfig /etc/xrootd/throttle-users.conf"); return 1;
374 }
375
376 m_user_config_file = val;
377 m_log.Emsg("Config Info: using user config file at '", val, "'.");
378 return 0;
379}
#define TS_Xeq(x, m)
Definition XrdConfig.cc:160
#define open
Definition XrdPosix.hh:76
#define TRACE_IOLOAD
#define TRACE_BANDWIDTH
#define TRACE_FILES
#define TRACE_CONNS
#define TRACE_IOPS
#define TRACE_NONE
Definition XrdTrace.hh:34
#define TRACE_DEBUG
Definition XrdTrace.hh:36
#define TRACE_ALL
Definition XrdTrace.hh:35
static int a2sp(XrdSysError &, const char *emsg, const char *item, long long *val, long long minv=-1, long long maxv=-1)
Definition XrdOuca2x.cc:213
static int a2sz(XrdSysError &, const char *emsg, const char *item, long long *val, long long minv=-1, long long maxv=-1)
Definition XrdOuca2x.cc:257
int Emsg(const char *esfx, int ecode, const char *text1, const char *text2=0)
int Configure(const std::string &config_file)
XrdCmsConfig Config