db

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

AltStyle によって変換されたページ (->オリジナル) /