00001
00002
00003
00004
00005
00006
00007
00008
00009
00010 #include "db_config.h"
00011
00012 #ifndef NO_SYSTEM_INCLUDES
00013 #include <sys/types.h>
00014
00015 #if TIME_WITH_SYS_TIME
00016 #include <sys/time.h>
00017 #include <time.h>
00018 #else
00019 #if HAVE_SYS_TIME_H
00020 #include <sys/time.h>
00021 #else
00022 #include <time.h>
00023 #endif
00024 #endif
00025
00026 #include <string.h>
00027 #endif
00028
00029 #include "db_int.h"
00030 #include "dbinc/db_shash.h"
00031 #include "dbinc/crypto.h"
00032 #include "dbinc/mp.h"
00033
00034 static void __db_des_destroy __P((DB_ENV *, REGION *));
00035 static int __db_des_get __P((DB_ENV *, REGINFO *, REGINFO *, REGION **));
00036 static int __db_e_remfile __P((DB_ENV *));
00037 static int __db_faultmem __P((DB_ENV *, void *, size_t, int));
00038
00039
00040
00041
00042
00043
00044
00045 int
00046 __db_e_attach(dbenv, init_flagsp)
00047 DB_ENV *dbenv;
00048 u_int32_t *init_flagsp;
00049 {
00050 REGENV *renv;
00051 REGENV_REF ref;
00052 REGINFO *infop;
00053 REGION *rp, tregion;
00054 size_t size;
00055 size_t nrw;
00056 u_int32_t bytes, i, mbytes, nregions;
00057 u_int retry_cnt;
00058 int majver, minver, patchver, ret, segid;
00059 char buf[sizeof(DB_REGION_FMT) + 20];
00060
00061
00062 retry_cnt = 0;
00063
00064
00065 loop: renv = NULL;
00066
00067
00068 if ((ret = __os_calloc(dbenv, 1, sizeof(REGINFO), &infop)) != 0)
00069 return (ret);
00070 infop->dbenv = dbenv;
00071 infop->type = REGION_TYPE_ENV;
00072 infop->id = REGION_ID_ENV;
00073 infop->flags = REGION_JOIN_OK;
00074 if (F_ISSET(dbenv, DB_ENV_CREATE))
00075 F_SET(infop, REGION_CREATE_OK);
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088 if (F_ISSET(dbenv, DB_ENV_PRIVATE)) {
00089 if ((ret = __os_strdup(dbenv,
00090 "process-private", &infop->name)) != 0)
00091 goto err;
00092 goto creation;
00093 }
00094
00095
00096 (void)snprintf(buf, sizeof(buf), "%s", DB_REGION_ENV);
00097 if ((ret = __db_appname(dbenv,
00098 DB_APP_NONE, buf, 0, NULL, &infop->name)) != 0)
00099 goto err;
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109 if (F_ISSET(dbenv, DB_ENV_CREATE)) {
00110 if ((ret = __os_open(dbenv, infop->name,
00111 DB_OSO_CREATE | DB_OSO_EXCL | DB_OSO_REGION,
00112 dbenv->db_mode, &dbenv->lockfhp)) == 0)
00113 goto creation;
00114 if (ret != EEXIST) {
00115 __db_err(dbenv,
00116 "%s: %s", infop->name, db_strerror(ret));
00117 goto err;
00118 }
00119 }
00120
00121
00122
00123
00124
00125 if ((ret = __os_open(
00126 dbenv, infop->name, DB_OSO_REGION, 0, &dbenv->lockfhp)) != 0)
00127 goto err;
00128
00129
00130 F_CLR(infop, REGION_CREATE_OK);
00131
00132
00133
00134
00135
00136
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 if ((ret = __os_ioinfo(dbenv, infop->name,
00162 dbenv->lockfhp, &mbytes, &bytes, NULL)) != 0) {
00163 __db_err(dbenv, "%s: %s", infop->name, db_strerror(ret));
00164 goto err;
00165 }
00166
00167
00168
00169
00170
00171
00172 size = mbytes * MEGABYTE + bytes;
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183 if (size <= sizeof(ref)) {
00184 if (size != sizeof(ref))
00185 goto retry;
00186
00187 if ((ret = __os_read(dbenv, dbenv->lockfhp, &ref,
00188 sizeof(ref), &nrw)) != 0 || nrw < (size_t)sizeof(ref)) {
00189 if (ret == 0)
00190 ret = EIO;
00191 __db_err(dbenv,
00192 "%s: unable to read system-memory information from: %s",
00193 infop->name, db_strerror(ret));
00194 goto err;
00195 }
00196 size = ref.size;
00197 segid = ref.segid;
00198
00199 F_SET(dbenv, DB_ENV_SYSTEM_MEM);
00200 } else if (F_ISSET(dbenv, DB_ENV_SYSTEM_MEM)) {
00201 ret = EINVAL;
00202 __db_err(dbenv,
00203 "%s: existing environment not created in system memory: %s",
00204 infop->name, db_strerror(ret));
00205 goto err;
00206 } else
00207 segid = INVALID_REGION_SEGID;
00208
00209 #ifndef HAVE_MUTEX_FCNTL
00210
00211
00212
00213
00214
00215 (void)__os_closehandle(dbenv, dbenv->lockfhp);
00216 dbenv->lockfhp = NULL;
00217 #endif
00218
00219
00220 memset(&tregion, 0, sizeof(tregion));
00221 tregion.size = (roff_t)size;
00222 tregion.segid = segid;
00223 if ((ret = __os_r_attach(dbenv, infop, &tregion)) != 0)
00224 goto err;
00225
00226
00227
00228
00229
00230
00231
00232
00233 infop->primary = infop->addr;
00234 infop->addr = (u_int8_t *)infop->addr + sizeof(REGENV);
00235 renv = infop->primary;
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245 if (renv->majver != DB_VERSION_MAJOR ||
00246 renv->minver != DB_VERSION_MINOR) {
00247 if (renv->majver != 0 || renv->minver != 0) {
00248 __db_err(dbenv,
00249 "Program version %d.%d doesn't match environment version %d.%d",
00250 DB_VERSION_MAJOR, DB_VERSION_MINOR,
00251 renv->majver, renv->minver);
00252 ret = DB_VERSION_MISMATCH;
00253 } else
00254 ret = EINVAL;
00255 goto err;
00256 }
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272 if (renv->panic && !F_ISSET(dbenv, DB_ENV_NOPANIC)) {
00273 ret = __db_panic_msg(dbenv);
00274 goto err;
00275 }
00276 if (renv->magic != DB_REGION_MAGIC)
00277 goto retry;
00278
00279
00280
00281
00282
00283 if ((ret = __db_des_get(dbenv, infop, infop, &rp)) != 0 || rp == NULL)
00284 goto find_err;
00285 infop->rp = rp;
00286
00287
00288
00289
00290
00291
00292
00293
00294
00295 if (rp->size != size)
00296 goto retry;
00297
00298
00299 MUTEX_LOCK(dbenv, renv->mtx_regenv);
00300 ++renv->refcnt;
00301 MUTEX_UNLOCK(dbenv, renv->mtx_regenv);
00302
00303
00304
00305
00306
00307
00308
00309 if (init_flagsp != NULL) {
00310 FLD_CLR(*init_flagsp, renv->init_flags);
00311 if (*init_flagsp != 0) {
00312 __db_err(dbenv,
00313 "configured environment flags incompatible with existing environment");
00314 ret = EINVAL;
00315 goto err;
00316 }
00317 *init_flagsp = renv->init_flags;
00318 }
00319
00320
00321
00322
00323
00324 (void)__db_faultmem(dbenv, infop->primary, rp->size, 0);
00325
00326
00327 dbenv->reginfo = infop;
00328 return (0);
00329
00330 creation:
00331
00332 F_SET(infop, REGION_CREATE);
00333
00334
00335
00336
00337
00338
00339
00340
00341
00342 memset(&tregion, 0, sizeof(tregion));
00343 nregions = dbenv->mp_ncache + 10;
00344 tregion.size =
00345 (roff_t)(nregions * sizeof(REGION) + dbenv->passwd_len + 16 * 1024);
00346 tregion.segid = INVALID_REGION_SEGID;
00347 if ((ret = __os_r_attach(dbenv, infop, &tregion)) != 0)
00348 goto err;
00349
00350
00351
00352
00353
00354 (void)__db_faultmem(dbenv, infop->addr, tregion.size, 1);
00355
00356
00357
00358
00359
00360
00361
00362
00363
00364
00365
00366
00367
00368
00369
00370
00371
00372
00373
00374 infop->primary = infop->addr;
00375 infop->addr = (u_int8_t *)infop->addr + sizeof(REGENV);
00376 __db_shalloc_init(infop, tregion.size - sizeof(REGENV));
00377
00378
00379
00380
00381
00382 renv = infop->primary;
00383 renv->magic = 0;
00384 renv->panic = 0;
00385
00386 (void)db_version(&majver, &minver, &patchver);
00387 renv->majver = (u_int32_t)majver;
00388 renv->minver = (u_int32_t)minver;
00389 renv->patchver = (u_int32_t)patchver;
00390
00391 (void)time(&renv->timestamp);
00392 __os_unique_id(dbenv, &renv->envid);
00393
00394 if ((ret = __mutex_alloc(
00395 dbenv, MTX_ENV_REGION, 0, &renv->mtx_regenv)) != 0)
00396 goto err;
00397 renv->refcnt = 1;
00398
00399
00400
00401
00402
00403 renv->init_flags = (init_flagsp == NULL) ? 0 : *init_flagsp;
00404
00405
00406
00407
00408
00409
00410
00411 renv->region_cnt = nregions;
00412 if ((ret =
00413 __db_shalloc(infop, nregions * sizeof(REGION), 0, &rp)) != 0) {
00414 __db_err(dbenv, "unable to create new master region array: %s",
00415 db_strerror(ret));
00416 goto err;
00417 }
00418 renv->region_off = R_OFFSET(infop, rp);
00419 for (i = 0; i < nregions; ++i, ++rp)
00420 rp->id = INVALID_REGION_ID;
00421
00422 renv->cipher_off = INVALID_ROFF;
00423
00424 renv->rep_off = INVALID_ROFF;
00425 renv->flags = 0;
00426 renv->op_timestamp = renv->rep_timestamp = 0;
00427
00428
00429
00430
00431
00432
00433
00434 if ((ret = __db_des_get(dbenv, infop, infop, &rp)) != 0) {
00435 find_err: __db_err(dbenv, "%s: unable to find environment", infop->name);
00436 if (ret == 0)
00437 ret = EINVAL;
00438 goto err;
00439 }
00440 infop->rp = rp;
00441 rp->size = tregion.size;
00442 rp->segid = tregion.segid;
00443
00444
00445
00446
00447
00448
00449
00450
00451
00452
00453
00454
00455
00456
00457 if (tregion.segid != INVALID_REGION_SEGID) {
00458 ref.size = tregion.size;
00459 ref.segid = tregion.segid;
00460 if ((ret = __os_write(
00461 dbenv, dbenv->lockfhp, &ref, sizeof(ref), &nrw)) != 0) {
00462 __db_err(dbenv,
00463 "%s: unable to write out public environment ID: %s",
00464 infop->name, db_strerror(ret));
00465 goto err;
00466 }
00467 }
00468
00469 #ifndef HAVE_MUTEX_FCNTL
00470
00471
00472
00473
00474
00475 if (dbenv->lockfhp != NULL) {
00476 (void)__os_closehandle(dbenv, dbenv->lockfhp);
00477 dbenv->lockfhp = NULL;
00478 }
00479 #endif
00480
00481
00482 dbenv->reginfo = infop;
00483 return (0);
00484
00485 err:
00486 retry:
00487 if (dbenv->lockfhp != NULL) {
00488 (void)__os_closehandle(dbenv, dbenv->lockfhp);
00489 dbenv->lockfhp = NULL;
00490 }
00491
00492
00493
00494
00495
00496
00497
00498
00499 if (infop->addr != NULL) {
00500 if (infop->rp == NULL)
00501 infop->rp = &tregion;
00502
00503
00504 infop->addr = infop->primary;
00505 (void)__os_r_detach(dbenv,
00506 infop, F_ISSET(infop, REGION_CREATE));
00507 }
00508
00509
00510 if (infop->name != NULL)
00511 __os_free(dbenv, infop->name);
00512 __os_free(dbenv, infop);
00513
00514
00515 if (ret == 0) {
00516 if (++retry_cnt > 3) {
00517 __db_err(dbenv, "unable to join the environment");
00518 ret = EAGAIN;
00519 } else {
00520 __os_sleep(dbenv, retry_cnt * 3, 0);
00521 goto loop;
00522 }
00523 }
00524
00525 return (ret);
00526 }
00527
00528
00529
00530
00531
00532
00533
00534 int
00535 __db_e_golive(dbenv)
00536 DB_ENV *dbenv;
00537 {
00538 REGENV *renv;
00539 REGINFO *infop;
00540
00541 infop = dbenv->reginfo;
00542 renv = infop->primary;
00543
00544
00545 if (!F_ISSET(infop, REGION_CREATE))
00546 return (0);
00547
00548
00549
00550
00551
00552 renv->magic = DB_REGION_MAGIC;
00553
00554 return (0);
00555 }
00556
00557
00558
00559
00560
00561
00562
00563 int
00564 __db_e_detach(dbenv, destroy)
00565 DB_ENV *dbenv;
00566 int destroy;
00567 {
00568 REGENV *renv;
00569 REGINFO *infop;
00570 REGION rp;
00571 int ret, t_ret;
00572
00573 infop = dbenv->reginfo;
00574 renv = infop->primary;
00575 ret = 0;
00576
00577 if (F_ISSET(dbenv, DB_ENV_PRIVATE))
00578 destroy = 1;
00579
00580
00581 MUTEX_LOCK(dbenv, renv->mtx_regenv);
00582 if (renv->refcnt == 0)
00583 __db_err(dbenv, "environment reference count went negative");
00584 else
00585 --renv->refcnt;
00586 MUTEX_UNLOCK(dbenv, renv->mtx_regenv);
00587
00588
00589 if (dbenv->lockfhp != NULL) {
00590 if ((t_ret =
00591 __os_closehandle(dbenv, dbenv->lockfhp)) != 0 && ret == 0)
00592 ret = t_ret;
00593 dbenv->lockfhp = NULL;
00594 }
00595
00596
00597
00598
00599 if (destroy) {
00600 #ifdef HAVE_CRYPTO
00601
00602
00603
00604
00605 if ((t_ret = __crypto_region_destroy(dbenv)) != 0 && ret == 0)
00606 ret = t_ret;
00607 #endif
00608
00609
00610
00611
00612 if ((t_ret = __rep_region_destroy(dbenv)) != 0 && ret == 0)
00613 ret = t_ret;
00614
00615
00616
00617
00618
00619
00620
00621
00622
00623 rp = *infop->rp;
00624 infop->rp = &rp;
00625
00626 if (renv->region_off != INVALID_ROFF)
00627 __db_shalloc_free(
00628 infop, R_ADDR(infop, renv->region_off));
00629
00630
00631 if ((t_ret =
00632 __mutex_free(dbenv, &renv->mtx_regenv)) != 0 && ret == 0)
00633 ret = t_ret;
00634 }
00635
00636
00637
00638
00639
00640
00641
00642
00643
00644
00645
00646
00647 dbenv->reginfo = NULL;
00648
00649
00650 infop->addr = infop->primary;
00651
00652 if ((t_ret = __os_r_detach(dbenv, infop, destroy)) != 0 && ret == 0)
00653 ret = t_ret;
00654 if (infop->name != NULL)
00655 __os_free(dbenv, infop->name);
00656
00657
00658 __os_free(dbenv, infop);
00659
00660 return (ret);
00661 }
00662
00663
00664
00665
00666
00667
00668
00669 int
00670 __db_e_remove(dbenv, flags)
00671 DB_ENV *dbenv;
00672 u_int32_t flags;
00673 {
00674 REGENV *renv;
00675 REGINFO *infop, reginfo;
00676 REGION *rp;
00677 u_int32_t db_env_reset, i;
00678 int ret;
00679
00680 db_env_reset = F_ISSET(dbenv, DB_ENV_NOLOCKING | DB_ENV_NOPANIC);
00681
00682
00683
00684
00685
00686
00687
00688
00689
00690
00691
00692
00693
00694
00695
00696
00697
00698
00699
00700
00701
00702
00703
00704
00705
00706
00707
00708
00709 if (LF_ISSET(DB_FORCE))
00710 F_SET(dbenv, DB_ENV_NOLOCKING);
00711 F_SET(dbenv, DB_ENV_NOPANIC);
00712
00713
00714 if ((ret = __db_e_attach(dbenv, NULL)) != 0) {
00715
00716
00717
00718
00719
00720 ret = 0;
00721 if (LF_ISSET(DB_FORCE))
00722 goto remfiles;
00723 goto done;
00724 }
00725
00726 infop = dbenv->reginfo;
00727 renv = infop->primary;
00728
00729
00730 MUTEX_LOCK(dbenv, renv->mtx_regenv);
00731
00732
00733
00734
00735
00736
00737 if (renv->refcnt == 1 || renv->panic == 1 || LF_ISSET(DB_FORCE)) {
00738
00739
00740
00741
00742
00743
00744
00745 renv->magic = 0;
00746 renv->panic = 1;
00747
00748
00749
00750
00751
00752 MUTEX_UNLOCK(dbenv, renv->mtx_regenv);
00753
00754
00755 for (rp = R_ADDR(infop, renv->region_off),
00756 i = 0; i < renv->region_cnt; ++i, ++rp) {
00757 if (rp->id == INVALID_REGION_ID ||
00758 rp->type == REGION_TYPE_ENV)
00759 continue;
00760
00761
00762
00763
00764
00765
00766
00767
00768 memset(®info, 0, sizeof(reginfo));
00769 reginfo.id = rp->id;
00770 reginfo.flags = REGION_CREATE_OK;
00771
00772
00773
00774
00775
00776
00777 if (__db_r_attach(dbenv, ®info, 0) != 0)
00778 continue;
00779
00780 #ifdef HAVE_MUTEX_SYSTEM_RESOURCES
00781
00782
00783
00784
00785 if (reginfo.type == REGION_TYPE_MUTEX)
00786 __mutex_resource_return(dbenv, ®info);
00787 #endif
00788 (void)__db_r_detach(dbenv, ®info, 1);
00789 }
00790
00791
00792 (void)__db_e_detach(dbenv, 1);
00793
00794
00795 remfiles: (void)__db_e_remfile(dbenv);
00796 } else {
00797
00798 MUTEX_UNLOCK(dbenv, renv->mtx_regenv);
00799
00800
00801 (void)__db_e_detach(dbenv, 0);
00802
00803 ret = EBUSY;
00804 }
00805
00806 done: F_CLR(dbenv, DB_ENV_NOLOCKING | DB_ENV_NOPANIC);
00807 F_SET(dbenv, db_env_reset);
00808
00809 return (ret);
00810 }
00811
00812
00813
00814
00815
00816 static int
00817 __db_e_remfile(dbenv)
00818 DB_ENV *dbenv;
00819 {
00820 int cnt, fcnt, lastrm, ret;
00821 const char *dir;
00822 char saved_char, *p, **names, *path, buf[sizeof(DB_REGION_FMT) + 20];
00823
00824
00825 (void)snprintf(buf, sizeof(buf), "%s", DB_REGION_ENV);
00826 if ((ret = __db_appname(dbenv, DB_APP_NONE, buf, 0, NULL, &path)) != 0)
00827 return (ret);
00828
00829
00830 if ((p = __db_rpath(path)) == NULL) {
00831 p = path;
00832 saved_char = *p;
00833
00834 dir = PATH_DOT;
00835 } else {
00836 saved_char = *p;
00837 *p = '\0';
00838
00839 dir = path;
00840 }
00841
00842
00843 if ((ret = __os_dirlist(dbenv, dir, &names, &fcnt)) != 0)
00844 __db_err(dbenv, "%s: %s", dir, db_strerror(ret));
00845
00846
00847 *p = saved_char;
00848 __os_free(dbenv, path);
00849
00850 if (ret != 0)
00851 return (ret);
00852
00853
00854
00855
00856 for (lastrm = -1, cnt = fcnt; --cnt >= 0;) {
00857
00858 if (strncmp(names[cnt],
00859 DB_REGION_PREFIX, sizeof(DB_REGION_PREFIX) - 1))
00860 continue;
00861
00862
00863 if (strncmp(names[cnt], "__dbq.", 6) == 0)
00864 continue;
00865
00866
00867 if (strncmp(names[cnt], "__db.register", 13) == 0)
00868 continue;
00869
00870
00871 if (strncmp(names[cnt], "__db.rep.", 9) == 0)
00872 continue;
00873
00874
00875
00876
00877
00878 if (strcmp(names[cnt], DB_REGION_ENV) == 0) {
00879 lastrm = cnt;
00880 continue;
00881 }
00882
00883
00884 if (__db_appname(dbenv,
00885 DB_APP_NONE, names[cnt], 0, NULL, &path) == 0) {
00886
00887
00888
00889
00890
00891
00892
00893
00894
00895 if (F_ISSET(dbenv, DB_ENV_OVERWRITE) &&
00896 strlen(names[cnt]) == DB_REGION_NAME_LENGTH)
00897 (void)__db_file_multi_write(dbenv, path);
00898 (void)__os_unlink(dbenv, path);
00899 __os_free(dbenv, path);
00900 }
00901 }
00902
00903 if (lastrm != -1)
00904 if (__db_appname(dbenv,
00905 DB_APP_NONE, names[lastrm], 0, NULL, &path) == 0) {
00906 if (F_ISSET(dbenv, DB_ENV_OVERWRITE))
00907 (void)__db_file_multi_write(dbenv, path);
00908 (void)__os_unlink(dbenv, path);
00909 __os_free(dbenv, path);
00910 }
00911 __os_dirfree(dbenv, names, fcnt);
00912
00913 return (0);
00914 }
00915
00916
00917
00918
00919
00920
00921
00922 int
00923 __db_r_attach(dbenv, infop, size)
00924 DB_ENV *dbenv;
00925 REGINFO *infop;
00926 size_t size;
00927 {
00928 REGION *rp;
00929 int ret;
00930 char buf[sizeof(DB_REGION_FMT) + 20];
00931
00932
00933
00934
00935
00936 F_CLR(infop, REGION_CREATE);
00937 if ((ret = __db_des_get(dbenv, dbenv->reginfo, infop, &rp)) != 0)
00938 return (ret);
00939 infop->dbenv = dbenv;
00940 infop->rp = rp;
00941 infop->type = rp->type;
00942 infop->id = rp->id;
00943
00944
00945
00946
00947
00948 if (F_ISSET(infop, REGION_CREATE))
00949 rp->size = (roff_t)size;
00950
00951
00952 (void)snprintf(buf, sizeof(buf), DB_REGION_FMT, infop->id);
00953 if ((ret = __db_appname(dbenv,
00954 DB_APP_NONE, buf, 0, NULL, &infop->name)) != 0)
00955 goto err;
00956 if ((ret = __os_r_attach(dbenv, infop, rp)) != 0)
00957 goto err;
00958
00959
00960
00961
00962
00963
00964 (void)__db_faultmem(dbenv,
00965 infop->addr, rp->size, F_ISSET(infop, REGION_CREATE));
00966
00967
00968
00969
00970
00971
00972
00973
00974
00975 if (F_ISSET(infop, REGION_CREATE))
00976 __db_shalloc_init(infop, rp->size);
00977
00978 return (0);
00979
00980 err:
00981 if (infop->addr != NULL)
00982 (void)__os_r_detach(dbenv,
00983 infop, F_ISSET(infop, REGION_CREATE));
00984 infop->rp = NULL;
00985 infop->id = INVALID_REGION_ID;
00986
00987
00988 if (F_ISSET(infop, REGION_CREATE)) {
00989 __db_des_destroy(dbenv, rp);
00990 F_CLR(infop, REGION_CREATE);
00991 }
00992
00993 return (ret);
00994 }
00995
00996
00997
00998
00999
01000
01001
01002 int
01003 __db_r_detach(dbenv, infop, destroy)
01004 DB_ENV *dbenv;
01005 REGINFO *infop;
01006 int destroy;
01007 {
01008 REGION *rp;
01009 int ret;
01010
01011 rp = infop->rp;
01012 if (F_ISSET(dbenv, DB_ENV_PRIVATE))
01013 destroy = 1;
01014
01015
01016
01017
01018
01019
01020
01021 if (F_ISSET(dbenv, DB_ENV_PRIVATE) && infop->primary != NULL)
01022 __db_shalloc_free(infop, infop->primary);
01023
01024
01025 ret = __os_r_detach(dbenv, infop, destroy);
01026
01027
01028 if (destroy)
01029 __db_des_destroy(dbenv, rp);
01030
01031
01032 if (infop->name != NULL)
01033 __os_free(dbenv, infop->name);
01034
01035 return (ret);
01036 }
01037
01038
01039
01040
01041
01042
01043 static int
01044 __db_des_get(dbenv, env_infop, infop, rpp)
01045 DB_ENV *dbenv;
01046 REGINFO *env_infop, *infop;
01047 REGION **rpp;
01048 {
01049 REGENV *renv;
01050 REGION *rp, *empty_slot, *first_type;
01051 u_int32_t i, maxid;
01052
01053 *rpp = NULL;
01054 renv = env_infop->primary;
01055
01056
01057
01058
01059
01060
01061
01062
01063
01064
01065
01066
01067
01068 maxid = REGION_ID_ENV;
01069 empty_slot = first_type = NULL;
01070 for (rp = R_ADDR(env_infop, renv->region_off),
01071 i = 0; i < renv->region_cnt; ++i, ++rp) {
01072 if (rp->id == INVALID_REGION_ID) {
01073 if (empty_slot == NULL)
01074 empty_slot = rp;
01075 continue;
01076 }
01077 if (infop->id != INVALID_REGION_ID) {
01078 if (infop->id == rp->id)
01079 break;
01080 continue;
01081 }
01082 if (infop->type == rp->type &&
01083 F_ISSET(infop, REGION_JOIN_OK) &&
01084 (first_type == NULL || first_type->id > rp->id))
01085 first_type = rp;
01086
01087 if (rp->id > maxid)
01088 maxid = rp->id;
01089 }
01090
01091
01092 if (i >= renv->region_cnt)
01093 rp = first_type;
01094 if (rp != NULL) {
01095 *rpp = rp;
01096 return (0);
01097 }
01098
01099
01100
01101
01102
01103 if (!F_ISSET(infop, REGION_CREATE_OK))
01104 return (ENOENT);
01105
01106
01107
01108
01109
01110 if (empty_slot == NULL) {
01111 __db_err(dbenv, "no room remaining for additional REGIONs");
01112 return (ENOENT);
01113 }
01114
01115
01116
01117
01118
01119 memset(empty_slot, 0, sizeof(REGION));
01120 empty_slot->segid = INVALID_REGION_SEGID;
01121
01122
01123
01124
01125
01126 empty_slot->type = infop->type;
01127 empty_slot->id = infop->id == INVALID_REGION_ID ? maxid + 1 : infop->id;
01128
01129 F_SET(infop, REGION_CREATE);
01130
01131 *rpp = empty_slot;
01132 return (0);
01133 }
01134
01135
01136
01137
01138
01139 static void
01140 __db_des_destroy(dbenv, rp)
01141 DB_ENV *dbenv;
01142 REGION *rp;
01143 {
01144 COMPQUIET(dbenv, NULL);
01145
01146 rp->id = INVALID_REGION_ID;
01147 }
01148
01149
01150
01151
01152
01153 static int
01154 __db_faultmem(dbenv, addr, size, created)
01155 DB_ENV *dbenv;
01156 void *addr;
01157 size_t size;
01158 int created;
01159 {
01160 int ret;
01161 u_int8_t *p, *t;
01162
01163
01164 if (F_ISSET(dbenv, DB_ENV_PRIVATE))
01165 return (0);
01166
01167
01168
01169
01170
01171
01172
01173
01174
01175
01176
01177
01178
01179
01180
01181
01182 ret = 0;
01183 if (F_ISSET(dbenv, DB_ENV_REGION_INIT)) {
01184 if (created)
01185 for (p = addr,
01186 t = (u_int8_t *)addr + size; p < t; p += 512)
01187 p[0] = 0xdb;
01188 else
01189 for (p = addr,
01190 t = (u_int8_t *)addr + size; p < t; p += 512)
01191 ret |= p[0];
01192 }
01193
01194 return (ret);
01195 }