bes  Updated for version 3.20.8
DebugFunctions.cc
1 // UgridFunctions.cc
2 
3 // This file is part of bes, A C++ back-end server implementation framework
4 // for the OPeNDAP Data Access Protocol.
5 
6 // Copyright (c) 2013 OPeNDAP, Inc.
7 // Author: James Gallagher <jgallagher@opendap.org>
8 //
9 // This library is free software; you can redistribute it and/or
10 // modify it under the terms of the GNU Lesser General Public
11 // License as published by the Free Software Foundation; either
12 // version 2.1 of the License, or (at your option) any later version.
13 //
14 // This library is distributed in the hope that it will be useful,
15 // but WITHOUT ANY WARRANTY; without even the implied warranty of
16 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 // Lesser General Public License for more details.
18 //
19 // You should have received a copy of the GNU Lesser General Public
20 // License along with this library; if not, write to the Free Software
21 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22 //
23 // You can contact OPeNDAP, Inc. at PO Box 112, Saunderstown, RI. 02874-0112.
24 
25 #include "config.h"
26 
27 #include <sstream> // std::stringstream
28 #include <stdlib.h> /* abort, NULL */
29 #include <iostream>
30 #include <signal.h>
31 
32 #include <sys/time.h>
33 #include <unistd.h>
34 
35 #include "DebugFunctions.h"
36 
37 #include "ServerFunctionsList.h"
38 #include "BESDebug.h"
39 #include <Int32.h>
40 #include <Structure.h>
41 #include <Str.h>
42 #include <BESError.h>
43 #include <BESInternalError.h>
44 #include <BESInternalFatalError.h>
45 #include <BESSyntaxUserError.h>
46 #include <BESForbiddenError.h>
47 #include <BESNotFoundError.h>
48 #include <BESTimeoutError.h>
49 
50 namespace debug_function {
51 
52 static string getFunctionNames()
53 {
54  vector<string> names;
55  libdap::ServerFunctionsList::TheList()->getFunctionNames(&names);
56 
57  string msg;
58  for (std::vector<string>::iterator it = names.begin(); it != names.end(); ++it) {
59  if (!msg.empty()) msg += ", ";
60 
61  msg += *it;
62  }
63 
64  return msg;
65 }
66 
67 void DebugFunctions::initialize(const string &/*modname*/)
68 {
69  BESDEBUG("DebugFunctions", "initialize() - BEGIN" << std::endl);
70  BESDEBUG("DebugFunctions", "initialize() - function names: " << getFunctionNames() << std::endl);
71 
73  libdap::ServerFunctionsList::TheList()->add_function(abortFunc);
74 
76  libdap::ServerFunctionsList::TheList()->add_function(sleepFunc);
77 
79  libdap::ServerFunctionsList::TheList()->add_function(sumUntilFunc);
80 
82  libdap::ServerFunctionsList::TheList()->add_function(errorFunc);
83 
84  BESDEBUG("DebugFunctions", "initialize() - function names: " << getFunctionNames() << std::endl);
85 
86  BESDEBUG("DebugFunctions", "initialize() - END" << std::endl);
87 }
88 
89 void DebugFunctions::terminate(const string &/*modname*/)
90 {
91  BESDEBUG("DebugFunctions", "Removing DebugFunctions Modules (this does nothing)." << std::endl);
92 }
93 
100 void DebugFunctions::dump(ostream &strm) const
101 {
102  strm << BESIndent::LMarg << "DebugFunctions::dump - (" << (void *) this << ")" << std::endl;
103 }
104 
105 /*****************************************************************************************
106  *
107  * Abort Function (Debug Functions)
108  *
109  * This server side function calls abort(). (boom)
110  *
111  */
112 string abort_usage = "abort(##) Where ## is the number of milliseconds to sleep before calling abort.";
113 AbortFunc::AbortFunc()
114 {
115  setName("abort");
116  setDescriptionString((string) "This function calls abort() killing the beslistner process.");
117  setUsageString(abort_usage);
118  setRole("http://services.opendap.org/dap4/server-side-function/debug/abort"); // 11/18/20 SBL - https not supported
119  setDocUrl("https://docs.opendap.org/index.php/Debug_Functions");
120  setFunction(debug_function::abort_ssf);
121  setVersion("1.0");
122 }
123 
124 void abort_ssf(int argc, libdap::BaseType * argv[], libdap::DDS &, libdap::BaseType **btpp)
125 {
126 
127  std::stringstream msg;
128  libdap::Str *response = new libdap::Str("info");
129  *btpp = response;
130 
131  if (argc != 1) {
132  msg << "Missing time parameter! USAGE: " << abort_usage;
133  }
134  else {
135  libdap::Int32 *param1 = dynamic_cast<libdap::Int32*>(argv[0]);
136  if (param1) {
137  libdap::dods_int32 milliseconds = param1->value();
138 
139  msg << "abort in " << milliseconds << "ms" << endl;
140  response->set_value(msg.str());
141 
142  usleep(milliseconds * 1000);
143  msg << "abort now. " << endl;
144  abort();
145  return;
146  }
147  else {
148  msg << "This function only accepts integer values " << "for the time (in milliseconds) parameter. USAGE: "
149  << abort_usage;
150  }
151 
152  }
153 
154  response->set_value(msg.str());
155  return;
156 }
157 
158 /*****************************************************************************************
159  *
160  * Sleep Function (Debug Functions)
161  *
162  * This server side function calls sleep() for the number
163  * of millisecs passed in at argv[0]. (Zzzzzzzzzzzzzzz)
164  *
165  */
166 
167 string sleep_usage = "sleep(##) where ## is the number of milliseconds to sleep.";
168 SleepFunc::SleepFunc()
169 {
170  setName("sleep");
171  setDescriptionString((string) "This function calls sleep() for the specified number of millisecs.");
172  setUsageString(sleep_usage);
173  setRole("http://services.opendap.org/dap4/server-side-function/debug/sleep"); // 11/18/20 SBL - https not supported
174  setDocUrl("https://docs.opendap.org/index.php/Debug_Functions");
175  setFunction(debug_function::sleep_ssf);
176  setVersion("1.0");
177 }
178 
179 void sleep_ssf(int argc, libdap::BaseType * argv[], libdap::DDS &, libdap::BaseType **btpp)
180 {
181 
182  std::stringstream msg;
183  libdap::Str *sleep_info = new libdap::Str("info");
184 
185  //libdap::Structure *sleepResult = new libdap::Structure("sleep_result_unwrap");
186  //sleepResult->add_var_nocopy(sleep_info);
187  //*btpp = sleepResult;
188 
189  *btpp = sleep_info;
190 
191  if (argc != 1) {
192  msg << "Missing time parameter! USAGE: " << sleep_usage;
193  }
194  else {
195  libdap::Int32 *param1 = dynamic_cast<libdap::Int32*>(argv[0]);
196  if (param1) {
197  libdap::dods_int32 milliseconds = param1->value();
198  usleep(milliseconds * 1000);
199  msg << "Slept for " << milliseconds << " ms.";
200  }
201  else {
202  msg << "This function only accepts integer values " << "for the time (in milliseconds) parameter. USAGE: "
203  << sleep_usage;
204  }
205 
206  }
207 
208  sleep_info->set_value(msg.str());
209 
210  /*
211  for (libdap::DDS::Vars_iter it = dds.var_begin(); it != dds.var_end(); ++it) {
212  libdap::BaseType *pBT = *it;
213  sleepResult->add_var(pBT);
214  }
215  */
216 
217  return;
218 }
219 
220 /*****************************************************************************************
221  *
222  * SumUntil (Debug Functions)
223  *
224  * This server side function computes a sum until the number of
225  * millisecs (passed in at argv[0]) has transpired. (+,+...+).
226  *
227  * @note Modified so that the actual sum value can be printed or not.
228  * When this is used in tests, the value reached can vary, so to make
229  * checking for success/failure, the value can be omitted.
230  *
231  */
232 
233 string sum_until_usage = "sum_until(<val> [,0|<true>]) Compute a sum until <val> of milliseconds has elapsed; 0|<true> print the sum value.";
234 SumUntilFunc::SumUntilFunc()
235 {
236  setName("sum_until");
237  setDescriptionString((string) "This function calls sleep() for the specified number of millisecs.");
238  setUsageString(sum_until_usage);
239  setRole("http://services.opendap.org/dap4/server-side-function/debug/sum_until"); // 11/18/20 SBL - https not supported
240  setDocUrl("https://docs.opendap.org/index.php/Debug_Functions");
241  setFunction(debug_function::sum_until_ssf);
242  setVersion("1.0");
243 }
244 
245 void sum_until_ssf(int argc, libdap::BaseType * argv[], libdap::DDS &, libdap::BaseType **btpp)
246 {
247 
248  std::stringstream msg;
249  libdap::Str *response = new libdap::Str("info");
250  *btpp = response;
251 
252  if (!(argc == 1 || argc == 2)) {
253  msg << "Missing time parameter! USAGE: " << sum_until_usage;
254 
255  response->set_value(msg.str());
256  return;
257  }
258 
259  libdap::Int32 *param1 = dynamic_cast<libdap::Int32*>(argv[0]);
260  // param1 is required
261  if (!param1) {
262  msg << "This function only accepts integer values " << "for the time (in milliseconds) parameter. USAGE: "
263  << sum_until_usage;
264 
265  response->set_value(msg.str());
266  return;
267  }
268 
269  bool print_sum_value = true;
270  // argument #2 is optional
271  if (argc == 2) {
272  libdap::Int32 *temp = dynamic_cast<libdap::Int32*>(argv[1]);
273  if (temp && temp->value() == 0)
274  print_sum_value = false;
275  }
276 
277  libdap::dods_int32 milliseconds = param1->value();
278 
279  struct timeval tv;
280  gettimeofday(&tv, NULL);
281  double start_time = (tv.tv_sec) * 1000 + (tv.tv_usec) / 1000; // convert tv_sec & tv_usec to millisecond
282  double end_time = start_time;
283 
284  long fib;
285  long one_past = 1;
286  long two_past = 0;
287  long n = 1;
288 
289  bool done = false;
290  while (!done) {
291  n++;
292  fib = one_past + two_past;
293  two_past = one_past;
294  one_past = fib;
295  gettimeofday(&tv, NULL);
296  end_time = (tv.tv_sec) * 1000 + (tv.tv_usec) / 1000; // convert tv_sec & tv_usec to millisecond
297  if (end_time - start_time >= milliseconds) {
298  done = true;
299  }
300  }
301 
302  if (!print_sum_value)
303  msg << "Summed for " << end_time - start_time << " ms.";
304  else
305  msg << "Summed for " << end_time - start_time << " ms. n: " << n;
306 
307  response->set_value(msg.str());
308  return;
309 }
310 
311 /*****************************************************************************************
312  *
313  * Error Function (Debug Functions)
314  *
315  * This server side function calls calls sleep() for the number
316  * of ms passed in at argv[0]. (Zzzzzzzzzzzzzzz)
317  *
318  */
319 string error_usage = "error(##) where ## is the BESError type to generate.";
320 ErrorFunc::ErrorFunc()
321 {
322  setName("error");
323  setDescriptionString((string) "This function triggers a BES Error of the type specified");
324  setUsageString(error_usage);
325  setRole("http://services.opendap.org/dap4/server-side-function/debug/error"); // 11/18/20 SBL - https not supported
326  setDocUrl("https://docs.opendap.org/index.php/Debug_Functions");
327  setFunction(debug_function::error_ssf);
328  setVersion("1.0");
329 }
330 
331 void error_ssf(int argc, libdap::BaseType * argv[], libdap::DDS &, libdap::BaseType **btpp)
332 {
333 
334  std::stringstream msg;
335  libdap::Str *response = new libdap::Str("info");
336  *btpp = response;
337 
338  string location = "error_ssf";
339 
340  if (argc != 1) {
341  msg << "Missing error type parameter! USAGE: " << error_usage;
342  }
343  else {
344  libdap::Int32 *param1 = dynamic_cast<libdap::Int32*>(argv[0]);
345  if (param1) {
346  libdap::dods_int32 error_type = param1->value();
347 
348  switch (error_type) {
349 
350  case BES_INTERNAL_ERROR: {
351  msg << "A BESInternalError was requested.";
352  BESInternalError error(msg.str(), location, 0);
353  throw error;
354  }
355  break;
356 
357  case BES_INTERNAL_FATAL_ERROR: {
358  msg << "A BESInternalFatalError was requested.";
359  BESInternalFatalError error(msg.str(), location, 0);
360  throw error;
361  }
362  break;
363 
364  case BES_SYNTAX_USER_ERROR: {
365  msg << "A BESSyntaxUserError was requested.";
366  BESSyntaxUserError error(msg.str(), location, 0);
367  throw error;
368  }
369  break;
370 
371  case BES_FORBIDDEN_ERROR: {
372  msg << "A BESForbiddenError was requested.";
373  BESForbiddenError error(msg.str(), location, 0);
374  throw error;
375  }
376  break;
377 
378  case BES_NOT_FOUND_ERROR: {
379  msg << "A BESNotFoundError was requested.";
380  BESNotFoundError error(msg.str(), location, 0);
381  throw error;
382  }
383  break;
384 
385  case BES_TIMEOUT_ERROR: {
386  msg << "A BESTimeOutError was requested.";
387  BESTimeoutError error(msg.str(), location, 0);
388  throw error;
389  }
390  break;
391 
392  case 666: {
393  msg << "A Segmentation Fault has been requested.";
394  cerr << msg.str() << endl;
395  raise(SIGSEGV);
396  }
397  break;
398 
399  default:
400  msg << "An unrecognized error_type parameter was received. Requested error_type: " << error_type;
401  break;
402  }
403 
404  }
405  else {
406  msg << "This function only accepts integer values " << "for the error type parameter. USAGE: "
407  << error_usage;
408  }
409 
410  }
411 
412  response->set_value(msg.str());
413  return;
414 
415 }
416 
417 } // namespace debug_function
418 
419 extern "C" {
420 BESAbstractModule *maker()
421 {
423 }
424 }
error thrown if the BES is not allowed to access the resource requested
exception thrown if internal error encountered
exception thrown if an internal error is found and is fatal to the BES
error thrown if the resource requested cannot be found
error thrown if there is a user syntax error in the request or any other user error
error thrown if there is a user syntax error in the request or any other user error
virtual void dump(ostream &strm) const
dumps information about this object