db_iface.c

Go to the documentation of this file.
00001 /*-
00002  * See the file LICENSE for redistribution information.
00003  *
00004  * Copyright (c) 1996, 1997, 1998, 1999, 2000
00005  *      Sleepycat Software.  All rights reserved.
00006  */
00007 
00008 #include "config.h"
00009 
00010 #ifndef lint
00011 static const char revid[] = "$Id: db__iface_8c-source.html,v 1.1 2008/06/08 10:17:40 sebdiaz Exp $";
00012 #endif /* not lint */
00013 
00014 #ifndef NO_SYSTEM_INCLUDES
00015 #include <sys/types.h>
00016 
00017 #include <errno.h>
00018 #endif
00019 
00020 #include "db_int.h"
00021 #include "db_page.h"
00022 #include "db_am.h"
00023 #include "btree.h"
00024 
00025 static int __db_curinval __P((const DB_ENV *));
00026 static int __db_rdonly __P((const DB_ENV *, const char *));
00027 static int __dbt_ferr __P((const DB *, const char *, const DBT *, int));
00028 
00029 /*
00030  * CDB___db_cursorchk --
00031  *      Common cursor argument checking routine.
00032  *
00033  * PUBLIC: int CDB___db_cursorchk __P((const DB *, u_int32_t, int));
00034  */
00035 int
00036 CDB___db_cursorchk(dbp, flags, isrdonly)
00037         const DB *dbp;
00038         u_int32_t flags;
00039         int isrdonly;
00040 {
00041         /* Check for invalid function flags. */
00042         switch (flags) {
00043         case 0:
00044                 break;
00045         case DB_WRITECURSOR:
00046                 if (isrdonly)
00047                         return (__db_rdonly(dbp->dbenv, "DB->cursor"));
00048                 if (!LOCKING(dbp->dbenv))
00049                         return (CDB___db_ferr(dbp->dbenv, "DB->cursor", 0));
00050                 break;
00051         case DB_WRITELOCK:
00052                 if (isrdonly)
00053                         return (__db_rdonly(dbp->dbenv, "DB->cursor"));
00054                 break;
00055         default:
00056                 return (CDB___db_ferr(dbp->dbenv, "DB->cursor", 0));
00057         }
00058 
00059         return (0);
00060 }
00061 
00062 /*
00063  * CDB___db_ccountchk --
00064  *      Common cursor count argument checking routine.
00065  *
00066  * PUBLIC: int CDB___db_ccountchk __P((const DB *, u_int32_t, int));
00067  */
00068 int
00069 CDB___db_ccountchk(dbp, flags, isvalid)
00070         const DB *dbp;
00071         u_int32_t flags;
00072         int isvalid;
00073 {
00074         /* Check for invalid function flags. */
00075         switch (flags) {
00076         case 0:
00077                 break;
00078         default:
00079                 return (CDB___db_ferr(dbp->dbenv, "DBcursor->c_count", 0));
00080         }
00081 
00082         /*
00083          * The cursor must be initialized, return EINVAL for an invalid cursor,
00084          * otherwise 0.
00085          */
00086         return (isvalid ? 0 : __db_curinval(dbp->dbenv));
00087 }
00088 
00089 /*
00090  * CDB___db_cdelchk --
00091  *      Common cursor delete argument checking routine.
00092  *
00093  * PUBLIC: int CDB___db_cdelchk __P((const DB *, u_int32_t, int, int));
00094  */
00095 int
00096 CDB___db_cdelchk(dbp, flags, isrdonly, isvalid)
00097         const DB *dbp;
00098         u_int32_t flags;
00099         int isrdonly, isvalid;
00100 {
00101         /* Check for changes to a read-only tree. */
00102         if (isrdonly)
00103                 return (__db_rdonly(dbp->dbenv, "c_del"));
00104 
00105         /* Check for invalid function flags. */
00106         switch (flags) {
00107         case 0:
00108                 break;
00109         default:
00110                 return (CDB___db_ferr(dbp->dbenv, "DBcursor->c_del", 0));
00111         }
00112 
00113         /*
00114          * The cursor must be initialized, return EINVAL for an invalid cursor,
00115          * otherwise 0.
00116          */
00117         return (isvalid ? 0 : __db_curinval(dbp->dbenv));
00118 }
00119 
00120 /*
00121  * CDB___db_cgetchk --
00122  *      Common cursor get argument checking routine.
00123  *
00124  * PUBLIC: int CDB___db_cgetchk __P((const DB *, DBT *, DBT *, u_int32_t, int));
00125  */
00126 int
00127 CDB___db_cgetchk(dbp, key, data, flags, isvalid)
00128         const DB *dbp;
00129         DBT *key, *data;
00130         u_int32_t flags;
00131         int isvalid;
00132 {
00133         int key_einval, ret;
00134 
00135         key_einval = 0;
00136 
00137         /*
00138          * Check for read-modify-write validity.  DB_RMW doesn't make sense
00139          * with CDB cursors since if you're going to write the cursor, you
00140          * had to create it with DB_WRITECURSOR.  Regardless, we check for
00141          * LOCKING_ON and not STD_LOCKING, as we don't want to disallow it.
00142          * If this changes, confirm that DB does not itself set the DB_RMW
00143          * flag in a path where CDB may have been configured.
00144          */
00145         if (LF_ISSET(DB_RMW)) {
00146                 if (!LOCKING_ON(dbp->dbenv)) {
00147                         CDB___db_err(dbp->dbenv,
00148                             "the DB_RMW flag requires locking");
00149                         return (EINVAL);
00150                 }
00151                 LF_CLR(DB_RMW);
00152         }
00153 
00154         /* Check for invalid function flags. */
00155         switch (flags) {
00156         case DB_CONSUME:
00157                 if (dbp->type != DB_QUEUE)
00158                         goto err;
00159                 break;
00160         case DB_CURRENT:
00161         case DB_FIRST:
00162         case DB_LAST:
00163         case DB_NEXT:
00164         case DB_NEXT_DUP:
00165         case DB_NEXT_NODUP:
00166         case DB_PREV:
00167         case DB_PREV_NODUP:
00168                 break;
00169         case DB_GET_BOTHC:
00170                 if (dbp->type == DB_QUEUE)
00171                         goto err;
00172                 /* FALLTHROUGH */
00173         case DB_GET_BOTH:
00174         case DB_SET:
00175         case DB_SET_RANGE:
00176                 key_einval = 1;
00177                 break;
00178         case DB_GET_RECNO:
00179                 if (!F_ISSET(dbp, DB_BT_RECNUM))
00180                         goto err;
00181                 break;
00182         case DB_SET_RECNO:
00183                 if (!F_ISSET(dbp, DB_BT_RECNUM))
00184                         goto err;
00185                 key_einval = 1;
00186                 break;
00187         default:
00188 err:            return (CDB___db_ferr(dbp->dbenv, "DBcursor->c_get", 0));
00189         }
00190 
00191         /* Check for invalid key/data flags. */
00192         if ((ret = __dbt_ferr(dbp, "key", key, 0)) != 0)
00193                 return (ret);
00194         if ((ret = __dbt_ferr(dbp, "data", data, 0)) != 0)
00195                 return (ret);
00196 
00197         /*
00198          * The cursor must be initialized for DB_CURRENT or DB_NEXT_DUP,
00199          * return EINVAL for an invalid cursor, otherwise 0.
00200          */
00201         if (isvalid || (flags != DB_CURRENT && flags != DB_NEXT_DUP))
00202                 return (0);
00203 
00204         return(__db_curinval(dbp->dbenv));
00205 }
00206 
00207 /*
00208  * CDB___db_cputchk --
00209  *      Common cursor put argument checking routine.
00210  *
00211  * PUBLIC: int CDB___db_cputchk __P((const DB *,
00212  * PUBLIC:    const DBT *, DBT *, u_int32_t, int, int));
00213  */
00214 int
00215 CDB___db_cputchk(dbp, key, data, flags, isrdonly, isvalid)
00216         const DB *dbp;
00217         const DBT *key;
00218         DBT *data;
00219         u_int32_t flags;
00220         int isrdonly, isvalid;
00221 {
00222         int key_einval, key_flags, ret;
00223 
00224         key_einval = key_flags = 0;
00225 
00226         /* Check for changes to a read-only tree. */
00227         if (isrdonly)
00228                 return (__db_rdonly(dbp->dbenv, "c_put"));
00229 
00230         /* Check for invalid function flags. */
00231         switch (flags) {
00232         case DB_AFTER:
00233         case DB_BEFORE:
00234                 switch (dbp->type) {
00235                 case DB_BTREE:
00236                 case DB_HASH:           /* Only with unsorted duplicates. */
00237                         if (!F_ISSET(dbp, DB_AM_DUP))
00238                                 goto err;
00239                         if (dbp->dup_compare != NULL)
00240                                 goto err;
00241                         break;
00242                 case DB_QUEUE:          /* Not permitted. */
00243                         goto err;
00244                 case DB_RECNO:          /* Only with mutable record numbers. */
00245                         if (!F_ISSET(dbp, DB_RE_RENUMBER))
00246                                 goto err;
00247                         key_flags = 1;
00248                         break;
00249                 default:
00250                         goto err;
00251                 }
00252                 break;
00253         case DB_CURRENT:
00254                 /*
00255                  * If there is a comparison function, doing a DB_CURRENT
00256                  * must not change the part of the data item that is used
00257                  * for the comparison.
00258                  */
00259                 break;
00260         case DB_NODUPDATA:
00261                 if (!F_ISSET(dbp, DB_AM_DUPSORT))
00262                         goto err;
00263                 /* FALLTHROUGH */
00264         case DB_KEYFIRST:
00265         case DB_KEYLAST:
00266                 if (dbp->type == DB_QUEUE || dbp->type == DB_RECNO)
00267                         goto err;
00268                 key_einval = key_flags = 1;
00269                 break;
00270         default:
00271 err:            return (CDB___db_ferr(dbp->dbenv, "DBcursor->c_put", 0));
00272         }
00273 
00274         /* Check for invalid key/data flags. */
00275         if (key_flags && (ret = __dbt_ferr(dbp, "key", key, 0)) != 0)
00276                 return (ret);
00277         if ((ret = __dbt_ferr(dbp, "data", data, 0)) != 0)
00278                 return (ret);
00279 
00280         /*
00281          * The cursor must be initialized for anything other than DB_KEYFIRST
00282          * and DB_KEYLAST, return EINVAL for an invalid cursor, otherwise 0.
00283          */
00284         if (isvalid || flags == DB_KEYFIRST ||
00285             flags == DB_KEYLAST || flags == DB_NODUPDATA)
00286                 return (0);
00287 
00288         return (__db_curinval(dbp->dbenv));
00289 }
00290 
00291 /*
00292  * CDB___db_closechk --
00293  *      DB->close flag check.
00294  *
00295  * PUBLIC: int CDB___db_closechk __P((const DB *, u_int32_t));
00296  */
00297 int
00298 CDB___db_closechk(dbp, flags)
00299         const DB *dbp;
00300         u_int32_t flags;
00301 {
00302         /* Check for invalid function flags. */
00303         switch (flags) {
00304         case 0:
00305         case DB_NOSYNC:
00306                 break;
00307         default:
00308                 return (CDB___db_ferr(dbp->dbenv, "DB->close", 0));
00309         }
00310 
00311         return (0);
00312 }
00313 
00314 /*
00315  * CDB___db_delchk --
00316  *      Common delete argument checking routine.
00317  *
00318  * PUBLIC: int CDB___db_delchk __P((const DB *, DBT *, u_int32_t, int));
00319  */
00320 int
00321 CDB___db_delchk(dbp, key, flags, isrdonly)
00322         const DB *dbp;
00323         DBT *key;
00324         u_int32_t flags;
00325         int isrdonly;
00326 {
00327         COMPQUIET(key, NULL);
00328 
00329         /* Check for changes to a read-only tree. */
00330         if (isrdonly)
00331                 return (__db_rdonly(dbp->dbenv, "delete"));
00332 
00333         /* Check for invalid function flags. */
00334         switch (flags) {
00335         case 0:
00336                 break;
00337         default:
00338                 return (CDB___db_ferr(dbp->dbenv, "DB->del", 0));
00339         }
00340 
00341         return (0);
00342 }
00343 
00344 /*
00345  * CDB___db_getchk --
00346  *      Common get argument checking routine.
00347  *
00348  * PUBLIC: int CDB___db_getchk __P((const DB *, const DBT *, DBT *, u_int32_t));
00349  */
00350 int
00351 CDB___db_getchk(dbp, key, data, flags)
00352         const DB *dbp;
00353         const DBT *key;
00354         DBT *data;
00355         u_int32_t flags;
00356 {
00357         int ret;
00358 
00359         /*
00360          * Check for read-modify-write validity.  DB_RMW doesn't make sense
00361          * with CDB cursors since if you're going to write the cursor, you
00362          * had to create it with DB_WRITECURSOR.  Regardless, we check for
00363          * LOCKING_ON and not STD_LOCKING, as we don't want to disallow it.
00364          * If this changes, confirm that DB does not itself set the DB_RMW
00365          * flag in a path where CDB may have been configured.
00366          */
00367         if (LF_ISSET(DB_RMW)) {
00368                 if (!LOCKING_ON(dbp->dbenv)) {
00369                         CDB___db_err(dbp->dbenv,
00370                             "the DB_RMW flag requires locking");
00371                         return (EINVAL);
00372                 }
00373                 LF_CLR(DB_RMW);
00374         }
00375 
00376         /* Check for invalid function flags. */
00377         switch (flags) {
00378         case 0:
00379         case DB_GET_BOTH:
00380                 break;
00381         case DB_SET_RECNO:
00382                 if (!F_ISSET(dbp, DB_BT_RECNUM))
00383                         goto err;
00384                 break;
00385         default:
00386 err:            return (CDB___db_ferr(dbp->dbenv, "DB->get", 0));
00387         }
00388 
00389         /* Check for invalid key/data flags. */
00390         if ((ret = __dbt_ferr(dbp, "key", key, flags == DB_SET_RECNO)) != 0)
00391                 return (ret);
00392         if ((ret = __dbt_ferr(dbp, "data", data, 1)) != 0)
00393                 return (ret);
00394 
00395         return (0);
00396 }
00397 
00398 /*
00399  * CDB___db_joinchk --
00400  *      Common join argument checking routine.
00401  *
00402  * PUBLIC: int CDB___db_joinchk __P((const DB *, u_int32_t));
00403  */
00404 int
00405 CDB___db_joinchk(dbp, flags)
00406         const DB *dbp;
00407         u_int32_t flags;
00408 {
00409         switch (flags) {
00410         case 0:
00411         case DB_JOIN_NOSORT:
00412                 break;
00413         default:
00414                 return (CDB___db_ferr(dbp->dbenv, "DB->join", 0));
00415         }
00416 
00417         return (0);
00418 }
00419 
00420 /*
00421  * CDB___db_joingetchk --
00422  *      Common join_get argument checking routine.
00423  *
00424  * PUBLIC: int CDB___db_joingetchk __P((const DB *, DBT *, u_int32_t));
00425  */
00426 int
00427 CDB___db_joingetchk(dbp, key, flags)
00428         const DB *dbp;
00429         DBT *key;
00430         u_int32_t flags;
00431 {
00432 
00433         if (LF_ISSET(DB_RMW)) {
00434                 if (!LOCKING_ON(dbp->dbenv)) {
00435                         CDB___db_err(dbp->dbenv,
00436                             "the DB_RMW flag requires locking");
00437                         return (EINVAL);
00438                 }
00439                 LF_CLR(DB_RMW);
00440         }
00441 
00442         switch (flags) {
00443         case 0:
00444         case DB_JOIN_ITEM:
00445                 break;
00446         default:
00447                 return (CDB___db_ferr(dbp->dbenv, "DBcursor->c_get", 0));
00448         }
00449 
00450         /*
00451          * A partial get of the key of a join cursor don't make much sense;
00452          * the entire key is necessary to query the primary database
00453          * and find the datum, and so regardless of the size of the key
00454          * it would not be a performance improvement.  Since it would require
00455          * special handling, we simply disallow it.
00456          *
00457          * A partial get of the data, however, potentially makes sense (if
00458          * all possible data are a predictable large structure, for instance)
00459          * and causes us no headaches, so we permit it.
00460          */
00461         if (F_ISSET(key, DB_DBT_PARTIAL)) {
00462                 CDB___db_err(dbp->dbenv,
00463                     "DB_DBT_PARTIAL may not be set on key during join_get");
00464                 return (EINVAL);
00465         }
00466 
00467         return (0);
00468 }
00469 
00470 /*
00471  * CDB___db_putchk --
00472  *      Common put argument checking routine.
00473  *
00474  * PUBLIC: int CDB___db_putchk
00475  * PUBLIC:    __P((const DB *, DBT *, const DBT *, u_int32_t, int, int));
00476  */
00477 int
00478 CDB___db_putchk(dbp, key, data, flags, isrdonly, isdup)
00479         const DB *dbp;
00480         DBT *key;
00481         const DBT *data;
00482         u_int32_t flags;
00483         int isrdonly, isdup;
00484 {
00485         int key_einval, key_flags, ret;
00486 
00487         key_einval = key_flags = 0;
00488 
00489         /* Check for changes to a read-only tree. */
00490         if (isrdonly)
00491                 return (__db_rdonly(dbp->dbenv, "put"));
00492 
00493         /* Check for invalid function flags. */
00494         switch (flags) {
00495         case 0:
00496         case DB_NOOVERWRITE:
00497                 key_einval = key_flags = 1;
00498                 break;
00499         case DB_APPEND:
00500                 if (dbp->type != DB_RECNO && dbp->type != DB_QUEUE)
00501                         goto err;
00502                 key_flags = 1;
00503                 break;
00504         case DB_NODUPDATA:
00505                 if (F_ISSET(dbp, DB_AM_DUPSORT))
00506                         break;
00507                 /* FALLTHROUGH */
00508         default:
00509 err:            return (CDB___db_ferr(dbp->dbenv, "DB->put", 0));
00510         }
00511 
00512         /* Check for invalid key/data flags. */
00513         if (key_flags && (ret = __dbt_ferr(dbp, "key", key, 0)) != 0)
00514                 return (ret);
00515         if ((ret = __dbt_ferr(dbp, "data", data, 0)) != 0)
00516                 return (ret);
00517 
00518         /* Check for partial puts in the presence of duplicates. */
00519         if (isdup && F_ISSET(data, DB_DBT_PARTIAL)) {
00520                 CDB___db_err(dbp->dbenv,
00521 "a partial put in the presence of duplicates requires a cursor operation");
00522                 return (EINVAL);
00523         }
00524 
00525         return (0);
00526 }
00527 
00528 /*
00529  * CDB___db_removechk --
00530  *      DB->remove flag check.
00531  *
00532  * PUBLIC: int CDB___db_removechk __P((const DB *, u_int32_t));
00533  */
00534 int
00535 CDB___db_removechk(dbp, flags)
00536         const DB *dbp;
00537         u_int32_t flags;
00538 {
00539         /* Check for invalid function flags. */
00540         switch (flags) {
00541         case 0:
00542                 break;
00543         default:
00544                 return (CDB___db_ferr(dbp->dbenv, "DB->remove", 0));
00545         }
00546 
00547         return (0);
00548 }
00549 
00550 /*
00551  * CDB___db_statchk --
00552  *      Common stat argument checking routine.
00553  *
00554  * PUBLIC: int CDB___db_statchk __P((const DB *, u_int32_t));
00555  */
00556 int
00557 CDB___db_statchk(dbp, flags)
00558         const DB *dbp;
00559         u_int32_t flags;
00560 {
00561         /* Check for invalid function flags. */
00562         switch (flags) {
00563         case 0:
00564         case DB_CACHED_COUNTS:
00565                 break;
00566         case DB_RECORDCOUNT:
00567                 if (dbp->type == DB_RECNO)
00568                         break;
00569                 if (dbp->type == DB_BTREE && F_ISSET(dbp, DB_BT_RECNUM))
00570                         break;
00571                 goto err;
00572         default:
00573 err:            return (CDB___db_ferr(dbp->dbenv, "DB->stat", 0));
00574         }
00575 
00576         return (0);
00577 }
00578 
00579 /*
00580  * CDB___db_syncchk --
00581  *      Common sync argument checking routine.
00582  *
00583  * PUBLIC: int CDB___db_syncchk __P((const DB *, u_int32_t));
00584  */
00585 int
00586 CDB___db_syncchk(dbp, flags)
00587         const DB *dbp;
00588         u_int32_t flags;
00589 {
00590         /* Check for invalid function flags. */
00591         switch (flags) {
00592         case 0:
00593                 break;
00594         default:
00595                 return (CDB___db_ferr(dbp->dbenv, "DB->sync", 0));
00596         }
00597 
00598         return (0);
00599 }
00600 
00601 /*
00602  * __dbt_ferr --
00603  *      Check a DBT for flag errors.
00604  */
00605 static int
00606 __dbt_ferr(dbp, name, dbt, check_thread)
00607         const DB *dbp;
00608         const char *name;
00609         const DBT *dbt;
00610         int check_thread;
00611 {
00612         DB_ENV *dbenv;
00613         int ret;
00614 
00615         dbenv = dbp->dbenv;
00616 
00617         /*
00618          * Check for invalid DBT flags.  We allow any of the flags to be
00619          * specified to any DB or DBcursor call so that applications can
00620          * set DB_DBT_MALLOC when retrieving a data item from a secondary
00621          * database and then specify that same DBT as a key to a primary
00622          * database, without having to clear flags.
00623          */
00624         if ((ret = CDB___db_fchk(dbenv, name, dbt->flags,
00625             DB_DBT_MALLOC | DB_DBT_DUPOK |
00626             DB_DBT_REALLOC | DB_DBT_USERMEM | DB_DBT_PARTIAL)) != 0)
00627                 return (ret);
00628         switch (F_ISSET(dbt, DB_DBT_MALLOC | DB_DBT_REALLOC | DB_DBT_USERMEM)) {
00629         case 0:
00630         case DB_DBT_MALLOC:
00631         case DB_DBT_REALLOC:
00632         case DB_DBT_USERMEM:
00633                 break;
00634         default:
00635                 return (CDB___db_ferr(dbenv, name, 1));
00636         }
00637 
00638         if (check_thread && DB_IS_THREADED(dbp) &&
00639             !F_ISSET(dbt, DB_DBT_MALLOC | DB_DBT_REALLOC | DB_DBT_USERMEM)) {
00640                 CDB___db_err(dbenv,
00641                     "DB_THREAD mandates memory allocation flag on DBT %s",
00642                     name);
00643                 return (EINVAL);
00644         }
00645         return (0);
00646 }
00647 
00648 /*
00649  * __db_rdonly --
00650  *      Common readonly message.
00651  */
00652 static int
00653 __db_rdonly(dbenv, name)
00654         const DB_ENV *dbenv;
00655         const char *name;
00656 {
00657         CDB___db_err(dbenv, "%s: attempt to modify a read-only tree", name);
00658         return (EACCES);
00659 }
00660 
00661 /*
00662  * __db_curinval
00663  *      Report that a cursor is in an invalid state.
00664  */
00665 static int
00666 __db_curinval(dbenv)
00667         const DB_ENV *dbenv;
00668 {
00669         CDB___db_err(dbenv,
00670             "Cursor position must be set before performing this operation");
00671         return (EINVAL);
00672 }

Generated on Sun Jun 8 10:56:36 2008 for GNUmifluz by  doxygen 1.5.5