mdbx: добавление UUID для идентификации БД.

This commit is contained in:
Леонид Юрьев (Leonid Yuriev) 2024-07-06 10:46:42 +03:00
parent 319753661a
commit fe31958d46
13 changed files with 246 additions and 72 deletions

View File

@ -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
View File

@ -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 */

View File

@ -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);

View File

@ -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);

View File

@ -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) &&

View File

@ -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)

View File

@ -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)))

View File

@ -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;
}

View File

@ -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);

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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);