1/*- 2 * See the file LICENSE for redistribution information. 3 * 4 * Copyright (c) 1996,2008 Oracle. All rights reserved. 5 * 6 * $Id: db_ret.c,v 12.13 2008/01/08 20:58:10 bostic Exp $ 7 */ 8 9#include "db_config.h" 10 11#include "db_int.h" 12#include "dbinc/db_page.h" 13#include "dbinc/db_am.h" 14 15/* 16 * __db_ret -- 17 * Build return DBT. 18 * 19 * PUBLIC: int __db_ret __P((DB *, DB_THREAD_INFO *, DB_TXN *, 20 * PUBLIC: PAGE *, u_int32_t, DBT *, void **, u_int32_t *)); 21 */ 22int 23__db_ret(dbp, ip, txn, h, indx, dbt, memp, memsize) 24 DB *dbp; 25 DB_THREAD_INFO *ip; 26 DB_TXN *txn; 27 PAGE *h; 28 u_int32_t indx; 29 DBT *dbt; 30 void **memp; 31 u_int32_t *memsize; 32{ 33 BKEYDATA *bk; 34 BOVERFLOW *bo; 35 HOFFPAGE ho; 36 u_int32_t len; 37 u_int8_t *hk; 38 void *data; 39 40 switch (TYPE(h)) { 41 case P_HASH_UNSORTED: 42 case P_HASH: 43 hk = P_ENTRY(dbp, h, indx); 44 if (HPAGE_PTYPE(hk) == H_OFFPAGE) { 45 memcpy(&ho, hk, sizeof(HOFFPAGE)); 46 return (__db_goff(dbp, ip, txn, dbt, 47 ho.tlen, ho.pgno, memp, memsize)); 48 } 49 len = LEN_HKEYDATA(dbp, h, dbp->pgsize, indx); 50 data = HKEYDATA_DATA(hk); 51 break; 52 case P_LBTREE: 53 case P_LDUP: 54 case P_LRECNO: 55 bk = GET_BKEYDATA(dbp, h, indx); 56 if (B_TYPE(bk->type) == B_OVERFLOW) { 57 bo = (BOVERFLOW *)bk; 58 return (__db_goff(dbp, ip, txn, dbt, 59 bo->tlen, bo->pgno, memp, memsize)); 60 } 61 len = bk->len; 62 data = bk->data; 63 break; 64 default: 65 return (__db_pgfmt(dbp->env, h->pgno)); 66 } 67 68 return (__db_retcopy(dbp->env, dbt, data, len, memp, memsize)); 69} 70 71/* 72 * __db_retcopy -- 73 * Copy the returned data into the user's DBT, handling special flags. 74 * 75 * PUBLIC: int __db_retcopy __P((ENV *, DBT *, 76 * PUBLIC: void *, u_int32_t, void **, u_int32_t *)); 77 */ 78int 79__db_retcopy(env, dbt, data, len, memp, memsize) 80 ENV *env; 81 DBT *dbt; 82 void *data; 83 u_int32_t len; 84 void **memp; 85 u_int32_t *memsize; 86{ 87 int ret; 88 89 ret = 0; 90 91 /* If returning a partial record, reset the length. */ 92 if (F_ISSET(dbt, DB_DBT_PARTIAL)) { 93 data = (u_int8_t *)data + dbt->doff; 94 if (len > dbt->doff) { 95 len -= dbt->doff; 96 if (len > dbt->dlen) 97 len = dbt->dlen; 98 } else 99 len = 0; 100 } 101 102 /* 103 * Allocate memory to be owned by the application: DB_DBT_MALLOC, 104 * DB_DBT_REALLOC. 105 * 106 * !!! 107 * We always allocate memory, even if we're copying out 0 bytes. This 108 * guarantees consistency, i.e., the application can always free memory 109 * without concern as to how many bytes of the record were requested. 110 * 111 * Use the memory specified by the application: DB_DBT_USERMEM. 112 * 113 * !!! 114 * If the length we're going to copy is 0, the application-supplied 115 * memory pointer is allowed to be NULL. 116 */ 117 if (F_ISSET(dbt, DB_DBT_USERCOPY)) { 118 dbt->size = len; 119 return (len == 0 ? 0 : env->dbt_usercopy(dbt, 0, data, 120 len, DB_USERCOPY_SETDATA)); 121 122 } else if (F_ISSET(dbt, DB_DBT_MALLOC)) 123 ret = __os_umalloc(env, len, &dbt->data); 124 else if (F_ISSET(dbt, DB_DBT_REALLOC)) { 125 if (dbt->data == NULL || dbt->size == 0 || dbt->size < len) 126 ret = __os_urealloc(env, len, &dbt->data); 127 } else if (F_ISSET(dbt, DB_DBT_USERMEM)) { 128 if (len != 0 && (dbt->data == NULL || dbt->ulen < len)) 129 ret = DB_BUFFER_SMALL; 130 } else if (memp == NULL || memsize == NULL) 131 ret = EINVAL; 132 else { 133 if (len != 0 && (*memsize == 0 || *memsize < len)) { 134 if ((ret = __os_realloc(env, len, memp)) == 0) 135 *memsize = len; 136 else 137 *memsize = 0; 138 } 139 if (ret == 0) 140 dbt->data = *memp; 141 } 142 143 if (ret == 0 && len != 0) 144 memcpy(dbt->data, data, len); 145 146 /* 147 * Return the length of the returned record in the DBT size field. 148 * This satisfies the requirement that if we're using user memory 149 * and insufficient memory was provided, return the amount necessary 150 * in the size field. 151 */ 152 dbt->size = len; 153 154 return (ret); 155} 156