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