source: tags/0.9/stoposserver.cpp @ 9

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

willem

File size: 10.6 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 <stdlib.h>
19#include <vector>
20#include <string>
21#include "stopos.h"
22#include "wutils.h"
23#include "stopos_pool.h"
24#ifdef MAKE_GDBM
25#include "gdbm_pool.h"
26#endif
27#ifdef MAKE_FLAT
28#include "flatfile_pool.h"
29#endif
30#ifdef MAKE_FILES
31#include "files_pool.h"
32#endif
33#ifdef MAKE_MYSQL
34#include "mysql_pool.h"
35#endif
36
37void output(const std::string &return_message, const std::string &key,
38             longuint committed, 
39             longuint count,
40             longuint present,
41             longuint present0,
42             const std::string &return_value)
43{
44  std::cout << "STOPOS:"                            << outsep <<
45               zstrtohex(return_message)            << outsep <<
46               zstrtohex(key)                       << outsep <<
47               zstrtohex(NumberToString(committed)) << outsep <<
48               zstrtohex(NumberToString(count))     << outsep <<
49               zstrtohex(NumberToString(present))   << outsep <<
50               zstrtohex(NumberToString(present0))  << outsep <<
51               zstrtohex(return_value)              << 
52               std::endl;
53}
54
55void output(const std::string &msg)
56{
57  output(msg,"",0,0,0,0,"");
58}
59struct commandline
60{
61  std::string header;
62  std::string prot;
63  std::string id;
64  std::string pool;
65  std::string command;
66  std::string multi;
67  std::string value;
68  std::string full_dbname;
69  std::string return_value;
70  stopos_pool *handler;
71
72  int create_full_dbname(void)
73  {
74    if (this->prot == "gdbm" ||
75        this->prot == "flat" ||
76        this->prot == "files")
77    {
78      std::string db_dir = DB_DIR;
79      if (db_dir == "" ) db_dir = "/tmp";
80      db_dir += "/";
81
82      this->full_dbname = db_dir                +
83                          zstrtohex(this->id)   +
84                          "/"                   +
85                          zstrtohex(this->pool) +
86                          "_"                   +
87                          this->prot;
88    }
89    else if (this->prot == "mysql")
90    {
91      this->full_dbname = zstrtohex(this->id) +
92                          "_"                 +
93                          zstrtohex(this->pool);
94    }
95    else
96      return 1;
97
98    if (this->command != "pools")
99      this->handler->set_db_name(this->full_dbname);
100    return 0;
101  }
102
103  int create_handler()
104  {
105#ifdef MAKE_GDBM
106    if (this->prot == "gdbm")
107    {
108      this->handler = new gdbm_pool();
109    }
110#endif
111#ifdef MAKE_FLAT
112    else if (this->prot == "flat")
113    {
114      this->handler = new flatfile_pool();
115    }
116#endif
117#ifdef MAKE_FILES
118    else if (this->prot == "files")
119    {
120      this->handler = new files_pool();
121    }
122#endif
123#ifdef MAKE_MYSQL
124    else if (this->prot == "mysql")
125    {
126      this->handler = new mysql_pool();
127    }
128#endif
129    else
130    {
131      this->return_value = "ERROR: Unknown handler:" + this->prot;
132      return 1;
133    }
134    return 0;
135  }
136
137  int init()
138  {
139
140    int rc;
141    if (this->command != "pools")
142    {
143      rc = this->create_handler();
144      if (rc != 0) 
145        return rc;
146      if (this->multi == "yes")
147        this->handler->set_kvp(1);
148      else
149        this->handler->set_kvp(0);
150    }
151    rc = this->create_full_dbname();
152    return rc;
153  }
154
155  int create_db()
156  {
157    int rc = this->handler->create_db();
158    return rc;
159  }
160
161  int purge_db()
162  {
163    int rc = this->handler->purge_db();
164    return rc;
165  }
166
167  int add_line(std::string &key, std::string &r)
168  {
169    r = "";
170    int rc;
171    rc = this->handler->open_db();
172    if (rc != 0)
173      return rc;
174
175    rc = this->handler->add_line(this->value,key);
176    if (rc != 0)
177      return rc;
178    return 0;
179  }
180
181  int get_line(std::string &key, longuint &comm, std::string &r)
182  {
183    r = "";
184    int rc;
185    rc = this->handler->open_db();
186    if (rc != 0)
187      return rc;
188
189    rc = this->handler->get_line(this->return_value, comm, key);
190    return rc;
191  }
192
193  int dump_line(std::string &key, longuint &comm, std::string &r)
194  {
195    r = "";
196    int rc;
197    rc = this->handler->open_db();
198    if (rc != 0)
199      return rc;
200
201    rc = this->handler->dump_line(this->return_value, comm, key);
202    return rc;
203  }
204
205  int remove_line(std::string & rkey,std::string &key, std::string &r)
206  {
207    r = "";
208    int rc;
209    rc = this->handler->open_db();
210    if (rc != 0)
211      return rc;
212
213    rkey = key;
214    rc = this->handler->remove_line(key);
215    return rc;
216  }
217
218  int get_status(longuint &count, 
219                 longuint &present, 
220                 longuint &present0, 
221                 std::string &r)
222  {
223    r = "";
224    int rc;
225    rc = this->handler->open_db();
226    if (rc != 0)
227      return rc;
228
229    rc = this->handler->get_counts(count, present, present0);
230
231    return rc;
232  }
233};
234
235std::string sanitycheck(commandline &l)
236{
237  if (l.header != "stopos")
238    return "invalid header: '" + l.header + "'";
239
240  if (l.prot.find_first_of(' ') != l.prot.npos)
241    return "ERROR: No valid protocol given";
242
243  if(l.id.find_first_of(' ') != l.id.npos)
244    return "ERROR: No valid id given";
245
246  if(l.command != "pools")
247    if(l.pool.find_first_of(' ') != l.pool.npos)
248    {
249      return "ERROR: No valid pool given";
250    }
251  if(l.command.find_first_of(' ') != l.command.npos)
252  {
253    return "ERROR: No valid command given";
254  }
255  return "";
256}
257
258int parsecom(commandline &l,std::string &line)
259{
260  std::vector <std::string> v;
261  split(v,line,httpsep); 
262                       
263  for (unsigned int i =0; i<v.size(); i++)
264  {
265    switch(i)
266    {
267      case 0: l.header   = zhextostr(v[i]); break;
268      case 1: l.prot     = zhextostr(v[i]); break;
269      case 2: l.id       = zhextostr(v[i]); break;
270      case 3: l.pool     = zhextostr(v[i]); break;
271      case 4: l.command  = zhextostr(v[i]); break;
272      case 5: l.multi    = zhextostr(v[i]); break;
273      case 6: l.value    = zhextostr(v[i]); break;
274    }
275  }
276  return 0;
277}
278
279
280int executecom(commandline &l)
281{
282  int rc;
283  longuint committed = 0;
284  longuint count     = 0;
285  longuint present   = 0;
286  longuint present0  = 0;
287
288  std::string return_message;
289  std::string key;
290  rc = l.init();
291
292  if (rc != 0)
293  {
294    if (l.return_value.size() == 0)
295      output("ERROR: cannot initialize server software");
296    else
297      output(l.return_value);
298    return rc;
299  }
300
301  if (l.command == "create")
302  {
303    rc = l.create_db();
304    if (rc != 0)
305      return_message = "ERROR: cannot create pool "+l.pool;
306  }
307  else if (l.command == "purge")
308  {
309    rc = l.purge_db();
310  }
311  else if (l.command == "add")
312  {
313    rc = l.add_line(key,return_message);
314  }
315  else if (l.command == "next")
316  {
317    rc = l.get_line(key, committed,return_message);
318  }
319  else if (l.command == "dump")
320  {
321    rc = l.dump_line(key, committed,return_message);
322  }
323  else if (l.command == "remove")
324  {
325    rc = l.remove_line(key,l.value, return_message);
326  }
327  else if (l.command == "status")
328  {
329    rc = l.get_status(count,present,present0,return_message);
330  }
331  else if (l.command == "pools")
332  {
333    if      (l.prot == "mysql")
334    {
335      l.return_value = "No pools for mysql";
336      rc = 0;
337    }
338    else if (l.prot == "files" ||
339             l.prot == "gdbm"  ||
340             l.prot == "flat"  )
341    {
342      // extract the directory from full_dbname:
343      size_t p = l.full_dbname.find_last_of('/');
344      if (p == l.full_dbname.npos)
345        rc = 1;
346      else
347      {
348        std::string dir = l.full_dbname.substr(0,p+1);
349        std::list <std::string> v;
350        get_dir_list(v,dir);
351        v.sort();
352
353        l.return_value = "";
354        for (std::list<std::string>::iterator it=v.begin(); it != v.end(); ++it)
355        {
356          std::string f = *it;
357          //
358          // if suffix ( eg: _files ) is found
359          // this could be a valid file name
360          //
361
362          size_t sufsize = l.prot.size()+1;
363          if (sufsize > f.size())
364            continue;
365          p = f.size() - sufsize;
366          if (f.substr(p) != "_"+l.prot)
367            continue;
368#if 0
369          p = f.rfind("_"+l.prot);
370          if (p == f.npos)
371            continue;
372#endif
373          f = f.substr(0,p);
374          //
375          // strip directory part
376          //
377          p = f.find_last_of('/');
378          f = f.substr(p+1);
379          l.return_value += zhextostr(f);
380          l.return_value.push_back(' ');
381        }
382        if (l.return_value.size() > 0)
383          l.return_value.erase(l.return_value.size()-1);
384      }
385      rc = 0;
386    }
387  }
388  else rc = 1;
389  if (rc == 0)
390    return_message="OK";
391  else
392    if (return_message == "")
393    {
394      switch (rc)
395      {
396        case stopos_pool::ERROR          : return_message = "ERROR";                                         break;
397        case stopos_pool::NOFILENAME     : return_message = "ERROR: No file name given";                     break;
398        case stopos_pool::OPENERROR      : return_message = "ERROR: Cannot find pool '"      + l.pool + "'"; break;
399        case stopos_pool::STOREERROR     : return_message = "ERROR: Cannot write to pool '"  + l.pool + "'"; break;
400        case stopos_pool::FETCHERROR     : return_message = "ERROR: Cannot read from pool '" + l.pool + "'"; break;
401        case stopos_pool::NOTFOUND       : return_message = "WARNING: Line not found";                       break;
402        case stopos_pool::NOTIMPLEMENTED : return_message = "ERROR: Feature not implemented";                break;
403        case stopos_pool::REMOVEERROR    : return_message = "ERROR: Cannot remove line";                     break;
404        case stopos_pool::LOCKERROR      : return_message = "ERROR: Cannot get lock";                        break;
405        case stopos_pool::CLOSEERROR     : return_message = "ERROR: Cannot close pool '"     + l.pool + "'"; break;
406        case stopos_pool::UNLOCKERROR    : return_message = "ERROR: Cannot unlock pool '"    + l.pool + "'"; break;
407        case stopos_pool::DBNOTOPEN      : return_message = "ERROR: Pool is not opened '"    + l.pool + "'"; break;
408        case stopos_pool::CREATEERROR    : return_message = "ERROR: Cannot create pool '"    + l.pool + "'"; break;
409        case stopos_pool::PURGEERROR     : return_message = "ERROR: Cannot purge pool '"     + l.pool + "'"; break;
410        case stopos_pool::RECORDTOOLONG  : return_message = "ERROR: Record too long";                        break;
411        default                          : return_message = "ERROR";                                         break;
412
413      }
414    }
415 
416
417  output(return_message, key, committed, count,
418         present, present0, l.return_value);
419  return rc;
420}
421
422int main()
423{
424  int rc;
425  std::cout << "Content-Type: text/plain\n\n";
426  std::string line;
427  line = envtostr("QUERY_STRING");
428  if (line.size() >0)
429    if (line[0] == '/')
430      line.erase(0,1);
431
432  commandline l;
433  parsecom(l,line);
434  std::string msg = sanitycheck(l);
435  if (msg != "")
436  {
437    output(msg);
438    return 1;
439  }
440  rc = executecom(l);
441
442  return rc;
443}
Note: See TracBrowser for help on using the repository browser.