katokay
05/03/2023, 10:21 PMimport kotlinx.cinterop.*
import lmdb.*
actual class Env : AutoCloseable {
private val envPtr: CPointerVar<MDB_env> = memScoped { allocPointerTo() }
internal val ptr: CPointer<MDB_env>
init {
check(mdb_env_create(envPtr.ptr))
ptr = envPtr.value!!
}
private var isOpened = false
actual var maxDatabases: UInt = 0u
set(value) {
check(mdb_env_set_maxdbs(ptr, value))
field = value
}
actual var mapSize: ULong = 1024UL * 1024UL * 50UL
set(value) {
check(mdb_env_set_mapsize(ptr, value))
field = value
}
actual var maxReaders: UInt = 0u
set(value) {
check(mdb_env_set_maxreaders(ptr, value))
field = value
}
actual val stat: Stat?
get() {
val statPtr: CValue<MDB_stat> = cValue<MDB_stat>()
check(mdb_env_stat(ptr, statPtr))
val pointed = memScoped {
statPtr.ptr.pointed
}
return Stat(
pointed.ms_branch_pages, pointed.ms_depth, pointed.ms_entries, pointed.ms_leaf_pages,
pointed.ms_overflow_pages, pointed.ms_psize
)
}
actual val info: EnvInfo?
get() {
val envInfo: CValue<MDB_envinfo> = cValue<MDB_envinfo>()
check(mdb_env_info(ptr, envInfo))
val pointed = memScoped {
envInfo.ptr.pointed
}
return EnvInfo(pointed.me_last_pgno, pointed.me_last_txnid,
pointed.me_mapaddr.toLong().toULong(), pointed.me_mapsize, pointed.me_maxreaders, pointed.me_numreaders)
}
actual fun open(path: String, vararg options: EnvOption, mode: UShort) {
check(mdb_env_open(ptr, path, options.asIterable().toFlags(), mode))
isOpened = true
}
actual fun beginTxn(vararg options: TxnOption) : Txn {
return Txn(this, *options)
}
actual fun copyTo(path: String, compact: Boolean) {
val flags = if (compact) {
0x01u
} else {
0u
}
check(mdb_env_copy2(ptr, path, flags))
}
actual fun sync(force: Boolean) {
val forceInt = if(force) 1 else 0
check(mdb_env_sync(ptr, forceInt))
}
actual override fun close() {
if (!isOpened)
return
mdb_env_close(ptr)
}
}
Landry Norris
05/04/2023, 2:20 AMLandry Norris
05/04/2023, 2:27 AMOleg Yukhnevich
05/04/2023, 8:09 AMallocPointerTo
inside memScoped
will be inaccessible just after exit from memScoped
block
So, you just need to move memScoped
to constructor (or variable declaration), f.e.:
internal val ptr: CPointer<MDB_env> = memScoped {
val ptrVar = allocPointerTo<MDB_env>()
check(mdb_env_create(ptrVar.ptr))
checkNotNull(ptrVar.value)
}
and then, of course, don’t forget to free it, like you do it in close
method, though, I prefer Cleaner
as pointed upper
if to use Cleaner
, you will need to add one more variable after ptr
declaration, like:
private val cleaner = createCleaner(ptr, ::mdb_env_close)
(Note: you will need to optIn for experimental stdlib API, so it’s up to you to decide on aproach)katokay
05/04/2023, 10:39 AMkatokay
05/04/2023, 9:12 PMLandry Norris
05/04/2023, 9:12 PMkatokay
05/04/2023, 9:16 PMLandry Norris
05/04/2023, 9:17 PMLandry Norris
05/04/2023, 9:17 PMkatokay
05/04/2023, 9:18 PMkatokay
05/04/2023, 9:19 PMLandry Norris
05/04/2023, 9:20 PMkatokay
05/04/2023, 9:21 PMLandry Norris
05/04/2023, 9:22 PMkatokay
05/04/2023, 9:23 PMkatokay
05/04/2023, 9:23 PMkatokay
05/04/2023, 9:24 PMLandry Norris
05/04/2023, 9:25 PMkatokay
05/04/2023, 9:26 PM