dcdbquery.cpp 5.83 KB
Newer Older
Axel Auweter's avatar
Axel Auweter committed
1
2
//================================================================================
// Name        : dcdbquery.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 : Main file of the dcdbquery command line utility
//================================================================================

//================================================================================
// 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

Axel Auweter's avatar
Axel Auweter committed
28
/* C++ standard headers */
29
#include <iostream>
Axel Auweter's avatar
Axel Auweter committed
30
#include <stdexcept>
31

Axel Auweter's avatar
Axel Auweter committed
32
33
/* C standard headers */
#include <cstdlib>
34
#include <cstring>
Axel Auweter's avatar
Axel Auweter committed
35
36
37
38
#include <unistd.h>

/* Custom headers */
#include "dcdb/timestamp.h"
39
#include "dcdb/version.h"
40
#include "version.h"
Axel Auweter's avatar
Axel Auweter committed
41
42
43
44
#include "query.h"

void usage(void)
{
45
46
  if (isatty(fileno(stdin))) {
      /*            0---------1---------2---------3---------4---------5---------6---------7--------- */
47
      std::cout << "Usage:" << std::endl;
48
49
      std::cout << "  dcdbquery [-h <host>] [-r] [-l] <Sensor 1> [<Sensor 2> ...] <Start> <End>" << std::endl;
      std::cout << "  dcdbquery [-h <host>] [-r] [-l] -j <jobId> <Sensor 1> [<Sensor 2> ...]" << std::endl;
50
51
      std::cout << std::endl;
      std::cout << "Parameters:" << std::endl;
52
      std::cout << "  <jobId>       a job to query sensors for" << std::endl;
53
54
55
56
57
58
59
60
      std::cout << "  <Sensor n>    a sensor name" << std::endl;
      std::cout << "  <Start>       start of time series" << std::endl;
      std::cout << "  <End>         end of time series" << std::endl;
      std::cout << std::endl;
      std::cout << "Options:" << std::endl;
      std::cout << "  -h<host>      Cassandra host                         [default: " << DEFAULT_CASSANDRAHOST << ":" << DEFAULT_CASSANDRAPORT << "]" << endl;
      std::cout << "  -r            Report timestamps in numerical format" << std::endl;
      std::cout << "  -l            Report times in local time (not UTC)" << std::endl;
61
62
63
64
  }
  else {
      std::cout << "Invalid request." << std::endl;
  }
Axel Auweter's avatar
Axel Auweter committed
65
66
67
  exit(EXIT_SUCCESS);
}

68
int main(int argc, char * const argv[])
69
{
70
71
  std::cout << "dcdbquery " << VERSION << " (libdcdb " << DCDB::Version::getVersion() << ")" << std::endl << std::endl;

72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
  /* Check if run from command line */
  int argcReal;
  char **argvReal;
  if (isatty(fileno(stdin))) {
      argcReal = argc;
      argvReal = (char**)argv;
  }
  else {
      /* Check if we are a CGI program */
      if (!getenv("QUERY_STRING")) {
          std::cout << "No terminal and no QUERY_STRING environment variable." << std::endl;
          std::cout << "Exiting." << std::endl;
          exit(EXIT_FAILURE);
      }

87
      /* Print content type */
88
      std::cout << "Content-type: text/plain" << std::endl << std::endl;
89

90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
      /* Create argcReal and argvReal */
      argcReal = 1;
      argvReal = (char**)malloc(sizeof(char*));
      argvReal[0] = strdup("dcdbquery"); /* dummy to make consistent with command line invocation */

      char *token = strtok(getenv("QUERY_STRING"), "&");
      while (token) {
          argcReal++;
          argvReal = (char**)realloc((void*)argvReal, argcReal*sizeof(char*));
          /* FIXME: should check if argvReal is NULL */
          argvReal[argcReal-1] = token;
          token = strtok(NULL, "&");
      }
  }

Axel Auweter's avatar
Axel Auweter committed
105
  /* Check command line arguments */
106
  if (argcReal <= 3) {
Axel Auweter's avatar
Axel Auweter committed
107
108
109
      usage();
  }

Axel Auweter's avatar
Axel Auweter committed
110
111
112
113
  /* Allocate our lovely helper class */
  DCDBQuery* myQuery;
  myQuery = new DCDBQuery();

114
  /* Get the options */
115
  int ret;
116
117
118
119
  const char *host = getenv("DCDB_HOSTNAME");
  if (!host) {
      host = "localhost";
  }
120
  std::string jobId;
121

122
  while ((ret=getopt(argcReal, argvReal, "+h:rlj:"))!=-1) {
Axel Auweter's avatar
Axel Auweter committed
123
124
125
126
      switch(ret) {
          case 'h':
              host = optarg;
              break;
127
          case 'r':
Axel Auweter's avatar
Axel Auweter committed
128
              myQuery->setRawOutputEnabled(true);
129
              break;
130
          case 'l':
Axel Auweter's avatar
Axel Auweter committed
131
              myQuery->setLocalTimeEnabled(true);
132
              break;
133
134
135
	  case 'j':
	      jobId = optarg;
	      break;
Axel Auweter's avatar
Axel Auweter committed
136
137
138
139
140
141
          default:
              usage();
              exit(EXIT_FAILURE);
      }
  }

142
143
  /* Try to create TimeStamp objects from the arguments */
  DCDB::TimeStamp start, end;
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
  if (jobId.size() == 0) {
      try {
	  bool local = myQuery->getLocalTimeEnabled();
	  start = DCDB::TimeStamp(argvReal[argcReal-2], local);
	  end   = DCDB::TimeStamp(argvReal[argcReal-1], local);
      } catch (std::exception& e) {
	  std::cout << "Wrong time format." << std::endl;
	  exit(EXIT_FAILURE);
      }
      
      /* Ensure start < end */
      if(start > end) {
	  std::cout << "Start time must be earlier than end time." << std::endl;
	  exit(EXIT_FAILURE);
      }
      argcReal-= 2;
Axel Auweter's avatar
Axel Auweter committed
160
161
162
163
  }

  /* Build a list of sensornames */
  std::list<std::string> sensors;
164
  for (int arg = optind; arg < argcReal; arg++) {
165
      sensors.push_back(argvReal[arg]);
Axel Auweter's avatar
Axel Auweter committed
166
167
  }

168
169
170
171
172
173
174
175
  if (myQuery->connect(host) == 0) {
      if (jobId.size() == 0) {
	  myQuery->doQuery(sensors, start, end);
      } else {
	  myQuery->dojobQuery(sensors, jobId);
      }
      myQuery->disconnect();
  }
Axel Auweter's avatar
Axel Auweter committed
176
177

  delete myQuery;
178
179
180

  return 0;
}