2.12.2021, 9:00 - 11:00: Due to updates GitLab may be unavailable for some minutes between 09:00 and 11:00.

sensoraction.cpp 24.5 KB
Newer Older
Axel Auweter's avatar
Axel Auweter committed
1
2
//================================================================================
// Name        : sensoraction.cpp
3
// Author      : Axel Auweter, Daniele Tafani
Micha Müller's avatar
Micha Müller committed
4
// Contact     : info@dcdb.it
Axel Auweter's avatar
Axel Auweter committed
5
6
7
8
9
10
// Copyright   : Leibniz Supercomputing Centre
// Description : Implementation of actions on the DCDB sensor configuration
//================================================================================

//================================================================================
// This file is part of DCDB (DataCenter DataBase)
11
// Copyright (C) 2011-2019 Leibniz Supercomputing Centre
Axel Auweter's avatar
Axel Auweter committed
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
//================================================================================
27
28

#include <iostream>
29
#include <string>
30
31
32

#include <cstdlib>
#include <cstring>
33
#include <cinttypes>
34

Axel Auweter's avatar
Axel Auweter committed
35
#include <dcdb/sensorconfig.h>
36
#include <dcdb/unitconv.h>
37
#include "cassandra.h"
38
#include "metadatastore.h"
39
40
41

#include "sensoraction.h"

42
43
44
/*
 * Print the help for the SENSOR command
 */
45
46
void SensorAction::printHelp(int argc, char* argv[])
{
47
  /*            01234567890123456789012345678901234567890123456789012345678901234567890123456789 */
48
  std::cout << "SENSOR command help" << std::endl << std::endl;
49
  std::cout << "The SENSOR command has the following options:" << std::endl;
50
51
52
  std::cout << "   PUBLISH <public name> <pattern>          - Make a sensor publicly available under" << std::endl;
  std::cout << "                                              <public name> comprising of all internal" << std::endl;
  std::cout << "                                              sensors matching the given <pattern>." << std::endl;
53
  std::cout << "   VCREATE <public name> <expr> <vsensorid> <t0> <freq>" << std::endl;
54
55
56
57
58
59
60
61
62
63
  std::cout << "                                            - Create a virtual public sensor that is" << std::endl;
  std::cout << "                                              visible as <public name> and evaluates" << std::endl;
  std::cout << "                                              <expr> starting at time t0 every <freq>" << std::endl;
  std::cout << "                                              nanoseconds. Cached values are stored" << std::endl;
  std::cout << "                                              under the unique <vsensorid>." << std::endl;
  std::cout << "   LIST                                     - List all public sensors." << std::endl;
  std::cout << "   LISTPUBLIC                               - Same as LIST, includes patterns." << std::endl;
  std::cout << "   SHOW <public name>                       - Show details for a given sensor." << std::endl;
  std::cout << "   SCALINGFACTOR <public name> <fac>        - Set scaling factor to <fac>." << std::endl;
  std::cout << "   UNIT <public name> <unit>                - Set unit to <unit>." << std::endl;
64
65
66
  std::cout << "   SENSORPROPERTY <public name> [<sensor property>,<sensor property>,...]" << std::endl;
  std::cout << "                                            - Get/Set sensor properties. Valid properties: " << std::endl;
  std::cout << "                                              integrable, monotonic, delta" << std::endl;
67
68
  std::cout << "   EXPRESSION <public name> <expr>          - Change expression of virt sensor." << std::endl;
  std::cout << "   TZERO <public name> <t0>                 - Change t0 of virt sensor." << std::endl;
69
70
  std::cout << "   INTERVAL <public name> <inter>           - Change interval of a sensor." << std::endl;
  std::cout << "   TTL <public name> <ttl>                  - Change time to live of a sensor." << std::endl;
71
72
  std::cout << "   OPERATIONS <public name> <operation>,<operation>,..." << std::endl;
  std::cout << "                                            - Set operations for the sensor (e.g., avg, stddev,...)." << std::endl;
73
  std::cout << "   CLEAROPERATIONS <public name>            - Remove all existing operations for the sensor." << std::endl;
74
  std::cout << "   CLEAROPERATIONSW <wildcard>              - Remove operations from sensors using a wildcard." << std::endl;
75
  std::cout << "   UNPUBLISH <public name>                  - Unpublish a sensor." << std::endl;
76
  std::cout << "   UNPUBLISHW <wildcard>                    - Unpublish sensors using a wildcard." << std::endl;
77
78
}

79
80
81
/*
 * Execute any of the SENSOR commands
 */
82
83
84
int SensorAction::executeCommand(int argc, char* argv[], int argvidx, const char* hostname)
{
  /* Independent from the command, we need to connect to the server */
85
  connection = new DCDB::Connection();
Axel Auweter's avatar
Axel Auweter committed
86
87
  connection->setHostname(hostname);
  if (!connection->connect()) {
88
      std::cerr << "Cannot connect to Cassandra database." << std::endl;
Axel Auweter's avatar
Axel Auweter committed
89
      return EXIT_FAILURE;
90
91
92
93
94
95
96
97
98
99
  }

  /* Check what we need to do (argv[argvidx] contains "SENSOR") */
  argvidx++;
  if (argvidx >= argc) {
      std::cout << "The SENSOR command needs at least one parameter." << std::endl;
      std::cout << "Run with 'HELP SENSOR' to see the list of possible SENSOR commands." << std::endl;
      goto executeCommandError;
  }

100
101
  if (strcasecmp(argv[argvidx], "PUBLISH") == 0) {
      /* PUBLISH needs two more parameters */
102
      if (argvidx+2 >= argc) {
103
          std::cout << "PUBLISH needs two more parameters!" << std::endl;
104
105
          goto executeCommandError;
      }
Axel Auweter's avatar
Axel Auweter committed
106
      doPublishSensor(argv[argvidx+1], argv[argvidx+2]);
107
  }
108
109
  else if (strcasecmp(argv[argvidx], "VCREATE") == 0) {
      /* VCREATE needs four more parameters */
110
111
      if (argvidx+5 >= argc) {
          std::cout << "VCREATE needs five more parameters!" << std::endl;
112
113
          goto executeCommandError;
      }
114
      doVCreateSensor(argv[argvidx+1], argv[argvidx+2], argv[argvidx+3], argv[argvidx+4], argv[argvidx+5]);
115
  }
116
117
118
  else if (strcasecmp(argv[argvidx], "LIST") == 0) {
      doList();
  }
119
  else if (strcasecmp(argv[argvidx], "LISTPUBLIC") == 0) {
Axel Auweter's avatar
Axel Auweter committed
120
      doListPublicSensors();
121
  }
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
  else if (strcasecmp(argv[argvidx], "SHOW") == 0) {
      if (argvidx+1 >= argc) {
          std::cout << "SHOW needs a sensor name as parameter!" << std::endl;
          goto executeCommandError;
      }
      doShow(argv[argvidx+1]);
  }
  else if (strcasecmp(argv[argvidx], "SCALINGFACTOR") == 0) {
      /* SCALINGFACTOR needs two more parameters */
      if (argvidx+2 >= argc) {
          std::cout << "SCALINGFACTOR needs two more parameters!" << std::endl;
          goto executeCommandError;
      }
      doScalingfactor(argv[argvidx+1], argv[argvidx+2]);
  }
  else if (strcasecmp(argv[argvidx], "UNIT") == 0) {
      /* UNIT needs two more parameters */
      if (argvidx+2 >= argc) {
          std::cout << "UNIT needs two more parameters!" << std::endl;
          goto executeCommandError;
      }
      doUnit(argv[argvidx+1], argv[argvidx+2]);
  }
145
  else if (strcasecmp(argv[argvidx], "SENSORPROPERTY") == 0) {
146
147
148
      /* SENSORPROPERTY needs at least one parameter */
      if (argvidx+1 >= argc) {
          std::cout << "SENSORPROPERTY needs at least one more parameter!" << std::endl;
149
150
          goto executeCommandError;
      }
151
152
153
154
155
156
      char* cmd = nullptr;
      if (argvidx+2 >= argc) {
	  cmd = argv[argvidx+2];
      }

      doSensorProperty(argv[argvidx+1], cmd);
157
  }
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
  else if (strcasecmp(argv[argvidx], "EXPRESSION") == 0) {
      /* EXPRESSION needs two more parameters */
      if (argvidx+2 >= argc) {
          std::cout << "EXPRESSION needs two more parameters!" << std::endl;
          goto executeCommandError;
      }
      doExpression(argv[argvidx+1], argv[argvidx+2]);
  }
  else if (strcasecmp(argv[argvidx], "TZERO") == 0) {
      /* TZERO needs two more parameters */
      if (argvidx+2 >= argc) {
          std::cout << "TZERO needs two more parameters!" << std::endl;
          goto executeCommandError;
      }
      doTZero(argv[argvidx+1], argv[argvidx+2]);
  }
174
175
  else if (strcasecmp(argv[argvidx], "INTERVAL") == 0) {
      /* INTERVAL needs two more parameters */
176
      if (argvidx+2 >= argc) {
177
          std::cout << "INTERVAL needs two more parameters!" << std::endl;
178
179
          goto executeCommandError;
      }
180
181
182
183
184
185
186
187
188
      doInterval(argv[argvidx+1], argv[argvidx+2]);
  }
  else if (strcasecmp(argv[argvidx], "TTL") == 0) {
      /* TTL needs two more parameters */
      if (argvidx+2 >= argc) {
          std::cout << "TTL needs two more parameters!" << std::endl;
          goto executeCommandError;
      }
      doTTL(argv[argvidx+1], argv[argvidx+2]);
189
  }
190
191
192
193
194
195
196
197
  else if (strcasecmp(argv[argvidx], "OPERATIONS") == 0) {
      /* OPERATIONS needs two more parameters */
      if (argvidx+2 >= argc) {
          std::cout << "OPERATIONS needs two more parameters!" << std::endl;
          goto executeCommandError;
      }
      doOperations(argv[argvidx+1], argv[argvidx+2]);
  }
198
199
200
201
202
203
204
205
  else if (strcasecmp(argv[argvidx], "CLEAROPERATIONS") == 0) {
      /* CLEAROPERATIONS needs one more parameter */
      if (argvidx+1 >= argc) {
          std::cout << "CLEAROPERATIONS needs one more parameter!" << std::endl;
          goto executeCommandError;
      }
      doClearOperations(argv[argvidx+1]);
  }
206
207
208
209
210
211
212
213
  else if (strcasecmp(argv[argvidx], "CLEAROPERATIONSW") == 0) {
      /* CLEAROPERATIONSW needs one more parameter */
      if (argvidx+1 >= argc) {
          std::cout << "CLEAROPERATIONSW needs one more parameter!" << std::endl;
          goto executeCommandError;
      }
      doClearOperationsByWildcard(argv[argvidx+1]);
  }
214
215
  else if (strcasecmp(argv[argvidx], "UNPUBLISH") == 0) {
      /* UNPUBLISH needs one more parameter */
216
      if (argvidx + 1 >= argc) {
217
218
219
          std::cout << "UNPUBLISH needs a parameter!" << std::endl;
          goto executeCommandError;
      }
220
221
222
223
224
225
226
227
228
      doUnPublishSensor(argv[argvidx + 1]);
  }
  else if (strcasecmp(argv[argvidx], "UNPUBLISHW") == 0) {
      /* UNPUBLISHW needs one more parameter */
      if (argvidx+1 >= argc) {
          std::cout << "UNPUBLISHW needs a parameter!" << std::endl;
          goto executeCommandError;
      }
      doUnPublishSensorsByWildcard(argv[argvidx+1]);
229
  }
230
231
232
233
234
235
  else {
      std::cout << "Invalid SENSOR command: " << argv[argvidx] << std::endl;
      goto executeCommandError;
  }

  /* Clean up */
Axel Auweter's avatar
Axel Auweter committed
236
237
  connection->disconnect();
  delete connection;
238
239
240
  return EXIT_SUCCESS;

executeCommandError:
Axel Auweter's avatar
Axel Auweter committed
241
242
  connection->disconnect();
  delete connection;
243
244
245
246
  return EXIT_FAILURE;
}


247
/*
Axel Auweter's avatar
Axel Auweter committed
248
 * Publish a sensor
249
 */
Axel Auweter's avatar
Axel Auweter committed
250
void SensorAction::doPublishSensor(const char* publicName, const char* sensorPattern)
251
{
252
  DCDB::SCError err;
253

254
  DCDB::SensorConfig sensorConfig(connection);
255
256
257
  err = sensorConfig.publishSensor(publicName, sensorPattern);

  switch(err) {
258
  case DCDB::SC_INVALIDPATTERN:
259
260
    std::cout << "Invalid sensor pattern: " << sensorPattern << std::endl;
    break;
261
  case DCDB::SC_INVALIDPUBLICNAME:
262
263
    std::cout << "Invalid sensor public name: " << publicName << std::endl;
    break;
264
  case DCDB::SC_INVALIDSESSION:
265
266
267
    std::cout << "Invalid dcdb session." << std::endl;
    break;
  default:
268
    sensorConfig.setPublishedSensorsWritetime(getTimestamp());
269
270
    break;
  }
271
}
272

273
274
275
/*
 * Create a virtual sensor
 */
276
void SensorAction::doVCreateSensor(const char* publicName, const char* expression, const char* vSensorId, const char* tZero, const char* interval)
277
278
279
280
{
  /* Convert tZero to TimeStamp */
  DCDB::TimeStamp tz(tZero);

281
  /* Convert interval to int64_t - sadly, there's no real C++ way of doing this */
282
  int64_t freq;
283
284
  if (sscanf(interval, "%" SCNd64, &freq) != 1) {
      std::cout << interval << " is not a valid number." << std::endl;
285
286
287
288
289
290
      return;
  }

  DCDB::SCError err;

  DCDB::SensorConfig sensorConfig(connection);
291
  err = sensorConfig.publishVirtualSensor(publicName, expression, vSensorId, tz, freq);
292
293

  switch(err) {
294
  case DCDB::SC_INVALIDEXPRESSION:
295
296
    // We should get a proper error message in the exception handler.
    //std::cout << "Invalid expression: " << expression << std::endl;
297
    break;
298
299
300
301
302
303
  case DCDB::SC_INVALIDVSENSORID:
    std::cout << "Invalid vsensorid: " << vSensorId << std::endl;
    std::cout << "Valid vsensorids are provided as 128 bits hex values." << std::endl;
    std::cout << "You may separate hex characters with slash characters for readability." << std::endl;
    std::cout << "Example: /00000000/deadbeef/cafeaffe/0000/0001" << std::endl;
    break;
304
305
306
  case DCDB::SC_EXPRESSIONSELFREF:
    std::cout << "Invalid expression: A virtual sensor must not reference itself." << std::endl;
    break;
307
308
309
310
311
312
313
  case DCDB::SC_INVALIDPUBLICNAME:
    std::cout << "Invalid sensor public name: " << publicName << std::endl;
    break;
  case DCDB::SC_INVALIDSESSION:
    std::cout << "Invalid dcdb session." << std::endl;
    break;
  default:
314
    sensorConfig.setPublishedSensorsWritetime(getTimestamp());
315
316
317
318
    break;
  }
}

319
/*
320
321
322
323
 * List all published sensors by name
 */
void SensorAction::doList()
{
324
  DCDB::SensorConfig sensorConfig(connection);
325
326
327
328
329
330
331
332
333
334
  std::list<std::string> publicSensors;

  sensorConfig.getPublicSensorNames(publicSensors);
  for (std::list<std::string>::iterator it=publicSensors.begin(); it != publicSensors.end(); it++) {
      std::cout << (*it) << std::endl;
  }
}

/*
 * List all published sensors with name and pattern
335
 */
Axel Auweter's avatar
Axel Auweter committed
336
void SensorAction::doListPublicSensors()
337
{
338
339
  DCDB::SensorConfig sensorConfig(connection);
  std::list<DCDB::PublicSensor> publicSensors;
340

341
  sensorConfig.getPublicSensorsVerbose(publicSensors);
342
  for (std::list<DCDB::PublicSensor>::iterator it=publicSensors.begin(); it != publicSensors.end(); it++) {
343
344
345
346
347
348
      if ((*it).is_virtual) {
          std::cout << "(v) " << (*it).name << " : " << (*it).expression << std::endl;
      }
      else {
          std::cout << "    " << (*it).name << " : " << (*it).pattern << std::endl;
      }
349
350
  }
}
351
352

/*
353
 * Show the details for a given sensor TODO:Change Integrable
354
355
356
 */
void SensorAction::doShow(const char* publicName)
{
357
358
359
  DCDB::SensorConfig sensorConfig(connection);
  DCDB::PublicSensor publicSensor;
  DCDB::SCError err = sensorConfig.getPublicSensorByName(publicSensor, publicName);
360

361
362
363
  SensorMetadata sm;
  sm.setOperations(publicSensor.operations);
  
364
  switch (err) {
365
  case DCDB::SC_OK:
366
367
    if (!publicSensor.is_virtual) {
    std::cout << "Details for public sensor " << publicSensor.name << ":" << std::endl;
368
    std::cout << "Pattern: " << publicSensor.pattern << std::endl;
369
370
371
372
    }
    else {
        std::cout << "Details for virtual sensor " << publicSensor.name << ":" << std::endl;
        std::cout << "Expression: " << publicSensor.expression << std::endl;
373
        std::cout << "vSensorId: " << publicSensor.v_sensorid << std::endl;
374
375
376
        DCDB::TimeStamp tz(publicSensor.t_zero);
        std::cout << "T-Zero: " << tz.getString() << " (" << tz.getRaw() << ")" << std::endl;
    }
377
378
    std::cout << "Unit: " << publicSensor.unit << std::endl;
    std::cout << "Scaling factor: " << publicSensor.scaling_factor << std::endl;
379
    std::cout << "Operations: " << sm.getOperationsString() << std::endl;
380
381
    std::cout << "Interval: " << publicSensor.interval << std::endl;
    std::cout << "TTL: " << publicSensor.ttl << std::endl;
382
383
384
385
386
387
    std::cout << "Sensor Properties: ";
    if((publicSensor.sensor_mask & INTEGRABLE) == INTEGRABLE)
        std::cout << "Integrable ";
    if((publicSensor.sensor_mask & MONOTONIC) == MONOTONIC)
        std::cout << "Monotonic ";
    std::cout << std::endl;
388
    break;
389
  case DCDB::SC_UNKNOWNSENSOR:
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
    std::cout << "Unknown sensor name: " << publicName << std::endl;
    break;
  default:
    std::cout << "Internal error." << std::endl;
  }
}

/*
 * Set the scaling factor for a sensor
 */
void SensorAction::doScalingfactor(const char* publicName, const char* factor)
{
  double f;
  std::string fact(factor);
  try {
      f = std::stod(fact);
  }
  catch(std::exception& e) {
      std::cout << factor << " is not a number." << std::endl;
      return;
  }

412
413
414
  DCDB::SensorConfig sensorConfig(connection);
  DCDB::PublicSensor publicSensor;
  DCDB::SCError err = sensorConfig.getPublicSensorByName(publicSensor, publicName);
415
416

  switch (err) {
417
  case DCDB::SC_OK:
418
    sensorConfig.setSensorScalingFactor(publicName, f);
419
    sensorConfig.setPublishedSensorsWritetime(getTimestamp());
420
    break;
421
  case DCDB::SC_UNKNOWNSENSOR:
422
423
424
425
426
427
428
429
430
431
432
433
    std::cout << "Unknown sensor name: " << publicName << std::endl;
    break;
  default:
    std::cout << "Internal error." << std::endl;
  }
}

/*
 * Set the unit for a sensor.
 */
void SensorAction::doUnit(const char* publicName, const char* unit)
{
434
435
436
  DCDB::SensorConfig sensorConfig(connection);
  DCDB::PublicSensor publicSensor;
  DCDB::SCError err = sensorConfig.getPublicSensorByName(publicSensor, publicName);
437
438

  switch (err) {
439
  case DCDB::SC_OK:
440
441
    if (DCDB::UnitConv::fromString(unit) != DCDB::Unit_None) {
      sensorConfig.setSensorUnit(publicName, unit);
442
      sensorConfig.setPublishedSensorsWritetime(getTimestamp());
443
444
445
    } else {
      std::cout << "Unknown unit: " << unit << std::endl;
    }
446
    break;
447
  case DCDB::SC_UNKNOWNSENSOR:
448
449
450
451
452
453
454
455
456
457
    std::cout << "Unknown sensor name: " << publicName << std::endl;
    break;
  default:
    std::cout << "Internal error." << std::endl;
  }
}

/*
 * Set or unset the integrable flag for a sensor
 */
458
void SensorAction::doSensorProperty(const char* publicName, const char* cmd)
459
{
460
461
462
  DCDB::SensorConfig sensorConfig(connection);
  DCDB::PublicSensor publicSensor;
  DCDB::SCError err = sensorConfig.getPublicSensorByName(publicSensor, publicName);
463
464

  switch (err) {
465
  case DCDB::SC_OK:
466
467
468
      {
          uint64_t mask = publicSensor.sensor_mask;
          
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
	  if (cmd != nullptr) {
	      if(strcasestr(cmd,"integrable")) {
		  if ((mask & INTEGRABLE) != INTEGRABLE) {
		      mask = mask | INTEGRABLE;
		  }
	      } else if(strcasestr(cmd, "monotonic")) {
		  if ((mask & MONOTONIC) != MONOTONIC) {
		      mask = mask | MONOTONIC;
		  }
	      } else if(strcasestr(cmd, "delta")) {
		  if ((mask & DELTA) != DELTA) {
		      mask = mask | DELTA;
		  }
	      } else {
		  std::cout << "Unknown option: " << cmd << std::endl;
		  std::cout << "Valid sensor properties are: INTEGRABLE, MONOTONIC, DELTA" << std::endl;
	      }
			
	      if(mask != publicSensor.sensor_mask) {
		  sensorConfig.setSensorMask(publicName, mask);
		  sensorConfig.setPublishedSensorsWritetime(getTimestamp());
	      }
	  }
      
	  std::cout << publicSensor.name << ":";
	  if ((mask & INTEGRABLE) == INTEGRABLE) {
	      std::cout << " integrable";
	  } else if ((mask & MONOTONIC) == MONOTONIC) {
	      std::cout << " monotonic";
	  } else if ((mask & DELTA) == DELTA) {
	      std::cout << " delta";
	  }
	  std::cout << std::endl;
502
503
504

          break;
      }
505
  case DCDB::SC_UNKNOWNSENSOR:
506
507
508
509
510
511
    std::cout << "Unknown sensor name: " << publicName << std::endl;
    break;
  default:
    std::cout << "Internal error." << std::endl;
  }
}
512

513
514
515
516
517
518
519
520
521
522
/*
 * Set the expression for a virtual sensor
 */
void SensorAction::doExpression(const char* publicName, const char* expression)
{
  DCDB::SensorConfig sensorConfig(connection);
  DCDB::SCError err = sensorConfig.setVirtualSensorExpression(publicName, expression);

  switch (err) {
  case DCDB::SC_OK:
523
    sensorConfig.setPublishedSensorsWritetime(getTimestamp());
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
    break;
  case DCDB::SC_UNKNOWNSENSOR:
    std::cout << "Unknown sensor name: " << publicName << std::endl;
    break;
  case DCDB::SC_INVALIDSESSION:
    std::cout << "Invalid session!" << std::endl;
    break;
  case DCDB::SC_WRONGTYPE:
    std::cout << "Sensor " << publicName << " is not virtual!" << std::endl;
    break;
  default:
    std::cout << "Internal error." << std::endl;
  }
}

/*
 * Set the T0 for a virtual sensor
 */
void SensorAction::doTZero(const char* publicName, const char* tZero)
{
  /* Convert tZero to TimeStamp */
  DCDB::TimeStamp tz(tZero);

  DCDB::SensorConfig sensorConfig(connection);
  DCDB::SCError err = sensorConfig.setVirtualSensorTZero(publicName, tz);

  switch (err) {
  case DCDB::SC_OK:
552
    sensorConfig.setPublishedSensorsWritetime(getTimestamp());
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
    break;
  case DCDB::SC_UNKNOWNSENSOR:
    std::cout << "Unknown sensor name: " << publicName << std::endl;
    break;
  case DCDB::SC_INVALIDSESSION:
    std::cout << "Invalid session!" << std::endl;
    break;
  case DCDB::SC_WRONGTYPE:
    std::cout << "Sensor " << publicName << " is not virtual!" << std::endl;
    break;
  default:
    std::cout << "Internal error." << std::endl;
  }
}

/*
569
 * Set the interval for a sensor
570
 */
571
void SensorAction::doInterval(const char* publicName, const char *interval)
572
{
573
  /* Convert interval to int64_t - sadly, there's no real C++ way of doing this */
574
  int64_t freq;
575
576
  if (sscanf(interval, "%" SCNd64, &freq) != 1) {
      std::cout << interval << " is not a valid number." << std::endl;
577
578
579
580
      return;
  }

  DCDB::SensorConfig sensorConfig(connection);
581
  DCDB::SCError err = sensorConfig.setSensorInterval(publicName, freq);
582
583
584

  switch (err) {
  case DCDB::SC_OK:
585
    sensorConfig.setPublishedSensorsWritetime(getTimestamp());
586
587
588
589
590
591
592
593
594
595
596
597
    break;
  case DCDB::SC_UNKNOWNSENSOR:
    std::cout << "Unknown sensor name: " << publicName << std::endl;
    break;
  case DCDB::SC_INVALIDSESSION:
    std::cout << "Invalid session!" << std::endl;
    break;
  default:
    std::cout << "Internal error." << std::endl;
  }
}

598
599
600
601
602
603
604
605
606
607
608
609
610
void SensorAction::doTTL(const char* publicName, const char *ttl) {
    /* Convert ttl to int64_t - sadly, there's no real C++ way of doing this */
    int64_t ttl_int;
    if (sscanf(ttl, "%" SCNd64, &ttl_int) != 1) {
        std::cout << ttl << " is not a valid number." << std::endl;
        return;
    }

    DCDB::SensorConfig sensorConfig(connection);
    DCDB::SCError err = sensorConfig.setTimeToLive(publicName, ttl_int);

    switch (err) {
        case DCDB::SC_OK:
611
            sensorConfig.setPublishedSensorsWritetime(getTimestamp());
612
613
614
615
616
617
618
619
620
621
622
623
            break;
        case DCDB::SC_UNKNOWNSENSOR:
            std::cout << "Unknown sensor name: " << publicName << std::endl;
            break;
        case DCDB::SC_INVALIDSESSION:
            std::cout << "Invalid session!" << std::endl;
            break;
        default:
            std::cout << "Internal error." << std::endl;
    }
}

624
625
void SensorAction::doOperations(const char* publicName, const char *operations)
{
626
627
    SensorMetadata sm;
    sm.setOperations(std::string(operations));
628
629
    
    DCDB::SensorConfig sensorConfig(connection);
630
    DCDB::SCError err = sensorConfig.setOperations(publicName, *sm.getOperations());
631
632
633
    
    switch (err) {
        case DCDB::SC_OK:
634
            sensorConfig.setPublishedSensorsWritetime(getTimestamp());
635
636
637
638
639
640
641
642
643
644
645
646
            break;
        case DCDB::SC_UNKNOWNSENSOR:
            std::cout << "Unknown sensor name: " << publicName << std::endl;
            break;
        case DCDB::SC_INVALIDSESSION:
            std::cout << "Invalid session!" << std::endl;
            break;
        default:
            std::cout << "Internal error." << std::endl;
    }
}

647
648
649
650
651
652
653
void SensorAction::doClearOperations(const char* publicName)
{
    DCDB::SensorConfig sensorConfig(connection);
    DCDB::SCError err = sensorConfig.clearOperations(publicName);

    switch (err) {
        case DCDB::SC_OK:
654
            sensorConfig.setPublishedSensorsWritetime(getTimestamp());
655
656
657
658
659
660
661
662
663
664
665
666
            break;
        case DCDB::SC_UNKNOWNSENSOR:
            std::cout << "Unknown sensor name: " << publicName << std::endl;
            break;
        case DCDB::SC_INVALIDSESSION:
            std::cout << "Invalid session!" << std::endl;
            break;
        default:
            std::cout << "Internal error." << std::endl;
    }
}

667
668
669
670
671
672
673
void SensorAction::doClearOperationsByWildcard(const char* wildcard)
{
    DCDB::SensorConfig sensorConfig(connection);
    DCDB::SCError err = sensorConfig.clearOperationsByWildcard(wildcard);

    switch (err) {
        case DCDB::SC_OK:
674
            sensorConfig.setPublishedSensorsWritetime(getTimestamp());
675
676
677
678
679
680
681
682
683
            break;
        case DCDB::SC_INVALIDSESSION:
            std::cout << "Invalid session!" << std::endl;
            break;
        default:
            std::cout << "Internal error." << std::endl;
    }
}

684
685
686
687
688
/*
 * Unpublish a sensor
 */
void SensorAction::doUnPublishSensor(const char* publicName)
{
689
  DCDB::SensorConfig sensorConfig(connection);
690
  sensorConfig.unPublishSensor(publicName);
691
  sensorConfig.setPublishedSensorsWritetime(getTimestamp());
692
}
693
694
695
696
697

void SensorAction::doUnPublishSensorsByWildcard(const char* wildcard)
{
    DCDB::SensorConfig sensorConfig(connection);
    sensorConfig.unPublishSensorsByWildcard(wildcard);
698
    sensorConfig.setPublishedSensorsWritetime(getTimestamp());
699
}