source: trunk/gdbm_pool.cpp

Last change on this file was 17, checked in by willem, 8 years ago

willem

File size: 4.5 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 <string>
19#include <sstream>
20#include <iomanip>
21#include "stopos_pool.h"
22#include "gdbm_pool.h"
23#include "gdbm.h"
24#include <string.h>
25#include <stdlib.h>
26#include "wutils.h"
27#include <algorithm>
28#include <vector>
29#include "stopos.h"
30#include <sys/types.h>
31#include <sys/stat.h>
32#include <fcntl.h>
33#include <unistd.h>
34
35gdbm_pool::gdbm_pool()
36{
37  this->whoami = "gdbm";
38}
39
40gdbm_pool::~gdbm_pool()
41{
42}
43
44int gdbm_pool::create_db(const std::string &dbname)
45{
46  int rc;
47
48  rc = this->purge_db();
49  if (rc != 0)
50    return rc;
51
52  // The db_name can be composed of parts separated with '/'
53  // we try to create this path until the last '/'
54 
55  size_t p = dbname.find_last_of('/');
56  rc = mkdir_p(dbname.substr(0,p+1),0755);
57  if (rc != 0)
58    return CREATEERROR;
59
60  this->dbf = gdbm_open(this->db_name,0,GDBM_NEWDB|this->sync,0644,0);
61
62  if (this->dbf == 0)
63    return this->OPENERROR;
64  this->close_db();
65
66  return 0;
67}
68
69int gdbm_pool::purge_db(void)
70{
71  if (this->db_name == 0)
72    return NOFILENAME;
73
74  this->close_db();
75
76  unlink(db_name);
77
78  return 0;
79}
80
81
82int gdbm_pool::open_db(void)
83{
84
85  if (this->db_open)
86    return 0;
87
88  if (this->db_name == 0)
89    return this->NOFILENAME;
90
91  // not really clear how gdbm signals that a file is not present
92  // so we open de file using open, and close it in close_db
93  //
94  this->ff = open(db_name,O_RDWR);
95  if (this->ff < 0)
96    return OPENERROR;
97
98  // only 'w' is used, left the other part in for future
99  // reference
100
101  // gdbm does not proper locking, somehow.
102  // so we use fcntl to get a lock on the file
103
104  struct flock lock;
105  lock.l_type   = F_RDLCK|F_WRLCK;
106  lock.l_whence = SEEK_SET;
107  lock.l_start  = 0;
108  lock.l_len    = 0;
109
110  int rc;
111
112  rc = fcntl(this->ff,F_SETLKW,&lock);
113  if (rc < 0)
114    return LOCKERROR;
115
116  char rw='w';
117  switch (rw)
118  {
119    case 'r':
120      do
121      {
122        dbf = gdbm_open(this->db_name,0,GDBM_READER,0644,0);
123        if (dbf == 0)
124          usleep(1000);
125      }
126      while (dbf == 0);
127      break;
128    case 'w':
129      do
130      {
131        dbf = gdbm_open(this->db_name,0,GDBM_WRCREAT|this->sync,0644,0);
132        if (dbf == 0)
133          usleep(1000);
134      }
135      while (dbf == 0);
136    break;
137    default:
138      break;
139  }
140  this->db_open = 1;
141  return 0;
142}
143
144int gdbm_pool::close_db(void)
145{
146  if (!db_open) 
147    return 0;
148
149  gdbm_close(this->dbf);
150
151  int rc;
152
153  struct flock lock;
154  lock.l_type   = F_UNLCK;
155  lock.l_whence = SEEK_SET;
156  lock.l_start  = 0;
157  lock.l_len    = 0;
158
159  rc = fcntl(this->ff,F_SETLKW,&lock);
160  if (rc < 0)
161    return UNLOCKERROR;
162
163  rc = close(this->ff);
164  if (rc == -1)
165    return CLOSEERROR;
166
167  this->db_open = 0;
168
169  return 0;
170}
171
172int gdbm_pool::get_record(std::string &r, const std::string &k, const std::string &l)
173{
174  datum key,content;
175  key.dptr = str_to_charp(k);
176  key.dsize = strlen(key.dptr) + 1;
177  content=gdbm_fetch(this->dbf,key);
178  free(key.dptr);
179  if (content.dptr == 0)
180    return this->FETCHERROR;
181
182  r = content.dptr;
183
184  free(content.dptr);
185
186  return 0;
187}
188
189int gdbm_pool::put_record(const std::string &r, const std::string &k, const std::string &l)
190{
191
192  datum key, content;
193  key.dptr = str_to_charp(k);
194  key.dsize = strlen(key.dptr) + 1;
195
196  content.dptr  = str_to_charp(r); 
197  content.dsize = strlen(content.dptr)+ 1;
198  bool rectoolong = 0;
199  /*
200  if (content.dsize > this->reclen)
201  {
202    rectoolong = 1;
203    WTD(this->reclen<<" "<<content.dsize<<" "<<strlen(content.dptr));
204    content.dsize = this->reclen;
205    content.dptr[this->reclen-1] = '\0';
206    WTD(this->reclen<<" "<<content.dsize<<" "<<strlen(content.dptr));
207  }
208  */
209  int rc = gdbm_store(this->dbf, key, content, GDBM_REPLACE);
210  free(content.dptr);
211  free(key.dptr);
212  if (!rectoolong)
213    return rc;
214  return this->RECORDTOOLONG;
215}
216
217int gdbm_pool::remove_record(const std::string &key, const std::string &l)
218{
219  datum k;
220  int rc;
221  k.dptr = str_to_charp(key);
222  k.dsize = strlen(k.dptr) + 1;
223
224  rc = gdbm_delete(this->dbf,k);
225  if (rc !=0)
226    return NOTFOUND;
227  return 0;
228}
229
Note: See TracBrowser for help on using the repository browser.