Main Page | Class Hierarchy | Data Structures | Directories | File List | Data Fields | Related Pages

db185.c

00001 /*-
00002  * See the file LICENSE for redistribution information.
00003  *
00004  * Copyright (c) 1996-2005
00005  *      Sleepycat Software.  All rights reserved.
00006  *
00007  * $Id: db185.c,v 12.2 2005/10/06 14:36:51 bostic Exp $
00008  */
00009 
00010 #include "db_config.h"
00011 
00012 #ifndef lint
00013 static const char copyright[] =
00014     "Copyright (c) 1996-2005\nSleepycat Software Inc.  All rights reserved.\n";
00015 #endif
00016 
00017 #ifndef NO_SYSTEM_INCLUDES
00018 #include <sys/types.h>
00019 
00020 #include <fcntl.h>
00021 #include <string.h>
00022 #endif
00023 
00024 #include "db_int.h"
00025 #include "db185_int.h"
00026 
00027 static int      db185_close __P((DB185 *));
00028 static int      db185_compare __P((DB *, const DBT *, const DBT *));
00029 static int      db185_del __P((const DB185 *, const DBT185 *, u_int));
00030 static int      db185_fd __P((const DB185 *));
00031 static int      db185_get __P((const DB185 *, const DBT185 *, DBT185 *, u_int));
00032 static u_int32_t
00033                 db185_hash __P((DB *, const void *, u_int32_t));
00034 static size_t   db185_prefix __P((DB *, const DBT *, const DBT *));
00035 static int      db185_put __P((const DB185 *, DBT185 *, const DBT185 *, u_int));
00036 static int      db185_seq __P((const DB185 *, DBT185 *, DBT185 *, u_int));
00037 static int      db185_sync __P((const DB185 *, u_int));
00038 
00039 /*
00040  * EXTERN: #ifdef _DB185_INT_H_
00041  * EXTERN: DB185 *__db185_open
00042  * EXTERN:     __P((const char *, int, int, DBTYPE, const void *));
00043  * EXTERN: #else
00044  * EXTERN: DB *__db185_open
00045  * EXTERN:     __P((const char *, int, int, DBTYPE, const void *));
00046  * EXTERN: #endif
00047  */
00048 DB185 *
00049 __db185_open(file, oflags, mode, type, openinfo)
00050         const char *file;
00051         int oflags, mode;
00052         DBTYPE type;
00053         const void *openinfo;
00054 {
00055         const BTREEINFO *bi;
00056         const HASHINFO *hi;
00057         const RECNOINFO *ri;
00058         DB *dbp;
00059         DB185 *db185p;
00060         DB_FH *fhp;
00061         int ret;
00062 
00063         dbp = NULL;
00064         db185p = NULL;
00065 
00066         if ((ret = db_create(&dbp, NULL, 0)) != 0)
00067                 goto err;
00068 
00069         if ((ret = __os_calloc(NULL, 1, sizeof(DB185), &db185p)) != 0)
00070                 goto err;
00071 
00072         /*
00073          * !!!
00074          * The DBTYPE enum wasn't initialized in DB 185, so it's off-by-one
00075          * from DB 2.0.
00076          */
00077         switch (type) {
00078         case 0:                                 /* DB_BTREE */
00079                 type = DB_BTREE;
00080                 if ((bi = openinfo) != NULL) {
00081                         if (bi->flags & ~R_DUP)
00082                                 goto einval;
00083                         if (bi->flags & R_DUP)
00084                                 (void)dbp->set_flags(dbp, DB_DUP);
00085                         if (bi->cachesize != 0)
00086                                 (void)dbp->set_cachesize
00087                                     (dbp, 0, bi->cachesize, 0);
00088                         if (bi->minkeypage != 0)
00089                                 (void)dbp->set_bt_minkey(dbp, bi->minkeypage);
00090                         if (bi->psize != 0)
00091                                 (void)dbp->set_pagesize(dbp, bi->psize);
00092                         if (bi->prefix != NULL) {
00093                                 db185p->prefix = bi->prefix;
00094                                 dbp->set_bt_prefix(dbp, db185_prefix);
00095                         }
00096                         if (bi->compare != NULL) {
00097                                 db185p->compare = bi->compare;
00098                                 dbp->set_bt_compare(dbp, db185_compare);
00099                         }
00100                         if (bi->lorder != 0)
00101                                 dbp->set_lorder(dbp, bi->lorder);
00102                 }
00103                 break;
00104         case 1:                                 /* DB_HASH */
00105                 type = DB_HASH;
00106                 if ((hi = openinfo) != NULL) {
00107                         if (hi->bsize != 0)
00108                                 (void)dbp->set_pagesize(dbp, hi->bsize);
00109                         if (hi->ffactor != 0)
00110                                 (void)dbp->set_h_ffactor(dbp, hi->ffactor);
00111                         if (hi->nelem != 0)
00112                                 (void)dbp->set_h_nelem(dbp, hi->nelem);
00113                         if (hi->cachesize != 0)
00114                                 (void)dbp->set_cachesize
00115                                     (dbp, 0, hi->cachesize, 0);
00116                         if (hi->hash != NULL) {
00117                                 db185p->hash = hi->hash;
00118                                 (void)dbp->set_h_hash(dbp, db185_hash);
00119                         }
00120                         if (hi->lorder != 0)
00121                                 dbp->set_lorder(dbp, hi->lorder);
00122                 }
00123 
00124                 break;
00125         case 2:                                 /* DB_RECNO */
00126                 type = DB_RECNO;
00127 
00128                 /* DB 1.85 did renumbering by default. */
00129                 (void)dbp->set_flags(dbp, DB_RENUMBER);
00130 
00131                 /*
00132                  * !!!
00133                  * The file name given to DB 1.85 recno is the name of the DB
00134                  * 2.0 backing file.  If the file doesn't exist, create it if
00135                  * the user has the O_CREAT flag set, DB 1.85 did it for you,
00136                  * and DB 2.0 doesn't.
00137                  *
00138                  * !!!
00139                  * Setting the file name to NULL specifies that we're creating
00140                  * a temporary backing file, in DB 2.X.  If we're opening the
00141                  * DB file read-only, change the flags to read-write, because
00142                  * temporary backing files cannot be opened read-only, and DB
00143                  * 2.X will return an error.  We are cheating here -- if the
00144                  * application does a put on the database, it will succeed --
00145                  * although that would be a stupid thing for the application
00146                  * to do.
00147                  *
00148                  * !!!
00149                  * Note, the file name in DB 1.85 was a const -- we don't do
00150                  * that in DB 2.0, so do that cast.
00151                  */
00152                 if (file != NULL) {
00153                         if (oflags & O_CREAT && __os_exists(file, NULL) != 0)
00154                                 if (__os_openhandle(NULL, file,
00155                                     oflags, mode, &fhp) == 0)
00156                                         (void)__os_closehandle(NULL, fhp);
00157                         (void)dbp->set_re_source(dbp, file);
00158 
00159                         if (O_RDONLY)
00160                                 oflags &= ~O_RDONLY;
00161                         oflags |= O_RDWR;
00162                         file = NULL;
00163                 }
00164 
00165                 if ((ri = openinfo) != NULL) {
00166                         /*
00167                          * !!!
00168                          * We can't support the bfname field.
00169                          */
00170 #define BFMSG \
00171         "Berkeley DB: DB 1.85's recno bfname field is not supported.\n"
00172                         if (ri->bfname != NULL) {
00173                                 dbp->errx(dbp, "%s", BFMSG);
00174                                 goto einval;
00175                         }
00176 
00177                         if (ri->flags & ~(R_FIXEDLEN | R_NOKEY | R_SNAPSHOT))
00178                                 goto einval;
00179                         if (ri->flags & R_FIXEDLEN) {
00180                                 if (ri->bval != 0)
00181                                         (void)dbp->set_re_pad(dbp, ri->bval);
00182                                 if (ri->reclen != 0)
00183                                         (void)dbp->set_re_len(dbp, ri->reclen);
00184                         } else
00185                                 if (ri->bval != 0)
00186                                         (void)dbp->set_re_delim(dbp, ri->bval);
00187 
00188                         /*
00189                          * !!!
00190                          * We ignore the R_NOKEY flag, but that's okay, it was
00191                          * only an optimization that was never implemented.
00192                          */
00193                         if (ri->flags & R_SNAPSHOT)
00194                                 (void)dbp->set_flags(dbp, DB_SNAPSHOT);
00195 
00196                         if (ri->cachesize != 0)
00197                                 (void)dbp->set_cachesize
00198                                     (dbp, 0, ri->cachesize, 0);
00199                         if (ri->psize != 0)
00200                                 (void)dbp->set_pagesize(dbp, ri->psize);
00201                         if (ri->lorder != 0)
00202                                 dbp->set_lorder(dbp, ri->lorder);
00203                 }
00204                 break;
00205         default:
00206                 goto einval;
00207         }
00208 
00209         db185p->close = db185_close;
00210         db185p->del = db185_del;
00211         db185p->fd = db185_fd;
00212         db185p->get = db185_get;
00213         db185p->put = db185_put;
00214         db185p->seq = db185_seq;
00215         db185p->sync = db185_sync;
00216 
00217         /*
00218          * Store a reference so we can indirect from the DB 1.85 structure
00219          * to the underlying DB structure, and vice-versa.  This has to be
00220          * done BEFORE the DB::open method call because the hash callback
00221          * is exercised as part of hash database initialization.
00222          */
00223         db185p->dbp = dbp;
00224         dbp->api_internal = db185p;
00225 
00226         /* Open the database. */
00227         if ((ret = dbp->open(dbp, NULL,
00228             file, NULL, type, __db_oflags(oflags), mode)) != 0)
00229                 goto err;
00230 
00231         /* Create the cursor used for sequential ops. */
00232         if ((ret = dbp->cursor(dbp, NULL, &((DB185 *)db185p)->dbc, 0)) != 0)
00233                 goto err;
00234 
00235         return (db185p);
00236 
00237 einval: ret = EINVAL;
00238 
00239 err:    if (db185p != NULL)
00240                 __os_free(NULL, db185p);
00241         if (dbp != NULL)
00242                 (void)dbp->close(dbp, 0);
00243 
00244         __os_set_errno(ret);
00245         return (NULL);
00246 }
00247 
00248 static int
00249 db185_close(db185p)
00250         DB185 *db185p;
00251 {
00252         DB *dbp;
00253         int ret;
00254 
00255         dbp = db185p->dbp;
00256 
00257         ret = dbp->close(dbp, 0);
00258 
00259         __os_free(NULL, db185p);
00260 
00261         if (ret == 0)
00262                 return (0);
00263 
00264         __os_set_errno(ret);
00265         return (-1);
00266 }
00267 
00268 static int
00269 db185_del(db185p, key185, flags)
00270         const DB185 *db185p;
00271         const DBT185 *key185;
00272         u_int flags;
00273 {
00274         DB *dbp;
00275         DBT key;
00276         int ret;
00277 
00278         dbp = db185p->dbp;
00279 
00280         memset(&key, 0, sizeof(key));
00281         key.data = key185->data;
00282         key.size = key185->size;
00283 
00284         if (flags & ~R_CURSOR)
00285                 goto einval;
00286         if (flags & R_CURSOR)
00287                 ret = db185p->dbc->c_del(db185p->dbc, 0);
00288         else
00289                 ret = dbp->del(dbp, NULL, &key, 0);
00290 
00291         switch (ret) {
00292         case 0:
00293                 return (0);
00294         case DB_NOTFOUND:
00295                 return (1);
00296         }
00297 
00298         if (0) {
00299 einval:         ret = EINVAL;
00300         }
00301         __os_set_errno(ret);
00302         return (-1);
00303 }
00304 
00305 static int
00306 db185_fd(db185p)
00307         const DB185 *db185p;
00308 {
00309         DB *dbp;
00310         int fd, ret;
00311 
00312         dbp = db185p->dbp;
00313 
00314         if ((ret = dbp->fd(dbp, &fd)) == 0)
00315                 return (fd);
00316 
00317         __os_set_errno(ret);
00318         return (-1);
00319 }
00320 
00321 static int
00322 db185_get(db185p, key185, data185, flags)
00323         const DB185 *db185p;
00324         const DBT185 *key185;
00325         DBT185 *data185;
00326         u_int flags;
00327 {
00328         DB *dbp;
00329         DBT key, data;
00330         int ret;
00331 
00332         dbp = db185p->dbp;
00333 
00334         memset(&key, 0, sizeof(key));
00335         key.data = key185->data;
00336         key.size = key185->size;
00337         memset(&data, 0, sizeof(data));
00338         data.data = data185->data;
00339         data.size = data185->size;
00340 
00341         if (flags)
00342                 goto einval;
00343 
00344         switch (ret = dbp->get(dbp, NULL, &key, &data, 0)) {
00345         case 0:
00346                 data185->data = data.data;
00347                 data185->size = data.size;
00348                 return (0);
00349         case DB_NOTFOUND:
00350                 return (1);
00351         }
00352 
00353         if (0) {
00354 einval:         ret = EINVAL;
00355         }
00356         __os_set_errno(ret);
00357         return (-1);
00358 }
00359 
00360 static int
00361 db185_put(db185p, key185, data185, flags)
00362         const DB185 *db185p;
00363         DBT185 *key185;
00364         const DBT185 *data185;
00365         u_int flags;
00366 {
00367         DB *dbp;
00368         DBC *dbcp_put;
00369         DBT key, data;
00370         int ret, t_ret;
00371 
00372         dbp = db185p->dbp;
00373 
00374         memset(&key, 0, sizeof(key));
00375         key.data = key185->data;
00376         key.size = key185->size;
00377         memset(&data, 0, sizeof(data));
00378         data.data = data185->data;
00379         data.size = data185->size;
00380 
00381         switch (flags) {
00382         case 0:
00383                 ret = dbp->put(dbp, NULL, &key, &data, 0);
00384                 break;
00385         case R_CURSOR:
00386                 ret = db185p->dbc->c_put(db185p->dbc, &key, &data, DB_CURRENT);
00387                 break;
00388         case R_IAFTER:
00389         case R_IBEFORE:
00390                 if (dbp->type != DB_RECNO)
00391                         goto einval;
00392 
00393                 if ((ret = dbp->cursor(dbp, NULL, &dbcp_put, 0)) != 0)
00394                         break;
00395                 if ((ret =
00396                     dbcp_put->c_get(dbcp_put, &key, &data, DB_SET)) == 0) {
00397                         memset(&data, 0, sizeof(data));
00398                         data.data = data185->data;
00399                         data.size = data185->size;
00400                         ret = dbcp_put->c_put(dbcp_put, &key, &data,
00401                             flags == R_IAFTER ? DB_AFTER : DB_BEFORE);
00402                 }
00403                 if ((t_ret = dbcp_put->c_close(dbcp_put)) != 0 && ret == 0)
00404                         ret = t_ret;
00405                 break;
00406         case R_NOOVERWRITE:
00407                 ret = dbp->put(dbp, NULL, &key, &data, DB_NOOVERWRITE);
00408                 break;
00409         case R_SETCURSOR:
00410                 if (dbp->type != DB_BTREE && dbp->type != DB_RECNO)
00411                         goto einval;
00412 
00413                 if ((ret = dbp->put(dbp, NULL, &key, &data, 0)) != 0)
00414                         break;
00415                 ret =
00416                     db185p->dbc->c_get(db185p->dbc, &key, &data, DB_SET_RANGE);
00417                 break;
00418         default:
00419                 goto einval;
00420         }
00421 
00422         switch (ret) {
00423         case 0:
00424                 key185->data = key.data;
00425                 key185->size = key.size;
00426                 return (0);
00427         case DB_KEYEXIST:
00428                 return (1);
00429         }
00430 
00431         if (0) {
00432 einval:         ret = EINVAL;
00433         }
00434         __os_set_errno(ret);
00435         return (-1);
00436 }
00437 
00438 static int
00439 db185_seq(db185p, key185, data185, flags)
00440         const DB185 *db185p;
00441         DBT185 *key185, *data185;
00442         u_int flags;
00443 {
00444         DB *dbp;
00445         DBT key, data;
00446         int ret;
00447 
00448         dbp = db185p->dbp;
00449 
00450         memset(&key, 0, sizeof(key));
00451         key.data = key185->data;
00452         key.size = key185->size;
00453         memset(&data, 0, sizeof(data));
00454         data.data = data185->data;
00455         data.size = data185->size;
00456 
00457         switch (flags) {
00458         case R_CURSOR:
00459                 flags = DB_SET_RANGE;
00460                 break;
00461         case R_FIRST:
00462                 flags = DB_FIRST;
00463                 break;
00464         case R_LAST:
00465                 if (dbp->type != DB_BTREE && dbp->type != DB_RECNO)
00466                         goto einval;
00467                 flags = DB_LAST;
00468                 break;
00469         case R_NEXT:
00470                 flags = DB_NEXT;
00471                 break;
00472         case R_PREV:
00473                 if (dbp->type != DB_BTREE && dbp->type != DB_RECNO)
00474                         goto einval;
00475                 flags = DB_PREV;
00476                 break;
00477         default:
00478                 goto einval;
00479         }
00480         switch (ret = db185p->dbc->c_get(db185p->dbc, &key, &data, flags)) {
00481         case 0:
00482                 key185->data = key.data;
00483                 key185->size = key.size;
00484                 data185->data = data.data;
00485                 data185->size = data.size;
00486                 return (0);
00487         case DB_NOTFOUND:
00488                 return (1);
00489         }
00490 
00491         if (0) {
00492 einval:         ret = EINVAL;
00493         }
00494         __os_set_errno(ret);
00495         return (-1);
00496 }
00497 
00498 static int
00499 db185_sync(db185p, flags)
00500         const DB185 *db185p;
00501         u_int flags;
00502 {
00503         DB *dbp;
00504         int ret;
00505 
00506         dbp = db185p->dbp;
00507 
00508         switch (flags) {
00509         case 0:
00510                 break;
00511         case R_RECNOSYNC:
00512                 /*
00513                  * !!!
00514                  * We can't support the R_RECNOSYNC flag.
00515                  */
00516 #define RSMSG \
00517         "Berkeley DB: DB 1.85's R_RECNOSYNC sync flag is not supported.\n"
00518                 dbp->errx(dbp, "%s", RSMSG);
00519                 /* FALLTHROUGH */
00520         default:
00521                 goto einval;
00522         }
00523 
00524         if ((ret = dbp->sync(dbp, 0)) == 0)
00525                 return (0);
00526 
00527         if (0) {
00528 einval:         ret = EINVAL;
00529         }
00530         __os_set_errno(ret);
00531         return (-1);
00532 }
00533 
00534 /*
00535  * db185_compare --
00536  *      Cutout routine to call the user's Btree comparison function.
00537  */
00538 static int
00539 db185_compare(dbp, a, b)
00540         DB *dbp;
00541         const DBT *a, *b;
00542 {
00543         DBT185 a185, b185;
00544 
00545         a185.data = a->data;
00546         a185.size = a->size;
00547         b185.data = b->data;
00548         b185.size = b->size;
00549 
00550         return (((DB185 *)dbp->api_internal)->compare(&a185, &b185));
00551 }
00552 
00553 /*
00554  * db185_prefix --
00555  *      Cutout routine to call the user's Btree prefix function.
00556  */
00557 static size_t
00558 db185_prefix(dbp, a, b)
00559         DB *dbp;
00560         const DBT *a, *b;
00561 {
00562         DBT185 a185, b185;
00563 
00564         a185.data = a->data;
00565         a185.size = a->size;
00566         b185.data = b->data;
00567         b185.size = b->size;
00568 
00569         return (((DB185 *)dbp->api_internal)->prefix(&a185, &b185));
00570 }
00571 
00572 /*
00573  * db185_hash --
00574  *      Cutout routine to call the user's hash function.
00575  */
00576 static u_int32_t
00577 db185_hash(dbp, key, len)
00578         DB *dbp;
00579         const void *key;
00580         u_int32_t len;
00581 {
00582         return (((DB185 *)dbp->api_internal)->hash(key, (size_t)len));
00583 }

Generated on Sun Dec 25 12:14:22 2005 for Berkeley DB 4.4.16 by  doxygen 1.4.2