mirror of
https://github.com/isar/libmdbx.git
synced 2025-01-30 22:47:16 +08:00
mdbx: добавление UUID для идентификации БД.
This commit is contained in:
parent
319753661a
commit
fe31958d46
@ -826,7 +826,7 @@ macro(libmdbx_setup_libs TARGET MODE)
|
||||
target_link_libraries(${TARGET} ${MODE} Threads::Threads)
|
||||
endif()
|
||||
if(${CMAKE_SYSTEM_NAME} STREQUAL "Windows")
|
||||
target_link_libraries(${TARGET} ${MODE} ntdll user32 kernel32 advapi32)
|
||||
target_link_libraries(${TARGET} ${MODE} ntdll user32 kernel32 advapi32 ole32)
|
||||
if(MDBX_NTDLL_EXTRA_IMPLIB AND MDBX_WITHOUT_MSVC_CRT)
|
||||
target_link_libraries(${TARGET} ${MODE} ntdll_extra)
|
||||
endif()
|
||||
|
5
mdbx.h
5
mdbx.h
@ -2745,6 +2745,11 @@ struct MDBX_envinfo {
|
||||
uint64_t
|
||||
fsync; /**< Number of explicit fsync-to-disk operations (not a pages) */
|
||||
} mi_pgop_stat;
|
||||
|
||||
/* GUID of the database DXB file. */
|
||||
struct {
|
||||
uint64_t x, y;
|
||||
} mi_dxbid;
|
||||
};
|
||||
#ifndef __cplusplus
|
||||
/** \ingroup c_statinfo */
|
||||
|
@ -727,6 +727,7 @@ static int env_info_snap(const MDBX_env *env, const MDBX_txn *txn,
|
||||
troika_t *const troika) {
|
||||
const size_t size_before_bootid = offsetof(MDBX_envinfo, mi_bootid);
|
||||
const size_t size_before_pgop_stat = offsetof(MDBX_envinfo, mi_pgop_stat);
|
||||
const size_t size_before_dxbid = offsetof(MDBX_envinfo, mi_dxbid);
|
||||
if (unlikely(env->flags & ENV_FATAL_ERROR))
|
||||
return MDBX_PANIC;
|
||||
|
||||
@ -773,6 +774,8 @@ static int env_info_snap(const MDBX_env *env, const MDBX_txn *txn,
|
||||
memcpy(&out->mi_bootid.meta[0], &meta0->bootid, 16);
|
||||
memcpy(&out->mi_bootid.meta[1], &meta1->bootid, 16);
|
||||
memcpy(&out->mi_bootid.meta[2], &meta2->bootid, 16);
|
||||
if (likely(bytes > size_before_dxbid))
|
||||
memcpy(&out->mi_dxbid, &meta0->dxbid, 16);
|
||||
}
|
||||
|
||||
const volatile meta_t *txn_meta = head.ptr_v;
|
||||
@ -895,8 +898,9 @@ __cold int mdbx_env_info_ex(const MDBX_env *env, const MDBX_txn *txn,
|
||||
|
||||
const size_t size_before_bootid = offsetof(MDBX_envinfo, mi_bootid);
|
||||
const size_t size_before_pgop_stat = offsetof(MDBX_envinfo, mi_pgop_stat);
|
||||
const size_t size_before_dxbid = offsetof(MDBX_envinfo, mi_dxbid);
|
||||
if (unlikely(bytes != sizeof(MDBX_envinfo)) && bytes != size_before_bootid &&
|
||||
bytes != size_before_pgop_stat)
|
||||
bytes != size_before_pgop_stat && bytes != size_before_dxbid)
|
||||
return MDBX_EINVAL;
|
||||
|
||||
if (txn) {
|
||||
@ -938,8 +942,9 @@ __cold int mdbx_preopen_snapinfoW(const wchar_t *pathname, MDBX_envinfo *out,
|
||||
|
||||
const size_t size_before_bootid = offsetof(MDBX_envinfo, mi_bootid);
|
||||
const size_t size_before_pgop_stat = offsetof(MDBX_envinfo, mi_pgop_stat);
|
||||
const size_t size_before_dxbid = offsetof(MDBX_envinfo, mi_dxbid);
|
||||
if (unlikely(bytes != sizeof(MDBX_envinfo)) && bytes != size_before_bootid &&
|
||||
bytes != size_before_pgop_stat)
|
||||
bytes != size_before_pgop_stat && bytes != size_before_dxbid)
|
||||
return MDBX_EINVAL;
|
||||
|
||||
memset(out, 0, bytes);
|
||||
@ -993,8 +998,11 @@ __cold int mdbx_preopen_snapinfoW(const wchar_t *pathname, MDBX_envinfo *out,
|
||||
const unsigned n = 0;
|
||||
out->mi_recent_txnid = constmeta_txnid(&header);
|
||||
out->mi_meta_sign[n] = unaligned_peek_u64(4, &header.sign);
|
||||
if (likely(bytes > size_before_bootid))
|
||||
if (likely(bytes > size_before_bootid)) {
|
||||
memcpy(&out->mi_bootid.meta[n], &header.bootid, 16);
|
||||
if (likely(bytes > size_before_dxbid))
|
||||
memcpy(&out->mi_dxbid, &header.dxbid, 16);
|
||||
}
|
||||
|
||||
bailout:
|
||||
env_close(&env, false);
|
||||
|
14
src/chk.c
14
src/chk.c
@ -1590,13 +1590,23 @@ __cold static int env_chk(MDBX_chk_scope_t *const scope) {
|
||||
return chk_error_rc(scope, err, "env_info");
|
||||
|
||||
MDBX_chk_line_t *line =
|
||||
chk_puts(chk_line_begin(scope, MDBX_chk_info), "current boot-id ");
|
||||
chk_puts(chk_line_begin(scope, MDBX_chk_info -
|
||||
(1 << MDBX_chk_severity_prio_shift)),
|
||||
"dxb-id ");
|
||||
if (chk->envinfo.mi_dxbid.x | chk->envinfo.mi_dxbid.y)
|
||||
line = chk_print(line, "%016" PRIx64 "-%016" PRIx64,
|
||||
chk->envinfo.mi_dxbid.x, chk->envinfo.mi_dxbid.y);
|
||||
else
|
||||
line = chk_puts(line, "is absent");
|
||||
chk_line_end(line);
|
||||
|
||||
line = chk_puts(chk_line_begin(scope, MDBX_chk_info), "current boot-id ");
|
||||
if (chk->envinfo.mi_bootid.current.x | chk->envinfo.mi_bootid.current.y)
|
||||
line = chk_print(line, "%016" PRIx64 "-%016" PRIx64,
|
||||
chk->envinfo.mi_bootid.current.x,
|
||||
chk->envinfo.mi_bootid.current.y);
|
||||
else
|
||||
line = chk_puts(line, "unavailable");
|
||||
line = chk_puts(line, "is unavailable");
|
||||
chk_line_end(line);
|
||||
|
||||
err = osal_filesize(env->lazy_fd, &env->dxb_mmap.filesize);
|
||||
|
10
src/dxb.c
10
src/dxb.c
@ -1045,14 +1045,16 @@ __cold int dxb_setup(MDBX_env *env, const int lck_rc,
|
||||
|
||||
if ((env->flags & MDBX_RDONLY) == 0 && env->stuck_meta < 0 &&
|
||||
(globals.runtime_flags & MDBX_DBG_DONT_UPGRADE) == 0) {
|
||||
for (int n = 0; n < NUM_METAS; ++n) {
|
||||
for (unsigned n = 0; n < NUM_METAS; ++n) {
|
||||
meta_t *const meta = METAPAGE(env, n);
|
||||
if (unlikely(unaligned_peek_u64(4, &meta->magic_and_version) !=
|
||||
MDBX_DATA_MAGIC)) {
|
||||
const txnid_t txnid = constmeta_txnid(meta);
|
||||
MDBX_DATA_MAGIC) ||
|
||||
(meta->dxbid.x | meta->dxbid.y) == 0) {
|
||||
const txnid_t txnid =
|
||||
meta_is_used(&troika, n) ? constmeta_txnid(meta) : 0;
|
||||
NOTICE("%s %s"
|
||||
"meta[%u], txnid %" PRIaTXN,
|
||||
"updating db-format signature for",
|
||||
"updating db-format/guid signature for",
|
||||
meta_is_steady(meta) ? "stead-" : "weak-", n, txnid);
|
||||
err = meta_override(env, n, txnid, meta);
|
||||
if (unlikely(err != MDBX_SUCCESS) &&
|
||||
|
@ -91,15 +91,6 @@ typedef struct geo {
|
||||
};
|
||||
} geo_t;
|
||||
|
||||
typedef union bin128 {
|
||||
__anonymous_struct_extension__ struct {
|
||||
uint64_t x, y;
|
||||
};
|
||||
__anonymous_struct_extension__ struct {
|
||||
uint32_t a, b, c, d;
|
||||
};
|
||||
} bin128_t;
|
||||
|
||||
/* Meta page content.
|
||||
* A meta page is the start point for accessing a database snapshot.
|
||||
* Pages 0-2 are meta pages. */
|
||||
@ -158,6 +149,9 @@ typedef struct meta {
|
||||
* steady sync point. Zeros mean that no relevant information is available
|
||||
* from the system. */
|
||||
bin128_t bootid;
|
||||
|
||||
/* GUID базы данных, начиная с v0.13.1 */
|
||||
bin128_t dxbid;
|
||||
} meta_t;
|
||||
|
||||
#pragma pack(1)
|
||||
|
21
src/meta.c
21
src/meta.c
@ -332,8 +332,8 @@ int meta_sync(const MDBX_env *env, const meta_ptr_t head) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
__cold static page_t *meta_model(const MDBX_env *env, page_t *model,
|
||||
size_t num) {
|
||||
__cold static page_t *meta_model(const MDBX_env *env, page_t *model, size_t num,
|
||||
const bin128_t *guid) {
|
||||
ENSURE(env, is_powerof2(env->ps));
|
||||
ENSURE(env, env->ps >= MDBX_MIN_PAGESIZE);
|
||||
ENSURE(env, env->ps <= MDBX_MAX_PAGESIZE);
|
||||
@ -373,6 +373,7 @@ __cold static page_t *meta_model(const MDBX_env *env, page_t *model,
|
||||
model_meta->trees.gc.flags = MDBX_INTEGERKEY;
|
||||
model_meta->trees.gc.root = P_INVALID;
|
||||
model_meta->trees.main.root = P_INVALID;
|
||||
memcpy(&model_meta->dxbid, guid, sizeof(model_meta->dxbid));
|
||||
meta_set_txnid(env, model_meta, MIN_TXNID + num);
|
||||
unaligned_poke_u64(4, model_meta->sign, meta_sign_calculate(model_meta));
|
||||
eASSERT(env, coherency_check_meta(env, model_meta, true));
|
||||
@ -380,10 +381,11 @@ __cold static page_t *meta_model(const MDBX_env *env, page_t *model,
|
||||
}
|
||||
|
||||
__cold meta_t *meta_init_triplet(const MDBX_env *env, void *buffer) {
|
||||
const bin128_t guid = osal_guid(env);
|
||||
page_t *page0 = (page_t *)buffer;
|
||||
page_t *page1 = meta_model(env, page0, 0);
|
||||
page_t *page2 = meta_model(env, page1, 1);
|
||||
meta_model(env, page2, 2);
|
||||
page_t *page1 = meta_model(env, page0, 0, &guid);
|
||||
page_t *page2 = meta_model(env, page1, 1, &guid);
|
||||
meta_model(env, page2, 2, &guid);
|
||||
return page_meta(page2);
|
||||
}
|
||||
|
||||
@ -394,7 +396,8 @@ __cold int __must_check_result meta_override(MDBX_env *env, size_t target,
|
||||
if (unlikely(rc != MDBX_SUCCESS))
|
||||
return rc;
|
||||
page_t *const page = env->page_auxbuf;
|
||||
meta_model(env, page, target);
|
||||
meta_model(env, page, target,
|
||||
&((target == 0 && shape) ? shape : METAPAGE(env, 0))->dxbid);
|
||||
meta_t *const model = page_meta(page);
|
||||
meta_set_txnid(env, model, txnid);
|
||||
if (txnid)
|
||||
@ -430,6 +433,12 @@ __cold int __must_check_result meta_override(MDBX_env *env, size_t target,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (target == 0 && (model->dxbid.x | model->dxbid.y) == 0) {
|
||||
const bin128_t guid = osal_guid(env);
|
||||
memcpy(&model->dxbid, &guid, sizeof(model->dxbid));
|
||||
}
|
||||
|
||||
meta_sign_as_steady(model);
|
||||
rc = meta_validate(env, model, page, (pgno_t)target, nullptr);
|
||||
if (unlikely(MDBX_IS_ERROR(rc)))
|
||||
|
@ -83,7 +83,12 @@ static inline meta_ptr_t meta_tail(const MDBX_env *env,
|
||||
return r;
|
||||
}
|
||||
|
||||
static inline bool meta_is_used(const troika_t *troika, unsigned n) {
|
||||
return n == troika->recent || n == troika->prefer_steady;
|
||||
}
|
||||
|
||||
static inline bool meta_bootid_match(const meta_t *meta) {
|
||||
|
||||
return memcmp(&meta->bootid, &globals.bootid, 16) == 0 &&
|
||||
(globals.bootid.x | globals.bootid.y) != 0;
|
||||
}
|
||||
|
215
src/osal.c
215
src/osal.c
@ -2931,17 +2931,40 @@ __cold static void bootid_collect(bin128_t *p, const void *s, size_t n) {
|
||||
bootid_shake(p);
|
||||
|
||||
/* minor non-linear tomfoolery */
|
||||
const unsigned z = p->x % 61;
|
||||
const unsigned z = p->x % 61 + 1;
|
||||
p->y = p->y << z | p->y >> (64 - z);
|
||||
bootid_shake(p);
|
||||
bootid_shake(p);
|
||||
const unsigned q = p->x % 59;
|
||||
const unsigned q = p->x % 59 + 1;
|
||||
p->y = p->y << q | p->y >> (64 - q);
|
||||
bootid_shake(p);
|
||||
bootid_shake(p);
|
||||
bootid_shake(p);
|
||||
}
|
||||
|
||||
static size_t hamming_weight(size_t v) {
|
||||
const size_t m1 = (size_t)UINT64_C(0x5555555555555555);
|
||||
const size_t m2 = (size_t)UINT64_C(0x3333333333333333);
|
||||
const size_t m4 = (size_t)UINT64_C(0x0f0f0f0f0f0f0f0f);
|
||||
const size_t h01 = (size_t)UINT64_C(0x0101010101010101);
|
||||
v -= (v >> 1) & m1;
|
||||
v = (v & m2) + ((v >> 2) & m2);
|
||||
v = (v + (v >> 4)) & m4;
|
||||
return (v * h01) >> (sizeof(v) * 8 - 8);
|
||||
}
|
||||
|
||||
static inline size_t hw64(uint64_t v) {
|
||||
size_t r = hamming_weight((size_t)v);
|
||||
if (sizeof(v) > sizeof(r))
|
||||
r += hamming_weight((size_t)(v >> sizeof(r) * 4 >> sizeof(r) * 4));
|
||||
return r;
|
||||
}
|
||||
|
||||
static bool check_uuid(bin128_t uuid) {
|
||||
size_t hw = hw64(uuid.x) + hw64(uuid.y) + hw64(uuid.x ^ uuid.y);
|
||||
return (hw >> 6) == 1;
|
||||
}
|
||||
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
|
||||
__cold static uint64_t windows_systemtime_ms() {
|
||||
@ -3043,7 +3066,7 @@ bootid_parse_uuid(bin128_t *s, const void *p, const size_t n) {
|
||||
s->y += aligned.y;
|
||||
} else
|
||||
bootid_collect(s, p, n);
|
||||
return true;
|
||||
return check_uuid(*s);
|
||||
}
|
||||
|
||||
if (n)
|
||||
@ -3051,28 +3074,33 @@ bootid_parse_uuid(bin128_t *s, const void *p, const size_t n) {
|
||||
return false;
|
||||
}
|
||||
|
||||
#if defined(__linux__) || defined(__gnu_linux__)
|
||||
__cold static bool proc_read_uuid(const char *path, bin128_t *target) {
|
||||
const int fd = open(path, O_RDONLY | O_NOFOLLOW);
|
||||
if (fd != -1) {
|
||||
struct statfs fs;
|
||||
char buf[42];
|
||||
const ssize_t len =
|
||||
(fstatfs(fd, &fs) == 0 && fs.f_type == /* procfs */ 0x9FA0)
|
||||
? read(fd, buf, sizeof(buf))
|
||||
: -1;
|
||||
const int err = close(fd);
|
||||
assert(err == 0);
|
||||
(void)err;
|
||||
if (len > 0)
|
||||
return bootid_parse_uuid(target, buf, len);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
#endif /* Linux */
|
||||
|
||||
__cold static bin128_t osal_bootid(void) {
|
||||
bin128_t bin = {{0, 0}};
|
||||
bin128_t uuid = {{0, 0}};
|
||||
bool got_machineid = false, got_boottime = false, got_bootseq = false;
|
||||
|
||||
#if defined(__linux__) || defined(__gnu_linux__)
|
||||
{
|
||||
const int fd =
|
||||
open("/proc/sys/kernel/random/boot_id", O_RDONLY | O_NOFOLLOW);
|
||||
if (fd != -1) {
|
||||
struct statfs fs;
|
||||
char buf[42];
|
||||
const ssize_t len =
|
||||
(fstatfs(fd, &fs) == 0 && fs.f_type == /* procfs */ 0x9FA0)
|
||||
? read(fd, buf, sizeof(buf))
|
||||
: -1;
|
||||
const int err = close(fd);
|
||||
assert(err == 0);
|
||||
(void)err;
|
||||
if (len > 0 && bootid_parse_uuid(&bin, buf, len))
|
||||
return bin;
|
||||
}
|
||||
}
|
||||
if (proc_read_uuid("/proc/sys/kernel/random/boot_id", &uuid))
|
||||
return uuid;
|
||||
#endif /* Linux */
|
||||
|
||||
#if defined(__APPLE__) || defined(__MACH__)
|
||||
@ -3080,16 +3108,15 @@ __cold static bin128_t osal_bootid(void) {
|
||||
char buf[42];
|
||||
size_t len = sizeof(buf);
|
||||
if (!sysctlbyname("kern.bootsessionuuid", buf, &len, nullptr, 0) &&
|
||||
bootid_parse_uuid(&bin, buf, len))
|
||||
return bin;
|
||||
bootid_parse_uuid(&uuid, buf, len))
|
||||
return uuid;
|
||||
|
||||
#if defined(__MAC_OS_X_VERSION_MIN_REQUIRED) && \
|
||||
__MAC_OS_X_VERSION_MIN_REQUIRED > 1050
|
||||
uuid_t uuid;
|
||||
uuid_t hostuuid;
|
||||
struct timespec wait = {0, 1000000000u / 42};
|
||||
if (!gethostuuid(uuid, &wait) &&
|
||||
bootid_parse_uuid(&bin, uuid, sizeof(uuid)))
|
||||
got_machineid = true;
|
||||
if (!gethostuuid(hostuuid, &wait))
|
||||
got_machineid = bootid_parse_uuid(&uuid, hostuuid, sizeof(hostuuid));
|
||||
#endif /* > 10.5 */
|
||||
|
||||
struct timeval boottime;
|
||||
@ -3127,7 +3154,7 @@ __cold static bin128_t osal_bootid(void) {
|
||||
"MachineGuid", &buf.MachineGuid,
|
||||
&len) == ERROR_SUCCESS &&
|
||||
len < sizeof(buf))
|
||||
got_machineid = bootid_parse_uuid(&bin, &buf.MachineGuid, len);
|
||||
got_machineid = bootid_parse_uuid(&uuid, &buf.MachineGuid, len);
|
||||
|
||||
if (!got_machineid) {
|
||||
/* again, Windows is madness */
|
||||
@ -3145,7 +3172,7 @@ __cold static bin128_t osal_bootid(void) {
|
||||
"DigitalProductId", &buf.DigitalProductId,
|
||||
&len) == ERROR_SUCCESS &&
|
||||
len > 42 && len < sizeof(buf)) {
|
||||
bootid_collect(&bin, &buf.DigitalProductId, len);
|
||||
bootid_collect(&uuid, &buf.DigitalProductId, len);
|
||||
got_machineid = true;
|
||||
}
|
||||
len = sizeof(buf);
|
||||
@ -3153,7 +3180,7 @@ __cold static bin128_t osal_bootid(void) {
|
||||
"DigitalProductId", &buf.DigitalProductId,
|
||||
&len) == ERROR_SUCCESS &&
|
||||
len > 42 && len < sizeof(buf)) {
|
||||
bootid_collect(&bin, &buf.DigitalProductId, len);
|
||||
bootid_collect(&uuid, &buf.DigitalProductId, len);
|
||||
got_machineid = true;
|
||||
}
|
||||
len = sizeof(buf);
|
||||
@ -3161,7 +3188,7 @@ __cold static bin128_t osal_bootid(void) {
|
||||
"DigitalProductId", &buf.DigitalProductId,
|
||||
&len) == ERROR_SUCCESS &&
|
||||
len > 42 && len < sizeof(buf)) {
|
||||
bootid_collect(&bin, &buf.DigitalProductId, len);
|
||||
bootid_collect(&uuid, &buf.DigitalProductId, len);
|
||||
got_machineid = true;
|
||||
}
|
||||
}
|
||||
@ -3173,7 +3200,7 @@ __cold static bin128_t osal_bootid(void) {
|
||||
if (mdbx_RegGetValue(HKEY_LOCAL_MACHINE, HKLM_PrefetcherParams, "BootId",
|
||||
&buf.BootId, &len) == ERROR_SUCCESS &&
|
||||
len > 1 && len < sizeof(buf)) {
|
||||
bootid_collect(&bin, &buf.BootId, len);
|
||||
bootid_collect(&uuid, &buf.BootId, len);
|
||||
got_bootseq = true;
|
||||
}
|
||||
|
||||
@ -3181,7 +3208,7 @@ __cold static bin128_t osal_bootid(void) {
|
||||
if (mdbx_RegGetValue(HKEY_LOCAL_MACHINE, HKLM_PrefetcherParams, "BaseTime",
|
||||
&buf.BaseTime, &len) == ERROR_SUCCESS &&
|
||||
len >= sizeof(buf.BaseTime) && buf.BaseTime) {
|
||||
bootid_collect(&bin, &buf.BaseTime, len);
|
||||
bootid_collect(&uuid, &buf.BaseTime, len);
|
||||
got_boottime = true;
|
||||
}
|
||||
|
||||
@ -3197,7 +3224,7 @@ __cold static bin128_t osal_bootid(void) {
|
||||
buf.SysTimeOfDayInfoHacked.BootTime.QuadPart -
|
||||
buf.SysTimeOfDayInfoHacked.BootTimeBias;
|
||||
if (UnbiasedBootTime) {
|
||||
bootid_collect(&bin, &UnbiasedBootTime, sizeof(UnbiasedBootTime));
|
||||
bootid_collect(&uuid, &UnbiasedBootTime, sizeof(UnbiasedBootTime));
|
||||
got_boottime = true;
|
||||
}
|
||||
}
|
||||
@ -3205,7 +3232,7 @@ __cold static bin128_t osal_bootid(void) {
|
||||
if (!got_boottime) {
|
||||
uint64_t boottime = windows_bootime();
|
||||
if (boottime) {
|
||||
bootid_collect(&bin, &boottime, sizeof(boottime));
|
||||
bootid_collect(&uuid, &boottime, sizeof(boottime));
|
||||
got_boottime = true;
|
||||
}
|
||||
}
|
||||
@ -3223,7 +3250,7 @@ __cold static bin128_t osal_bootid(void) {
|
||||
#endif
|
||||
mib,
|
||||
ARRAY_LENGTH(mib), &buf, &len, nullptr, 0) == 0)
|
||||
got_machineid = bootid_parse_uuid(&bin, buf, len);
|
||||
got_machineid = bootid_parse_uuid(&uuid, buf, len);
|
||||
}
|
||||
#endif /* CTL_HW && HW_UUID */
|
||||
|
||||
@ -3238,7 +3265,7 @@ __cold static bin128_t osal_bootid(void) {
|
||||
#endif
|
||||
mib,
|
||||
ARRAY_LENGTH(mib), &buf, &len, nullptr, 0) == 0)
|
||||
got_machineid = bootid_parse_uuid(&bin, buf, len);
|
||||
got_machineid = bootid_parse_uuid(&uuid, buf, len);
|
||||
}
|
||||
#endif /* CTL_KERN && KERN_HOSTUUID */
|
||||
|
||||
@ -3247,7 +3274,7 @@ __cold static bin128_t osal_bootid(void) {
|
||||
char buf[42];
|
||||
size_t len = sizeof(buf);
|
||||
if (sysctlbyname("machdep.dmi.system-uuid", buf, &len, nullptr, 0) == 0)
|
||||
got_machineid = bootid_parse_uuid(&bin, buf, len);
|
||||
got_machineid = bootid_parse_uuid(&uuid, buf, len);
|
||||
}
|
||||
#endif /* __NetBSD__ */
|
||||
|
||||
@ -3255,7 +3282,7 @@ __cold static bin128_t osal_bootid(void) {
|
||||
if (!got_machineid) {
|
||||
const int hostid = gethostid();
|
||||
if (hostid > 0) {
|
||||
bootid_collect(&bin, &hostid, sizeof(hostid));
|
||||
bootid_collect(&uuid, &hostid, sizeof(hostid));
|
||||
got_machineid = true;
|
||||
}
|
||||
}
|
||||
@ -3263,8 +3290,8 @@ __cold static bin128_t osal_bootid(void) {
|
||||
|
||||
if (!got_machineid) {
|
||||
lack:
|
||||
bin.x = bin.y = 0;
|
||||
return bin;
|
||||
uuid.x = uuid.y = 0;
|
||||
return uuid;
|
||||
}
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
@ -3281,7 +3308,7 @@ __cold static bin128_t osal_bootid(void) {
|
||||
mib,
|
||||
ARRAY_LENGTH(mib), &boottime, &len, nullptr, 0) == 0 &&
|
||||
len == sizeof(boottime) && boottime.tv_sec) {
|
||||
bootid_collect(&bin, &boottime, len);
|
||||
bootid_collect(&uuid, &boottime, len);
|
||||
got_boottime = true;
|
||||
}
|
||||
}
|
||||
@ -3298,11 +3325,11 @@ __cold static bin128_t osal_bootid(void) {
|
||||
switch (kn->data_type) {
|
||||
case KSTAT_DATA_INT32:
|
||||
case KSTAT_DATA_UINT32:
|
||||
bootid_collect(&bin, &kn->value, sizeof(int32_t));
|
||||
bootid_collect(&uuid, &kn->value, sizeof(int32_t));
|
||||
got_boottime = true;
|
||||
case KSTAT_DATA_INT64:
|
||||
case KSTAT_DATA_UINT64:
|
||||
bootid_collect(&bin, &kn->value, sizeof(int64_t));
|
||||
bootid_collect(&uuid, &kn->value, sizeof(int64_t));
|
||||
got_boottime = true;
|
||||
}
|
||||
}
|
||||
@ -3318,12 +3345,12 @@ __cold static bin128_t osal_bootid(void) {
|
||||
const struct utmpx id = {.ut_type = BOOT_TIME};
|
||||
const struct utmpx *entry = getutxid(&id);
|
||||
if (entry) {
|
||||
bootid_collect(&bin, entry, sizeof(*entry));
|
||||
bootid_collect(&uuid, entry, sizeof(*entry));
|
||||
got_boottime = true;
|
||||
while (unlikely((entry = getutxid(&id)) != nullptr)) {
|
||||
/* have multiple reboot records, assuming we can distinguish next
|
||||
* bootsession even if RTC is wrong or absent */
|
||||
bootid_collect(&bin, entry, sizeof(*entry));
|
||||
bootid_collect(&uuid, entry, sizeof(*entry));
|
||||
got_bootseq = true;
|
||||
}
|
||||
}
|
||||
@ -3352,7 +3379,7 @@ __cold static bin128_t osal_bootid(void) {
|
||||
goto lack;
|
||||
}
|
||||
|
||||
return bin;
|
||||
return uuid;
|
||||
}
|
||||
|
||||
__cold int mdbx_get_sysraminfo(intptr_t *page_size, intptr_t *total_pages,
|
||||
@ -3474,6 +3501,100 @@ __cold int mdbx_get_sysraminfo(intptr_t *page_size, intptr_t *total_pages,
|
||||
return MDBX_SUCCESS;
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------*/
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
#include <sys/uuid.h>
|
||||
#endif /* FreeBSD */
|
||||
|
||||
#if __GLIBC_PREREQ(2, 25) || defined(__FreeBSD__) || defined(__NetBSD__) || \
|
||||
defined(__BSD__) || defined(__bsdi__) || defined(__DragonFly__) || \
|
||||
defined(__APPLE__) || __has_include(<sys/random.h>)
|
||||
#include <sys/random.h>
|
||||
#endif /* sys/random.h */
|
||||
|
||||
MDBX_INTERNAL bin128_t osal_guid(const MDBX_env *env) {
|
||||
struct {
|
||||
uint64_t begin, end, cputime;
|
||||
uintptr_t thread, pid;
|
||||
const void *x, *y;
|
||||
bin128_t (*z)(const MDBX_env *env);
|
||||
} salt;
|
||||
|
||||
salt.begin = osal_monotime();
|
||||
bin128_t uuid = {{0, 0}};
|
||||
|
||||
#if defined(__linux__) || defined(__gnu_linux__)
|
||||
if (proc_read_uuid("/proc/sys/kernel/random/uuid", &uuid) && check_uuid(uuid))
|
||||
return uuid;
|
||||
#endif /* Linux */
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
STATIC_ASSERT(sizeof(uuid) == sizeof(struct uuid));
|
||||
if (uuidgen((struct uuid *)&uuid, 1) == 0 && check_uuid(uuid))
|
||||
return uuid;
|
||||
#endif /* FreeBSD */
|
||||
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
if (imports.CoCreateGuid && imports.CoCreateGuid(&uuid) == 0 &&
|
||||
check_uuid(uuid))
|
||||
return uuid;
|
||||
|
||||
HCRYPTPROV hCryptProv = 0;
|
||||
if (CryptAcquireContextW(&hCryptProv, nullptr, nullptr, PROV_RSA_FULL,
|
||||
CRYPT_VERIFYCONTEXT | CRYPT_SILENT)) {
|
||||
const BOOL ok =
|
||||
CryptGenRandom(hCryptProv, sizeof(uuid), (unsigned char *)&uuid);
|
||||
CryptReleaseContext(hCryptProv, 0);
|
||||
if (ok && check_uuid(uuid))
|
||||
return uuid;
|
||||
}
|
||||
#elif defined(__IPHONE_OS_VERSION_MIN_REQUIRED) && defined(__IPHONE_8_0)
|
||||
#if __IPHONE_OS_VERSION_MIN_REQUIRED >= __IPHONE_8_0
|
||||
if (CCRandomGenerateBytes(&uuid, sizeof(uuid)) == kCCSuccess &&
|
||||
check_uuid(uuid))
|
||||
return uuid;
|
||||
#endif /* iOS >= 8.x */
|
||||
#else
|
||||
const int fd = open("/dev/urandom", O_RDONLY);
|
||||
if (fd != -1) {
|
||||
const ssize_t len = read(fd, &uuid, sizeof(uuid));
|
||||
const int err = close(fd);
|
||||
assert(err == 0);
|
||||
(void)err;
|
||||
if (len == sizeof(uuid) && check_uuid(uuid))
|
||||
return uuid;
|
||||
}
|
||||
#if (__GLIBC_PREREQ(2, 25) || defined(__FreeBSD__) || defined(__NetBSD__) || \
|
||||
defined(__BSD__) || defined(__bsdi__) || defined(__DragonFly__)) && \
|
||||
!defined(__APPLE__) && !defined(__ANDROID_API__)
|
||||
if (getrandom(&uuid, sizeof(uuid), 0) == sizeof(uuid) && check_uuid(uuid))
|
||||
return uuid;
|
||||
#elif defined(__OpenBSD__) || (defined(__sun) && defined(__SVR4)) || \
|
||||
(defined(__MAC_OS_X_VERSION_MIN_REQUIRED) && \
|
||||
__MAC_OS_X_VERSION_MIN_REQUIRED >= 101200)
|
||||
if (getentropy(&uuid, sizeof(uuid)) == 0 && check_uuid(uuid))
|
||||
return uuid;
|
||||
#endif /* getrandom() / getentropy() */
|
||||
#endif /* !Windows */
|
||||
|
||||
uuid = globals.bootid;
|
||||
bootid_collect(&uuid, env, sizeof(*env));
|
||||
salt.thread = osal_thread_self();
|
||||
salt.pid = osal_getpid();
|
||||
salt.x = &salt;
|
||||
salt.y = env;
|
||||
salt.z = &osal_guid;
|
||||
do {
|
||||
salt.cputime = osal_cputime(nullptr);
|
||||
salt.end = osal_monotime();
|
||||
bootid_collect(&uuid, &salt, sizeof(salt));
|
||||
} while (!check_uuid(uuid));
|
||||
return uuid;
|
||||
}
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
void osal_ctor(void) {
|
||||
#if MDBX_HAVE_PWRITEV && defined(_SC_IOV_MAX)
|
||||
osal_iov_max = sysconf(_SC_IOV_MAX);
|
||||
|
11
src/osal.h
11
src/osal.h
@ -576,6 +576,17 @@ MDBX_INTERNAL void osal_dtor(void);
|
||||
MDBX_INTERNAL int osal_mb2w(const char *const src, wchar_t **const pdst);
|
||||
#endif /* Windows */
|
||||
|
||||
typedef union bin128 {
|
||||
__anonymous_struct_extension__ struct {
|
||||
uint64_t x, y;
|
||||
};
|
||||
__anonymous_struct_extension__ struct {
|
||||
uint32_t a, b, c, d;
|
||||
};
|
||||
} bin128_t;
|
||||
|
||||
MDBX_INTERNAL bin128_t osal_guid(const MDBX_env *);
|
||||
|
||||
/*----------------------------------------------------------------------------*/
|
||||
|
||||
MDBX_MAYBE_UNUSED MDBX_NOTHROW_PURE_FUNCTION static inline uint64_t
|
||||
|
@ -839,6 +839,7 @@ int mdbx_txn_commit_ex(MDBX_txn *txn, MDBX_commit_latency *latency) {
|
||||
meta.trees.gc = txn->dbs[FREE_DBI];
|
||||
meta.trees.main = txn->dbs[MAIN_DBI];
|
||||
meta.canary = txn->canary;
|
||||
memcpy(&meta.dxbid, &head.ptr_c->dxbid, sizeof(meta.dxbid));
|
||||
|
||||
txnid_t commit_txnid = txn->txnid;
|
||||
#if MDBX_ENABLE_BIGFOOT
|
||||
|
@ -147,6 +147,11 @@ void windows_import(void) {
|
||||
if (hAdvapi32dll) {
|
||||
MDBX_IMPORT(hAdvapi32dll, RegGetValueA);
|
||||
}
|
||||
|
||||
const HINSTANCE hOle32dll = GetModuleHandleA("ole32.dll");
|
||||
if (hOle32dll) {
|
||||
MDBX_IMPORT(hOle32dll, CoCreateGuid);
|
||||
}
|
||||
}
|
||||
|
||||
#undef MDBX_IMPORT
|
||||
|
@ -109,6 +109,8 @@ typedef LSTATUS(WINAPI *MDBX_RegGetValueA)(HKEY hkey, LPCSTR lpSubKey,
|
||||
LPDWORD pdwType, PVOID pvData,
|
||||
LPDWORD pcbData);
|
||||
|
||||
typedef long(WINAPI *MDBX_CoCreateGuid)(bin128_t *guid);
|
||||
|
||||
NTSYSAPI ULONG RtlRandomEx(PULONG Seed);
|
||||
|
||||
typedef BOOL(WINAPI *MDBX_SetFileIoOverlappedRange)(HANDLE FileHandle,
|
||||
@ -131,6 +133,7 @@ struct libmdbx_imports {
|
||||
MDBX_GetTickCount64 GetTickCount64;
|
||||
MDBX_RegGetValueA RegGetValueA;
|
||||
MDBX_SetFileIoOverlappedRange SetFileIoOverlappedRange;
|
||||
MDBX_CoCreateGuid CoCreateGuid;
|
||||
};
|
||||
|
||||
MDBX_INTERNAL void windows_import(void);
|
||||
|
Loading…
x
Reference in New Issue
Block a user