source: trunk/stoposclient.cpp @ 14

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

willem

File size: 11.3 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    if (line.size() > maxlinelength)
167    {
168      r.msg =  "Error: line length exeeds "+ NumberToString(maxlinelength);
169      break;
170    }
171    w.set_value(line);
172
173    rc = w.send_message(body,header);
174
175    if (rc != 0)
176    {
177      r.msg = "ERROR: Cannot connect to server";
178      return 1;
179    }
180    r.parse(body);
181    if (r.msg != "OK")
182      break;
183    n++;
184  }
185  if (! quiet)
186  {
187    bar.clear();
188    if (read_from_stdin)
189      std::cerr << '\r' << bar.show(n) << std::endl;
190    else
191      std::cerr << '\r' << bar.show(n,1.0) << std::endl;
192
193    std::cerr << program_name << ": Number of lines added = "<<n<<std::endl;
194  }
195  if (r.msg != "OK")
196    return 1;
197  return 0;
198}
199
200int main(int argc, char*argv[])
201{
202  wrequest w;
203 
204  int rc;
205
206  rc = w.read_config();
207  if (rc != 0 || w.get_config().size() != w.config_size)
208  {
209    std::cerr << "No valid config file found, creating it ..." << std::endl;
210    rc = w.write_config();
211    rc = rc | w.read_config();
212    if (rc != 0)
213    {
214      std::cerr << "Cannot write config file, exiting." << std::endl;
215      return 1;
216    }
217  }
218
219  bool addflag=0;
220  std::string inputfilename;
221  std::vector <std::string> parms;
222
223  static struct option long_options[] =
224  {
225    {"help",     0, 0, 'h'},
226    {"pool",     1, 0, 'p'},
227    {"version",  0, 0, 'v'},
228    {"multi",    0, 0, 'm'},
229    {"quiet",    0, 0, 'q'},
230    {0,          0, 0, 0}
231  };
232
233  // determine name of pool, in case it is not set on commandline
234
235  std::string pool = default_pool;
236  std::string p = envtostr("STOPOS_POOL");
237
238  if (p != "")
239    pool = p;
240
241  if (trim(w.get_pool()) != "")
242    pool = w.get_pool();
243
244  bool quiet = 0;
245
246  while(1)
247  {
248    int c = getopt_long(argc,argv,"-hp:vmq",long_options,0);
249    if (c == -1)
250    {
251      if (optind < argc)  // unexpected extra argument
252      {
253        std::cerr << program_name << ": Unexpected argument:" << argv[optind] << std::endl;
254        return 1;
255      }
256      break;
257    }
258    if ( c == '?' || c == ':' )
259    {
260      std::cerr << program_name << ": Invalid parameter, try "<< program_name<<" --help " <<std::endl;
261      return 1;
262    }
263    switch(c)
264    {
265      case 'h':
266        usage();
267        return 0;
268        break;
269      case 'p':
270        pool = optarg;
271        break;
272      case 'f':
273        inputfilename = optarg;
274        break;
275      case 'v':
276        std::cerr << program_version << std::endl;
277        return 0;
278        break;
279      case 'm':
280        w.set_multi("yes");
281        break;
282      case 'q':
283        quiet = 1;
284        break;
285      case 1:
286        parms.push_back(optarg);
287    }
288  }
289
290  w.set_pool(pool);
291  std::string serverurl=envtostr("STOPOS_SERVER_URL");
292  if (serverurl == "")
293    serverurl = SERVER_URL;
294  w.set_serverurl(serverurl);
295#ifdef DEFAULT_FLAT
296  std::string prot = "flat";
297#endif
298#ifdef DEFAULT_GDBM
299  std::string prot = "gdbm";
300#endif
301#ifdef DEFAULT_FILES
302  std::string prot = "files";
303#endif
304#ifdef DEFAULT_MYSQL
305  std::string prot = "mysql";
306#endif
307  std::string protenv;
308  protenv = envtostr("STOPOS_PROT");
309  if (protenv.size() !=0)
310    prot = protenv;
311  w.set_protocol(prot);
312  w.set_whoami(envtostr("USER"));
313
314  rc = 0;
315  returnvalue r;
316
317  if (parms.size() == 0)
318  {
319    std::cerr << program_name << ": No command given." << std::endl;
320    return 1;
321  }
322
323  std::string command = parms[0];
324
325  // only the remove and add commands can accept an extra parameter
326  //
327
328  if (parms.size() >1)
329    if (command !="remove" && command != "add")
330    {
331      std::cerr << program_name << ": Extraneous parameter:'"<<parms[1]<<"'."<<std::endl;
332      return 1;
333    }
334
335  bool count_set     = 0;
336  bool value_set     = 0;
337  bool committed_set = 0;
338  bool present_set   = 0;
339  bool present0_set  = 0;
340  bool key_set       = 0;
341  bool rc_set        = 0;
342
343  if(command == "create")
344  {
345    rc_set = 1;
346    w.set_command("create");
347  }
348  else if(command == "purge")
349  {
350    rc_set = 1;
351    w.set_command("purge");
352  }
353  else if(command == "status")
354  {
355    rc_set       = 1;
356    present_set  = 1;
357    present0_set = 1;
358    count_set    = 1;
359    w.set_command("status");
360  }
361  else if(command == "next")
362  {
363    rc_set        = 1;
364    value_set     = 1;
365    key_set       = 1;
366    committed_set = 1;
367    w.set_command("next");
368  }
369  else if(command == "dump")
370  {
371    rc_set        = 1;
372    value_set     = 1;
373    key_set       = 1;
374    committed_set = 1;
375    w.set_command("dump");
376  }
377  else if(command == "pools")
378  {
379    rc_set    = 1;
380    value_set = 1;
381    w.set_command("pools");
382  }
383  else if(command == "remove")
384  {
385    rc_set    = 1;
386    w.set_command("remove");
387    if (parms.size() < 2)
388    {
389      std::string a=envtostr("STOPOS_KEY");
390      if (a == "")
391      {
392        std::cerr << program_name << ": No key found, exit.\n";
393        return 1;
394      }
395      w.set_value(a);
396    }
397    else
398      w.set_value(parms[1]);
399  }
400  else if(command == "add")
401  {
402    rc_set  = 1;
403    key_set = 1;
404    addflag = 1;
405  }
406  else
407  {
408    std::cerr << program_name << ": Invalid command: '"<<command<<"'"<<std::endl;
409    return 1;
410  }
411
412  if(addflag)
413  {
414    if (parms.size() > 1)
415      inputfilename = parms[1];
416    rc |= handle_add(w,inputfilename,r,quiet);
417  }
418  else
419  {
420    std::string body,header;
421
422    rc = w.send_message(body,header);
423
424    if (rc != 0)
425      r.msg = "ERROR: Cannot connect to server";
426    else
427      r.parse(body);
428  }
429
430  int shelltype;
431
432  char *shell = getenv("SHELL");
433  std::string sh;
434  if (shell == 0)
435    sh = "bash";
436  else
437    sh = shell;
438
439  if (sh.find("csh") != sh.npos)
440    shelltype=SHELL_CSH;
441  else
442    shelltype = SHELL_SH;
443
444  if(rc_set)        std::cout << shellenv(r.msg,      "STOPOS_RC",        shelltype);
445  if(key_set)       std::cout << shellenv(r.key,      "STOPOS_KEY",       shelltype);
446  if(committed_set) std::cout << shellenv(r.comm,     "STOPOS_COMMITTED", shelltype);
447  if(count_set)     std::cout << shellenv(r.count,    "STOPOS_COUNT",     shelltype);
448  if(present_set)   std::cout << shellenv(r.present,  "STOPOS_PRESENT",   shelltype);
449  if(present0_set)  std::cout << shellenv(r.present0, "STOPOS_PRESENT0",  shelltype);
450  if(value_set)     std::cout << shellenv(r.value,    "STOPOS_VALUE",     shelltype);
451
452  if (command == "status" && r.msg == "OK" && ! quiet)
453  {
454    std::cerr << "lines added:           " << r.count    <<std::endl;
455    std::cerr << "lines present:         " << r.present  <<std::endl;
456    std::cerr << "lines never committed: " << r.present0 << std::endl;
457  }
458  else if (command == "pools" && ! quiet)
459  {
460    if(r.value.size()>0) std::cerr << r.value << std::endl;
461  }
462  if (r.msg != "OK" && ! quiet)
463  {
464    std::cerr << program_name<<": "<<r.msg << std::endl;
465    rc = 1;
466  }
467
468  return rc;
469}
Note: See TracBrowser for help on using the repository browser.