00001
00002
00003
00004
00005
00006
00007 #include "config.h"
00008
00009 #ifndef lint
00010 static const char revid[] = "$Id: mp__fget_8c-source.html,v 1.1 2008/06/08 10:20:45 sebdiaz Exp $";
00011 #endif
00012
00013 #ifndef NO_SYSTEM_INCLUDES
00014 #include <sys/types.h>
00015
00016 #include <errno.h>
00017 #include <string.h>
00018 #endif
00019
00020 #ifdef HAVE_RPC
00021 #include "db_server.h"
00022 #endif
00023
00024 #include "db_int.h"
00025 #include "db_shash.h"
00026 #include "db_page.h"
00027 #include "mp.h"
00028
00029 #ifdef DEBUG
00030 #include "WordMonitor.h"
00031 #endif
00032
00033 #ifdef HAVE_RPC
00034 #include "gen_client_ext.h"
00035 #include "rpc_client_ext.h"
00036 #endif
00037
00038
00039
00040
00041
00042 int
00043 CDB_memp_fget(dbmfp, pgnoaddr, flags, addrp)
00044 DB_MPOOLFILE *dbmfp;
00045 db_pgno_t *pgnoaddr;
00046 u_int32_t flags;
00047 void *addrp;
00048 {
00049 BH *bhp;
00050 DB_ENV *dbenv;
00051 DB_MPOOL *dbmp;
00052 DB_HASHTAB *dbht;
00053 MPOOL *c_mp, *mp;
00054 MPOOLFILE *mfp;
00055 size_t n_bucket, n_cache, mf_offset;
00056 u_int32_t st_hsearch;
00057 int b_incr, first, ret;
00058
00059 dbmp = dbmfp->dbmp;
00060 dbenv = dbmp->dbenv;
00061 mp = dbmp->reginfo[0].primary;
00062 mfp = dbmfp->mfp;
00063 #ifdef HAVE_RPC
00064 if (F_ISSET(dbenv, DB_ENV_RPCCLIENT))
00065 return (__dbcl_memp_fget(dbmfp, pgnoaddr, flags, addrp));
00066 #endif
00067
00068 PANIC_CHECK(dbenv);
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083 #define OKFLAGS \
00084 (DB_MPOOL_CREATE | DB_MPOOL_LAST | DB_MPOOL_NEW | DB_MPOOL_NEW_GROUP)
00085 if (flags != 0) {
00086 if ((ret = CDB___db_fchk(dbenv, "CDB_memp_fget", flags, OKFLAGS)) != 0)
00087 return (ret);
00088
00089 switch (flags) {
00090 case DB_MPOOL_CREATE:
00091 case DB_MPOOL_LAST:
00092 case DB_MPOOL_NEW:
00093 case DB_MPOOL_NEW_GROUP:
00094 case 0:
00095 break;
00096 default:
00097 return (CDB___db_ferr(dbenv, "CDB_memp_fget", 1));
00098 }
00099 }
00100
00101 #ifdef DIAGNOSTIC
00102
00103
00104
00105
00106
00107 if (DB_GLOBAL(db_pageyield))
00108 CDB___os_yield(dbenv, 1);
00109 #endif
00110
00111
00112 mf_offset = R_OFFSET(dbmp->reginfo, mfp);
00113 bhp = NULL;
00114 st_hsearch = 0;
00115 b_incr = ret = 0;
00116
00117 R_LOCK(dbenv, dbmp->reginfo);
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142 if (LF_ISSET(DB_MPOOL_LAST | DB_MPOOL_NEW | DB_MPOOL_NEW_GROUP)) {
00143 if (LF_ISSET(DB_MPOOL_NEW)) {
00144 if ((ret = CDB___os_fpinit(dbenv,
00145 &dbmfp->fh, mfp->last_pgno + 1,
00146 1, mfp->stat.st_pagesize)) != 0) {
00147 R_UNLOCK(dbenv, dbmp->reginfo);
00148 return (ret);
00149 }
00150 ++mfp->last_pgno;
00151 #ifdef DEBUG
00152 word_monitor_set(DB_MONITOR(dbenv), WORD_MONITOR_PGNO, mfp->last_pgno);
00153 #endif
00154 }
00155 if (LF_ISSET(DB_MPOOL_NEW_GROUP)) {
00156 if ((ret = CDB___os_fpinit(dbenv,
00157 &dbmfp->fh, mfp->last_pgno + 1,
00158 (int)*pgnoaddr, mfp->stat.st_pagesize)) != 0) {
00159 R_UNLOCK(dbenv, dbmp->reginfo);
00160 return (ret);
00161 }
00162 mfp->last_pgno += *pgnoaddr;
00163 }
00164 *pgnoaddr = mfp->last_pgno;
00165 }
00166
00167
00168
00169
00170
00171 n_cache = NCACHE(mp, *pgnoaddr);
00172 c_mp = dbmp->reginfo[n_cache].primary;
00173 n_bucket = NBUCKET(c_mp, mf_offset, *pgnoaddr);
00174 dbht = R_ADDR(&dbmp->reginfo[n_cache], c_mp->htab);
00175
00176 if (LF_ISSET(DB_MPOOL_NEW | DB_MPOOL_NEW_GROUP))
00177 goto alloc;
00178
00179
00180
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200 if (dbmfp->addr != NULL && F_ISSET(mfp, MP_CAN_MMAP)) {
00201 if (*pgnoaddr > mfp->orig_last_pgno) {
00202
00203
00204
00205
00206
00207 if (!LF_ISSET(DB_MPOOL_CREATE)) {
00208 CDB___db_err(dbenv, "%s: page %lu doesn't exist",
00209 CDB___memp_fn(dbmfp), (u_long)*pgnoaddr);
00210 ret = EINVAL;
00211 goto err;
00212 }
00213 } else {
00214 *(void **)addrp =
00215 R_ADDR(dbmfp, *pgnoaddr * mfp->stat.st_pagesize);
00216 ++mfp->stat.st_map;
00217 goto done;
00218 }
00219 }
00220
00221
00222 for (bhp = SH_TAILQ_FIRST(&dbht[n_bucket], __bh);
00223 bhp != NULL; bhp = SH_TAILQ_NEXT(bhp, hq, __bh)) {
00224 ++st_hsearch;
00225 if (bhp->pgno != *pgnoaddr || bhp->mf_offset != mf_offset)
00226 continue;
00227
00228
00229 if (bhp->ref == UINT16_T_MAX) {
00230 CDB___db_err(dbenv,
00231 "%s: page %lu: reference count overflow",
00232 CDB___memp_fn(dbmfp), (u_long)bhp->pgno);
00233 ret = EINVAL;
00234 goto err;
00235 }
00236
00237
00238
00239
00240
00241
00242
00243 ++bhp->ref;
00244 b_incr = 1;
00245
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255 for (first = 1; F_ISSET(bhp, BH_LOCKED); first = 0) {
00256 R_UNLOCK(dbenv, dbmp->reginfo);
00257
00258
00259
00260
00261
00262
00263
00264 if (!first)
00265 CDB___os_yield(dbenv, 1);
00266
00267 MUTEX_LOCK(&bhp->mutex, dbenv->lockfhp);
00268
00269 MUTEX_UNLOCK(&bhp->mutex);
00270 R_LOCK(dbenv, dbmp->reginfo);
00271 }
00272
00273
00274
00275
00276
00277
00278 if (F_ISSET(bhp, BH_TRASH))
00279 goto reread;
00280
00281
00282
00283
00284
00285
00286 if (F_ISSET(bhp, BH_CALLPGIN)) {
00287 if ((ret = CDB___memp_pg(dbmfp, bhp, 1)) != 0)
00288 goto err;
00289 F_CLR(bhp, BH_CALLPGIN);
00290 }
00291
00292 ++mfp->stat.st_cache_hit;
00293 *(void **)addrp = bhp->buf;
00294 goto done;
00295 }
00296
00297 alloc:
00298 if ((ret = CDB___memp_alloc(dbmp,
00299 &dbmp->reginfo[n_cache], mfp, 0, NULL, &bhp)) != 0)
00300 goto err;
00301
00302 ++c_mp->stat.st_page_clean;
00303
00304
00305
00306
00307
00308 memset(bhp, 0, sizeof(BH));
00309 bhp->ref = 1;
00310 bhp->pgno = *pgnoaddr;
00311 bhp->mf_offset = mf_offset;
00312
00313
00314 ++mfp->ref_cnt;
00315
00316
00317
00318
00319
00320
00321 SH_TAILQ_INSERT_HEAD(&dbht[n_bucket], bhp, hq, __bh);
00322 SH_TAILQ_INSERT_TAIL(&c_mp->bhq, bhp, q);
00323
00324 #ifdef DIAGNOSTIC
00325 if ((db_alignp_t)bhp->buf & (sizeof(size_t) - 1)) {
00326 CDB___db_err(dbenv, "Internal error: BH data NOT size_t aligned.");
00327 ret = EINVAL;
00328 CDB___memp_bhfree(dbmp, bhp, 1);
00329 goto err;
00330 }
00331 #endif
00332
00333 if ((ret = __db_mutex_init(dbenv, &bhp->mutex, R_OFFSET(
00334 dbmp->reginfo, &bhp->mutex) + DB_FCNTL_OFF_MPOOL, 0)) != 0) {
00335 CDB___memp_bhfree(dbmp, bhp, 1);
00336 goto err;
00337 }
00338
00339
00340
00341
00342
00343
00344
00345
00346
00347
00348
00349
00350
00351 if (LF_ISSET(DB_MPOOL_NEW | DB_MPOOL_NEW_GROUP)) {
00352 if (mfp->clear_len == 0)
00353 memset(bhp->buf, 0, mfp->stat.st_pagesize);
00354 else {
00355 memset(bhp->buf, 0, mfp->clear_len);
00356 #ifdef DIAGNOSTIC
00357 memset(bhp->buf + mfp->clear_len, CLEAR_BYTE,
00358 mfp->stat.st_pagesize - mfp->clear_len);
00359 #endif
00360 }
00361
00362 ++mfp->stat.st_page_create;
00363 } else {
00364
00365
00366
00367
00368
00369
00370 reread: if ((ret = CDB___memp_pgread(
00371 dbmfp, bhp, LF_ISSET(DB_MPOOL_CREATE))) != 0) {
00372
00373
00374
00375
00376
00377
00378 if (bhp->ref == 1)
00379 CDB___memp_bhfree(dbmp, bhp, 1);
00380 goto err;
00381 }
00382
00383 ++mfp->stat.st_cache_miss;
00384 }
00385
00386
00387
00388
00389
00390
00391 if (bhp->pgno > mfp->last_pgno)
00392 mfp->last_pgno = bhp->pgno;
00393
00394 *(void **)addrp = bhp->buf;
00395
00396 done:
00397 if (st_hsearch) {
00398 ++c_mp->stat.st_hash_searches;
00399 if (st_hsearch > c_mp->stat.st_hash_longest)
00400 c_mp->stat.st_hash_longest = st_hsearch;
00401 c_mp->stat.st_hash_examined += st_hsearch;
00402 }
00403
00404 ++dbmfp->pinref;
00405
00406 R_UNLOCK(dbenv, dbmp->reginfo);
00407
00408 return (0);
00409
00410 err:
00411 if (b_incr)
00412 --bhp->ref;
00413 R_UNLOCK(dbenv, dbmp->reginfo);
00414
00415 *(void **)addrp = NULL;
00416 return (ret);
00417 }