XRootD
XrdThrottleConfig.cc
Go to the documentation of this file.
1 
2 #include "XrdOuc/XrdOuca2x.hh"
3 #include "XrdOuc/XrdOucEnv.hh"
4 #include "XrdOuc/XrdOucStream.hh"
5 #include "XrdSys/XrdSysError.hh"
8 
9 #include <cstring>
10 #include <string>
11 #include <fcntl.h>
12 
13 using namespace XrdThrottle;
14 
15 #define TS_Xeq(key, func) NoGo = (strcmp(key, var) == 0) ? func(Config) : 0
16 int
17 Configuration::Configure(const std::string &config_file)
18 {
19  XrdOucEnv myEnv;
20  XrdOucStream Config(&m_log, getenv("XRDINSTANCE"), &myEnv, "(Throttle Config)> ");
21  int cfgFD;
22  if (config_file.empty()) {
23  m_log.Say("No filename specified.");
24  return 1;
25  }
26  if ((cfgFD = open(config_file.c_str(), O_RDONLY)) < 0) {
27  m_log.Emsg("Config", errno, "Unable to open configuration file", config_file.c_str());
28  return 1;
29  }
30  Config.Attach(cfgFD);
31  static const char *cvec[] = { "*** throttle (ofs) plugin config:", 0 };
32  Config.Capture(cvec);
33 
34  char *var, *val;
35  int NoGo = 0;
36  while( (var = Config.GetMyFirstWord()) )
37  {
38  if (!strcmp("throttle.fslib", var)) {
39  val = Config.GetWord();
40  if (!val || !val[0]) {m_log.Emsg("Config", "fslib not specified."); continue;}
41  m_fslib = val;
42  }
43  TS_Xeq("throttle.max_open_files", xmaxopen);
44  TS_Xeq("throttle.max_active_connections", xmaxconn);
45  TS_Xeq("throttle.throttle", xthrottle);
46  TS_Xeq("throttle.loadshed", xloadshed);
47  TS_Xeq("throttle.max_wait_time", xmaxwait);
48  TS_Xeq("throttle.trace", xtrace);
49  if (NoGo)
50  {
51  m_log.Emsg("Config", "Throttle configuration failed.");
52  return 1;
53  }
54  }
55  return 0;
56 }
57 
58 /******************************************************************************/
59 /* x m a x o p e n */
60 /******************************************************************************/
61 
62 /* Function: xmaxopen
63 
64  Purpose: Parse the directive: throttle.max_open_files <limit>
65 
66  <limit> maximum number of open file handles for a unique entity.
67 
68  Output: 0 upon success or !0 upon failure.
69 */
70 int
71 Configuration::xmaxopen(XrdOucStream &Config)
72 {
73  auto val = Config.GetWord();
74  if (!val || val[0] == '\0')
75  {m_log.Emsg("Config", "Max open files not specified! Example usage: throttle.max_open_files 16000");}
76  long long max_open = -1;
77  if (XrdOuca2x::a2sz(m_log, "max open files value", val, &max_open, 1)) return 1;
78 
79  m_max_open = max_open;
80  return 0;
81 }
82 
83 
84 /******************************************************************************/
85 /* x m a x c o n n */
86 /******************************************************************************/
87 
88 /* Function: xmaxconn
89 
90  Purpose: Parse the directive: throttle.max_active_connections <limit>
91 
92  <limit> maximum number of connections with at least one open file for a given entity
93 
94  Output: 0 upon success or !0 upon failure.
95 */
96 int
97 Configuration::xmaxconn(XrdOucStream &Config)
98 {
99  auto val = Config.GetWord();
100  if (!val || val[0] == '\0')
101  {m_log.Emsg("Config", "Max active connections not specified! Example usage: throttle.max_active_connections 4000");}
102  long long max_conn = -1;
103  if (XrdOuca2x::a2sz(m_log, "max active connections value", val, &max_conn, 1)) return 1;
104 
105  m_max_conn = max_conn;
106  return 0;
107 }
108 
109 /******************************************************************************/
110 /* x m a x w a i t */
111 /******************************************************************************/
112 
113 /* Function: xmaxwait
114 
115  Purpose: Parse the directive: throttle.max_wait_time <limit>
116 
117  <limit> maximum wait time, in seconds, before an operation should fail
118 
119  If the directive is not provided, the default is 30 seconds.
120 
121  Output: 0 upon success or !0 upon failure.
122 */
123 int
124 Configuration::xmaxwait(XrdOucStream &Config)
125 {
126  auto val = Config.GetWord();
127  if (!val || val[0] == '\0')
128  {m_log.Emsg("Config", "Max waiting time not specified (must be in seconds)! Example usage: throttle.max_wait_time 20");}
129  long long max_wait = -1;
130  if (XrdOuca2x::a2sz(m_log, "max waiting time value", val, &max_wait, 1)) return 1;
131 
132  return 0;
133 }
134 
135 /******************************************************************************/
136 /* x t h r o t t l e */
137 /******************************************************************************/
138 
139 /* Function: xthrottle
140 
141  Purpose: To parse the directive: throttle [data <drate>] [iops <irate>] [concurrency <climit>] [interval <rint>]
142 
143  <drate> maximum bytes per second through the server.
144  <irate> maximum IOPS per second through the server.
145  <climit> maximum number of concurrent IO connections.
146  <rint> minimum interval in milliseconds between throttle re-computing.
147 
148  Output: 0 upon success or !0 upon failure.
149 */
150 int
151 Configuration::xthrottle(XrdOucStream &Config)
152 {
153  long long drate = -1, irate = -1, rint = 1000, climit = -1;
154  char *val;
155 
156  while ((val = Config.GetWord()))
157  {
158  if (strcmp("data", val) == 0)
159  {
160  if (!(val = Config.GetWord()))
161  {m_log.Emsg("Config", "data throttle limit not specified."); return 1;}
162  if (XrdOuca2x::a2sz(m_log,"data throttle value",val,&drate,1)) return 1;
163  }
164  else if (strcmp("iops", val) == 0)
165  {
166  if (!(val = Config.GetWord()))
167  {m_log.Emsg("Config", "IOPS throttle limit not specified."); return 1;}
168  if (XrdOuca2x::a2sz(m_log,"IOPS throttle value",val,&irate,1)) return 1;
169  }
170  else if (strcmp("rint", val) == 0)
171  {
172  if (!(val = Config.GetWord()))
173  {m_log.Emsg("Config", "recompute interval not specified (in ms)."); return 1;}
174  if (XrdOuca2x::a2sp(m_log,"recompute interval value (in ms)",val,&rint,10)) return 1;
175  }
176  else if (strcmp("concurrency", val) == 0)
177  {
178  if (!(val = Config.GetWord()))
179  {m_log.Emsg("Config", "Concurrency limit not specified."); return 1;}
180  if (XrdOuca2x::a2sz(m_log,"Concurrency limit value",val,&climit,1)) return 1;
181  }
182  else
183  {
184  m_log.Emsg("Config", "Warning - unknown throttle option specified", val, ".");
185  }
186  }
187 
188  m_throttle_data_rate = drate;
189  m_throttle_iops_rate = irate;
190  m_throttle_concurrency_limit = climit;
191  m_throttle_recompute_interval_ms = rint;
192 
193  return 0;
194 }
195 
196 /******************************************************************************/
197 /* x l o a d s h e d */
198 /******************************************************************************/
199 
200 /* Function: xloadshed
201 
202  Purpose: To parse the directive: loadshed host <hostname> [port <port>] [frequency <freq>]
203 
204  <hostname> hostname of server to shed load to. Required
205  <port> port of server to shed load to. Defaults to 1094
206  <freq> A value from 1 to 100 specifying how often to shed load
207  (1 = 1% chance; 100 = 100% chance; defaults to 10).
208 
209  Output: 0 upon success or !0 upon failure.
210 */
211 int Configuration::xloadshed(XrdOucStream &Config)
212 {
213  long long port = 0, freq = 0;
214  char *val;
215  std::string hostname;
216 
217  while ((val = Config.GetWord()))
218  {
219  if (strcmp("host", val) == 0)
220  {
221  if (!(val = Config.GetWord()))
222  {m_log.Emsg("Config", "loadshed hostname not specified."); return 1;}
223  hostname = val;
224  }
225  else if (strcmp("port", val) == 0)
226  {
227  if (!(val = Config.GetWord()))
228  {m_log.Emsg("Config", "Port number not specified."); return 1;}
229  if (XrdOuca2x::a2sz(m_log,"Port number",val,&port,1, 65536)) return 1;
230  }
231  else if (strcmp("frequency", val) == 0)
232  {
233  if (!(val = Config.GetWord()))
234  {m_log.Emsg("Config", "Loadshed frequency not specified."); return 1;}
235  if (XrdOuca2x::a2sz(m_log,"Loadshed frequency",val,&freq,1,100)) return 1;
236  }
237  else
238  {
239  m_log.Emsg("Config", "Warning - unknown loadshed option specified", val, ".");
240  }
241  }
242 
243  if (hostname.empty())
244  {
245  m_log.Emsg("Config", "must specify hostname for loadshed parameter.");
246  return 1;
247  }
248 
249  m_loadshed_freq = freq;
250  m_loadshed_hostname = hostname;
251  m_loadshed_port = port;
252 
253  return 0;
254 }
255 
256 /******************************************************************************/
257 /* x t r a c e */
258 /******************************************************************************/
259 
260 /* Function: xtrace
261 
262  Purpose: To parse the directive: trace <events>
263 
264  <events> the blank separated list of events to trace. Trace
265  directives are cummalative.
266 
267  Output: 0 upon success or 1 upon failure.
268 */
269 
270 int Configuration::xtrace(XrdOucStream &Config)
271 {
272  char *val;
273  static const struct traceopts {const char *opname; int opval;} tropts[] =
274  {
275  {"all", TRACE_ALL},
276  {"off", TRACE_NONE},
277  {"none", TRACE_NONE},
278  {"debug", TRACE_DEBUG},
279  {"iops", TRACE_IOPS},
280  {"bandwidth", TRACE_BANDWIDTH},
281  {"ioload", TRACE_IOLOAD},
282  {"files", TRACE_FILES},
283  {"connections",TRACE_CONNS},
284  };
285  int i, neg, trval = 0, numopts = sizeof(tropts)/sizeof(struct traceopts);
286 
287  if (!(val = Config.GetWord()))
288  {
289  m_log.Emsg("Config", "trace option not specified");
290  return 1;
291  }
292  while (val)
293  {
294  if (!strcmp(val, "off"))
295  {
296  trval = 0;
297  }
298  else
299  {
300  if ((neg = (val[0] == '-' && val[1])))
301  {
302  val++;
303  }
304  for (i = 0; i < numopts; i++)
305  {
306  if (!strcmp(val, tropts[i].opname))
307  {
308  if (neg)
309  {
310  if (tropts[i].opval) trval &= ~tropts[i].opval;
311  else trval = TRACE_ALL;
312  }
313  else if (tropts[i].opval) trval |= tropts[i].opval;
314  else trval = TRACE_NONE;
315  break;
316  }
317  }
318  if (i >= numopts)
319  {
320  m_log.Say("Config warning: ignoring invalid trace option '", val, "'.");
321  }
322  }
323  val = Config.GetWord();
324  }
325  m_trace_levels = trval;
326  return 0;
327 }
int open(const char *path, int oflag,...)
#define TS_Xeq(key, func)
#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)
Definition: XrdSysError.cc:95
void Say(const char *text1, const char *text2=0, const char *txt3=0, const char *text4=0, const char *text5=0, const char *txt6=0)
Definition: XrdSysError.cc:141
int Configure(const std::string &config_file)
XrdCmsConfig Config