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

db_ret.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: db_ret.c,v 12.1 2005/06/16 20:21:14 bostic Exp $
00008  */
00009 
00010 #include "db_config.h"
00011 
00012 #ifndef NO_SYSTEM_INCLUDES
00013 #include <sys/types.h>
00014 
00015 #include <string.h>
00016 #endif
00017 
00018 #include "db_int.h"
00019 #include "dbinc/db_page.h"
00020 #include "dbinc/db_am.h"
00021 
00022 /*
00023  * __db_ret --
00024  *      Build return DBT.
00025  *
00026  * PUBLIC: int __db_ret __P((DB *,
00027  * PUBLIC:    PAGE *, u_int32_t, DBT *, void **, u_int32_t *));
00028  */
00029 int
00030 __db_ret(dbp, h, indx, dbt, memp, memsize)
00031         DB *dbp;
00032         PAGE *h;
00033         u_int32_t indx;
00034         DBT *dbt;
00035         void **memp;
00036         u_int32_t *memsize;
00037 {
00038         BKEYDATA *bk;
00039         HOFFPAGE ho;
00040         BOVERFLOW *bo;
00041         u_int32_t len;
00042         u_int8_t *hk;
00043         void *data;
00044 
00045         switch (TYPE(h)) {
00046         case P_HASH:
00047                 hk = P_ENTRY(dbp, h, indx);
00048                 if (HPAGE_PTYPE(hk) == H_OFFPAGE) {
00049                         memcpy(&ho, hk, sizeof(HOFFPAGE));
00050                         return (__db_goff(dbp, dbt,
00051                             ho.tlen, ho.pgno, memp, memsize));
00052                 }
00053                 len = LEN_HKEYDATA(dbp, h, dbp->pgsize, indx);
00054                 data = HKEYDATA_DATA(hk);
00055                 break;
00056         case P_LBTREE:
00057         case P_LDUP:
00058         case P_LRECNO:
00059                 bk = GET_BKEYDATA(dbp, h, indx);
00060                 if (B_TYPE(bk->type) == B_OVERFLOW) {
00061                         bo = (BOVERFLOW *)bk;
00062                         return (__db_goff(dbp, dbt,
00063                             bo->tlen, bo->pgno, memp, memsize));
00064                 }
00065                 len = bk->len;
00066                 data = bk->data;
00067                 break;
00068         default:
00069                 return (__db_pgfmt(dbp->dbenv, h->pgno));
00070         }
00071 
00072         return (__db_retcopy(dbp->dbenv, dbt, data, len, memp, memsize));
00073 }
00074 
00075 /*
00076  * __db_retcopy --
00077  *      Copy the returned data into the user's DBT, handling special flags.
00078  *
00079  * PUBLIC: int __db_retcopy __P((DB_ENV *, DBT *,
00080  * PUBLIC:    void *, u_int32_t, void **, u_int32_t *));
00081  */
00082 int
00083 __db_retcopy(dbenv, dbt, data, len, memp, memsize)
00084         DB_ENV *dbenv;
00085         DBT *dbt;
00086         void *data;
00087         u_int32_t len;
00088         void **memp;
00089         u_int32_t *memsize;
00090 {
00091         int ret;
00092 
00093         ret = 0;
00094 
00095         /* If returning a partial record, reset the length. */
00096         if (F_ISSET(dbt, DB_DBT_PARTIAL)) {
00097                 data = (u_int8_t *)data + dbt->doff;
00098                 if (len > dbt->doff) {
00099                         len -= dbt->doff;
00100                         if (len > dbt->dlen)
00101                                 len = dbt->dlen;
00102                 } else
00103                         len = 0;
00104         }
00105 
00106         /*
00107          * Allocate memory to be owned by the application: DB_DBT_MALLOC,
00108          * DB_DBT_REALLOC.
00109          *
00110          * !!!
00111          * We always allocate memory, even if we're copying out 0 bytes. This
00112          * guarantees consistency, i.e., the application can always free memory
00113          * without concern as to how many bytes of the record were requested.
00114          *
00115          * Use the memory specified by the application: DB_DBT_USERMEM.
00116          *
00117          * !!!
00118          * If the length we're going to copy is 0, the application-supplied
00119          * memory pointer is allowed to be NULL.
00120          */
00121         if (F_ISSET(dbt, DB_DBT_MALLOC)) {
00122                 ret = __os_umalloc(dbenv, len, &dbt->data);
00123         } else if (F_ISSET(dbt, DB_DBT_REALLOC)) {
00124                 if (dbt->data == NULL || dbt->size == 0 || dbt->size < len)
00125                         ret = __os_urealloc(dbenv, len, &dbt->data);
00126         } else if (F_ISSET(dbt, DB_DBT_USERMEM)) {
00127                 if (len != 0 && (dbt->data == NULL || dbt->ulen < len))
00128                         ret = DB_BUFFER_SMALL;
00129         } else if (memp == NULL || memsize == NULL) {
00130                 ret = EINVAL;
00131         } else {
00132                 if (len != 0 && (*memsize == 0 || *memsize < len)) {
00133                         if ((ret = __os_realloc(dbenv, len, memp)) == 0)
00134                                 *memsize = len;
00135                         else
00136                                 *memsize = 0;
00137                 }
00138                 if (ret == 0)
00139                         dbt->data = *memp;
00140         }
00141 
00142         if (ret == 0 && len != 0)
00143                 memcpy(dbt->data, data, len);
00144 
00145         /*
00146          * Return the length of the returned record in the DBT size field.
00147          * This satisfies the requirement that if we're using user memory
00148          * and insufficient memory was provided, return the amount necessary
00149          * in the size field.
00150          */
00151         dbt->size = len;
00152 
00153         return (ret);
00154 }

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