source: tags/0.9/gdbm_pool.cpp @ 9

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

willem

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