]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/lib/tokyocabinet/tcadb.c
ebl Add tokyocabinet source to bacula
[bacula/bacula] / bacula / src / lib / tokyocabinet / tcadb.c
1 /*************************************************************************************************
2  * The abstract database API of Tokyo Cabinet
3  *                                                      Copyright (C) 2006-2008 Mikio Hirabayashi
4  * This file is part of Tokyo Cabinet.
5  * Tokyo Cabinet is free software; you can redistribute it and/or modify it under the terms of
6  * the GNU Lesser General Public License as published by the Free Software Foundation; either
7  * version 2.1 of the License or any later version.  Tokyo Cabinet is distributed in the hope
8  * that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
10  * License for more details.
11  * You should have received a copy of the GNU Lesser General Public License along with Tokyo
12  * Cabinet; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
13  * Boston, MA 02111-1307 USA.
14  *************************************************************************************************/
15
16
17 #include "tcutil.h"
18 #include "tchdb.h"
19 #include "tcbdb.h"
20 #include "tcadb.h"
21 #include "myconf.h"
22
23
24
25 /*************************************************************************************************
26  * API
27  *************************************************************************************************/
28
29
30 /* Create an abstract database object. */
31 TCADB *tcadbnew(void){
32   TCADB *adb;
33   TCMALLOC(adb, sizeof(*adb));
34   adb->name = NULL;
35   adb->mdb = NULL;
36   adb->hdb = NULL;
37   adb->bdb = NULL;
38   adb->capnum = -1;
39   adb->capsiz = -1;
40   adb->capcnt = 0;
41   adb->cur = NULL;
42   return adb;
43 }
44
45
46 /* Delete an abstract database object. */
47 void tcadbdel(TCADB *adb){
48   assert(adb);
49   if(adb->name) tcadbclose(adb);
50   free(adb);
51 }
52
53
54 /* Open an abstract database. */
55 bool tcadbopen(TCADB *adb, const char *name){
56   assert(adb && name);
57   TCLIST *elems = tcstrsplit(name, "#");
58   char *path = tclistshift2(elems);
59   if(!path){
60     tclistdel(elems);
61     return false;
62   }
63   int64_t bnum = -1;
64   int64_t capnum = -1;
65   int64_t capsiz = -1;
66   bool owmode = true;
67   bool ocmode = true;
68   bool otmode = false;
69   bool onlmode = false;
70   bool onbmode = false;
71   int8_t apow = -1;
72   int8_t fpow = -1;
73   bool tlmode = false;
74   bool tdmode = false;
75   int32_t rcnum = -1;
76   int32_t lmemb = -1;
77   int32_t nmemb = -1;
78   int32_t lcnum = -1;
79   int32_t ncnum = -1;
80   int ln = TCLISTNUM(elems);
81   for(int i = 0; i < ln; i++){
82     const char *elem = TCLISTVALPTR(elems, i);
83     char *pv = strchr(elem, '=');
84     if(!pv) continue;
85     *(pv++) = '\0';
86     if(!tcstricmp(elem, "bnum")){
87       bnum = strtoll(pv, NULL, 10);
88     } else if(!tcstricmp(elem, "capnum")){
89       capnum = strtoll(pv, NULL, 10);
90     } else if(!tcstricmp(elem, "capsiz")){
91       capsiz = strtoll(pv, NULL, 10);
92     } else if(!tcstricmp(elem, "mode")){
93       owmode = strchr(pv, 'w') || strchr(pv, 'W');
94       ocmode = strchr(pv, 'c') || strchr(pv, 'C');
95       otmode = strchr(pv, 't') || strchr(pv, 'T');
96       onlmode = strchr(pv, 'e') || strchr(pv, 'E');
97       onbmode = strchr(pv, 'f') || strchr(pv, 'F');
98     } else if(!tcstricmp(elem, "apow")){
99       apow = strtol(pv, NULL, 10);
100     } else if(!tcstricmp(elem, "fpow")){
101       fpow = strtol(pv, NULL, 10);
102     } else if(!tcstricmp(elem, "opts")){
103       if(strchr(pv, 'l') || strchr(pv, 'L')) tlmode = true;
104       if(strchr(pv, 'd') || strchr(pv, 'D')) tdmode = true;
105     } else if(!tcstricmp(elem, "rcnum")){
106       rcnum = strtol(pv, NULL, 10);
107     } else if(!tcstricmp(elem, "lmemb")){
108       lmemb = strtol(pv, NULL, 10);
109     } else if(!tcstricmp(elem, "nmemb")){
110       nmemb = strtol(pv, NULL, 10);
111     } else if(!tcstricmp(elem, "lcnum")){
112       lcnum = strtol(pv, NULL, 10);
113     } else if(!tcstricmp(elem, "ncnum")){
114       ncnum = strtol(pv, NULL, 10);
115     }
116   }
117   tclistdel(elems);
118   if(!tcstricmp(path, "*")){
119     adb->mdb = bnum > 0 ? tcmdbnew2(bnum) : tcmdbnew();
120     adb->capnum = capnum;
121     adb->capsiz = capsiz;
122     adb->capcnt = 0;
123   } else if(tcstribwm(path, ".tch")){
124     TCHDB *hdb = tchdbnew();
125     tchdbsetmutex(hdb);
126     int opts = 0;
127     if(tlmode) opts |= HDBTLARGE;
128     if(tdmode) opts |= HDBTDEFLATE;
129     tchdbtune(hdb, bnum, apow, fpow, opts);
130     tchdbsetcache(hdb, rcnum);
131     int omode = owmode ? HDBOWRITER : HDBOREADER;
132     if(ocmode) omode |= HDBOCREAT;
133     if(otmode) omode |= HDBOTRUNC;
134     if(onlmode) omode |= HDBONOLCK;
135     if(onbmode) omode |= HDBOLCKNB;
136     if(!tchdbopen(hdb, path, omode)){
137       tchdbdel(hdb);
138       free(path);
139       return false;
140     }
141     adb->hdb = hdb;
142   } else if(tcstribwm(path, ".tcb")){
143     TCBDB *bdb = tcbdbnew();
144     tcbdbsetmutex(bdb);
145     int opts = 0;
146     if(tlmode) opts |= BDBTLARGE;
147     if(tdmode) opts |= BDBTDEFLATE;
148     tcbdbtune(bdb, lmemb, nmemb, bnum, apow, fpow, opts);
149     tcbdbsetcache(bdb, lcnum, ncnum);
150     if(capnum > 0) tcbdbsetcapnum(bdb, capnum);
151     int omode = owmode ? BDBOWRITER : BDBOREADER;
152     if(ocmode) omode |= BDBOCREAT;
153     if(otmode) omode |= BDBOTRUNC;
154     if(onlmode) omode |= BDBONOLCK;
155     if(onbmode) omode |= BDBOLCKNB;
156     if(!tcbdbopen(bdb, path, omode)){
157       tcbdbdel(bdb);
158       free(path);
159       return false;
160     }
161     adb->bdb = bdb;
162     adb->cur = tcbdbcurnew(bdb);
163   } else {
164     free(path);
165     return false;
166   }
167   free(path);
168   adb->name = tcstrdup(name);
169   return true;
170 }
171
172
173 /* Close an abstract database object. */
174 bool tcadbclose(TCADB *adb){
175   assert(adb);
176   int err = false;
177   if(!adb->name) return false;
178   if(adb->mdb){
179     tcmdbdel(adb->mdb);
180     adb->mdb = NULL;
181   } else if(adb->hdb){
182     if(!tchdbclose(adb->hdb)) err = true;
183     tchdbdel(adb->hdb);
184     adb->hdb = NULL;
185   } else if(adb->bdb){
186     tcbdbcurdel(adb->cur);
187     if(!tcbdbclose(adb->bdb)) err = true;
188     tcbdbdel(adb->bdb);
189     adb->bdb = NULL;
190   }
191   free(adb->name);
192   adb->name = NULL;
193   return !err;
194 }
195
196
197 /* Store a record into an abstract database object. */
198 bool tcadbput(TCADB *adb, const void *kbuf, int ksiz, const void *vbuf, int vsiz){
199   assert(adb && kbuf && ksiz >= 0 && vbuf && vsiz >= 0);
200   bool err = false;
201   if(adb->mdb){
202     tcmdbput(adb->mdb, kbuf, ksiz, vbuf, vsiz);
203     if(adb->capnum > 0 || adb->capsiz > 0){
204       adb->capcnt++;
205       if((adb->capcnt & 0xff) == 0){
206         if(adb->capnum > 0 && tcmdbrnum(adb->mdb) > adb->capnum) tcmdbcutfront(adb->mdb, 0x100);
207         if(adb->capsiz > 0 && tcmdbmsiz(adb->mdb) > adb->capsiz) tcmdbcutfront(adb->mdb, 0x200);
208       }
209     }
210   } else if(adb->hdb){
211     if(!tchdbput(adb->hdb, kbuf, ksiz, vbuf, vsiz)) err = true;
212   } else if(adb->bdb){
213     if(!tcbdbput(adb->bdb, kbuf, ksiz, vbuf, vsiz)) err = true;
214   } else {
215     err = true;
216   }
217   return !err;
218 }
219
220
221 /* Store a string record into an abstract object. */
222 bool tcadbput2(TCADB *adb, const char *kstr, const char *vstr){
223   assert(adb && kstr && vstr);
224   return tcadbput(adb, kstr, strlen(kstr), vstr, strlen(vstr));
225 }
226
227
228 /* Store a new record into an abstract database object. */
229 bool tcadbputkeep(TCADB *adb, const void *kbuf, int ksiz, const void *vbuf, int vsiz){
230   assert(adb && kbuf && ksiz >= 0 && vbuf && vsiz >= 0);
231   bool err = false;
232   if(adb->mdb){
233     if(tcmdbputkeep(adb->mdb, kbuf, ksiz, vbuf, vsiz)){
234       if(adb->capnum > 0 || adb->capsiz > 0){
235         adb->capcnt++;
236         if((adb->capcnt & 0xff) == 0){
237           if(adb->capnum > 0 && tcmdbrnum(adb->mdb) > adb->capnum) tcmdbcutfront(adb->mdb, 0x100);
238           if(adb->capsiz > 0 && tcmdbmsiz(adb->mdb) > adb->capsiz) tcmdbcutfront(adb->mdb, 0x200);
239         }
240       }
241     } else {
242       err = true;
243     }
244   } else if(adb->hdb){
245     if(!tchdbputkeep(adb->hdb, kbuf, ksiz, vbuf, vsiz)) err = true;
246   } else if(adb->bdb){
247     if(!tcbdbputkeep(adb->bdb, kbuf, ksiz, vbuf, vsiz)) err = true;
248   } else {
249     err = true;
250   }
251   return !err;
252 }
253
254
255 /* Store a new string record into an abstract database object. */
256 bool tcadbputkeep2(TCADB *adb, const char *kstr, const char *vstr){
257   assert(adb && kstr && vstr);
258   return tcadbputkeep(adb, kstr, strlen(kstr), vstr, strlen(vstr));
259 }
260
261
262 /* Concatenate a value at the end of the existing record in an abstract database object. */
263 bool tcadbputcat(TCADB *adb, const void *kbuf, int ksiz, const void *vbuf, int vsiz){
264   assert(adb && kbuf && ksiz >= 0 && vbuf && vsiz >= 0);
265   bool err = false;
266   if(adb->mdb){
267     tcmdbputcat(adb->mdb, kbuf, ksiz, vbuf, vsiz);
268     if(adb->capnum > 0 || adb->capsiz > 0){
269       adb->capcnt++;
270       if((adb->capcnt & 0xff) == 0){
271         if(adb->capnum > 0 && tcmdbrnum(adb->mdb) > adb->capnum) tcmdbcutfront(adb->mdb, 0x100);
272         if(adb->capsiz > 0 && tcmdbmsiz(adb->mdb) > adb->capsiz) tcmdbcutfront(adb->mdb, 0x200);
273       }
274     }
275   } else if(adb->hdb){
276     if(!tchdbputcat(adb->hdb, kbuf, ksiz, vbuf, vsiz)) err = true;
277   } else if(adb->bdb){
278     if(!tcbdbputcat(adb->bdb, kbuf, ksiz, vbuf, vsiz)) err = true;
279   } else {
280     err = true;
281   }
282   return !err;
283 }
284
285
286 /* Concatenate a string value at the end of the existing record in an abstract database object. */
287 bool tcadbputcat2(TCADB *adb, const char *kstr, const char *vstr){
288   assert(adb && kstr && vstr);
289   return tcadbputcat(adb, kstr, strlen(kstr), vstr, strlen(vstr));
290 }
291
292
293 /* Remove a record of an abstract database object. */
294 bool tcadbout(TCADB *adb, const void *kbuf, int ksiz){
295   assert(adb && kbuf && ksiz >= 0);
296   bool err = false;
297   if(adb->mdb){
298     if(!tcmdbout(adb->mdb, kbuf, ksiz)) err = true;
299   } else if(adb->hdb){
300     if(!tchdbout(adb->hdb, kbuf, ksiz)) err = true;
301   } else if(adb->bdb){
302     if(!tcbdbout(adb->bdb, kbuf, ksiz)) err = true;
303   } else {
304     err = true;
305   }
306   return !err;
307 }
308
309
310 /* Remove a string record of an abstract database object. */
311 bool tcadbout2(TCADB *adb, const char *kstr){
312   assert(adb && kstr);
313   return tcadbout(adb, kstr, strlen(kstr));
314 }
315
316
317 /* Retrieve a record in an abstract database object. */
318 void *tcadbget(TCADB *adb, const void *kbuf, int ksiz, int *sp){
319   assert(adb && kbuf && ksiz >= 0 && sp);
320   char *rv;
321   if(adb->mdb){
322     rv = tcmdbget(adb->mdb, kbuf, ksiz, sp);
323   } else if(adb->hdb){
324     rv = tchdbget(adb->hdb, kbuf, ksiz, sp);
325   } else if(adb->bdb){
326     rv = tcbdbget(adb->bdb, kbuf, ksiz, sp);
327   } else {
328     rv = NULL;
329   }
330   return rv;
331 }
332
333
334 /* Retrieve a string record in an abstract database object. */
335 char *tcadbget2(TCADB *adb, const char *kstr){
336   assert(adb && kstr);
337   int vsiz;
338   return tcadbget(adb, kstr, strlen(kstr), &vsiz);
339 }
340
341
342 /* Get the size of the value of a record in an abstract database object. */
343 int tcadbvsiz(TCADB *adb, const void *kbuf, int ksiz){
344   assert(adb && kbuf && ksiz >= 0);
345   int rv;
346   if(adb->mdb){
347     rv = tcmdbvsiz(adb->mdb, kbuf, ksiz);
348   } else if(adb->hdb){
349     rv = tchdbvsiz(adb->hdb, kbuf, ksiz);
350   } else if(adb->bdb){
351     rv = tcbdbvsiz(adb->bdb, kbuf, ksiz);
352   } else {
353     rv = -1;
354   }
355   return rv;
356 }
357
358
359 /* Get the size of the value of a string record in an abstract database object. */
360 int tcadbvsiz2(TCADB *adb, const char *kstr){
361   assert(adb && kstr);
362   return tcadbvsiz(adb, kstr, strlen(kstr));
363 }
364
365
366 /* Initialize the iterator of an abstract database object. */
367 bool tcadbiterinit(TCADB *adb){
368   assert(adb);
369   bool err = false;
370   if(adb->mdb){
371     tcmdbiterinit(adb->mdb);
372   } else if(adb->hdb){
373     if(!tchdbiterinit(adb->hdb)) err = true;
374   } else if(adb->bdb){
375     if(!tcbdbcurfirst(adb->cur)){
376       int ecode = tcbdbecode(adb->bdb);
377       if(ecode != TCESUCCESS && ecode != TCEINVALID && ecode != TCEKEEP && ecode != TCENOREC)
378         err = true;
379     }
380   } else {
381     err = true;
382   }
383   return !err;
384 }
385
386
387 /* Get the next key of the iterator of an abstract database object. */
388 void *tcadbiternext(TCADB *adb, int *sp){
389   assert(adb && sp);
390   char *rv;
391   if(adb->mdb){
392     rv = tcmdbiternext(adb->mdb, sp);
393   } else if(adb->hdb){
394     rv = tchdbiternext(adb->hdb, sp);
395   } else if(adb->bdb){
396     rv = tcbdbcurkey(adb->cur, sp);
397     tcbdbcurnext(adb->cur);
398   } else {
399     rv = NULL;
400   }
401   return rv;
402 }
403
404
405 /* Get the next key string of the iterator of an abstract database object. */
406 char *tcadbiternext2(TCADB *adb){
407   assert(adb);
408   int vsiz;
409   return tcadbiternext(adb, &vsiz);
410 }
411
412
413 /* Get forward matching keys in an abstract database object. */
414 TCLIST *tcadbfwmkeys(TCADB *adb, const void *pbuf, int psiz, int max){
415   assert(adb && pbuf && psiz >= 0);
416   TCLIST *rv;
417   if(adb->mdb){
418     rv = tcmdbfwmkeys(adb->mdb, pbuf, psiz, max);
419   } else if(adb->hdb){
420     rv = tchdbfwmkeys(adb->hdb, pbuf, psiz, max);
421   } else if(adb->bdb){
422     rv = tcbdbfwmkeys(adb->bdb, pbuf, psiz, max);
423   } else {
424     rv = tclistnew();
425   }
426   return rv;
427 }
428
429
430 /* Get forward matching string keys in an abstract database object. */
431 TCLIST *tcadbfwmkeys2(TCADB *adb, const char *pstr, int max){
432   assert(adb && pstr);
433   return tcadbfwmkeys(adb, pstr, strlen(pstr), max);
434 }
435
436
437 /* Synchronize updated contents of an abstract database object with the file and the device. */
438 bool tcadbsync(TCADB *adb){
439   assert(adb);
440   bool err = false;
441   if(adb->mdb){
442     err = true;
443   } else if(adb->hdb){
444     if(!tchdbsync(adb->hdb)) err = true;
445   } else if(adb->bdb){
446     if(!tcbdbsync(adb->bdb)) err = true;
447   } else {
448     err = true;
449   }
450   return !err;
451 }
452
453
454 /* Remove all records of an abstract database object. */
455 bool tcadbvanish(TCADB *adb){
456   assert(adb);
457   bool err = false;
458   if(adb->mdb){
459     tcmdbvanish(adb->mdb);
460   } else if(adb->hdb){
461     if(!tchdbvanish(adb->hdb)) err = true;
462   } else if(adb->bdb){
463     if(!tcbdbvanish(adb->bdb)) err = true;
464   } else {
465     err = true;
466   }
467   return !err;
468 }
469
470
471 /* Copy the database file of an abstract database object. */
472 bool tcadbcopy(TCADB *adb, const char *path){
473   assert(adb && path);
474   bool err = false;
475   if(adb->mdb){
476     err = true;
477   } else if(adb->hdb){
478     if(!tchdbcopy(adb->hdb, path)) err = true;
479   } else if(adb->bdb){
480     if(!tcbdbcopy(adb->bdb, path)) err = true;
481   } else {
482     err = true;
483   }
484   return !err;
485 }
486
487
488 /* Get the number of records of an abstract database object. */
489 uint64_t tcadbrnum(TCADB *adb){
490   assert(adb);
491   uint64_t rv;
492   if(adb->mdb){
493     rv = tcmdbrnum(adb->mdb);
494   } else if(adb->hdb){
495     rv = tchdbrnum(adb->hdb);
496   } else if(adb->bdb){
497     rv = tcbdbrnum(adb->bdb);
498   } else {
499     rv = 0;
500   }
501   return rv;
502 }
503
504
505 /* Get the size of the database of an abstract database object. */
506 uint64_t tcadbsize(TCADB *adb){
507   assert(adb);
508   uint64_t rv;
509   if(adb->mdb){
510     rv = tcmdbmsiz(adb->mdb);
511   } else if(adb->hdb){
512     rv = tchdbfsiz(adb->hdb);
513   } else if(adb->bdb){
514     rv = tcbdbfsiz(adb->bdb);
515   } else {
516     rv = 0;
517   }
518   return rv;
519 }
520
521
522
523 // END OF FILE