|
1 | 1 | module LMDB |
2 | 2 |
|
3 | 3 | import Base: open, close, getindex, setindex!, put!, pop!, replace!, reset, |
4 | | - isopen, count, delete!, keys, get, show, show, stat, copy, |
| 4 | + isopen, count, delete!, keys, get, show, stat, copy, |
5 | 5 | empty!, length, isempty, iterate, haskey |
6 | 6 | import Base.Iterators: drop |
7 | 7 |
|
8 | | -export |
9 | | - # error type + matchers |
10 | | - LMDBError, is_notfound, is_keyexist, is_map_full, |
11 | | - |
12 | | - # commonly-needed status codes |
13 | | - MDB_NOTFOUND, MDB_KEYEXIST, MDB_MAP_FULL, |
14 | | - |
15 | | - # commonly-needed env flags |
16 | | - MDB_RDONLY, MDB_NOTLS, MDB_NORDAHEAD, MDB_NOSUBDIR, |
17 | | - MDB_NOSYNC, MDB_NOMETASYNC, MDB_WRITEMAP, MDB_NOMEMINIT, |
18 | | - |
19 | | - # commonly-needed db flags |
20 | | - MDB_CREATE, MDB_DUPSORT, MDB_INTEGERKEY, MDB_REVERSEKEY, |
21 | | - MDB_DUPFIXED, MDB_INTEGERDUP, MDB_REVERSEDUP, |
22 | | - |
23 | | - # commonly-needed write flags |
24 | | - MDB_NOOVERWRITE, MDB_NODUPDATA, MDB_APPEND, MDB_RESERVE, |
25 | | - |
26 | | - # Julia wrappers: environment |
27 | | - Environment, create, environment, |
28 | | - sync, set!, unset!, info, stat, path, isopen, isflagset, |
29 | | - reader_check, reader_list, |
30 | | - |
31 | | - # Julia wrappers: transaction |
32 | | - Transaction, start, abort, commit, reset, renew, |
33 | | - |
34 | | - # Julia wrappers: database (DBI) |
35 | | - DBI, drop, get, put!, put_reserved!, delete!, tryget, replace!, |
36 | | - |
37 | | - # Julia wrappers: cursor |
38 | | - Cursor, count, transaction, database, |
39 | | - seek!, seek_last!, seek_range!, next!, prev!, |
40 | | - key, value, item, walk, |
41 | | - seek_first_dup!, seek_last_dup!, |
42 | | - next_dup!, prev_dup!, next_nodup!, prev_nodup!, |
43 | | - |
44 | | - # High-level interface |
45 | | - LMDBDict |
46 | | - |
47 | | -# --------------------------------------------------------------------------- |
48 | | -# Error type. Defined here so the `@checked` macro can reference it; the |
49 | | -# constructor itself defers to `errormsg` (defined after `liblmdb.jl` once |
50 | | -# `mdb_strerror` is in scope). |
51 | | -# --------------------------------------------------------------------------- |
52 | | - |
53 | | -"""LMDB exception type. `code` is the raw status code; use `is_notfound`, |
54 | | -`is_keyexist`, `is_map_full` for common matches.""" |
55 | | -struct LMDBError <: Exception |
56 | | - code::Cint |
57 | | - msg::AbstractString |
58 | | - LMDBError(code::Integer) = new(Cint(code), errormsg(Cint(code))) |
59 | | - LMDBError(code::Integer, msg::AbstractString) = new(Cint(code), msg) |
60 | | -end |
61 | | -show(io::IO, err::LMDBError) = print(io, "Code[$(err.code)]: $(err.msg)") |
62 | | - |
63 | | -"Throw an `LMDBError` if `code` is non-zero. Returns `code` otherwise." |
64 | | -@inline check(code) = iszero(code) ? code : throw(LMDBError(code)) |
65 | | - |
66 | | -""" |
67 | | - is_notfound(err::LMDBError) -> Bool |
68 | | -
|
69 | | -`true` if `err.code == MDB_NOTFOUND` (LMDB's "key not present" status). |
70 | | -
|
71 | | -Use this to recover from a missing key when the lookup is not point-typed |
72 | | -(otherwise `tryget` / `get(..., default)` are simpler): |
73 | | -
|
74 | | -```julia |
75 | | -try |
76 | | - LMDB.get(txn, dbi, "key", String) |
77 | | -catch e |
78 | | - e isa LMDBError && is_notfound(e) || rethrow() |
79 | | - # treat as missing |
| 8 | +# `public name1, name2, ...` on 1.11+, no-op on 1.10. |
| 9 | +macro public(names) |
| 10 | + @static if VERSION >= v"1.11" |
| 11 | + syms = names isa Symbol ? (names,) : |
| 12 | + Meta.isexpr(names, :tuple) ? names.args : |
| 13 | + error("@public expects a symbol or a comma-separated list of symbols") |
| 14 | + return esc(Expr(:public, syms...)) |
| 15 | + else |
| 16 | + return nothing |
| 17 | + end |
80 | 18 | end |
81 | | -``` |
82 | | -""" |
83 | | -is_notfound |
84 | | - |
85 | | -""" |
86 | | - is_keyexist(err::LMDBError) -> Bool |
87 | | -
|
88 | | -`true` if `err.code == MDB_KEYEXIST`. Raised by `put!` with `MDB_NOOVERWRITE` |
89 | | -or `MDB_NODUPDATA` when the key (or duplicate) is already present. |
90 | | -""" |
91 | | -is_keyexist |
92 | | - |
93 | | -""" |
94 | | - is_map_full(err::LMDBError) -> Bool |
95 | 19 |
|
96 | | -`true` if `err.code == MDB_MAP_FULL`. Raised when a write txn would exceed |
97 | | -the environment's `MapSize`. The remedy is to grow `mapsize` (which can be |
98 | | -done after `close(env)` without rewriting the database). |
99 | | -""" |
100 | | -is_map_full |
| 20 | +include("error.jl") |
101 | 21 |
|
102 | | -# --------------------------------------------------------------------------- |
103 | | -# C API: raw bindings, types, constants. Public-but-unexported. |
104 | | -# |
105 | | -# Every status-returning binding has a `@checked` wrapper (auto-throws) and an |
106 | | -# `unchecked_*` companion (returns the raw `Cint` for callers that need to |
107 | | -# inspect it, e.g. branching on `MDB_NOTFOUND`). |
108 | | -# |
109 | | -# Use as `LMDB.mdb_env_create`, `LMDB.MDB_NOTLS`, `LMDB.MDB_val`. The Julia |
110 | | -# wrappers (`Environment`, `Transaction`, …) wrap these and are what most |
111 | | -# callers should reach for. |
112 | | -# --------------------------------------------------------------------------- |
113 | | - |
114 | | -include("checked.jl") |
| 22 | +# C API |
115 | 23 | include("liblmdb.jl") |
116 | 24 |
|
117 | | -"""Return a string describing a given LMDB status code.""" |
118 | | -errormsg(err::Cint) = unsafe_string(mdb_strerror(err)) |
119 | | - |
120 | | -# Common status-code matchers, mirroring `is_notfound`/`is_keyexist` patterns. |
121 | | -is_notfound(err::LMDBError) = err.code == MDB_NOTFOUND |
122 | | -is_keyexist(err::LMDBError) = err.code == MDB_KEYEXIST |
123 | | -is_map_full(err::LMDBError) = err.code == MDB_MAP_FULL |
124 | | - |
125 | | -# --------------------------------------------------------------------------- |
126 | | -# ccall glue between the C API and the Julia wrappers: `MDBValue`, `MDBArg`, |
127 | | -# and the `MDBValueIO <: IO` wrapper used to plug in custom decoders via |
128 | | -# `Base.read(io, T)`. |
129 | | -# --------------------------------------------------------------------------- |
130 | | - |
131 | 25 | include("common.jl") |
132 | 26 |
|
133 | | -# --------------------------------------------------------------------------- |
134 | | -# Julia wrappers around the raw bindings. |
135 | | -# --------------------------------------------------------------------------- |
136 | | - |
| 27 | +# Julia wrappers |
137 | 28 | include("env.jl") |
138 | 29 | include("txn.jl") |
139 | 30 | include("dbi.jl") |
140 | 31 | include("cur.jl") |
141 | 32 |
|
142 | | -# --------------------------------------------------------------------------- |
143 | | -# High-level interface: `LMDBDict`. |
144 | | -# --------------------------------------------------------------------------- |
145 | | - |
| 33 | +# High-level abstractions |
146 | 34 | include("dicts.jl") |
147 | 35 |
|
148 | 36 | end # module |
0 commit comments