00001
00002
00003
00004
00005
00006
00007
00008
00009
00010 #include "db_config.h"
00011
00012 #ifndef NO_SYSTEM_INCLUDES
00013 #include <sys/types.h>
00014 #include <string.h>
00015 #endif
00016
00017 #include "db_int.h"
00018 #include "dbinc/db_page.h"
00019 #include "dbinc/db_shash.h"
00020 #include "dbinc/btree.h"
00021 #include "dbinc/mp.h"
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034 int
00035 __db_traverse_big(dbp, pgno, callback, cookie)
00036 DB *dbp;
00037 db_pgno_t pgno;
00038 int (*callback) __P((DB *, PAGE *, void *, int *));
00039 void *cookie;
00040 {
00041 DB_MPOOLFILE *mpf;
00042 PAGE *p;
00043 int did_put, ret;
00044
00045 mpf = dbp->mpf;
00046
00047 do {
00048 did_put = 0;
00049 if ((ret = __memp_fget(mpf, &pgno, 0, &p)) != 0)
00050 return (ret);
00051
00052
00053
00054
00055 pgno = NEXT_PGNO(p);
00056 if (callback == __db_truncate_callback && OV_REF(p) != 1)
00057 pgno = PGNO_INVALID;
00058 if ((ret = callback(dbp, p, cookie, &did_put)) == 0 &&
00059 !did_put)
00060 ret = __memp_fput(mpf, p, 0);
00061 } while (ret == 0 && pgno != PGNO_INVALID);
00062
00063 return (ret);
00064 }
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077 int
00078 __db_reclaim_callback(dbp, p, cookie, putp)
00079 DB *dbp;
00080 PAGE *p;
00081 void *cookie;
00082 int *putp;
00083 {
00084 int ret;
00085
00086
00087
00088
00089
00090
00091
00092 if ((dbp->type == DB_BTREE || dbp->type == DB_RECNO) &&
00093 PGNO(p) == ((BTREE *)dbp->bt_internal)->bt_root)
00094 return (0);
00095 if ((ret = __db_free(cookie, p)) != 0)
00096 return (ret);
00097 *putp = 1;
00098
00099 return (0);
00100 }
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110 int
00111 __db_truncate_callback(dbp, p, cookie, putp)
00112 DB *dbp;
00113 PAGE *p;
00114 void *cookie;
00115 int *putp;
00116 {
00117 DB_MPOOLFILE *mpf;
00118 DBT ddbt, ldbt;
00119 db_indx_t indx, len, off, tlen, top;
00120 db_trunc_param *param;
00121 u_int8_t *hk, type;
00122 int ret;
00123
00124 top = NUM_ENT(p);
00125 mpf = dbp->mpf;
00126 param = cookie;
00127 *putp = 1;
00128
00129 switch (TYPE(p)) {
00130 case P_LBTREE:
00131
00132 for (indx = 0; indx < top; indx += P_INDX) {
00133 type = GET_BKEYDATA(dbp, p, indx + O_INDX)->type;
00134 if (!B_DISSET(type) && B_TYPE(type) != B_DUPLICATE)
00135 ++param->count;
00136 }
00137
00138 case P_IBTREE:
00139 case P_IRECNO:
00140 case P_INVALID:
00141 if (dbp->type != DB_HASH &&
00142 ((BTREE *)dbp->bt_internal)->bt_root == PGNO(p)) {
00143 type = dbp->type == DB_RECNO ? P_LRECNO : P_LBTREE;
00144 goto reinit;
00145 }
00146 break;
00147 case P_OVERFLOW:
00148 if (DBC_LOGGING(param->dbc)) {
00149 if ((ret = __db_ovref_log(dbp, param->dbc->txn,
00150 &LSN(p), 0, p->pgno, -1, &LSN(p))) != 0)
00151 return (ret);
00152 } else
00153 LSN_NOT_LOGGED(LSN(p));
00154 if (--OV_REF(p) != 0)
00155 *putp = 0;
00156 break;
00157 case P_LRECNO:
00158 for (indx = 0; indx < top; indx += O_INDX) {
00159 type = GET_BKEYDATA(dbp, p, indx)->type;
00160 if (!B_DISSET(type))
00161 ++param->count;
00162 }
00163
00164 if (((BTREE *)dbp->bt_internal)->bt_root == PGNO(p)) {
00165 type = P_LRECNO;
00166 goto reinit;
00167 }
00168 break;
00169 case P_LDUP:
00170
00171 for (indx = 0; indx < top; indx += O_INDX)
00172 if (!B_DISSET(GET_BKEYDATA(dbp, p, indx)->type))
00173 ++param->count;
00174
00175 break;
00176 case P_HASH:
00177
00178 for (indx = 0; indx < top; indx += P_INDX) {
00179 switch (*H_PAIRDATA(dbp, p, indx)) {
00180 case H_OFFDUP:
00181 break;
00182 case H_OFFPAGE:
00183 case H_KEYDATA:
00184 ++param->count;
00185 break;
00186 case H_DUPLICATE:
00187 tlen = LEN_HDATA(dbp, p, 0, indx);
00188 hk = H_PAIRDATA(dbp, p, indx);
00189 for (off = 0; off < tlen;
00190 off += len + 2 * sizeof(db_indx_t)) {
00191 ++param->count;
00192 memcpy(&len,
00193 HKEYDATA_DATA(hk)
00194 + off, sizeof(db_indx_t));
00195 }
00196 break;
00197 default:
00198 return (__db_pgfmt(dbp->dbenv, p->pgno));
00199 }
00200 }
00201
00202 if (PREV_PGNO(p) == PGNO_INVALID) {
00203 type = P_HASH;
00204
00205 reinit: *putp = 0;
00206 if (DBC_LOGGING(param->dbc)) {
00207 memset(&ldbt, 0, sizeof(ldbt));
00208 memset(&ddbt, 0, sizeof(ddbt));
00209 ldbt.data = p;
00210 ldbt.size = P_OVERHEAD(dbp);
00211 ldbt.size += p->entries * sizeof(db_indx_t);
00212 ddbt.data = (u_int8_t *)p + HOFFSET(p);
00213 ddbt.size = dbp->pgsize - HOFFSET(p);
00214 if ((ret = __db_pg_init_log(dbp,
00215 param->dbc->txn, &LSN(p), 0,
00216 p->pgno, &ldbt, &ddbt)) != 0)
00217 return (ret);
00218 } else
00219 LSN_NOT_LOGGED(LSN(p));
00220
00221 P_INIT(p, dbp->pgsize, PGNO(p), PGNO_INVALID,
00222 PGNO_INVALID, type == P_HASH ? 0 : 1, type);
00223 }
00224 break;
00225 default:
00226 return (__db_pgfmt(dbp->dbenv, p->pgno));
00227 }
00228
00229 if (*putp == 1) {
00230 if ((ret = __db_free(param->dbc, p)) != 0)
00231 return (ret);
00232 } else {
00233 if ((ret = __memp_fput(mpf, p, DB_MPOOL_DIRTY)) != 0)
00234 return (ret);
00235 *putp = 1;
00236 }
00237
00238 return (0);
00239 }