source: tags/0.9/stoposclient.cpp @ 9

Last change on this file since 9 was 9, checked in by willem, 11 years ago

willem

File size: 11.2 KB
Line 
1
2/*
3   Copyright 2013 Willem Vermin, SURFsara
4
5   Licensed under the Apache License, Version 2.0 (the "License");
6   you may not use this file except in compliance with the License.
7   You may obtain a copy of the License at
8
9       http://www.apache.org/licenses/LICENSE-2.0
10
11   Unless required by applicable law or agreed to in writing, software
12   distributed under the License is distributed on an "AS IS" BASIS,
13   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   See the License for the specific language governing permissions and
15   limitations under the License.
16 */
17#include <iostream>
18#include <vector>
19#include <stdlib.h>
20#include <getopt.h>
21#include <fstream>
22#include "wrequest.h"
23#include "shellenv.h"
24#include "stopos.h"
25
26struct returnvalue
27{
28  std::string msg;
29  std::string key;
30  std::string comm;
31  std::string count;
32  std::string present;
33  std::string present0;
34  std::string value;
35
36  void parse(std::string &s)
37  {
38    // we expect somewhere in the output of the server a line like
39    // STOPOS:/OK/123/beautiful
40    // OK        -> msg
41    // 123       -> key
42    // 1         -> comm
43    // beautiful -> value
44    //
45    // OK, 123 and beautiful are hex coded
46    this->msg       = "";
47    this->key       = "";
48    this->comm      = "0";
49    this->count     = "0";
50    this->present   = "0";
51    this->present0  = "0";
52    this->value     = "";
53
54    size_t p = s.find("STOPOS:");
55    if (p == s.npos)
56    {
57      this->msg="Error: stopos server not running.";
58      return;
59    }
60
61    size_t q = s.find('\n',p+1);
62    std::string l = s.substr(p,q-p);
63    std::vector <std::string> v;
64
65    split(v,l,outsep);
66    for (unsigned int i=1; i<v.size(); i++)
67    {
68      switch (i)
69      {
70        case 1: this->msg       = zhextostr(v[i]); break;
71        case 2: this->key       = zhextostr(v[i]); break;
72        case 3: this->comm      = zhextostr(v[i]); break;
73        case 4: this->count     = zhextostr(v[i]); break;
74        case 5: this->present   = zhextostr(v[i]); break;
75        case 6: this->present0  = zhextostr(v[i]); break;
76        case 7: this->value     = zhextostr(v[i]); break;
77      }
78      // special case for key: if key == "", we try to take
79      // it from the environment.
80      if (trim(this->key) == "")
81        this->key = envtostr("STOPOS_KEY");
82    }
83  }
84};
85
86void usage()
87{
88  std::cerr << "Usage:" << std::endl;
89
90  std::cerr << program_name << " -h,--help"                           << std::endl;
91  std::cerr << program_name << " -v,--version"                        << std::endl;
92  std::cerr << program_name << " create [-p,--pool POOL]"             << std::endl;
93  std::cerr << program_name << " purge  [-p,--pool POOL]"             << std::endl;
94  std::cerr << program_name << " pools"                               << std::endl;
95  std::cerr << program_name << " add    [-p,--pool POOL] [FILENAME]"  << std::endl;
96  std::cerr << program_name << " next   [-p,--pool POOL] [-m,--mult]" << std::endl;
97  std::cerr << program_name << " remove [-p,--pool POOL] [KEY]"       << std::endl;
98  std::cerr << program_name << " status [-p,--pool POOL]"             << std::endl;
99  std::cerr << program_name << " dump   [-p,--pool POOL]"             << std::endl;
100  std::cerr << " -q,--quiet added to any command will reduce the ouput" << std::endl;
101  std::cerr << "Defaults:"                                            << std::endl;
102  std::cerr << "  POOL     : pool"                                    << std::endl;
103  std::cerr << "  FILENAME : standard input"                          << std::endl;
104
105  std::cerr << "Environment:"<<std::endl;
106  std::cerr << "   Defined by user:"<<std::endl;
107  std::cerr << "     STOPOS_POOL    : name of pool"<<std::endl;
108  std::cerr << "     STOPOS_KEY     : key"<<std::endl;
109  std::cerr << "   Defined by "<<program_name<<":"<<std::endl;
110  std::cerr << "     STOPOS_RC      : return message of all commands. OK == good" << std::endl;
111  std::cerr << "     STOPOS_VALUE   : result of 'next' or 'pools'"<<std::endl;
112  std::cerr << "     STOPOS_KEY     : result of 'next'"<<std::endl;
113  std::cerr << "     STOPOS_COUNT   : result of 'status'"<<std::endl;
114  std::cerr << "     STOPOS_PRESENT : result of 'status'"<<std::endl;
115  std::cerr << "     STOPOS_PRESENT0: result of 'status'"<<std::endl;
116
117
118
119}
120
121int handle_add(wrequest &w,const std::string &fname,returnvalue &r, const bool quiet)
122{
123  size_t number_of_lines;
124
125  bool read_from_stdin = 0;
126  int rc;
127  std::ifstream inp;
128  std::istream *pinp;
129  if(fname == "")  // read from stdin
130  {
131    read_from_stdin = 1;
132    pinp = &std::cin;
133  }
134  else
135  {
136    inp.open(fname.c_str());
137    if (!inp.is_open())
138    {
139      r.msg = "ERROR: Cannot open '"+fname+"'";
140      return 1;
141    }
142
143    number_of_lines = count_lines(inp);
144    pinp = &inp;
145  }
146  std::string line;
147  size_t n = 0;
148  w.set_command("add");
149  std::string body,header;
150
151  progress_bar bar;
152
153  while (getline(*pinp,line))
154  {
155    if (! quiet)
156    {
157      bool c;
158      std::string s;
159      if (read_from_stdin)
160        s = bar.show(n,c);
161      else
162        s = bar.show(n,(double)n/number_of_lines,c);
163      if (c)
164        std::cerr << '\r' << s;
165    }
166    w.set_value(line);
167    rc = w.send_message(body,header);
168    if (rc != 0)
169    {
170      r.msg = "ERROR: Cannot connect to server";
171      return 1;
172    }
173    r.parse(body);
174    if (r.msg != "OK")
175      break;
176    n++;
177  }
178  if (! quiet)
179  {
180    bar.clear();
181    if (read_from_stdin)
182      std::cerr << '\r' << bar.show(n) << std::endl;
183    else
184      std::cerr << '\r' << bar.show(n,1.0) << std::endl;
185
186    std::cerr << program_name << ": Number of lines added = "<<n<<std::endl;
187  }
188  if (r.msg != "OK")
189    return 1;
190  return 0;
191}
192
193int main(int argc, char*argv[])
194{
195  wrequest w;
196 
197  int rc;
198
199  rc = w.read_config();
200  if (rc != 0 || w.get_config().size() != w.config_size)
201  {
202    std::cerr << "No valid config file found, creating it ..." << std::endl;
203    rc = w.write_config();
204    if (rc != 0)
205    {
206      std::cerr << "Cannot write config file, exiting." << std::endl;
207      return 1;
208    }
209  }
210
211  bool addflag=0;
212  std::string inputfilename;
213  std::vector <std::string> parms;
214
215  static struct option long_options[] =
216  {
217    {"help",     0, 0, 'h'},
218    {"pool",     1, 0, 'p'},
219    {"version",  0, 0, 'v'},
220    {"multi",    0, 0, 'm'},
221    {"quiet",    0, 0, 'q'},
222    {0,          0, 0, 0}
223  };
224
225  // determine name of pool, in case it is not set on commandline
226
227  std::string pool = default_pool;
228  std::string p = envtostr("STOPOS_POOL");
229
230  if (p != "")
231    pool = p;
232
233  if (trim(w.get_pool()) != "")
234    pool = w.get_pool();
235
236  bool quiet = 0;
237
238  while(1)
239  {
240    int c = getopt_long(argc,argv,"-hp:vmq",long_options,0);
241    if (c == -1)
242    {
243      if (optind < argc)  // unexpected extra argument
244      {
245        std::cerr << program_name << ": Unexpected argument:" << argv[optind] << std::endl;
246        return 1;
247      }
248      break;
249    }
250    if ( c == '?' || c == ':' )
251    {
252      std::cerr << program_name << ": Invalid parameter, try "<< program_name<<" --help " <<std::endl;
253      return 1;
254    }
255    switch(c)
256    {
257      case 'h':
258        usage();
259        return 0;
260        break;
261      case 'p':
262        pool = optarg;
263        break;
264      case 'f':
265        inputfilename = optarg;
266        break;
267      case 'v':
268        std::cerr << program_version << std::endl;
269        return 0;
270        break;
271      case 'm':
272        w.set_multi("yes");
273        break;
274      case 'q':
275        quiet = 1;
276        break;
277      case 1:
278        parms.push_back(optarg);
279    }
280  }
281
282  w.set_pool(pool);
283  std::string serverurl=envtostr("STOPOS_SERVER_URL");
284  if (serverurl == "")
285    serverurl = SERVER_URL;
286  w.set_serverurl(serverurl);
287#ifdef DEFAULT_FLAT
288  std::string prot = "flat";
289#endif
290#ifdef DEFAULT_GDBM
291  std::string prot = "gdbm";
292#endif
293#ifdef DEFAULT_FILES
294  std::string prot = "files";
295#endif
296#ifdef DEFAULT_MYSQL
297  std::string prot = "mysql";
298#endif
299  std::string protenv;
300  protenv = envtostr("STOPOS_PROT");
301  if (protenv.size() !=0)
302    prot = protenv;
303  w.set_protocol(prot);
304  w.set_whoami(envtostr("USER"));
305
306  rc = 0;
307  returnvalue r;
308
309  if (parms.size() == 0)
310  {
311    std::cerr << program_name << ": No command given." << std::endl;
312    return 1;
313  }
314
315  std::string command = parms[0];
316
317  // only the remove and add commands can accept an extra parameter
318  //
319
320  if (parms.size() >1)
321    if (command !="remove" && command != "add")
322    {
323      std::cerr << program_name << ": Extraneous parameter:'"<<parms[1]<<"'."<<std::endl;
324      return 1;
325    }
326
327  bool count_set     = 0;
328  bool value_set     = 0;
329  bool committed_set = 0;
330  bool present_set   = 0;
331  bool present0_set  = 0;
332  bool key_set       = 0;
333  bool rc_set        = 0;
334
335  if(command == "create")
336  {
337    rc_set = 1;
338    w.set_command("create");
339  }
340  else if(command == "purge")
341  {
342    rc_set = 1;
343    w.set_command("purge");
344  }
345  else if(command == "status")
346  {
347    rc_set       = 1;
348    present_set  = 1;
349    present0_set = 1;
350    count_set    = 1;
351    w.set_command("status");
352  }
353  else if(command == "next")
354  {
355    rc_set        = 1;
356    value_set     = 1;
357    key_set       = 1;
358    committed_set = 1;
359    w.set_command("next");
360  }
361  else if(command == "dump")
362  {
363    rc_set        = 1;
364    value_set     = 1;
365    key_set       = 1;
366    committed_set = 1;
367    w.set_command("dump");
368  }
369  else if(command == "pools")
370  {
371    rc_set    = 1;
372    value_set = 1;
373    w.set_command("pools");
374  }
375  else if(command == "remove")
376  {
377    rc_set    = 1;
378    w.set_command("remove");
379    if (parms.size() < 2)
380    {
381      std::string a=envtostr("STOPOS_KEY");
382      if (a == "")
383      {
384        std::cerr << program_name << ": No key found, exit.\n";
385        return 1;
386      }
387      w.set_value(a);
388    }
389    else
390      w.set_value(parms[1]);
391  }
392  else if(command == "add")
393  {
394    rc_set  = 1;
395    key_set = 1;
396    addflag = 1;
397  }
398  else
399  {
400    std::cerr << program_name << ": Invalid command: '"<<command<<"'"<<std::endl;
401    return 1;
402  }
403
404  if(addflag)
405  {
406    if (parms.size() > 1)
407      inputfilename = parms[1];
408    rc |= handle_add(w,inputfilename,r,quiet);
409  }
410  else
411  {
412    std::string body,header;
413
414    rc = w.send_message(body,header);
415
416    if (rc != 0)
417      r.msg = "ERROR: Cannot connect to server";
418    else
419      r.parse(body);
420  }
421
422  int shelltype;
423
424  char *shell = getenv("SHELL");
425  std::string sh;
426  if (shell == 0)
427    sh = "bash";
428  else
429    sh = shell;
430
431  if (sh.find("csh") != sh.npos)
432    shelltype=SHELL_CSH;
433  else
434    shelltype = SHELL_SH;
435
436  if(rc_set)        std::cout << shellenv(r.msg,      "STOPOS_RC",        shelltype);
437  if(key_set)       std::cout << shellenv(r.key,      "STOPOS_KEY",       shelltype);
438  if(committed_set) std::cout << shellenv(r.comm,     "STOPOS_COMMITTED", shelltype);
439  if(count_set)     std::cout << shellenv(r.count,    "STOPOS_COUNT",     shelltype);
440  if(present_set)   std::cout << shellenv(r.present,  "STOPOS_PRESENT",   shelltype);
441  if(present0_set)  std::cout << shellenv(r.present0, "STOPOS_PRESENT0",  shelltype);
442  if(value_set)     std::cout << shellenv(r.value,    "STOPOS_VALUE",     shelltype);
443
444  if (command == "status" && r.msg == "OK" && ! quiet)
445  {
446    std::cerr << "lines added:           " << r.count    <<std::endl;
447    std::cerr << "lines present:         " << r.present  <<std::endl;
448    std::cerr << "lines never committed: " << r.present0 << std::endl;
449  }
450  else if (command == "pools" && ! quiet)
451  {
452    if(r.value.size()>0) std::cerr << r.value << std::endl;
453  }
454  if (r.msg != "OK" && ! quiet)
455  {
456    std::cerr << program_name<<": "<<r.msg << std::endl;
457    rc = 1;
458  }
459
460  return rc;
461}
Note: See TracBrowser for help on using the repository browser.