source: tags/0.58/flatfile_pool.cpp @ 9

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

willem

File size: 5.2 KB
Line 
1#include "stopos_pool.h"
2#include "flatfile_pool.h"
3#include <sys/types.h>
4#include <sys/stat.h>
5#include <errno.h>
6#include <fcntl.h>
7#include <stdlib.h>
8#include "wutils.h"
9#include <string.h>
10#include <strings.h>
11#include <stdio.h>
12#include <algorithm>
13#include "stopos.h"
14
15//
16// this->status.extra is always pointing to
17// the first free slot
18//
19// records are stored thusly:
20// character to denote if this record exists or is deleted
21// dbsep
22//
23//   for a not deleted record, next fields:
24//   key for this record
25//   dbsep
26//   1st parameter of put_record
27//
28//   for a deleted record:
29//   pointer to next deleted record
30//
31
32// constructor
33flatfile_pool::flatfile_pool()
34{
35  this->whoami = "flat";
36  this->statuskey.set_slot(this->statuskey.get_key());
37}
38
39std::string flatfile_pool::key_to_slot(const std::string &k)
40{
41
42  if (strtoslot(this->status.extra) == 0)
43    return k;
44
45  std::string slot = this->status.extra;
46  std::string r;
47  off_t p = strtoslot(slot)*this->reclen;
48  this->read_string(r, p);
49  this->status.extra = r.substr(2);
50
51  return slot;
52}
53
54off_t flatfile_pool::strtoslot(const std::string &s)
55{
56  return stopos_key::KeyToNumber(s);
57}
58
59std::string flatfile_pool::slottostr(off_t l)
60{
61  return stopos_key::NumberToKey(l);
62}
63
64int flatfile_pool::haskey(std::string &r, const std::string &k)
65{
66  size_t q1 = 1; 
67  // find second separator. The first one is on postion 1
68  size_t q2 = r.find(dbsep,2);
69
70  std::string key = r.substr(q1+1,q2-q1-1);
71  if (key != k)
72    return this->NOTFOUND;
73  r.erase(0,q2+1);
74  return 0;
75}
76
77int flatfile_pool::get_record(std::string &r, const std::string &k, const std::string &l)
78{
79  int rc;
80
81  off_t p = this->strtoslot(l)*reclen;
82
83  rc = this->read_string(r,p);
84  if (rc !=0 )
85    return rc;
86
87  if (r[0] == this->deleted)
88    return this->NOTFOUND;
89
90  // this record was not deleted, but it could be that
91  // the key does not match
92  //
93
94  rc = this->haskey(r,k);
95  if (rc != 0)
96    return rc;
97
98  return 0;
99}
100
101int flatfile_pool::put_record(const std::string &r, 
102                              const std::string &k,
103                              const std::string &l)
104{
105  std::string buf;
106
107  buf = buf + this->exists + dbsep + k + dbsep + r;
108
109  if (buf.size() >= this->reclen) // >= because we need place for
110                                  // end-of-string zero
111    return RECORDTOOLONG;
112
113  off_t p = this->strtoslot(l)*reclen;
114
115  return this->write_string(buf,p);
116}
117
118int flatfile_pool::remove_record(const std::string &k, const std::string &l)
119{
120  int rc;
121
122  off_t p = this->strtoslot(l)*reclen;
123
124  std::string r;
125  rc = this->read_string(r,p);
126  if (rc != 0)
127    return rc;
128
129  rc = haskey(r,k);
130  if (rc != 0)
131    return rc;
132
133  r = this->deleted;
134
135  if (status.extra == slottostr(0))
136    r = r + dbsep + slottostr(0);
137  else
138    r = r + dbsep + status.extra;
139  status.extra = l;
140
141  return this->write_string(r,p);
142}
143
144int flatfile_pool::read_string(std::string &r, off_t p)
145{
146
147  char b[this->reclen];
148  off_t rc;
149  rc = lseek(this->ff, p, SEEK_SET);
150  if (rc == -1)
151    return FETCHERROR;
152
153  ssize_t rc1;
154  rc1 = read(this->ff, b, this->reclen);
155  if (rc1 != this->reclen)
156    return FETCHERROR;
157
158  r = b;
159
160  return 0;
161}
162
163
164int flatfile_pool::write_string(const std::string &r, off_t p)
165{
166  int rc;
167  char b[this->reclen];
168
169  rc = lseek(this->ff,p,SEEK_SET);
170  if (rc == -1)
171    return STOREERROR;
172
173  bzero(b, this->reclen);
174  strncpy(b,r.c_str(),r.size());
175  ssize_t first = 0;
176  ssize_t togo  = this->reclen;
177  ssize_t written;
178
179  do
180  {
181    written = write(ff,&b[first],togo);
182    if (written == -1)
183    {
184      perror("write:");
185      return 2;
186    }
187    togo   -= written;
188    first  += written;
189  } while(togo !=0);
190
191  return 0;
192}
193
194
195int flatfile_pool::create_db(const std::string &dbname)
196{
197  int rc; 
198
199  rc = this->purge_db();
200  if (rc != 0)
201    return rc;
202
203  // The db_name can be composed of parts separated with '/'
204  // we try to create this path until the last '/'
205 
206  size_t p = dbname.find_last_of('/');
207  rc = mkdir_p(dbname.substr(0,p+1),0755);
208  if (rc != 0)
209    return CREATEERROR;
210
211  rc = this->open_db();
212  if (rc != 0)
213    return rc;
214  this->close_db();
215
216  this->status.extra = stopos_key::NumberToKey(0);
217
218  return 0;
219}
220
221int flatfile_pool::purge_db(void)
222{
223  if (this->db_name == 0)
224    return NOFILENAME;
225
226  this->close_db();
227
228  unlink(this->db_name);
229  return 0;
230}
231
232int flatfile_pool::open_db(void)
233{
234  int rc;
235
236  if (this->db_name == 0)
237    return NOFILENAME;
238
239  if (this->db_open)
240    return 0;
241
242  this->ff = open(this->db_name, O_CREAT|O_RDWR,0644);
243  if (this->ff < 0)
244    return OPENERROR;
245
246  struct flock lock;
247  lock.l_type   = F_RDLCK|F_WRLCK;
248  lock.l_whence = SEEK_SET;
249  lock.l_start  = 0;
250  lock.l_len    = 0;
251
252  rc = fcntl(this->ff,F_SETLKW,&lock);
253  if (rc < 0)
254    return LOCKERROR;
255
256  this->db_open = 1;
257
258  return 0;
259}
260
261int flatfile_pool::close_db(void)
262{
263  if (!this->db_open)
264     return 0;
265
266  int rc;
267
268  struct flock lock;
269  lock.l_type   = F_UNLCK;
270  lock.l_whence = SEEK_SET;
271  lock.l_start  = 0;
272  lock.l_len    = 0;
273
274  rc = fcntl(this->ff,F_SETLKW,&lock);
275  if (rc < 0)
276    return UNLOCKERROR;
277
278  rc = close(this->ff);
279  if (rc == -1)
280    return CLOSEERROR;
281
282  this->db_open = 0;
283
284  return 0;
285}
286
287void flatfile_pool::dump_db(void)
288{
289  std::string r;
290  off_t n = 1;
291
292  while (read_string(r,n*this->reclen)==0)
293  {
294    std::cerr << r << std::endl;
295    n++;
296  }
297}
Note: See TracBrowser for help on using the repository browser.