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