00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045 #include "db_config.h"
00046
00047 #ifndef NO_SYSTEM_INCLUDES
00048 #include <sys/types.h>
00049
00050 #include <string.h>
00051 #endif
00052
00053 #include "db_int.h"
00054 #include "dbinc/db_page.h"
00055 #include "dbinc/db_shash.h"
00056 #include "dbinc/db_am.h"
00057 #include "dbinc/mp.h"
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075 int
00076 __db_goff(dbp, dbt, tlen, pgno, bpp, bpsz)
00077 DB *dbp;
00078 DBT *dbt;
00079 u_int32_t tlen;
00080 db_pgno_t pgno;
00081 void **bpp;
00082 u_int32_t *bpsz;
00083 {
00084 DB_ENV *dbenv;
00085 DB_MPOOLFILE *mpf;
00086 PAGE *h;
00087 db_indx_t bytes;
00088 u_int32_t curoff, needed, start;
00089 u_int8_t *p, *src;
00090 int ret;
00091
00092 dbenv = dbp->dbenv;
00093 mpf = dbp->mpf;
00094
00095
00096
00097
00098
00099
00100
00101 if (F_ISSET(dbt, DB_DBT_PARTIAL)) {
00102 start = dbt->doff;
00103 if (start > tlen)
00104 needed = 0;
00105 else if (dbt->dlen > tlen - start)
00106 needed = tlen - start;
00107 else
00108 needed = dbt->dlen;
00109 } else {
00110 start = 0;
00111 needed = tlen;
00112 }
00113
00114
00115 if (F_ISSET(dbt, DB_DBT_USERMEM)) {
00116 if (needed > dbt->ulen) {
00117 dbt->size = needed;
00118 return (DB_BUFFER_SMALL);
00119 }
00120 } else if (F_ISSET(dbt, DB_DBT_MALLOC)) {
00121 if ((ret = __os_umalloc(dbenv, needed, &dbt->data)) != 0)
00122 return (ret);
00123 } else if (F_ISSET(dbt, DB_DBT_REALLOC)) {
00124 if ((ret = __os_urealloc(dbenv, needed, &dbt->data)) != 0)
00125 return (ret);
00126 } else if (bpsz != NULL && (*bpsz == 0 || *bpsz < needed)) {
00127 if ((ret = __os_realloc(dbenv, needed, bpp)) != 0)
00128 return (ret);
00129 *bpsz = needed;
00130 dbt->data = *bpp;
00131 } else if (bpp != NULL)
00132 dbt->data = *bpp;
00133 else {
00134 DB_ASSERT(
00135 F_ISSET(dbt,
00136 DB_DBT_USERMEM | DB_DBT_MALLOC | DB_DBT_REALLOC) ||
00137 bpsz != NULL || bpp != NULL);
00138 return (DB_BUFFER_SMALL);
00139 }
00140
00141
00142
00143
00144
00145 dbt->size = needed;
00146 for (curoff = 0, p = dbt->data; pgno != PGNO_INVALID && needed > 0;) {
00147 if ((ret = __memp_fget(mpf, &pgno, 0, &h)) != 0)
00148 return (ret);
00149
00150
00151 if (curoff + OV_LEN(h) >= start) {
00152 src = (u_int8_t *)h + P_OVERHEAD(dbp);
00153 bytes = OV_LEN(h);
00154 if (start > curoff) {
00155 src += start - curoff;
00156 bytes -= start - curoff;
00157 }
00158 if (bytes > needed)
00159 bytes = needed;
00160 memcpy(p, src, bytes);
00161 p += bytes;
00162 needed -= bytes;
00163 }
00164 curoff += OV_LEN(h);
00165 pgno = h->next_pgno;
00166 (void)__memp_fput(mpf, h, 0);
00167 }
00168 return (0);
00169 }
00170
00171
00172
00173
00174
00175
00176
00177 int
00178 __db_poff(dbc, dbt, pgnop)
00179 DBC *dbc;
00180 const DBT *dbt;
00181 db_pgno_t *pgnop;
00182 {
00183 DB *dbp;
00184 DBT tmp_dbt;
00185 DB_LSN new_lsn, null_lsn;
00186 DB_MPOOLFILE *mpf;
00187 PAGE *pagep, *lastp;
00188 db_indx_t pagespace;
00189 u_int32_t sz;
00190 u_int8_t *p;
00191 int ret, t_ret;
00192
00193
00194
00195
00196
00197
00198 dbp = dbc->dbp;
00199 mpf = dbp->mpf;
00200 pagespace = P_MAXSPACE(dbp, dbp->pgsize);
00201
00202 ret = 0;
00203 lastp = NULL;
00204 for (p = dbt->data,
00205 sz = dbt->size; sz > 0; p += pagespace, sz -= pagespace) {
00206
00207
00208
00209
00210 if (sz < pagespace)
00211 pagespace = sz;
00212
00213
00214
00215
00216
00217
00218 if ((ret = __db_new(dbc, P_OVERFLOW, &pagep)) != 0)
00219 break;
00220 if (DBC_LOGGING(dbc)) {
00221 tmp_dbt.data = p;
00222 tmp_dbt.size = pagespace;
00223 ZERO_LSN(null_lsn);
00224 if ((ret = __db_big_log(dbp, dbc->txn,
00225 &new_lsn, 0, DB_ADD_BIG, PGNO(pagep),
00226 lastp ? PGNO(lastp) : PGNO_INVALID,
00227 PGNO_INVALID, &tmp_dbt, &LSN(pagep),
00228 lastp == NULL ? &null_lsn : &LSN(lastp),
00229 &null_lsn)) != 0) {
00230 if (lastp != NULL)
00231 (void)__memp_fput(mpf,
00232 lastp, DB_MPOOL_DIRTY);
00233 lastp = pagep;
00234 break;
00235 }
00236 } else
00237 LSN_NOT_LOGGED(new_lsn);
00238
00239
00240 if (lastp != NULL)
00241 LSN(lastp) = new_lsn;
00242 LSN(pagep) = new_lsn;
00243
00244 OV_LEN(pagep) = pagespace;
00245 OV_REF(pagep) = 1;
00246 memcpy((u_int8_t *)pagep + P_OVERHEAD(dbp), p, pagespace);
00247
00248
00249
00250
00251
00252
00253 if (lastp == NULL)
00254 *pgnop = PGNO(pagep);
00255 else {
00256 lastp->next_pgno = PGNO(pagep);
00257 pagep->prev_pgno = PGNO(lastp);
00258 (void)__memp_fput(mpf, lastp, DB_MPOOL_DIRTY);
00259 }
00260 lastp = pagep;
00261 }
00262 if (lastp != NULL &&
00263 (t_ret = __memp_fput(mpf, lastp, DB_MPOOL_DIRTY)) != 0 && ret == 0)
00264 ret = t_ret;
00265 return (ret);
00266 }
00267
00268
00269
00270
00271
00272
00273
00274 int
00275 __db_ovref(dbc, pgno, adjust)
00276 DBC *dbc;
00277 db_pgno_t pgno;
00278 int32_t adjust;
00279 {
00280 DB *dbp;
00281 DB_MPOOLFILE *mpf;
00282 PAGE *h;
00283 int ret;
00284
00285 dbp = dbc->dbp;
00286 mpf = dbp->mpf;
00287
00288 if ((ret = __memp_fget(mpf, &pgno, 0, &h)) != 0)
00289 return (ret);
00290
00291 if (DBC_LOGGING(dbc)) {
00292 if ((ret = __db_ovref_log(dbp,
00293 dbc->txn, &LSN(h), 0, h->pgno, adjust, &LSN(h))) != 0) {
00294 (void)__memp_fput(mpf, h, 0);
00295 return (ret);
00296 }
00297 } else
00298 LSN_NOT_LOGGED(LSN(h));
00299 OV_REF(h) += adjust;
00300
00301 (void)__memp_fput(mpf, h, DB_MPOOL_DIRTY);
00302 return (0);
00303 }
00304
00305
00306
00307
00308
00309
00310
00311 int
00312 __db_doff(dbc, pgno)
00313 DBC *dbc;
00314 db_pgno_t pgno;
00315 {
00316 DB *dbp;
00317 PAGE *pagep;
00318 DB_LSN null_lsn;
00319 DB_MPOOLFILE *mpf;
00320 DBT tmp_dbt;
00321 int ret;
00322
00323 dbp = dbc->dbp;
00324 mpf = dbp->mpf;
00325
00326 do {
00327 if ((ret = __memp_fget(mpf, &pgno, 0, &pagep)) != 0)
00328 return (ret);
00329
00330 DB_ASSERT(TYPE(pagep) == P_OVERFLOW);
00331
00332
00333
00334
00335 if (OV_REF(pagep) > 1) {
00336 (void)__memp_fput(mpf, pagep, 0);
00337 return (__db_ovref(dbc, pgno, -1));
00338 }
00339
00340 if (DBC_LOGGING(dbc)) {
00341 tmp_dbt.data = (u_int8_t *)pagep + P_OVERHEAD(dbp);
00342 tmp_dbt.size = OV_LEN(pagep);
00343 ZERO_LSN(null_lsn);
00344 if ((ret = __db_big_log(dbp, dbc->txn,
00345 &LSN(pagep), 0, DB_REM_BIG,
00346 PGNO(pagep), PREV_PGNO(pagep),
00347 NEXT_PGNO(pagep), &tmp_dbt,
00348 &LSN(pagep), &null_lsn, &null_lsn)) != 0) {
00349 (void)__memp_fput(mpf, pagep, 0);
00350 return (ret);
00351 }
00352 } else
00353 LSN_NOT_LOGGED(LSN(pagep));
00354 pgno = pagep->next_pgno;
00355 OV_LEN(pagep) = 0;
00356 if ((ret = __db_free(dbc, pagep)) != 0)
00357 return (ret);
00358 } while (pgno != PGNO_INVALID);
00359
00360 return (0);
00361 }
00362
00363
00364
00365
00366
00367
00368
00369
00370
00371
00372
00373
00374
00375
00376 int
00377 __db_moff(dbp, dbt, pgno, tlen, cmpfunc, cmpp)
00378 DB *dbp;
00379 const DBT *dbt;
00380 db_pgno_t pgno;
00381 u_int32_t tlen;
00382 int (*cmpfunc) __P((DB *, const DBT *, const DBT *)), *cmpp;
00383 {
00384 DBT local_dbt;
00385 DB_MPOOLFILE *mpf;
00386 PAGE *pagep;
00387 void *buf;
00388 u_int32_t bufsize, cmp_bytes, key_left;
00389 u_int8_t *p1, *p2;
00390 int ret;
00391
00392 mpf = dbp->mpf;
00393
00394
00395
00396
00397
00398 if (cmpfunc != NULL) {
00399 memset(&local_dbt, 0, sizeof(local_dbt));
00400 buf = NULL;
00401 bufsize = 0;
00402
00403 if ((ret = __db_goff(dbp,
00404 &local_dbt, tlen, pgno, &buf, &bufsize)) != 0)
00405 return (ret);
00406
00407 *cmpp = cmpfunc(dbp, dbt, &local_dbt);
00408 __os_free(dbp->dbenv, buf);
00409 return (0);
00410 }
00411
00412
00413 for (*cmpp = 0, p1 = dbt->data,
00414 key_left = dbt->size; key_left > 0 && pgno != PGNO_INVALID;) {
00415 if ((ret = __memp_fget(mpf, &pgno, 0, &pagep)) != 0)
00416 return (ret);
00417
00418 cmp_bytes = OV_LEN(pagep) < key_left ? OV_LEN(pagep) : key_left;
00419 tlen -= cmp_bytes;
00420 key_left -= cmp_bytes;
00421 for (p2 = (u_int8_t *)pagep + P_OVERHEAD(dbp);
00422 cmp_bytes-- > 0; ++p1, ++p2)
00423 if (*p1 != *p2) {
00424 *cmpp = (long)*p1 - (long)*p2;
00425 break;
00426 }
00427 pgno = NEXT_PGNO(pagep);
00428 if ((ret = __memp_fput(mpf, pagep, 0)) != 0)
00429 return (ret);
00430 if (*cmpp != 0)
00431 return (0);
00432 }
00433 if (key_left > 0)
00434 *cmpp = 1;
00435 else if (tlen > 0)
00436 *cmpp = -1;
00437 else
00438 *cmpp = 0;
00439
00440 return (0);
00441 }