#define _GNU_SOURCE // SPDX-FileCopyrightText: © 2026 Vladimir Zorin // SPDX-License-Identifier: LicenseRef-OWL-1.0-or-later // Licensed under OWL v1.0+. See LICENSE. #include "mneme.h" #include #include #include #include #include #include static int reader_lock_start(uint64_t txn_id, off_t *start_out) { if (txn_id > (uint64_t)(INT64_MAX - MNEME_READER_LOCK_BASE)) return -1; *start_out = MNEME_READER_LOCK_BASE + (off_t)txn_id; return 0; } static int reader_lock_apply(int fd, short type, off_t start) { struct flock fl; memset(&fl, 0, sizeof(fl)); fl.l_type = type; fl.l_whence = SEEK_SET; fl.l_start = start; fl.l_len = 0; return fcntl(fd, F_OFD_SETLK, &fl); } static int reader_lock_test(int fd, off_t start) { struct flock fl; memset(&fl, 0, sizeof(fl)); fl.l_type = F_WRLCK; fl.l_whence = SEEK_SET; fl.l_start = start; fl.l_len = 1; if (fcntl(fd, F_OFD_GETLK, &fl) < 0) return -1; return (fl.l_type != F_UNLCK) ? 1 : 0; } int mneme_reader_lock_acquire(mneme_txn_t *txn) { off_t start; if (!txn || !txn->db) return -1; if (reader_lock_start(txn->reader_txn_id, &start) < 0) return -1; txn->reader_lock_fd = open(txn->db->path, O_RDONLY | O_CLOEXEC); if (txn->reader_lock_fd < 0) return -1; if (reader_lock_apply(txn->reader_lock_fd, F_RDLCK, start) < 0) { close(txn->reader_lock_fd); txn->reader_lock_fd = -1; return -1; } return 0; } void mneme_reader_lock_release(mneme_txn_t *txn) { if (!txn) return; if (txn->reader_lock_fd >= 0) close(txn->reader_lock_fd); txn->reader_lock_fd = -1; txn->reader_txn_id = 0; } int mneme_reader_probe_older(mneme_db_t *db, uint64_t retire_txn_id_minus_one) { off_t start; if (!db || db->probe_fd < 0) return -1; if (reader_lock_start(retire_txn_id_minus_one, &start) < 0) return -1; return reader_lock_test(db->probe_fd, start); } int mneme_ofd_lock_probe(int fd) { struct flock fl; memset(&fl, 0, sizeof(fl)); fl.l_type = F_RDLCK; fl.l_whence = SEEK_SET; fl.l_start = MNEME_READER_LOCK_BASE; fl.l_len = 1; if (fcntl(fd, F_OFD_SETLK, &fl) < 0) return -1; fl.l_type = F_UNLCK; if (fcntl(fd, F_OFD_SETLK, &fl) < 0) return -1; return 0; }