source: trunk/stoposclient.cpp @ 7

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