1/*- 2 * See the file LICENSE for redistribution information. 3 * 4 * Copyright (c) 1996-2009 Oracle. All rights reserved. 5 * 6 * $Id$ 7 */ 8 9#include "db_config.h" 10 11#include "db_int.h" 12#include "dbinc/log.h" 13#include "dbinc/mp.h" 14 15static int __memp_get_clear_len __P((DB_MPOOLFILE *, u_int32_t *)); 16static int __memp_get_lsn_offset __P((DB_MPOOLFILE *, int32_t *)); 17static int __memp_get_maxsize __P((DB_MPOOLFILE *, u_int32_t *, u_int32_t *)); 18static int __memp_set_maxsize __P((DB_MPOOLFILE *, u_int32_t, u_int32_t)); 19static int __memp_get_priority __P((DB_MPOOLFILE *, DB_CACHE_PRIORITY *)); 20static int __memp_set_priority __P((DB_MPOOLFILE *, DB_CACHE_PRIORITY)); 21 22/* 23 * __memp_fcreate_pp -- 24 * ENV->memp_fcreate pre/post processing. 25 * 26 * PUBLIC: int __memp_fcreate_pp __P((DB_ENV *, DB_MPOOLFILE **, u_int32_t)); 27 */ 28int 29__memp_fcreate_pp(dbenv, retp, flags) 30 DB_ENV *dbenv; 31 DB_MPOOLFILE **retp; 32 u_int32_t flags; 33{ 34 DB_THREAD_INFO *ip; 35 ENV *env; 36 int ret; 37 38 env = dbenv->env; 39 40 /* Validate arguments. */ 41 if ((ret = __db_fchk(env, "DB_ENV->memp_fcreate", flags, 0)) != 0) 42 return (ret); 43 44 if (REP_ON(env)) { 45 __db_errx(env, 46 "DB_ENV->memp_fcreate: method not permitted when replication is configured"); 47 return (EINVAL); 48 } 49 50 ENV_ENTER(env, ip); 51 ret = __memp_fcreate(env, retp); 52 ENV_LEAVE(env, ip); 53 return (ret); 54} 55 56/* 57 * __memp_fcreate -- 58 * ENV->memp_fcreate. 59 * 60 * PUBLIC: int __memp_fcreate __P((ENV *, DB_MPOOLFILE **)); 61 */ 62int 63__memp_fcreate(env, retp) 64 ENV *env; 65 DB_MPOOLFILE **retp; 66{ 67 DB_MPOOLFILE *dbmfp; 68 int ret; 69 70 /* Allocate and initialize the per-process structure. */ 71 if ((ret = __os_calloc(env, 1, sizeof(DB_MPOOLFILE), &dbmfp)) != 0) 72 return (ret); 73 74 dbmfp->ref = 1; 75 dbmfp->lsn_offset = DB_LSN_OFF_NOTSET; 76 dbmfp->env = env; 77 dbmfp->mfp = INVALID_ROFF; 78 79 dbmfp->close = __memp_fclose_pp; 80 dbmfp->get = __memp_fget_pp; 81 dbmfp->get_clear_len = __memp_get_clear_len; 82 dbmfp->get_fileid = __memp_get_fileid; 83 dbmfp->get_flags = __memp_get_flags; 84 dbmfp->get_ftype = __memp_get_ftype; 85 dbmfp->get_last_pgno = __memp_get_last_pgno; 86 dbmfp->get_lsn_offset = __memp_get_lsn_offset; 87 dbmfp->get_maxsize = __memp_get_maxsize; 88 dbmfp->get_pgcookie = __memp_get_pgcookie; 89 dbmfp->get_priority = __memp_get_priority; 90 dbmfp->open = __memp_fopen_pp; 91 dbmfp->put = __memp_fput_pp; 92 dbmfp->set_clear_len = __memp_set_clear_len; 93 dbmfp->set_fileid = __memp_set_fileid; 94 dbmfp->set_flags = __memp_set_flags; 95 dbmfp->set_ftype = __memp_set_ftype; 96 dbmfp->set_lsn_offset = __memp_set_lsn_offset; 97 dbmfp->set_maxsize = __memp_set_maxsize; 98 dbmfp->set_pgcookie = __memp_set_pgcookie; 99 dbmfp->set_priority = __memp_set_priority; 100 dbmfp->sync = __memp_fsync_pp; 101 102 *retp = dbmfp; 103 return (0); 104} 105 106/* 107 * __memp_get_clear_len -- 108 * Get the clear length. 109 */ 110static int 111__memp_get_clear_len(dbmfp, clear_lenp) 112 DB_MPOOLFILE *dbmfp; 113 u_int32_t *clear_lenp; 114{ 115 *clear_lenp = dbmfp->clear_len; 116 return (0); 117} 118 119/* 120 * __memp_set_clear_len -- 121 * DB_MPOOLFILE->set_clear_len. 122 * 123 * PUBLIC: int __memp_set_clear_len __P((DB_MPOOLFILE *, u_int32_t)); 124 */ 125int 126__memp_set_clear_len(dbmfp, clear_len) 127 DB_MPOOLFILE *dbmfp; 128 u_int32_t clear_len; 129{ 130 MPF_ILLEGAL_AFTER_OPEN(dbmfp, "DB_MPOOLFILE->set_clear_len"); 131 132 dbmfp->clear_len = clear_len; 133 return (0); 134} 135 136/* 137 * __memp_get_fileid -- 138 * DB_MPOOLFILE->get_fileid. 139 * 140 * PUBLIC: int __memp_get_fileid __P((DB_MPOOLFILE *, u_int8_t *)); 141 */ 142int 143__memp_get_fileid(dbmfp, fileid) 144 DB_MPOOLFILE *dbmfp; 145 u_int8_t *fileid; 146{ 147 if (!F_ISSET(dbmfp, MP_FILEID_SET)) { 148 __db_errx(dbmfp->env, "get_fileid: file ID not set"); 149 return (EINVAL); 150 } 151 152 memcpy(fileid, dbmfp->fileid, DB_FILE_ID_LEN); 153 return (0); 154} 155 156/* 157 * __memp_set_fileid -- 158 * DB_MPOOLFILE->set_fileid. 159 * 160 * PUBLIC: int __memp_set_fileid __P((DB_MPOOLFILE *, u_int8_t *)); 161 */ 162int 163__memp_set_fileid(dbmfp, fileid) 164 DB_MPOOLFILE *dbmfp; 165 u_int8_t *fileid; 166{ 167 MPF_ILLEGAL_AFTER_OPEN(dbmfp, "DB_MPOOLFILE->set_fileid"); 168 169 memcpy(dbmfp->fileid, fileid, DB_FILE_ID_LEN); 170 F_SET(dbmfp, MP_FILEID_SET); 171 172 return (0); 173} 174 175/* 176 * __memp_get_flags -- 177 * Get the DB_MPOOLFILE flags; 178 * 179 * PUBLIC: int __memp_get_flags __P((DB_MPOOLFILE *, u_int32_t *)); 180 */ 181int 182__memp_get_flags(dbmfp, flagsp) 183 DB_MPOOLFILE *dbmfp; 184 u_int32_t *flagsp; 185{ 186 MPOOLFILE *mfp; 187 188 mfp = dbmfp->mfp; 189 190 *flagsp = 0; 191 192 if (mfp == NULL) 193 *flagsp = FLD_ISSET(dbmfp->config_flags, 194 DB_MPOOL_NOFILE | DB_MPOOL_UNLINK); 195 else { 196 if (mfp->no_backing_file) 197 FLD_SET(*flagsp, DB_MPOOL_NOFILE); 198 if (mfp->unlink_on_close) 199 FLD_SET(*flagsp, DB_MPOOL_UNLINK); 200 } 201 return (0); 202} 203 204/* 205 * __memp_set_flags -- 206 * Set the DB_MPOOLFILE flags; 207 * 208 * PUBLIC: int __memp_set_flags __P((DB_MPOOLFILE *, u_int32_t, int)); 209 */ 210int 211__memp_set_flags(dbmfp, flags, onoff) 212 DB_MPOOLFILE *dbmfp; 213 u_int32_t flags; 214 int onoff; 215{ 216 ENV *env; 217 MPOOLFILE *mfp; 218 int ret; 219 220 env = dbmfp->env; 221 mfp = dbmfp->mfp; 222 223 switch (flags) { 224 case DB_MPOOL_NOFILE: 225 if (mfp == NULL) 226 if (onoff) 227 FLD_SET(dbmfp->config_flags, DB_MPOOL_NOFILE); 228 else 229 FLD_CLR(dbmfp->config_flags, DB_MPOOL_NOFILE); 230 else 231 mfp->no_backing_file = onoff; 232 break; 233 case DB_MPOOL_UNLINK: 234 if (mfp == NULL) 235 if (onoff) 236 FLD_SET(dbmfp->config_flags, DB_MPOOL_UNLINK); 237 else 238 FLD_CLR(dbmfp->config_flags, DB_MPOOL_UNLINK); 239 else 240 mfp->unlink_on_close = onoff; 241 break; 242 default: 243 if ((ret = __db_fchk(env, "DB_MPOOLFILE->set_flags", 244 flags, DB_MPOOL_NOFILE | DB_MPOOL_UNLINK)) != 0) 245 return (ret); 246 break; 247 } 248 return (0); 249} 250 251/* 252 * __memp_get_ftype -- 253 * Get the file type (as registered). 254 * 255 * PUBLIC: int __memp_get_ftype __P((DB_MPOOLFILE *, int *)); 256 */ 257int 258__memp_get_ftype(dbmfp, ftypep) 259 DB_MPOOLFILE *dbmfp; 260 int *ftypep; 261{ 262 *ftypep = dbmfp->ftype; 263 return (0); 264} 265 266/* 267 * __memp_set_ftype -- 268 * DB_MPOOLFILE->set_ftype. 269 * 270 * PUBLIC: int __memp_set_ftype __P((DB_MPOOLFILE *, int)); 271 */ 272int 273__memp_set_ftype(dbmfp, ftype) 274 DB_MPOOLFILE *dbmfp; 275 int ftype; 276{ 277 MPF_ILLEGAL_AFTER_OPEN(dbmfp, "DB_MPOOLFILE->set_ftype"); 278 279 dbmfp->ftype = ftype; 280 return (0); 281} 282 283/* 284 * __memp_get_lsn_offset -- 285 * Get the page's LSN offset. 286 */ 287static int 288__memp_get_lsn_offset(dbmfp, lsn_offsetp) 289 DB_MPOOLFILE *dbmfp; 290 int32_t *lsn_offsetp; 291{ 292 *lsn_offsetp = dbmfp->lsn_offset; 293 return (0); 294} 295 296/* 297 * __memp_set_lsn_offset -- 298 * Set the page's LSN offset. 299 * 300 * PUBLIC: int __memp_set_lsn_offset __P((DB_MPOOLFILE *, int32_t)); 301 */ 302int 303__memp_set_lsn_offset(dbmfp, lsn_offset) 304 DB_MPOOLFILE *dbmfp; 305 int32_t lsn_offset; 306{ 307 MPF_ILLEGAL_AFTER_OPEN(dbmfp, "DB_MPOOLFILE->set_lsn_offset"); 308 309 dbmfp->lsn_offset = lsn_offset; 310 return (0); 311} 312 313/* 314 * __memp_get_maxsize -- 315 * Get the file's maximum size. 316 */ 317static int 318__memp_get_maxsize(dbmfp, gbytesp, bytesp) 319 DB_MPOOLFILE *dbmfp; 320 u_int32_t *gbytesp, *bytesp; 321{ 322 ENV *env; 323 MPOOLFILE *mfp; 324 325 if ((mfp = dbmfp->mfp) == NULL) { 326 *gbytesp = dbmfp->gbytes; 327 *bytesp = dbmfp->bytes; 328 } else { 329 env = dbmfp->env; 330 331 MUTEX_LOCK(env, mfp->mutex); 332 *gbytesp = (u_int32_t) 333 (mfp->maxpgno / (GIGABYTE / mfp->stat.st_pagesize)); 334 *bytesp = (u_int32_t) 335 ((mfp->maxpgno % (GIGABYTE / mfp->stat.st_pagesize)) * 336 mfp->stat.st_pagesize); 337 MUTEX_UNLOCK(env, mfp->mutex); 338 } 339 340 return (0); 341} 342 343/* 344 * __memp_set_maxsize -- 345 * Set the file's maximum size. 346 */ 347static int 348__memp_set_maxsize(dbmfp, gbytes, bytes) 349 DB_MPOOLFILE *dbmfp; 350 u_int32_t gbytes, bytes; 351{ 352 ENV *env; 353 MPOOLFILE *mfp; 354 355 if ((mfp = dbmfp->mfp) == NULL) { 356 dbmfp->gbytes = gbytes; 357 dbmfp->bytes = bytes; 358 } else { 359 env = dbmfp->env; 360 361 MUTEX_LOCK(env, mfp->mutex); 362 mfp->maxpgno = (db_pgno_t) 363 (gbytes * (GIGABYTE / mfp->stat.st_pagesize)); 364 mfp->maxpgno += (db_pgno_t) 365 ((bytes + mfp->stat.st_pagesize - 1) / 366 mfp->stat.st_pagesize); 367 MUTEX_UNLOCK(env, mfp->mutex); 368 } 369 370 return (0); 371} 372 373/* 374 * __memp_get_pgcookie -- 375 * Get the pgin/pgout cookie. 376 * 377 * PUBLIC: int __memp_get_pgcookie __P((DB_MPOOLFILE *, DBT *)); 378 */ 379int 380__memp_get_pgcookie(dbmfp, pgcookie) 381 DB_MPOOLFILE *dbmfp; 382 DBT *pgcookie; 383{ 384 if (dbmfp->pgcookie == NULL) { 385 pgcookie->size = 0; 386 pgcookie->data = ""; 387 } else 388 memcpy(pgcookie, dbmfp->pgcookie, sizeof(DBT)); 389 return (0); 390} 391 392/* 393 * __memp_set_pgcookie -- 394 * Set the pgin/pgout cookie. 395 * 396 * PUBLIC: int __memp_set_pgcookie __P((DB_MPOOLFILE *, DBT *)); 397 */ 398int 399__memp_set_pgcookie(dbmfp, pgcookie) 400 DB_MPOOLFILE *dbmfp; 401 DBT *pgcookie; 402{ 403 DBT *cookie; 404 ENV *env; 405 int ret; 406 407 MPF_ILLEGAL_AFTER_OPEN(dbmfp, "DB_MPOOLFILE->set_pgcookie"); 408 env = dbmfp->env; 409 410 if ((ret = __os_calloc(env, 1, sizeof(*cookie), &cookie)) != 0) 411 return (ret); 412 if ((ret = __os_malloc(env, pgcookie->size, &cookie->data)) != 0) { 413 __os_free(env, cookie); 414 return (ret); 415 } 416 417 memcpy(cookie->data, pgcookie->data, pgcookie->size); 418 cookie->size = pgcookie->size; 419 420 dbmfp->pgcookie = cookie; 421 return (0); 422} 423 424/* 425 * __memp_get_priority -- 426 * Set the cache priority for pages from this file. 427 */ 428static int 429__memp_get_priority(dbmfp, priorityp) 430 DB_MPOOLFILE *dbmfp; 431 DB_CACHE_PRIORITY *priorityp; 432{ 433 switch (dbmfp->priority) { 434 case MPOOL_PRI_VERY_LOW: 435 *priorityp = DB_PRIORITY_VERY_LOW; 436 break; 437 case MPOOL_PRI_LOW: 438 *priorityp = DB_PRIORITY_LOW; 439 break; 440 case MPOOL_PRI_DEFAULT: 441 *priorityp = DB_PRIORITY_DEFAULT; 442 break; 443 case MPOOL_PRI_HIGH: 444 *priorityp = DB_PRIORITY_HIGH; 445 break; 446 case MPOOL_PRI_VERY_HIGH: 447 *priorityp = DB_PRIORITY_VERY_HIGH; 448 break; 449 default: 450 __db_errx(dbmfp->env, 451 "DB_MPOOLFILE->get_priority: unknown priority value: %d", 452 dbmfp->priority); 453 return (EINVAL); 454 } 455 456 return (0); 457} 458 459/* 460 * __memp_set_priority -- 461 * Set the cache priority for pages from this file. 462 */ 463static int 464__memp_set_priority(dbmfp, priority) 465 DB_MPOOLFILE *dbmfp; 466 DB_CACHE_PRIORITY priority; 467{ 468 switch (priority) { 469 case DB_PRIORITY_VERY_LOW: 470 dbmfp->priority = MPOOL_PRI_VERY_LOW; 471 break; 472 case DB_PRIORITY_LOW: 473 dbmfp->priority = MPOOL_PRI_LOW; 474 break; 475 case DB_PRIORITY_DEFAULT: 476 dbmfp->priority = MPOOL_PRI_DEFAULT; 477 break; 478 case DB_PRIORITY_HIGH: 479 dbmfp->priority = MPOOL_PRI_HIGH; 480 break; 481 case DB_PRIORITY_VERY_HIGH: 482 dbmfp->priority = MPOOL_PRI_VERY_HIGH; 483 break; 484 default: 485 __db_errx(dbmfp->env, 486 "DB_MPOOLFILE->set_priority: unknown priority value: %d", 487 priority); 488 return (EINVAL); 489 } 490 491 /* Update the underlying file if we've already opened it. */ 492 if (dbmfp->mfp != NULL) 493 dbmfp->mfp->priority = dbmfp->priority; 494 495 return (0); 496} 497 498/* 499 * __memp_get_last_pgno -- 500 * Return the page number of the last page in the file. 501 * 502 * !!! 503 * The method is undocumented, but the handle is exported, users occasionally 504 * ask for it. 505 * 506 * PUBLIC: int __memp_get_last_pgno __P((DB_MPOOLFILE *, db_pgno_t *)); 507 */ 508int 509__memp_get_last_pgno(dbmfp, pgnoaddr) 510 DB_MPOOLFILE *dbmfp; 511 db_pgno_t *pgnoaddr; 512{ 513 ENV *env; 514 MPOOLFILE *mfp; 515 516 env = dbmfp->env; 517 mfp = dbmfp->mfp; 518 519 MUTEX_LOCK(env, mfp->mutex); 520 *pgnoaddr = mfp->last_pgno; 521 MUTEX_UNLOCK(env, mfp->mutex); 522 523 return (0); 524} 525 526/* 527 * __memp_fn -- 528 * On errors we print whatever is available as the file name. 529 * 530 * PUBLIC: char * __memp_fn __P((DB_MPOOLFILE *)); 531 */ 532char * 533__memp_fn(dbmfp) 534 DB_MPOOLFILE *dbmfp; 535{ 536 return (__memp_fns(dbmfp->env->mp_handle, dbmfp->mfp)); 537} 538 539/* 540 * __memp_fns -- 541 * On errors we print whatever is available as the file name. 542 * 543 * PUBLIC: char * __memp_fns __P((DB_MPOOL *, MPOOLFILE *)); 544 * 545 */ 546char * 547__memp_fns(dbmp, mfp) 548 DB_MPOOL *dbmp; 549 MPOOLFILE *mfp; 550{ 551 if (mfp == NULL || mfp->path_off == 0) 552 return ((char *)"unknown"); 553 554 return ((char *)R_ADDR(dbmp->reginfo, mfp->path_off)); 555} 556