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 }