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

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