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

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