Compare commits
5 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ea19b83ba4 | ||
|
|
7650b90d91 | ||
|
|
ba522fa051 | ||
|
|
a4623a13b5 | ||
|
|
f85187eff3 |
@@ -1,18 +1,19 @@
|
|||||||
package examples
|
package examples
|
||||||
|
|
||||||
import "core:fmt"
|
import "core:fmt"
|
||||||
import "core:log"
|
|
||||||
import "core:mem"
|
import "core:mem"
|
||||||
import "core:os"
|
import "core:os"
|
||||||
|
|
||||||
main :: proc() {
|
main :: proc() {
|
||||||
//----- General setup ----------------------------------
|
//----- Tracking allocator ----------------------------------
|
||||||
{
|
{
|
||||||
|
tracking_temp_allocator := false
|
||||||
// Temp
|
// Temp
|
||||||
track_temp: mem.Tracking_Allocator
|
track_temp: mem.Tracking_Allocator
|
||||||
mem.tracking_allocator_init(&track_temp, context.temp_allocator)
|
if tracking_temp_allocator {
|
||||||
context.temp_allocator = mem.tracking_allocator(&track_temp)
|
mem.tracking_allocator_init(&track_temp, context.temp_allocator)
|
||||||
|
context.temp_allocator = mem.tracking_allocator(&track_temp)
|
||||||
|
}
|
||||||
// Default
|
// Default
|
||||||
track: mem.Tracking_Allocator
|
track: mem.Tracking_Allocator
|
||||||
mem.tracking_allocator_init(&track, context.allocator)
|
mem.tracking_allocator_init(&track, context.allocator)
|
||||||
@@ -21,10 +22,18 @@ main :: proc() {
|
|||||||
// This could be fine for some global state or it could be a memory leak.
|
// This could be fine for some global state or it could be a memory leak.
|
||||||
defer {
|
defer {
|
||||||
// Temp allocator
|
// Temp allocator
|
||||||
if len(track_temp.bad_free_array) > 0 {
|
if tracking_temp_allocator {
|
||||||
fmt.eprintf("=== %v incorrect frees - temp allocator: ===\n", len(track_temp.bad_free_array))
|
if len(track_temp.allocation_map) > 0 {
|
||||||
for entry in track_temp.bad_free_array {
|
fmt.eprintf("=== %v allocations not freed - temp allocator: ===\n", len(track_temp.allocation_map))
|
||||||
fmt.eprintf("- %p @ %v\n", entry.memory, entry.location)
|
for _, entry in track_temp.allocation_map {
|
||||||
|
fmt.eprintf("- %v bytes @ %v\n", entry.size, entry.location)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if len(track_temp.bad_free_array) > 0 {
|
||||||
|
fmt.eprintf("=== %v incorrect frees - temp allocator: ===\n", len(track_temp.bad_free_array))
|
||||||
|
for entry in track_temp.bad_free_array {
|
||||||
|
fmt.eprintf("- %p @ %v\n", entry.memory, entry.location)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
mem.tracking_allocator_destroy(&track_temp)
|
mem.tracking_allocator_destroy(&track_temp)
|
||||||
}
|
}
|
||||||
@@ -43,9 +52,6 @@ main :: proc() {
|
|||||||
}
|
}
|
||||||
mem.tracking_allocator_destroy(&track)
|
mem.tracking_allocator_destroy(&track)
|
||||||
}
|
}
|
||||||
// Logger
|
|
||||||
context.logger = log.create_console_logger()
|
|
||||||
defer log.destroy_console_logger(context.logger)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
args := os.args
|
args := os.args
|
||||||
@@ -1,8 +1,6 @@
|
|||||||
package meta
|
package meta
|
||||||
|
|
||||||
import "core:fmt"
|
import "core:fmt"
|
||||||
import "core:log"
|
|
||||||
import "core:mem"
|
|
||||||
import "core:os"
|
import "core:os"
|
||||||
|
|
||||||
Command :: struct {
|
Command :: struct {
|
||||||
@@ -22,48 +20,6 @@ COMMANDS :: []Command {
|
|||||||
}
|
}
|
||||||
|
|
||||||
main :: proc() {
|
main :: proc() {
|
||||||
//----- General setup ----------------------------------
|
|
||||||
when ODIN_DEBUG {
|
|
||||||
// Temp
|
|
||||||
track_temp: mem.Tracking_Allocator
|
|
||||||
mem.tracking_allocator_init(&track_temp, context.temp_allocator)
|
|
||||||
context.temp_allocator = mem.tracking_allocator(&track_temp)
|
|
||||||
|
|
||||||
// Default
|
|
||||||
track: mem.Tracking_Allocator
|
|
||||||
mem.tracking_allocator_init(&track, context.allocator)
|
|
||||||
context.allocator = mem.tracking_allocator(&track)
|
|
||||||
// Log a warning about any memory that was not freed by the end of the program.
|
|
||||||
// This could be fine for some global state or it could be a memory leak.
|
|
||||||
defer {
|
|
||||||
// Temp allocator
|
|
||||||
if len(track_temp.bad_free_array) > 0 {
|
|
||||||
fmt.eprintf("=== %v incorrect frees - temp allocator: ===\n", len(track_temp.bad_free_array))
|
|
||||||
for entry in track_temp.bad_free_array {
|
|
||||||
fmt.eprintf("- %p @ %v\n", entry.memory, entry.location)
|
|
||||||
}
|
|
||||||
mem.tracking_allocator_destroy(&track_temp)
|
|
||||||
}
|
|
||||||
// Default allocator
|
|
||||||
if len(track.allocation_map) > 0 {
|
|
||||||
fmt.eprintf("=== %v allocations not freed - main allocator: ===\n", len(track.allocation_map))
|
|
||||||
for _, entry in track.allocation_map {
|
|
||||||
fmt.eprintf("- %v bytes @ %v\n", entry.size, entry.location)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if len(track.bad_free_array) > 0 {
|
|
||||||
fmt.eprintf("=== %v incorrect frees - main allocator: ===\n", len(track.bad_free_array))
|
|
||||||
for entry in track.bad_free_array {
|
|
||||||
fmt.eprintf("- %p @ %v\n", entry.memory, entry.location)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
mem.tracking_allocator_destroy(&track)
|
|
||||||
}
|
|
||||||
// Logger
|
|
||||||
context.logger = log.create_console_logger()
|
|
||||||
defer log.destroy_console_logger(context.logger)
|
|
||||||
}
|
|
||||||
|
|
||||||
args := os.args[1:]
|
args := os.args[1:]
|
||||||
|
|
||||||
if len(args) == 0 {
|
if len(args) == 0 {
|
||||||
|
|||||||
@@ -1,32 +1,39 @@
|
|||||||
package examples
|
package examples
|
||||||
|
|
||||||
import "core:fmt"
|
import "core:fmt"
|
||||||
import "core:log"
|
|
||||||
import "core:mem"
|
import "core:mem"
|
||||||
import "core:os"
|
import "core:os"
|
||||||
|
|
||||||
import qr ".."
|
import qr ".."
|
||||||
|
|
||||||
main :: proc() {
|
main :: proc() {
|
||||||
//----- General setup ----------------------------------
|
//----- Tracking allocator ----------------------------------
|
||||||
{
|
{
|
||||||
|
tracking_temp_allocator := false
|
||||||
// Temp
|
// Temp
|
||||||
track_temp: mem.Tracking_Allocator
|
track_temp: mem.Tracking_Allocator
|
||||||
mem.tracking_allocator_init(&track_temp, context.temp_allocator)
|
if tracking_temp_allocator {
|
||||||
context.temp_allocator = mem.tracking_allocator(&track_temp)
|
mem.tracking_allocator_init(&track_temp, context.temp_allocator)
|
||||||
|
context.temp_allocator = mem.tracking_allocator(&track_temp)
|
||||||
|
}
|
||||||
// Default
|
// Default
|
||||||
track: mem.Tracking_Allocator
|
track: mem.Tracking_Allocator
|
||||||
mem.tracking_allocator_init(&track, context.allocator)
|
mem.tracking_allocator_init(&track, context.allocator)
|
||||||
context.allocator = mem.tracking_allocator(&track)
|
context.allocator = mem.tracking_allocator(&track)
|
||||||
// Log a warning about any memory that was not freed by the end of the program.
|
|
||||||
// This could be fine for some global state or it could be a memory leak.
|
|
||||||
defer {
|
defer {
|
||||||
// Temp allocator
|
// Temp allocator
|
||||||
if len(track_temp.bad_free_array) > 0 {
|
if tracking_temp_allocator {
|
||||||
fmt.eprintf("=== %v incorrect frees - temp allocator: ===\n", len(track_temp.bad_free_array))
|
if len(track_temp.allocation_map) > 0 {
|
||||||
for entry in track_temp.bad_free_array {
|
fmt.eprintf("=== %v allocations not freed - temp allocator: ===\n", len(track_temp.allocation_map))
|
||||||
fmt.eprintf("- %p @ %v\n", entry.memory, entry.location)
|
for _, entry in track_temp.allocation_map {
|
||||||
|
fmt.eprintf("- %v bytes @ %v\n", entry.size, entry.location)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if len(track_temp.bad_free_array) > 0 {
|
||||||
|
fmt.eprintf("=== %v incorrect frees - temp allocator: ===\n", len(track_temp.bad_free_array))
|
||||||
|
for entry in track_temp.bad_free_array {
|
||||||
|
fmt.eprintf("- %p @ %v\n", entry.memory, entry.location)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
mem.tracking_allocator_destroy(&track_temp)
|
mem.tracking_allocator_destroy(&track_temp)
|
||||||
}
|
}
|
||||||
@@ -45,9 +52,6 @@ main :: proc() {
|
|||||||
}
|
}
|
||||||
mem.tracking_allocator_destroy(&track)
|
mem.tracking_allocator_destroy(&track)
|
||||||
}
|
}
|
||||||
// Logger
|
|
||||||
context.logger = log.create_console_logger()
|
|
||||||
defer log.destroy_console_logger(context.logger)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
args := os.args
|
args := os.args
|
||||||
|
|||||||
1718
vendor/libusb/libusb.odin
vendored
1718
vendor/libusb/libusb.odin
vendored
File diff suppressed because it is too large
Load Diff
BIN
vendor/libusb/windows-x64/libusb-1.0-static.lib
vendored
BIN
vendor/libusb/windows-x64/libusb-1.0-static.lib
vendored
Binary file not shown.
BIN
vendor/libusb/windows-x64/libusb-1.0.dll
vendored
BIN
vendor/libusb/windows-x64/libusb-1.0.dll
vendored
Binary file not shown.
BIN
vendor/libusb/windows-x64/libusb-1.0.lib
vendored
BIN
vendor/libusb/windows-x64/libusb-1.0.lib
vendored
Binary file not shown.
BIN
vendor/libusb/windows-x86/libusb-1.0-static.lib
vendored
BIN
vendor/libusb/windows-x86/libusb-1.0-static.lib
vendored
Binary file not shown.
BIN
vendor/libusb/windows-x86/libusb-1.0.dll
vendored
BIN
vendor/libusb/windows-x86/libusb-1.0.dll
vendored
Binary file not shown.
BIN
vendor/libusb/windows-x86/libusb-1.0.lib
vendored
BIN
vendor/libusb/windows-x86/libusb-1.0.lib
vendored
Binary file not shown.
98
vendor/lmdb/examples/examples.odin
vendored
98
vendor/lmdb/examples/examples.odin
vendored
@@ -1,11 +1,8 @@
|
|||||||
package examples
|
package examples
|
||||||
|
|
||||||
import "core:fmt"
|
import "core:fmt"
|
||||||
import "core:log"
|
|
||||||
import "core:mem"
|
|
||||||
import "core:os"
|
import "core:os"
|
||||||
import "core:sys/posix"
|
import "core:sys/posix"
|
||||||
|
|
||||||
import mdb "../../lmdb"
|
import mdb "../../lmdb"
|
||||||
|
|
||||||
// 0o660
|
// 0o660
|
||||||
@@ -13,75 +10,34 @@ DB_MODE :: posix.mode_t{.IWGRP, .IRGRP, .IWUSR, .IRUSR}
|
|||||||
DB_PATH :: "out/debug/lmdb_example_db"
|
DB_PATH :: "out/debug/lmdb_example_db"
|
||||||
|
|
||||||
main :: proc() {
|
main :: proc() {
|
||||||
//----- General setup ----------------------------------
|
environment: ^mdb.Env
|
||||||
{
|
|
||||||
// Temp
|
|
||||||
track_temp: mem.Tracking_Allocator
|
|
||||||
mem.tracking_allocator_init(&track_temp, context.temp_allocator)
|
|
||||||
context.temp_allocator = mem.tracking_allocator(&track_temp)
|
|
||||||
|
|
||||||
// Default
|
// Create environment for lmdb
|
||||||
track: mem.Tracking_Allocator
|
mdb.panic_on_err(mdb.env_create(&environment))
|
||||||
mem.tracking_allocator_init(&track, context.allocator)
|
// Create directory for databases. Won't do anything if it already exists.
|
||||||
context.allocator = mem.tracking_allocator(&track)
|
// 0o774 gives all permissions for owner and group, read for everyone else.
|
||||||
// Log a warning about any memory that was not freed by the end of the program.
|
os.make_directory(DB_PATH, 0o774)
|
||||||
// This could be fine for some global state or it could be a memory leak.
|
// Open the database files (creates them if they don't already exist)
|
||||||
defer {
|
mdb.panic_on_err(mdb.env_open(environment, DB_PATH, 0, DB_MODE))
|
||||||
// Temp allocator
|
|
||||||
if len(track_temp.bad_free_array) > 0 {
|
|
||||||
fmt.eprintf("=== %v incorrect frees - temp allocator: ===\n", len(track_temp.bad_free_array))
|
|
||||||
for entry in track_temp.bad_free_array {
|
|
||||||
fmt.eprintf("- %p @ %v\n", entry.memory, entry.location)
|
|
||||||
}
|
|
||||||
mem.tracking_allocator_destroy(&track_temp)
|
|
||||||
}
|
|
||||||
// Default allocator
|
|
||||||
if len(track.allocation_map) > 0 {
|
|
||||||
fmt.eprintf("=== %v allocations not freed - main allocator: ===\n", len(track.allocation_map))
|
|
||||||
for _, entry in track.allocation_map {
|
|
||||||
fmt.eprintf("- %v bytes @ %v\n", entry.size, entry.location)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if len(track.bad_free_array) > 0 {
|
|
||||||
fmt.eprintf("=== %v incorrect frees - main allocator: ===\n", len(track.bad_free_array))
|
|
||||||
for entry in track.bad_free_array {
|
|
||||||
fmt.eprintf("- %p @ %v\n", entry.memory, entry.location)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
mem.tracking_allocator_destroy(&track)
|
|
||||||
}
|
|
||||||
// Logger
|
|
||||||
context.logger = log.create_console_logger()
|
|
||||||
defer log.destroy_console_logger(context.logger)
|
|
||||||
}
|
|
||||||
|
|
||||||
environment: ^mdb.Env
|
// Transactions
|
||||||
|
txn_handle: ^mdb.Txn
|
||||||
|
db_handle: mdb.Dbi
|
||||||
|
// Put transaction
|
||||||
|
key := 7
|
||||||
|
key_val := mdb.autoval(&key)
|
||||||
|
put_data := 12
|
||||||
|
put_data_val := mdb.autoval(&put_data)
|
||||||
|
mdb.panic_on_err(mdb.txn_begin(environment, nil, 0, &txn_handle))
|
||||||
|
mdb.panic_on_err(mdb.dbi_open(txn_handle, nil, 0, &db_handle))
|
||||||
|
mdb.panic_on_err(mdb.put(txn_handle, db_handle, &key_val.raw, &put_data_val.raw, 0))
|
||||||
|
mdb.panic_on_err(mdb.txn_commit(txn_handle))
|
||||||
|
|
||||||
// Create environment for lmdb
|
// Get transaction
|
||||||
mdb.panic_on_err(mdb.env_create(&environment))
|
get_data_val := mdb.nil_autoval(int)
|
||||||
// Create directory for databases. Won't do anything if it already exists.
|
mdb.panic_on_err(mdb.txn_begin(environment, nil, 0, &txn_handle))
|
||||||
os.make_directory(DB_PATH)
|
mdb.panic_on_err(mdb.get(txn_handle, db_handle, &key_val.raw, &get_data_val.raw))
|
||||||
// Open the database files (creates them if they don't already exist)
|
mdb.panic_on_err(mdb.txn_commit(txn_handle))
|
||||||
mdb.panic_on_err(mdb.env_open(environment, DB_PATH, {}, DB_MODE))
|
data_cpy := mdb.autoval_get_data(&get_data_val)^
|
||||||
|
fmt.println("Get result:", data_cpy)
|
||||||
// Transactions
|
|
||||||
txn_handle: ^mdb.Txn
|
|
||||||
db_handle: mdb.Dbi
|
|
||||||
// Put transaction
|
|
||||||
key := 7
|
|
||||||
key_val := mdb.blittable_val(&key)
|
|
||||||
put_data := 12
|
|
||||||
put_data_val := mdb.blittable_val(&put_data)
|
|
||||||
mdb.panic_on_err(mdb.txn_begin(environment, nil, {}, &txn_handle))
|
|
||||||
mdb.panic_on_err(mdb.dbi_open(txn_handle, nil, {}, &db_handle))
|
|
||||||
mdb.panic_on_err(mdb.put(txn_handle, db_handle, &key_val, &put_data_val, {}))
|
|
||||||
mdb.panic_on_err(mdb.txn_commit(txn_handle))
|
|
||||||
|
|
||||||
// Get transaction
|
|
||||||
data_val: mdb.Val
|
|
||||||
mdb.panic_on_err(mdb.txn_begin(environment, nil, {}, &txn_handle))
|
|
||||||
mdb.panic_on_err(mdb.get(txn_handle, db_handle, &key_val, &data_val))
|
|
||||||
data_cpy := mdb.blittable_copy(&data_val, int)
|
|
||||||
mdb.panic_on_err(mdb.txn_commit(txn_handle))
|
|
||||||
fmt.println("Get result:", data_cpy)
|
|
||||||
}
|
}
|
||||||
|
|||||||
350
vendor/lmdb/lmdb.odin
vendored
350
vendor/lmdb/lmdb.odin
vendored
@@ -164,123 +164,24 @@
|
|||||||
*/
|
*/
|
||||||
package lmdb
|
package lmdb
|
||||||
|
|
||||||
|
foreign import lib "system:lmdb"
|
||||||
|
|
||||||
import "core:c"
|
import "core:c"
|
||||||
import "core:fmt"
|
import "core:fmt"
|
||||||
import "core:reflect"
|
|
||||||
import "core:sys/posix"
|
import "core:sys/posix"
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------------------------------------------------
|
|
||||||
// ----- Added Odin Helpers ------------------------
|
|
||||||
// ---------------------------------------------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
// Wrap a blittable value's bytes as an LMDB Val.
|
|
||||||
// T must be a contiguous type with no indirection (no pointers, slices, strings, maps, etc.).
|
|
||||||
blittable_val :: #force_inline proc(val_ptr: ^$T) -> Val {
|
|
||||||
fmt.assertf(
|
|
||||||
reflect.has_no_indirections(type_info_of(T)),
|
|
||||||
"blitval: type '%v' contains indirection and cannot be stored directly in LMDB",
|
|
||||||
typeid_of(T),
|
|
||||||
)
|
|
||||||
return Val{size_of(T), val_ptr}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Reads a blittable T out of the LMDB memory map by copying it into caller
|
|
||||||
// storage. The returned T has no lifetime tie to the transaction.
|
|
||||||
blittable_copy :: #force_inline proc(val: ^Val, $T: typeid) -> T {
|
|
||||||
fmt.assertf(
|
|
||||||
reflect.has_no_indirections(type_info_of(T)),
|
|
||||||
"blitval_copy: type '%v' contains indirection and cannot be read directly from LMDB",
|
|
||||||
typeid_of(T),
|
|
||||||
)
|
|
||||||
return (cast(^T)val.data)^
|
|
||||||
}
|
|
||||||
|
|
||||||
// Zero-copy pointer view into the LMDB memory map as a ^T.
|
|
||||||
// Useful for large blittable types where you want to read individual fields
|
|
||||||
// without copying the entire value (e.g. ptr.timestamp, ptr.flags).
|
|
||||||
// MUST NOT be written through — writes either segfault (default env mode)
|
|
||||||
// or silently corrupt the database (ENV_WRITEMAP).
|
|
||||||
// MUST NOT be retained past txn_commit, txn_abort, or any subsequent write
|
|
||||||
// operation on the same env — the pointer is invalidated.
|
|
||||||
blittable_view :: #force_inline proc(val: ^Val, $T: typeid) -> ^T {
|
|
||||||
fmt.assertf(
|
|
||||||
reflect.has_no_indirections(type_info_of(T)),
|
|
||||||
"blitval_view: type '%v' contains indirection and cannot be viewed directly from LMDB",
|
|
||||||
typeid_of(T),
|
|
||||||
)
|
|
||||||
return cast(^T)val.data
|
|
||||||
}
|
|
||||||
|
|
||||||
// Wrap a slice of blittable elements as an LMDB Val for use with put/get.
|
|
||||||
// T must be a contiguous type with no indirection.
|
|
||||||
// The caller's slice must remain valid (not freed, not resized) for the
|
|
||||||
// duration of the put call that consumes this Val.
|
|
||||||
slice_val :: #force_inline proc(s: []$T) -> Val {
|
|
||||||
fmt.assertf(
|
|
||||||
reflect.has_no_indirections(type_info_of(T)),
|
|
||||||
"slice_val: element type '%v' contains indirection and cannot be stored directly in LMDB",
|
|
||||||
typeid_of(T),
|
|
||||||
)
|
|
||||||
return Val{uint(len(s) * size_of(T)), raw_data(s)}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Zero-copy slice view into the LMDB memory map.
|
|
||||||
// T must match the element type that was originally stored.
|
|
||||||
// MUST NOT be modified — writes through this slice either segfault (default
|
|
||||||
// env mode) or silently corrupt the database (ENV_WRITEMAP).
|
|
||||||
// MUST be copied (e.g. slice.clone) if it needs to outlive the current
|
|
||||||
// transaction; the view is invalidated by txn_commit, txn_abort, or any
|
|
||||||
// subsequent write operation on the same env.
|
|
||||||
slice_view :: #force_inline proc(val: ^Val, $T: typeid) -> []T {
|
|
||||||
fmt.assertf(
|
|
||||||
reflect.has_no_indirections(type_info_of(T)),
|
|
||||||
"slice_view: element type '%v' contains indirection and cannot be read directly from LMDB",
|
|
||||||
typeid_of(T),
|
|
||||||
)
|
|
||||||
return (cast([^]T)val.data)[:val.size / size_of(T)]
|
|
||||||
}
|
|
||||||
|
|
||||||
// Wrap a string's bytes as an LMDB Val for use with put/get.
|
|
||||||
// The caller's string must remain valid (backing memory not freed) for the
|
|
||||||
// duration of the put call that consumes this Val.
|
|
||||||
string_val :: #force_inline proc(s: string) -> Val {
|
|
||||||
return Val{uint(len(s)), raw_data(s)}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Zero-copy string view into the LMDB memory map.
|
|
||||||
// MUST NOT be modified — writes through the underlying bytes either segfault
|
|
||||||
// (default env mode) or silently corrupt the database (ENV_WRITEMAP).
|
|
||||||
// MUST be copied (e.g. strings.clone) if it needs to outlive the current
|
|
||||||
// transaction; the view is invalidated by txn_commit, txn_abort, or any
|
|
||||||
// subsequent write operation on the same env.
|
|
||||||
string_view :: #force_inline proc(val: ^Val) -> string {
|
|
||||||
return string((cast([^]u8)val.data)[:val.size])
|
|
||||||
}
|
|
||||||
|
|
||||||
// Panic if there is an error
|
|
||||||
panic_on_err :: #force_inline proc(error: Error, loc := #caller_location) {
|
|
||||||
if error != .NONE {
|
|
||||||
fmt.panicf("LMDB error %v: %s", error, strerror(i32(error)), loc = loc)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------------------------------------------------
|
|
||||||
// ----- Bindings ------------------------
|
|
||||||
// ---------------------------------------------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
_ :: c
|
_ :: c
|
||||||
|
|
||||||
when ODIN_OS == .Windows {
|
when ODIN_OS == .Windows {
|
||||||
#panic("TODO: Compile windows .lib for lmdb")
|
|
||||||
mode_t :: c.int
|
mode_t :: c.int
|
||||||
filehandle_t :: rawptr
|
|
||||||
} else when ODIN_OS ==
|
|
||||||
.Linux || ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .OpenBSD || ODIN_OS == .NetBSD {
|
|
||||||
foreign import lib "system:lmdb"
|
|
||||||
mode_t :: posix.mode_t
|
|
||||||
filehandle_t :: c.int
|
|
||||||
} else {
|
} else {
|
||||||
#panic("levlib/vendor/lmdb: unsupported OS target")
|
mode_t :: posix.mode_t
|
||||||
|
}
|
||||||
|
|
||||||
|
when ODIN_OS == .Windows {
|
||||||
|
filehandle_t :: rawptr
|
||||||
|
} else {
|
||||||
|
filehandle_t :: c.int
|
||||||
}
|
}
|
||||||
|
|
||||||
Env :: struct {}
|
Env :: struct {}
|
||||||
@@ -288,7 +189,7 @@ Env :: struct {}
|
|||||||
Txn :: struct {}
|
Txn :: struct {}
|
||||||
|
|
||||||
/** @brief A handle for an individual database in the DB environment. */
|
/** @brief A handle for an individual database in the DB environment. */
|
||||||
Dbi :: c.uint
|
Dbi :: u32
|
||||||
|
|
||||||
Cursor :: struct {}
|
Cursor :: struct {}
|
||||||
|
|
||||||
@@ -304,8 +205,33 @@ Cursor :: struct {}
|
|||||||
* Other data items can in theory be from 0 to 0xffffffff bytes long.
|
* Other data items can in theory be from 0 to 0xffffffff bytes long.
|
||||||
*/
|
*/
|
||||||
Val :: struct {
|
Val :: struct {
|
||||||
size: uint, /**< size of the data item */
|
mv_size: uint, /**< size of the data item */
|
||||||
data: rawptr, /**< address of the data item */
|
mv_data: rawptr, /**< address of the data item */
|
||||||
|
}
|
||||||
|
|
||||||
|
// Automatic `Val` handling for a given type 'T'.
|
||||||
|
// Will not traverse pointers. If `T` stores pointers, you probably don't want to use this.
|
||||||
|
Auto_Val :: struct($T: typeid) {
|
||||||
|
raw: Val,
|
||||||
|
}
|
||||||
|
|
||||||
|
autoval :: #force_inline proc "contextless" (val_ptr: ^$T) -> Auto_Val(T) {
|
||||||
|
return Auto_Val(T){Val{size_of(T), val_ptr}}
|
||||||
|
}
|
||||||
|
|
||||||
|
nil_autoval :: #force_inline proc "contextless" ($T: typeid) -> Auto_Val(T) {
|
||||||
|
return Auto_Val(T){Val{size_of(T), nil}}
|
||||||
|
}
|
||||||
|
|
||||||
|
autoval_get_data :: #force_inline proc "contextless" (val: ^Auto_Val($T)) -> ^T {
|
||||||
|
return cast(^T)val.raw.mv_data
|
||||||
|
}
|
||||||
|
|
||||||
|
// Panic if there is an error
|
||||||
|
panic_on_err :: #force_inline proc(error: Error) {
|
||||||
|
if error != .NONE {
|
||||||
|
fmt.panicf("Irrecoverable LMDB error", strerror(i32(error)))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @brief A callback function used to compare two keys in a database */
|
/** @brief A callback function used to compare two keys in a database */
|
||||||
@@ -327,65 +253,85 @@ Cmp_Func :: #type proc "c" (_: ^Val, _: ^Val) -> i32
|
|||||||
*/
|
*/
|
||||||
Rel_Func :: #type proc "c" (item: ^Val, oldptr, newptr, relctx: rawptr)
|
Rel_Func :: #type proc "c" (item: ^Val, oldptr, newptr, relctx: rawptr)
|
||||||
|
|
||||||
/** @defgroup mdb_env Environment Flags
|
/** @defgroup mdb_env Environment Flags
|
||||||
* @{
|
* @{
|
||||||
*/
|
*/
|
||||||
Env_Flag :: enum u32 {
|
/** mmap at a fixed address (experimental) */
|
||||||
FIXEDMAP = 0, /**< mmap at a fixed address (experimental) */
|
ENV_FIXEDMAP :: 0x01
|
||||||
NOSUBDIR = 14, /**< no environment directory */
|
/** no environment directory */
|
||||||
NOSYNC = 16, /**< don't fsync after commit */
|
ENV_NOSUBDIR :: 0x4000
|
||||||
RDONLY = 17, /**< read only */
|
/** don't fsync after commit */
|
||||||
NOMETASYNC = 18, /**< don't fsync metapage after commit */
|
ENV_NOSYNC :: 0x10000
|
||||||
WRITEMAP = 19, /**< use writable mmap */
|
/** read only */
|
||||||
MAPASYNC = 20, /**< use asynchronous msync when WRITEMAP is used */
|
ENV_RDONLY :: 0x20000
|
||||||
NOTLS = 21, /**< tie reader locktable slots to Txn objects instead of to threads */
|
/** don't fsync metapage after commit */
|
||||||
NOLOCK = 22, /**< don't do any locking, caller must manage their own locks */
|
ENV_NOMETASYNC :: 0x40000
|
||||||
NORDAHEAD = 23, /**< don't do readahead (no effect on Windows) */
|
/** use writable mmap */
|
||||||
NOMEMINIT = 24, /**< don't initialize malloc'd memory before writing to datafile */
|
ENV_WRITEMAP :: 0x80000
|
||||||
PREVSNAPSHOT = 25, /**< use the previous snapshot rather than the latest one */
|
/** use asynchronous msync when #MDB_WRITEMAP is used */
|
||||||
}
|
ENV_MAPASYNC :: 0x100000
|
||||||
Env_Flags :: distinct bit_set[Env_Flag;c.uint]
|
/** tie reader locktable slots to #MDB_txn objects instead of to threads */
|
||||||
|
ENV_NOTLS :: 0x200000
|
||||||
|
/** don't do any locking, caller must manage their own locks */
|
||||||
|
ENV_NOLOCK :: 0x400000
|
||||||
|
/** don't do readahead (no effect on Windows) */
|
||||||
|
ENV_NORDAHEAD :: 0x800000
|
||||||
|
/** don't initialize malloc'd memory before writing to datafile */
|
||||||
|
ENV_NOMEMINIT :: 0x1000000
|
||||||
/** @} */
|
/** @} */
|
||||||
|
|
||||||
/** @defgroup mdb_dbi_open Database Flags
|
/** @defgroup mdb_dbi_open Database Flags
|
||||||
* @{
|
* @{
|
||||||
*/
|
*/
|
||||||
Db_Flag :: enum u32 {
|
/** use reverse string keys */
|
||||||
REVERSEKEY = 1, /**< use reverse string keys */
|
DB_REVERSEKEY :: 0x02
|
||||||
DUPSORT = 2, /**< use sorted duplicates */
|
/** use sorted duplicates */
|
||||||
INTEGERKEY = 3, /**< numeric keys in native byte order */
|
DB_DUPSORT :: 0x04
|
||||||
DUPFIXED = 4, /**< with DUPSORT, sorted dup items have fixed size */
|
/** numeric keys in native byte order: either unsigned int or size_t.
|
||||||
INTEGERDUP = 5, /**< with DUPSORT, dups are INTEGERKEY-style integers */
|
* The keys must all be of the same size. */
|
||||||
REVERSEDUP = 6, /**< with DUPSORT, use reverse string dups */
|
DB_INTEGERKEY :: 0x08
|
||||||
CREATE = 18, /**< create DB if not already existing */
|
/** with #MDB_DUPSORT, sorted dup items have fixed size */
|
||||||
}
|
DB_DUPFIXED :: 0x10
|
||||||
Db_Flags :: distinct bit_set[Db_Flag;c.uint]
|
/** with #MDB_DUPSORT, dups are #MDB_INTEGERKEY-style integers */
|
||||||
|
DB_INTEGERDUP :: 0x20
|
||||||
|
/** with #MDB_DUPSORT, use reverse string dups */
|
||||||
|
DB_REVERSEDUP :: 0x40
|
||||||
|
/** create DB if not already existing */
|
||||||
|
DB_CREATE :: 0x40000
|
||||||
/** @} */
|
/** @} */
|
||||||
|
|
||||||
/** @defgroup mdb_put Write Flags
|
/** @defgroup mdb_put Write Flags
|
||||||
* @{
|
* @{
|
||||||
*/
|
*/
|
||||||
Write_Flag :: enum u32 {
|
/** For put: Don't write if the key already exists. */
|
||||||
NOOVERWRITE = 4, /**< For put: Don't write if the key already exists */
|
WRITE_NOOVERWRITE :: 0x10
|
||||||
NODUPDATA = 5, /**< For DUPSORT: don't write if the key and data pair already exist.
|
/** Only for #MDB_DUPSORT<br>
|
||||||
For mdb_cursor_del: remove all duplicate data items. */
|
* For put: don't write if the key and data pair already exist.<br>
|
||||||
CURRENT = 6, /**< For mdb_cursor_put: overwrite the current key/data pair */
|
* For mdb_cursor_del: remove all duplicate data items.
|
||||||
RESERVE = 16, /**< For put: Just reserve space for data, don't copy it */
|
*/
|
||||||
APPEND = 17, /**< Data is being appended, don't split full pages */
|
WRITE_NODUPDATA :: 0x20
|
||||||
APPENDDUP = 18, /**< Duplicate data is being appended, don't split full pages */
|
/** For mdb_cursor_put: overwrite the current key/data pair */
|
||||||
MULTIPLE = 19, /**< Store multiple data items in one call. Only for DUPFIXED. */
|
WRITE_CURRENT :: 0x40
|
||||||
}
|
/** For put: Just reserve space for data, don't copy it. Return a
|
||||||
Write_Flags :: distinct bit_set[Write_Flag;c.uint]
|
* pointer to the reserved space.
|
||||||
/** @} */
|
*/
|
||||||
|
WRITE_RESERVE :: 0x10000
|
||||||
|
/** Data is being appended, don't split full pages. */
|
||||||
|
WRITE_APPEND :: 0x20000
|
||||||
|
/** Duplicate data is being appended, don't split full pages. */
|
||||||
|
WRITE_APPENDDUP :: 0x40000
|
||||||
|
/** Store multiple data items in one call. Only for #MDB_DUPFIXED. */
|
||||||
|
WRITE_MULTIPLE :: 0x80000
|
||||||
|
/* @} */
|
||||||
|
|
||||||
/** @defgroup mdb_copy Copy Flags
|
/** @defgroup mdb_copy Copy Flags
|
||||||
* @{
|
* @{
|
||||||
*/
|
*/
|
||||||
Copy_Flag :: enum u32 {
|
/** Compacting copy: Omit free space from copy, and renumber all
|
||||||
COMPACT = 0, /**< Compacting copy: Omit free space from copy, and renumber all pages sequentially. */
|
* pages sequentially.
|
||||||
}
|
*/
|
||||||
Copy_Flags :: distinct bit_set[Copy_Flag;c.uint]
|
CP_COMPACT :: 0x01
|
||||||
/** @} */
|
/* @} */
|
||||||
|
|
||||||
/** @brief Cursor Get operations.
|
/** @brief Cursor Get operations.
|
||||||
*
|
*
|
||||||
@@ -394,24 +340,33 @@ Copy_Flags :: distinct bit_set[Copy_Flag;c.uint]
|
|||||||
*/
|
*/
|
||||||
Cursor_Op :: enum c.int {
|
Cursor_Op :: enum c.int {
|
||||||
FIRST, /**< Position at first key/data item */
|
FIRST, /**< Position at first key/data item */
|
||||||
FIRST_DUP, /**< Position at first data item of current key. Only for DUPSORT */
|
FIRST_DUP, /**< Position at first data item of current key.
|
||||||
GET_BOTH, /**< Position at key/data pair. Only for DUPSORT */
|
Only for #MDB_DUPSORT */
|
||||||
GET_BOTH_RANGE, /**< Position at key, nearest data. Only for DUPSORT */
|
GET_BOTH, /**< Position at key/data pair. Only for #MDB_DUPSORT */
|
||||||
|
GET_BOTH_RANGE, /**< position at key, nearest data. Only for #MDB_DUPSORT */
|
||||||
GET_CURRENT, /**< Return key/data at current cursor position */
|
GET_CURRENT, /**< Return key/data at current cursor position */
|
||||||
GET_MULTIPLE, /**< Return up to a page of duplicate data items from current cursor position. Only for DUPFIXED */
|
GET_MULTIPLE, /**< Return up to a page of duplicate data items
|
||||||
|
from current cursor position. Move cursor to prepare
|
||||||
|
for #MDB_NEXT_MULTIPLE. Only for #MDB_DUPFIXED */
|
||||||
LAST, /**< Position at last key/data item */
|
LAST, /**< Position at last key/data item */
|
||||||
LAST_DUP, /**< Position at last data item of current key. Only for DUPSORT */
|
LAST_DUP, /**< Position at last data item of current key.
|
||||||
|
Only for #MDB_DUPSORT */
|
||||||
NEXT, /**< Position at next data item */
|
NEXT, /**< Position at next data item */
|
||||||
NEXT_DUP, /**< Position at next data item of current key. Only for DUPSORT */
|
NEXT_DUP, /**< Position at next data item of current key.
|
||||||
NEXT_MULTIPLE, /**< Return up to a page of duplicate data items from next cursor position. Only for DUPFIXED */
|
Only for #MDB_DUPSORT */
|
||||||
|
NEXT_MULTIPLE, /**< Return up to a page of duplicate data items
|
||||||
|
from next cursor position. Move cursor to prepare
|
||||||
|
for #MDB_NEXT_MULTIPLE. Only for #MDB_DUPFIXED */
|
||||||
NEXT_NODUP, /**< Position at first data item of next key */
|
NEXT_NODUP, /**< Position at first data item of next key */
|
||||||
PREV, /**< Position at previous data item */
|
PREV, /**< Position at previous data item */
|
||||||
PREV_DUP, /**< Position at previous data item of current key. Only for DUPSORT */
|
PREV_DUP, /**< Position at previous data item of current key.
|
||||||
|
Only for #MDB_DUPSORT */
|
||||||
PREV_NODUP, /**< Position at last data item of previous key */
|
PREV_NODUP, /**< Position at last data item of previous key */
|
||||||
SET, /**< Position at specified key */
|
SET, /**< Position at specified key */
|
||||||
SET_KEY, /**< Position at specified key, return key + data */
|
SET_KEY, /**< Position at specified key, return key + data */
|
||||||
SET_RANGE, /**< Position at first key greater than or equal to specified key */
|
SET_RANGE, /**< Position at first key greater than or equal to specified key. */
|
||||||
PREV_MULTIPLE, /**< Position at previous page and return up to a page of duplicate data items. Only for DUPFIXED */
|
PREV_MULTIPLE, /**< Position at previous page and return up to
|
||||||
|
a page of duplicate data items. Only for #MDB_DUPFIXED */
|
||||||
}
|
}
|
||||||
|
|
||||||
Error :: enum c.int {
|
Error :: enum c.int {
|
||||||
@@ -464,28 +419,33 @@ Error :: enum c.int {
|
|||||||
BAD_VALSIZE = -30781,
|
BAD_VALSIZE = -30781,
|
||||||
/** The specified DBI was changed unexpectedly */
|
/** The specified DBI was changed unexpectedly */
|
||||||
BAD_DBI = -30780,
|
BAD_DBI = -30780,
|
||||||
/** Unexpected problem - txn should abort */
|
|
||||||
PROBLEM = -30779,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @brief Statistics for a database in the environment */
|
/** @brief Statistics for a database in the environment */
|
||||||
Stat :: struct {
|
Stat :: struct {
|
||||||
psize: u32, /**< Size of a database page. This is currently the same for all databases. */
|
ms_psize: u32,
|
||||||
depth: u32, /**< Depth (height) of the B-tree */
|
/**< Size of a database page.
|
||||||
branch_pages: uint, /**< Number of internal (non-leaf) pages */
|
This is currently the same for all databases. */
|
||||||
leaf_pages: uint, /**< Number of leaf pages */
|
ms_depth: u32,
|
||||||
overflow_pages: uint, /**< Number of overflow pages */
|
/**< Depth (height) of the B-tree */
|
||||||
entries: uint, /**< Number of data items */
|
ms_branch_pages: uint,
|
||||||
|
/**< Number of internal (non-leaf) pages */
|
||||||
|
ms_leaf_pages: uint,
|
||||||
|
/**< Number of leaf pages */
|
||||||
|
ms_overflow_pages: uint,
|
||||||
|
/**< Number of overflow pages */
|
||||||
|
ms_entries: uint,
|
||||||
|
/**< Number of data items */
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @brief Information about the environment */
|
/** @brief Information about the environment */
|
||||||
Env_Info :: struct {
|
Env_Info :: struct {
|
||||||
mapaddr: rawptr, /**< Address of map, if fixed */
|
me_mapaddr: rawptr, /**< Address of map, if fixed */
|
||||||
mapsize: uint, /**< Size of the data memory map */
|
me_mapsize: uint, /**< Size of the data memory map */
|
||||||
last_pgno: uint, /**< ID of the last used page */
|
me_last_pgno: uint, /**< ID of the last used page */
|
||||||
last_txnid: uint, /**< ID of the last committed transaction */
|
me_last_txnid: uint, /**< ID of the last committed transaction */
|
||||||
maxreaders: u32, /**< max reader slots in the environment */
|
me_maxreaders: u32, /**< max reader slots in the environment */
|
||||||
numreaders: u32, /**< max reader slots used in the environment */
|
me_numreaders: u32, /**< max reader slots used in the environment */
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @brief A callback function for most LMDB assert() failures,
|
/** @brief A callback function for most LMDB assert() failures,
|
||||||
@@ -494,7 +454,7 @@ Env_Info :: struct {
|
|||||||
* @param[in] env An environment handle returned by #mdb_env_create().
|
* @param[in] env An environment handle returned by #mdb_env_create().
|
||||||
* @param[in] msg The assertion message, not including newline.
|
* @param[in] msg The assertion message, not including newline.
|
||||||
*/
|
*/
|
||||||
Assert_Func :: #type proc "c" (_: ^Env, _: cstring)
|
Assert_Func :: proc "c" (_: ^Env, _: cstring)
|
||||||
|
|
||||||
/** @brief A callback function used to print a message from the library.
|
/** @brief A callback function used to print a message from the library.
|
||||||
*
|
*
|
||||||
@@ -502,7 +462,7 @@ Assert_Func :: #type proc "c" (_: ^Env, _: cstring)
|
|||||||
* @param[in] ctx An arbitrary context pointer for the callback.
|
* @param[in] ctx An arbitrary context pointer for the callback.
|
||||||
* @return < 0 on failure, >= 0 on success.
|
* @return < 0 on failure, >= 0 on success.
|
||||||
*/
|
*/
|
||||||
Msg_Func :: #type proc "c" (_: cstring, _: rawptr) -> i32
|
Msg_Func :: proc "c" (_: cstring, _: rawptr) -> i32
|
||||||
|
|
||||||
@(default_calling_convention = "c", link_prefix = "mdb_")
|
@(default_calling_convention = "c", link_prefix = "mdb_")
|
||||||
foreign lib {
|
foreign lib {
|
||||||
@@ -663,7 +623,7 @@ foreign lib {
|
|||||||
* </ul>
|
* </ul>
|
||||||
*/
|
*/
|
||||||
@(require_results)
|
@(require_results)
|
||||||
env_open :: proc(env: ^Env, path: cstring, flags: Env_Flags, mode: mode_t) -> Error ---
|
env_open :: proc(env: ^Env, path: cstring, flags: u32, mode: mode_t) -> Error ---
|
||||||
|
|
||||||
/** @brief Copy an LMDB environment to the specified path.
|
/** @brief Copy an LMDB environment to the specified path.
|
||||||
*
|
*
|
||||||
@@ -722,7 +682,7 @@ foreign lib {
|
|||||||
* @return A non-zero error value on failure and 0 on success.
|
* @return A non-zero error value on failure and 0 on success.
|
||||||
*/
|
*/
|
||||||
@(require_results)
|
@(require_results)
|
||||||
env_copy2 :: proc(env: ^Env, path: cstring, flags: Copy_Flags) -> Error ---
|
env_copy2 :: proc(env: ^Env, path: cstring, flags: u32) -> Error ---
|
||||||
|
|
||||||
/** @brief Copy an LMDB environment to the specified file descriptor,
|
/** @brief Copy an LMDB environment to the specified file descriptor,
|
||||||
* with options.
|
* with options.
|
||||||
@@ -742,7 +702,7 @@ foreign lib {
|
|||||||
* @return A non-zero error value on failure and 0 on success.
|
* @return A non-zero error value on failure and 0 on success.
|
||||||
*/
|
*/
|
||||||
@(require_results)
|
@(require_results)
|
||||||
env_copyfd2 :: proc(env: ^Env, fd: filehandle_t, flags: Copy_Flags) -> Error ---
|
env_copyfd2 :: proc(env: ^Env, fd: filehandle_t, flags: u32) -> Error ---
|
||||||
|
|
||||||
/** @brief Return statistics about the LMDB environment.
|
/** @brief Return statistics about the LMDB environment.
|
||||||
*
|
*
|
||||||
@@ -807,7 +767,7 @@ foreign lib {
|
|||||||
* </ul>
|
* </ul>
|
||||||
*/
|
*/
|
||||||
@(require_results)
|
@(require_results)
|
||||||
env_set_flags :: proc(env: ^Env, flags: Env_Flags, onoff: i32) -> Error ---
|
env_set_flags :: proc(env: ^Env, flags: u32, onoff: i32) -> Error ---
|
||||||
|
|
||||||
/** @brief Get environment flags.
|
/** @brief Get environment flags.
|
||||||
*
|
*
|
||||||
@@ -820,7 +780,7 @@ foreign lib {
|
|||||||
* </ul>
|
* </ul>
|
||||||
*/
|
*/
|
||||||
@(require_results)
|
@(require_results)
|
||||||
env_get_flags :: proc(env: ^Env, flags: ^Env_Flags) -> Error ---
|
env_get_flags :: proc(env: ^Env, flags: ^u32) -> Error ---
|
||||||
|
|
||||||
/** @brief Return the path that was used in #mdb_env_open().
|
/** @brief Return the path that was used in #mdb_env_open().
|
||||||
*
|
*
|
||||||
@@ -1013,7 +973,7 @@ foreign lib {
|
|||||||
* </ul>
|
* </ul>
|
||||||
*/
|
*/
|
||||||
@(require_results)
|
@(require_results)
|
||||||
txn_begin :: proc(env: ^Env, parent: ^Txn, flags: Env_Flags, txn: ^^Txn) -> Error ---
|
txn_begin :: proc(env: ^Env, parent: ^Txn, flags: u32, txn: ^^Txn) -> Error ---
|
||||||
|
|
||||||
/** @brief Returns the transaction's #MDB_env
|
/** @brief Returns the transaction's #MDB_env
|
||||||
*
|
*
|
||||||
@@ -1166,7 +1126,7 @@ foreign lib {
|
|||||||
* </ul>
|
* </ul>
|
||||||
*/
|
*/
|
||||||
@(require_results)
|
@(require_results)
|
||||||
dbi_open :: proc(txn: ^Txn, name: cstring, flags: Db_Flags, dbi: ^Dbi) -> Error ---
|
dbi_open :: proc(txn: ^Txn, name: cstring, flags: u32, dbi: ^Dbi) -> Error ---
|
||||||
|
|
||||||
/** @brief Retrieve statistics for a database.
|
/** @brief Retrieve statistics for a database.
|
||||||
*
|
*
|
||||||
@@ -1191,7 +1151,7 @@ foreign lib {
|
|||||||
* @return A non-zero error value on failure and 0 on success.
|
* @return A non-zero error value on failure and 0 on success.
|
||||||
*/
|
*/
|
||||||
@(require_results)
|
@(require_results)
|
||||||
dbi_flags :: proc(txn: ^Txn, dbi: Dbi, flags: ^Db_Flags) -> Error ---
|
dbi_flags :: proc(txn: ^Txn, dbi: Dbi, flags: ^u32) -> Error ---
|
||||||
|
|
||||||
/** @brief Close a database handle. Normally unnecessary. Use with care:
|
/** @brief Close a database handle. Normally unnecessary. Use with care:
|
||||||
*
|
*
|
||||||
@@ -1269,7 +1229,6 @@ foreign lib {
|
|||||||
@(require_results)
|
@(require_results)
|
||||||
set_dupsort :: proc(txn: ^Txn, dbi: Dbi, cmp: Cmp_Func) -> Error ---
|
set_dupsort :: proc(txn: ^Txn, dbi: Dbi, cmp: Cmp_Func) -> Error ---
|
||||||
|
|
||||||
// NOTE: Unimplemented in current LMDB — this function has no effect.
|
|
||||||
/** @brief Set a relocation function for a #MDB_FIXEDMAP database.
|
/** @brief Set a relocation function for a #MDB_FIXEDMAP database.
|
||||||
*
|
*
|
||||||
* @todo The relocation function is called whenever it is necessary to move the data
|
* @todo The relocation function is called whenever it is necessary to move the data
|
||||||
@@ -1291,7 +1250,6 @@ foreign lib {
|
|||||||
@(require_results)
|
@(require_results)
|
||||||
set_relfunc :: proc(txn: ^Txn, dbi: Dbi, rel: Rel_Func) -> Error ---
|
set_relfunc :: proc(txn: ^Txn, dbi: Dbi, rel: Rel_Func) -> Error ---
|
||||||
|
|
||||||
// NOTE: Unimplemented in current LMDB — this function has no effect.
|
|
||||||
/** @brief Set a context pointer for a #MDB_FIXEDMAP database's relocation function.
|
/** @brief Set a context pointer for a #MDB_FIXEDMAP database's relocation function.
|
||||||
*
|
*
|
||||||
* See #mdb_set_relfunc and #MDB_rel_func for more details.
|
* See #mdb_set_relfunc and #MDB_rel_func for more details.
|
||||||
@@ -1386,7 +1344,7 @@ foreign lib {
|
|||||||
* </ul>
|
* </ul>
|
||||||
*/
|
*/
|
||||||
@(require_results)
|
@(require_results)
|
||||||
put :: proc(txn: ^Txn, dbi: Dbi, key: ^Val, data: ^Val, flags: Write_Flags) -> Error ---
|
put :: proc(txn: ^Txn, dbi: Dbi, key: ^Val, data: ^Val, flags: u32) -> Error ---
|
||||||
|
|
||||||
/** @brief Delete items from a database.
|
/** @brief Delete items from a database.
|
||||||
*
|
*
|
||||||
@@ -1559,7 +1517,7 @@ foreign lib {
|
|||||||
* </ul>
|
* </ul>
|
||||||
*/
|
*/
|
||||||
@(require_results)
|
@(require_results)
|
||||||
cursor_put :: proc(cursor: ^Cursor, key: ^Val, data: ^Val, flags: Write_Flags) -> Error ---
|
cursor_put :: proc(cursor: ^Cursor, key: ^Val, data: ^Val, flags: u32) -> Error ---
|
||||||
|
|
||||||
/** @brief Delete current key/data pair
|
/** @brief Delete current key/data pair
|
||||||
*
|
*
|
||||||
@@ -1583,7 +1541,7 @@ foreign lib {
|
|||||||
* </ul>
|
* </ul>
|
||||||
*/
|
*/
|
||||||
@(require_results)
|
@(require_results)
|
||||||
cursor_del :: proc(cursor: ^Cursor, flags: Write_Flags) -> Error ---
|
cursor_del :: proc(cursor: ^Cursor, flags: u32) -> Error ---
|
||||||
|
|
||||||
/** @brief Return count of duplicates for current key.
|
/** @brief Return count of duplicates for current key.
|
||||||
*
|
*
|
||||||
|
|||||||
Reference in New Issue
Block a user