00001
00002
00003
00004
00005
00006
00007
00008 #include "config.h"
00009
00010 #ifndef lint
00011 static const char revid[] = "$Id: env__region_8c-source.html,v 1.1 2008/06/08 10:18:46 sebdiaz Exp $";
00012 #endif
00013
00014 #ifndef NO_SYSTEM_INCLUDES
00015 #include <sys/types.h>
00016
00017 #include <ctype.h>
00018 #include <errno.h>
00019 #include <string.h>
00020 #include <unistd.h>
00021 #endif
00022
00023 #include "db_int.h"
00024
00025 static int __db_des_destroy __P((DB_ENV *, REGION *));
00026 static int __db_des_get __P((DB_ENV *, REGINFO *, REGINFO *, REGION **));
00027 static int __db_e_remfile __P((DB_ENV *));
00028 static int __db_faultmem __P((void *, size_t, int));
00029
00030
00031
00032
00033
00034
00035
00036 int
00037 CDB___db_e_attach(dbenv)
00038 DB_ENV *dbenv;
00039 {
00040 REGENV *renv;
00041 REGENV_REF ref;
00042 REGINFO *infop;
00043 REGION *rp, tregion;
00044 size_t size;
00045 size_t nrw;
00046 u_int32_t mbytes, bytes;
00047 int retry_cnt, ret, segid;
00048 char buf[sizeof(DB_REGION_FMT) + 20];
00049
00050 #if !defined(HAVE_MUTEX_THREADS)
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069 if (F_ISSET(dbenv, DB_ENV_THREAD)) {
00070 CDB___db_err(dbenv,
00071 "architecture lacks fast mutexes: applications cannot be threaded");
00072 return (EINVAL);
00073 }
00074 #endif
00075
00076
00077 retry_cnt = 0;
00078
00079
00080 loop: renv = NULL;
00081
00082
00083 if ((ret = CDB___os_calloc(dbenv, 1, sizeof(REGINFO), &infop)) != 0)
00084 return (ret);
00085 infop->id = REG_ID_ENV;
00086 infop->mode = dbenv->db_mode;
00087 if (F_ISSET(dbenv, DB_ENV_CREATE))
00088 F_SET(infop, REGION_CREATE_OK);
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101 if (F_ISSET(dbenv, DB_ENV_PRIVATE))
00102 goto creation;
00103
00104
00105 (void)snprintf(buf, sizeof(buf), "%s", DB_REGION_ENV);
00106 if ((ret = CDB___db_appname(dbenv,
00107 DB_APP_NONE, NULL, buf, 0, NULL, &infop->name)) != 0)
00108 goto err;
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118 if (F_ISSET(dbenv, DB_ENV_CREATE)) {
00119 if ((ret = CDB___os_open(dbenv,
00120 infop->name, DB_OSO_CREATE | DB_OSO_EXCL,
00121 dbenv->db_mode, dbenv->lockfhp)) == 0)
00122 goto creation;
00123 if (ret != EEXIST) {
00124 CDB___db_err(dbenv,
00125 "%s: %s", infop->name, CDB_db_strerror(ret));
00126 goto err;
00127 }
00128 }
00129
00130
00131
00132
00133
00134 if ((ret = CDB___os_open(dbenv,
00135 infop->name, 0, dbenv->db_mode, dbenv->lockfhp)) != 0)
00136 goto err;
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167 if ((ret = CDB___os_ioinfo(dbenv, infop->name,
00168 dbenv->lockfhp, &mbytes, &bytes, NULL)) != 0) {
00169 CDB___db_err(dbenv, "%s: %s", infop->name, CDB_db_strerror(ret));
00170 goto err;
00171 }
00172
00173
00174
00175
00176
00177
00178 size = mbytes * MEGABYTE + bytes;
00179
00180
00181
00182
00183
00184
00185
00186
00187
00188 if (size <= sizeof(ref)) {
00189 if (size != sizeof(ref))
00190 goto retry;
00191
00192 if ((ret = CDB___os_read(dbenv, dbenv->lockfhp, &ref,
00193 sizeof(ref), &nrw)) != 0 || nrw < (size_t)sizeof(ref)) {
00194 if (ret == 0)
00195 ret = EIO;
00196 CDB___db_err(dbenv,
00197 "%s: unable to read system-memory information from: %s",
00198 infop->name, CDB_db_strerror(ret));
00199 goto err;
00200 }
00201 size = ref.size;
00202 segid = ref.segid;
00203
00204 F_SET(dbenv, DB_ENV_SYSTEM_MEM);
00205 } else if (F_ISSET(dbenv, DB_ENV_SYSTEM_MEM)) {
00206 ret = EINVAL;
00207 CDB___db_err(dbenv,
00208 "%s: existing environment not created in system memory: %s",
00209 infop->name, CDB_db_strerror(ret));
00210 goto err;
00211 } else
00212 segid = INVALID_REGION_SEGID;
00213
00214
00215
00216
00217
00218
00219
00220 #ifdef HAVE_MUTEX_THREADS
00221 CDB___os_closehandle(dbenv->lockfhp);
00222 #endif
00223
00224
00225 memset(&tregion, 0, sizeof(tregion));
00226 tregion.size = size;
00227 tregion.segid = segid;
00228 if ((ret = CDB___os_r_attach(dbenv, infop, &tregion)) != 0)
00229 goto err;
00230
00231
00232
00233
00234
00235
00236
00237
00238 infop->primary = R_ADDR(infop, 0);
00239 infop->addr = (u_int8_t *)infop->addr + sizeof(REGENV);
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255 renv = infop->primary;
00256 if (renv->panic) {
00257 ret = CDB___db_panic_msg(dbenv);
00258 goto err;
00259 }
00260 if (renv->magic != DB_REGION_MAGIC)
00261 goto retry;
00262
00263
00264 MUTEX_LOCK(&renv->mutex, dbenv->lockfhp);
00265
00266
00267
00268
00269
00270 if (renv->panic) {
00271 ret = CDB___db_panic_msg(dbenv);
00272 goto err_unlock;
00273 }
00274
00275
00276
00277
00278
00279 if ((ret = __db_des_get(dbenv,
00280 infop, infop, &rp)) != 0 || rp == NULL) {
00281 MUTEX_UNLOCK(&renv->mutex);
00282 goto find_err;
00283 }
00284 infop->rp = rp;
00285
00286
00287
00288
00289
00290
00291
00292
00293
00294 if (rp->size != size) {
00295 err_unlock: MUTEX_UNLOCK(&renv->mutex);
00296 goto retry;
00297 }
00298
00299
00300 ++renv->refcnt;
00301
00302
00303 MUTEX_UNLOCK(&renv->mutex);
00304
00305
00306
00307
00308
00309 (void)__db_faultmem(infop->primary, rp->size, 0);
00310
00311
00312 dbenv->reginfo = infop;
00313 return (0);
00314
00315 creation:
00316
00317 F_SET(infop, REGION_CREATE);
00318
00319
00320
00321
00322
00323
00324 memset(&tregion, 0, sizeof(tregion));
00325 tregion.size = 50 * sizeof(REGION) + 50 * sizeof(MUTEX) + 2048;
00326 tregion.segid = INVALID_REGION_SEGID;
00327 if ((ret = CDB___os_r_attach(dbenv, infop, &tregion)) != 0)
00328 goto err;
00329
00330
00331
00332
00333
00334 (void)__db_faultmem(infop->addr, tregion.size, 1);
00335
00336
00337
00338
00339
00340
00341
00342
00343
00344
00345
00346
00347
00348
00349
00350
00351
00352
00353
00354 infop->primary = R_ADDR(infop, 0);
00355 infop->addr = (u_int8_t *)infop->addr + sizeof(REGENV);
00356 CDB___db_shalloc_init(infop->addr, tregion.size - sizeof(REGENV));
00357
00358
00359
00360
00361
00362 renv = infop->primary;
00363 renv->panic = 0;
00364 CDB_db_version(&renv->majver, &renv->minver, &renv->patch);
00365 SH_LIST_INIT(&renv->regionq);
00366 renv->refcnt = 1;
00367
00368
00369
00370
00371
00372
00373
00374
00375
00376
00377 if ((ret =
00378 __db_mutex_init(dbenv, &renv->mutex, DB_FCNTL_OFF_GEN, 0)) != 0) {
00379 CDB___db_err(dbenv, "%s: unable to initialize environment lock: %s",
00380 infop->name, CDB_db_strerror(ret));
00381 goto err;
00382 }
00383
00384 if (!F_ISSET(&renv->mutex, MUTEX_IGNORE) &&
00385 (ret = __db_mutex_lock(&renv->mutex, dbenv->lockfhp)) != 0) {
00386 CDB___db_err(dbenv, "%s: unable to acquire environment lock: %s",
00387 infop->name, CDB_db_strerror(ret));
00388 goto err;
00389 }
00390
00391
00392
00393
00394
00395
00396
00397 if ((ret = __db_des_get(dbenv, infop, infop, &rp)) != 0) {
00398 find_err: CDB___db_err(dbenv,
00399 "%s: unable to find environment", infop->name);
00400 if (ret == 0)
00401 ret = EINVAL;
00402 goto err;
00403 }
00404 infop->rp = rp;
00405 rp->size = tregion.size;
00406 rp->segid = tregion.segid;
00407
00408
00409
00410
00411
00412
00413
00414
00415
00416
00417
00418
00419
00420
00421 if (tregion.segid != INVALID_REGION_SEGID) {
00422 ref.size = tregion.size;
00423 ref.segid = tregion.segid;
00424 if ((ret = CDB___os_write(dbenv, dbenv->lockfhp,
00425 &ref, sizeof(ref), &nrw)) != 0 || nrw != sizeof(ref)) {
00426 CDB___db_err(dbenv,
00427 "%s: unable to write out public environment ID: %s",
00428 infop->name, CDB_db_strerror(ret));
00429 goto err;
00430 }
00431 }
00432
00433
00434
00435
00436
00437
00438
00439 #if defined(HAVE_MUTEX_THREADS)
00440 if (F_ISSET(dbenv->lockfhp, DB_FH_VALID))
00441 CDB___os_closehandle(dbenv->lockfhp);
00442 #endif
00443
00444
00445 renv->magic = DB_REGION_MAGIC;
00446
00447
00448 MUTEX_UNLOCK(&renv->mutex);
00449
00450
00451 dbenv->reginfo = infop;
00452 return (0);
00453
00454 err:
00455 retry:
00456 if (F_ISSET(dbenv->lockfhp, DB_FH_VALID))
00457 (void)CDB___os_closehandle(dbenv->lockfhp);
00458
00459
00460
00461
00462
00463
00464
00465
00466 if (infop->addr != NULL) {
00467 if (infop->rp == NULL)
00468 infop->rp = &tregion;
00469
00470
00471 infop->addr = infop->primary;
00472 (void)CDB___os_r_detach(dbenv,
00473 infop, F_ISSET(infop, REGION_CREATE));
00474 }
00475
00476
00477 if (infop->name != NULL)
00478 CDB___os_freestr(infop->name);
00479 CDB___os_free(infop, sizeof(REGINFO));
00480
00481
00482 if (ret == 0) {
00483 if (++retry_cnt > 3) {
00484 CDB___db_err(dbenv, "unable to join the environment");
00485 ret = EAGAIN;
00486 } else {
00487 CDB___os_sleep(dbenv, retry_cnt * 3, 0);
00488 goto loop;
00489 }
00490 }
00491
00492 return (ret);
00493 }
00494
00495
00496
00497
00498
00499
00500
00501 int
00502 CDB___db_e_detach(dbenv, destroy)
00503 DB_ENV *dbenv;
00504 int destroy;
00505 {
00506 REGENV *renv;
00507 REGINFO *infop;
00508
00509 infop = dbenv->reginfo;
00510 renv = infop->primary;
00511
00512
00513 MUTEX_LOCK(&renv->mutex, dbenv->lockfhp);
00514
00515
00516 if (renv->refcnt == 0) {
00517 CDB___db_err(dbenv,
00518 "region %lu (environment): reference count went negative",
00519 infop->rp->id);
00520 } else
00521 --renv->refcnt;
00522
00523
00524 MUTEX_UNLOCK(&renv->mutex);
00525
00526
00527 if (F_ISSET(dbenv->lockfhp, DB_FH_VALID))
00528 (void)CDB___os_closehandle(dbenv->lockfhp);
00529
00530
00531 infop->addr = infop->primary;
00532
00533
00534
00535
00536
00537
00538
00539
00540
00541
00542 (void)CDB___os_r_detach(dbenv, infop, destroy);
00543
00544 if (infop->name != NULL)
00545 CDB___os_free(infop->name, 0);
00546 CDB___os_free(dbenv->reginfo, sizeof(REGINFO));
00547 dbenv->reginfo = NULL;
00548
00549 return (0);
00550 }
00551
00552
00553
00554
00555
00556
00557
00558 int
00559 CDB___db_e_remove(dbenv, force)
00560 DB_ENV *dbenv;
00561 int force;
00562 {
00563 REGENV *renv;
00564 REGINFO *infop, reginfo;
00565 REGION *rp;
00566 int ret, saved_value;
00567
00568
00569
00570
00571
00572
00573
00574
00575
00576
00577
00578
00579
00580
00581
00582
00583
00584
00585
00586
00587
00588
00589 saved_value = DB_GLOBAL(db_mutexlocks);
00590 if (force)
00591 DB_GLOBAL(db_mutexlocks) = 0;
00592
00593
00594 if ((ret = CDB___db_e_attach(dbenv)) != 0) {
00595
00596
00597
00598
00599
00600 ret = 0;
00601 if (force)
00602 goto remfiles;
00603 goto err;
00604 }
00605
00606 infop = dbenv->reginfo;
00607 renv = infop->primary;
00608
00609
00610 MUTEX_LOCK(&renv->mutex, dbenv->lockfhp);
00611
00612
00613 if (renv->refcnt == 1 || force) {
00614
00615
00616
00617
00618
00619
00620
00621 renv->panic = 1;
00622 renv->magic = 0;
00623
00624
00625
00626
00627
00628
00629 MUTEX_UNLOCK(&renv->mutex);
00630
00631
00632
00633
00634
00635
00636
00637
00638
00639
00640 memset(®info, 0, sizeof(reginfo));
00641 restart: for (rp = SH_LIST_FIRST(&renv->regionq, __db_region);
00642 rp != NULL; rp = SH_LIST_NEXT(rp, q, __db_region)) {
00643 if (rp->id == REG_ID_ENV)
00644 continue;
00645
00646 reginfo.id = rp->id;
00647 reginfo.flags = REGION_CREATE_OK;
00648 if (CDB___db_r_attach(dbenv, ®info, 0) == 0) {
00649 R_UNLOCK(dbenv, ®info);
00650 (void)CDB___db_r_detach(dbenv, ®info, 1);
00651 }
00652 goto restart;
00653 }
00654
00655
00656 (void)CDB___db_e_detach(dbenv, 1);
00657
00658
00659 remfiles: (void)__db_e_remfile(dbenv);
00660 } else {
00661
00662 MUTEX_UNLOCK(&renv->mutex);
00663
00664
00665 (void)CDB___db_e_detach(dbenv, 0);
00666
00667 ret = EBUSY;
00668 }
00669
00670 err: if (force)
00671 DB_GLOBAL(db_mutexlocks) = saved_value;
00672
00673 return (ret);
00674 }
00675
00676
00677
00678
00679
00680 static int
00681 __db_e_remfile(dbenv)
00682 DB_ENV *dbenv;
00683 {
00684 static char *old_region_names[] = {
00685 "__db_lock.share",
00686 "__db_log.share",
00687 "__db_mpool.share",
00688 "__db_txn.share",
00689 NULL,
00690 };
00691 int cnt, fcnt, lastrm, ret;
00692 u_int8_t saved_byte;
00693 const char *dir;
00694 char *p, **names, *path, buf[sizeof(DB_REGION_FMT) + 20];
00695
00696
00697 (void)snprintf(buf, sizeof(buf), "%s", DB_REGION_ENV);
00698 if ((ret =
00699 CDB___db_appname(dbenv, DB_APP_NONE, NULL, buf, 0, NULL, &path)) != 0)
00700 return (ret);
00701
00702
00703 if ((p = CDB___db_rpath(path)) == NULL) {
00704 p = path;
00705 saved_byte = *p;
00706
00707 dir = PATH_DOT;
00708 } else {
00709 saved_byte = *p;
00710 *p = '\0';
00711
00712 dir = path;
00713 }
00714
00715
00716 ret = CDB___os_dirlist(dbenv, dir, &names, &fcnt);
00717
00718
00719 *p = saved_byte;
00720 CDB___os_freestr(path);
00721
00722 if (ret != 0) {
00723 CDB___db_err(dbenv, "%s: %s", dir, CDB_db_strerror(ret));
00724 return (ret);
00725 }
00726
00727
00728
00729
00730
00731 for (lastrm = -1, cnt = fcnt; --cnt >= 0;) {
00732 if (strlen(names[cnt]) != DB_REGION_NAME_LENGTH ||
00733 memcmp(names[cnt], DB_REGION_FMT, DB_REGION_NAME_NUM) != 0)
00734 continue;
00735 if (strcmp(names[cnt], DB_REGION_ENV) == 0) {
00736 lastrm = cnt;
00737 continue;
00738 }
00739 for (p = names[cnt] + DB_REGION_NAME_NUM;
00740 *p != '\0' && isdigit((int)*p); ++p)
00741 ;
00742 if (*p != '\0')
00743 continue;
00744
00745 if (CDB___db_appname(dbenv,
00746 DB_APP_NONE, NULL, names[cnt], 0, NULL, &path) == 0) {
00747 (void)CDB___os_unlink(dbenv, path);
00748 CDB___os_freestr(path);
00749 }
00750 }
00751
00752 if (lastrm != -1)
00753 if (CDB___db_appname(dbenv,
00754 DB_APP_NONE, NULL, names[lastrm], 0, NULL, &path) == 0) {
00755 (void)CDB___os_unlink(dbenv, path);
00756 CDB___os_freestr(path);
00757 }
00758 CDB___os_dirfree(names, fcnt);
00759
00760
00761
00762
00763
00764
00765 for (names = (char **)old_region_names; *names != NULL; ++names)
00766 if (CDB___db_appname(dbenv,
00767 DB_APP_NONE, NULL, *names, 0, NULL, &path) == 0) {
00768 (void)CDB___os_unlink(dbenv, path);
00769 CDB___os_freestr(path);
00770 }
00771
00772 return (0);
00773 }
00774
00775
00776
00777
00778
00779
00780
00781 int
00782 CDB___db_e_stat(dbenv, arg_renv, arg_regions, arg_regions_cnt)
00783 DB_ENV *dbenv;
00784 REGENV *arg_renv;
00785 REGION *arg_regions;
00786 int *arg_regions_cnt;
00787 {
00788 REGENV *renv;
00789 REGINFO *infop;
00790 REGION *rp;
00791 int n;
00792
00793 infop = dbenv->reginfo;
00794 renv = infop->primary;
00795 rp = infop->rp;
00796
00797
00798 MUTEX_LOCK(&rp->mutex, dbenv->lockfhp);
00799
00800 *arg_renv = *renv;
00801
00802 for (n = 0, rp = SH_LIST_FIRST(&renv->regionq, __db_region);
00803 n < *arg_regions_cnt && rp != NULL;
00804 ++n, rp = SH_LIST_NEXT(rp, q, __db_region))
00805 arg_regions[n] = *rp;
00806
00807
00808 rp = infop->rp;
00809 MUTEX_UNLOCK(&rp->mutex);
00810
00811 *arg_regions_cnt = n == 0 ? n : n - 1;
00812
00813 return (0);
00814 }
00815
00816
00817
00818
00819
00820
00821
00822 int
00823 CDB___db_r_attach(dbenv, infop, size)
00824 DB_ENV *dbenv;
00825 REGINFO *infop;
00826 size_t size;
00827 {
00828 REGENV *renv;
00829 REGION *rp;
00830 int ret;
00831 char buf[sizeof(DB_REGION_FMT) + 20];
00832
00833 renv = ((REGINFO *)dbenv->reginfo)->primary;
00834 F_CLR(infop, REGION_CREATE);
00835
00836
00837 MUTEX_LOCK(&renv->mutex, dbenv->lockfhp);
00838
00839
00840 if ((ret = __db_des_get(dbenv, dbenv->reginfo, infop, &rp)) != 0) {
00841 MUTEX_UNLOCK(&renv->mutex);
00842 return (ret);
00843 }
00844 infop->rp = rp;
00845 infop->id = rp->id;
00846
00847
00848 if (F_ISSET(infop, REGION_CREATE))
00849 rp->size = size;
00850
00851
00852 (void)snprintf(buf, sizeof(buf), DB_REGION_FMT, infop->id);
00853 if ((ret = CDB___db_appname(dbenv,
00854 DB_APP_NONE, NULL, buf, 0, NULL, &infop->name)) != 0)
00855 goto err;
00856 if ((ret = CDB___os_r_attach(dbenv, infop, rp)) != 0)
00857 goto err;
00858
00859
00860
00861
00862
00863
00864 (void)__db_faultmem(infop->addr,
00865 rp->size, F_ISSET(infop, REGION_CREATE));
00866
00867
00868
00869
00870
00871
00872
00873
00874
00875 if (F_ISSET(infop, REGION_CREATE)) {
00876 ((REGION *)(infop->addr))->magic = DB_REGION_MAGIC;
00877
00878 (void)CDB___db_shalloc_init(infop->addr, rp->size);
00879 }
00880
00881
00882
00883
00884
00885 if (infop->id != REG_ID_ENV) {
00886 MUTEX_LOCK(&rp->mutex, dbenv->lockfhp);
00887 MUTEX_UNLOCK(&renv->mutex);
00888 }
00889
00890 return (0);
00891
00892
00893 err: if (infop->addr != NULL)
00894 (void)CDB___os_r_detach(dbenv,
00895 infop, F_ISSET(infop, REGION_CREATE));
00896 infop->rp = NULL;
00897 infop->id = REG_ID_INVALID;
00898
00899
00900 if (F_ISSET(infop, REGION_CREATE))
00901 (void)__db_des_destroy(dbenv, rp);
00902
00903
00904 MUTEX_UNLOCK(&renv->mutex);
00905
00906 return (ret);
00907 }
00908
00909
00910
00911
00912
00913
00914
00915 int
00916 CDB___db_r_detach(dbenv, infop, destroy)
00917 DB_ENV *dbenv;
00918 REGINFO *infop;
00919 int destroy;
00920 {
00921 REGENV *renv;
00922 REGION *rp;
00923 int ret, t_ret;
00924
00925 renv = ((REGINFO *)dbenv->reginfo)->primary;
00926 rp = infop->rp;
00927
00928
00929 MUTEX_LOCK(&renv->mutex, dbenv->lockfhp);
00930
00931
00932 MUTEX_LOCK(&rp->mutex, dbenv->lockfhp);
00933
00934
00935 ret = CDB___os_r_detach(dbenv, infop, destroy);
00936
00937
00938 MUTEX_UNLOCK(&rp->mutex);
00939
00940
00941 if (destroy &&
00942 ((t_ret = __db_des_destroy(dbenv, rp)) != 0) && ret == 0)
00943 ret = t_ret;
00944
00945
00946 MUTEX_UNLOCK(&renv->mutex);
00947
00948
00949 if (infop->name != NULL)
00950 CDB___os_freestr(infop->name);
00951
00952 return (ret);
00953 }
00954
00955
00956
00957
00958
00959
00960 static int
00961 __db_des_get(dbenv, env_infop, infop, rpp)
00962 DB_ENV *dbenv;
00963 REGINFO *env_infop, *infop;
00964 REGION **rpp;
00965 {
00966 REGENV *renv;
00967 REGION *rp;
00968 int maxid, ret;
00969
00970
00971
00972
00973
00974 *rpp = NULL;
00975 renv = env_infop->primary;
00976
00977 maxid = REG_ID_ASSIGN;
00978 for (rp = SH_LIST_FIRST(&renv->regionq, __db_region);
00979 rp != NULL; rp = SH_LIST_NEXT(rp, q, __db_region)) {
00980 if (rp->id == infop->id)
00981 break;
00982 if (rp->id > maxid)
00983 maxid = rp->id;
00984 }
00985
00986
00987
00988
00989
00990
00991 if (!F_ISSET(infop, REGION_CREATE_OK) &&
00992 (rp == NULL || F_ISSET(rp, REG_DEAD)))
00993 return (ENOENT);
00994
00995
00996
00997
00998
00999
01000 if (rp == NULL) {
01001 if ((ret = CDB___db_shalloc(env_infop->addr,
01002 sizeof(REGION), MUTEX_ALIGN, &rp)) != 0)
01003 return (ret);
01004
01005
01006 memset(rp, 0, sizeof(*rp));
01007 if ((ret = __db_mutex_init(dbenv, &rp->mutex,
01008 R_OFFSET(env_infop, &rp->mutex) + DB_FCNTL_OFF_GEN,
01009 0)) != 0) {
01010 CDB___db_shalloc_free(env_infop->addr, rp);
01011 return (ret);
01012 }
01013 rp->segid = INVALID_REGION_SEGID;
01014 rp->id = infop->id == REG_ID_INVALID ? maxid + 1 : infop->id;
01015
01016 SH_LIST_INSERT_HEAD(&renv->regionq, rp, q, __db_region);
01017 F_SET(infop, REGION_CREATE);
01018 } else {
01019
01020
01021
01022
01023
01024
01025
01026 if (F_ISSET(rp, REG_DEAD)) {
01027 rp->primary = INVALID_ROFF;
01028
01029 F_CLR(rp, REG_DEAD);
01030 F_SET(infop, REGION_CREATE);
01031 }
01032 }
01033
01034 *rpp = rp;
01035 return (0);
01036 }
01037
01038
01039
01040
01041
01042 static int
01043 __db_des_destroy(dbenv, rp)
01044 DB_ENV *dbenv;
01045 REGION *rp;
01046 {
01047 REGINFO *infop;
01048
01049
01050
01051
01052
01053 infop = dbenv->reginfo;
01054
01055 SH_LIST_REMOVE(rp, q, __db_region);
01056 CDB___db_shalloc_free(infop->addr, rp);
01057
01058 return (0);
01059 }
01060
01061
01062
01063
01064
01065 static int
01066 __db_faultmem(addr, size, created)
01067 void *addr;
01068 size_t size;
01069 int created;
01070 {
01071 int ret;
01072 u_int8_t *p, *t;
01073
01074
01075
01076
01077
01078
01079
01080
01081
01082
01083
01084
01085
01086 ret = 0;
01087 if (DB_GLOBAL(db_region_init)) {
01088 if (created)
01089 for (p = addr, t = (u_int8_t *)addr + size;
01090 p < t; p += OS_VMPAGESIZE)
01091 p[0] = 0xdb;
01092 else
01093 for (p = addr, t = (u_int8_t *)addr + size;
01094 p < t; p += OS_VMPAGESIZE)
01095 ret |= p[0];
01096 }
01097
01098 return (ret);
01099 }