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 *************************************************************************************************/
25 /*************************************************************************************************
27 *************************************************************************************************/
30 /* Create an abstract database object. */
31 TCADB *tcadbnew(void){
33 TCMALLOC(adb, sizeof(*adb));
46 /* Delete an abstract database object. */
47 void tcadbdel(TCADB *adb){
49 if(adb->name) tcadbclose(adb);
54 /* Open an abstract database. */
55 bool tcadbopen(TCADB *adb, const char *name){
57 TCLIST *elems = tcstrsplit(name, "#");
58 char *path = tclistshift2(elems);
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, '=');
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);
118 if(!tcstricmp(path, "*")){
119 adb->mdb = bnum > 0 ? tcmdbnew2(bnum) : tcmdbnew();
120 adb->capnum = capnum;
121 adb->capsiz = capsiz;
123 } else if(tcstribwm(path, ".tch")){
124 TCHDB *hdb = tchdbnew();
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)){
142 } else if(tcstribwm(path, ".tcb")){
143 TCBDB *bdb = tcbdbnew();
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)){
162 adb->cur = tcbdbcurnew(bdb);
168 adb->name = tcstrdup(name);
173 /* Close an abstract database object. */
174 bool tcadbclose(TCADB *adb){
177 if(!adb->name) return false;
182 if(!tchdbclose(adb->hdb)) err = true;
186 tcbdbcurdel(adb->cur);
187 if(!tcbdbclose(adb->bdb)) err = true;
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);
202 tcmdbput(adb->mdb, kbuf, ksiz, vbuf, vsiz);
203 if(adb->capnum > 0 || adb->capsiz > 0){
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);
211 if(!tchdbput(adb->hdb, kbuf, ksiz, vbuf, vsiz)) err = true;
213 if(!tcbdbput(adb->bdb, kbuf, ksiz, vbuf, vsiz)) err = true;
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));
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);
233 if(tcmdbputkeep(adb->mdb, kbuf, ksiz, vbuf, vsiz)){
234 if(adb->capnum > 0 || adb->capsiz > 0){
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);
245 if(!tchdbputkeep(adb->hdb, kbuf, ksiz, vbuf, vsiz)) err = true;
247 if(!tcbdbputkeep(adb->bdb, kbuf, ksiz, vbuf, vsiz)) err = true;
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));
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);
267 tcmdbputcat(adb->mdb, kbuf, ksiz, vbuf, vsiz);
268 if(adb->capnum > 0 || adb->capsiz > 0){
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);
276 if(!tchdbputcat(adb->hdb, kbuf, ksiz, vbuf, vsiz)) err = true;
278 if(!tcbdbputcat(adb->bdb, kbuf, ksiz, vbuf, vsiz)) err = true;
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));
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);
298 if(!tcmdbout(adb->mdb, kbuf, ksiz)) err = true;
300 if(!tchdbout(adb->hdb, kbuf, ksiz)) err = true;
302 if(!tcbdbout(adb->bdb, kbuf, ksiz)) err = true;
310 /* Remove a string record of an abstract database object. */
311 bool tcadbout2(TCADB *adb, const char *kstr){
313 return tcadbout(adb, kstr, strlen(kstr));
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);
322 rv = tcmdbget(adb->mdb, kbuf, ksiz, sp);
324 rv = tchdbget(adb->hdb, kbuf, ksiz, sp);
326 rv = tcbdbget(adb->bdb, kbuf, ksiz, sp);
334 /* Retrieve a string record in an abstract database object. */
335 char *tcadbget2(TCADB *adb, const char *kstr){
338 return tcadbget(adb, kstr, strlen(kstr), &vsiz);
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);
347 rv = tcmdbvsiz(adb->mdb, kbuf, ksiz);
349 rv = tchdbvsiz(adb->hdb, kbuf, ksiz);
351 rv = tcbdbvsiz(adb->bdb, kbuf, ksiz);
359 /* Get the size of the value of a string record in an abstract database object. */
360 int tcadbvsiz2(TCADB *adb, const char *kstr){
362 return tcadbvsiz(adb, kstr, strlen(kstr));
366 /* Initialize the iterator of an abstract database object. */
367 bool tcadbiterinit(TCADB *adb){
371 tcmdbiterinit(adb->mdb);
373 if(!tchdbiterinit(adb->hdb)) err = true;
375 if(!tcbdbcurfirst(adb->cur)){
376 int ecode = tcbdbecode(adb->bdb);
377 if(ecode != TCESUCCESS && ecode != TCEINVALID && ecode != TCEKEEP && ecode != TCENOREC)
387 /* Get the next key of the iterator of an abstract database object. */
388 void *tcadbiternext(TCADB *adb, int *sp){
392 rv = tcmdbiternext(adb->mdb, sp);
394 rv = tchdbiternext(adb->hdb, sp);
396 rv = tcbdbcurkey(adb->cur, sp);
397 tcbdbcurnext(adb->cur);
405 /* Get the next key string of the iterator of an abstract database object. */
406 char *tcadbiternext2(TCADB *adb){
409 return tcadbiternext(adb, &vsiz);
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);
418 rv = tcmdbfwmkeys(adb->mdb, pbuf, psiz, max);
420 rv = tchdbfwmkeys(adb->hdb, pbuf, psiz, max);
422 rv = tcbdbfwmkeys(adb->bdb, pbuf, psiz, max);
430 /* Get forward matching string keys in an abstract database object. */
431 TCLIST *tcadbfwmkeys2(TCADB *adb, const char *pstr, int max){
433 return tcadbfwmkeys(adb, pstr, strlen(pstr), max);
437 /* Synchronize updated contents of an abstract database object with the file and the device. */
438 bool tcadbsync(TCADB *adb){
444 if(!tchdbsync(adb->hdb)) err = true;
446 if(!tcbdbsync(adb->bdb)) err = true;
454 /* Remove all records of an abstract database object. */
455 bool tcadbvanish(TCADB *adb){
459 tcmdbvanish(adb->mdb);
461 if(!tchdbvanish(adb->hdb)) err = true;
463 if(!tcbdbvanish(adb->bdb)) err = true;
471 /* Copy the database file of an abstract database object. */
472 bool tcadbcopy(TCADB *adb, const char *path){
478 if(!tchdbcopy(adb->hdb, path)) err = true;
480 if(!tcbdbcopy(adb->bdb, path)) err = true;
488 /* Get the number of records of an abstract database object. */
489 uint64_t tcadbrnum(TCADB *adb){
493 rv = tcmdbrnum(adb->mdb);
495 rv = tchdbrnum(adb->hdb);
497 rv = tcbdbrnum(adb->bdb);
505 /* Get the size of the database of an abstract database object. */
506 uint64_t tcadbsize(TCADB *adb){
510 rv = tcmdbmsiz(adb->mdb);
512 rv = tchdbfsiz(adb->hdb);
514 rv = tcbdbfsiz(adb->bdb);