Vendors: import ocaml-lmdb
This commit is contained in:
parent
6d7fe70c44
commit
cbef4c4d0c
283
.gitlab-ci.yml
283
.gitlab-ci.yml
@ -310,202 +310,207 @@ opam:13:tezos-micheline:
|
||||
variables:
|
||||
package: tezos-micheline
|
||||
|
||||
opam:14:tezos-base:
|
||||
<<: *opam_definition
|
||||
variables:
|
||||
package: tezos-base
|
||||
|
||||
opam:15:pbkdf:
|
||||
opam:14:pbkdf:
|
||||
<<: *opam_definition
|
||||
variables:
|
||||
package: pbkdf
|
||||
|
||||
opam:16:ocplib-resto-cohttp:
|
||||
opam:15:ocplib-resto-cohttp:
|
||||
<<: *opam_definition
|
||||
variables:
|
||||
package: ocplib-resto-cohttp
|
||||
|
||||
opam:16:tezos-base:
|
||||
<<: *opam_definition
|
||||
variables:
|
||||
package: tezos-base
|
||||
|
||||
opam:17:irmin-leveldb:
|
||||
<<: *opam_definition
|
||||
variables:
|
||||
package: irmin-leveldb
|
||||
|
||||
opam:18:tezos-protocol-environment-sigs:
|
||||
<<: *opam_definition
|
||||
variables:
|
||||
package: tezos-protocol-environment-sigs
|
||||
|
||||
opam:19:tezos-stdlib-unix:
|
||||
<<: *opam_definition
|
||||
variables:
|
||||
package: tezos-stdlib-unix
|
||||
|
||||
opam:20:bip39:
|
||||
opam:18:bip39:
|
||||
<<: *opam_definition
|
||||
variables:
|
||||
package: bip39
|
||||
|
||||
opam:21:tezos-rpc-http:
|
||||
opam:19:tezos-rpc-http:
|
||||
<<: *opam_definition
|
||||
variables:
|
||||
package: tezos-rpc-http
|
||||
|
||||
opam:22:tezos-shell-services:
|
||||
opam:20:tezos-shell-services:
|
||||
<<: *opam_definition
|
||||
variables:
|
||||
package: tezos-shell-services
|
||||
|
||||
opam:23:tezos-storage:
|
||||
opam:21:tezos-stdlib-unix:
|
||||
<<: *opam_definition
|
||||
variables:
|
||||
package: tezos-stdlib-unix
|
||||
|
||||
opam:22:tezos-storage:
|
||||
<<: *opam_definition
|
||||
variables:
|
||||
package: tezos-storage
|
||||
|
||||
opam:24:tezos-protocol-compiler:
|
||||
opam:23:tezos-protocol-environment-sigs:
|
||||
<<: *opam_definition
|
||||
variables:
|
||||
package: tezos-protocol-compiler
|
||||
package: tezos-protocol-environment-sigs
|
||||
|
||||
opam:25:tezos-client-base:
|
||||
opam:24:tezos-client-base:
|
||||
<<: *opam_definition
|
||||
variables:
|
||||
package: tezos-client-base
|
||||
|
||||
opam:26:tezos-protocol-alpha:
|
||||
opam:25:tezos-protocol-compiler:
|
||||
<<: *opam_definition
|
||||
variables:
|
||||
package: tezos-protocol-alpha
|
||||
package: tezos-protocol-compiler
|
||||
|
||||
opam:27:tezos-protocol-environment:
|
||||
<<: *opam_definition
|
||||
variables:
|
||||
package: tezos-protocol-environment
|
||||
|
||||
opam:28:tezos-client-alpha:
|
||||
<<: *opam_definition
|
||||
variables:
|
||||
package: tezos-client-alpha
|
||||
|
||||
opam:29:tezos-client-commands:
|
||||
<<: *opam_definition
|
||||
variables:
|
||||
package: tezos-client-commands
|
||||
|
||||
opam:30:tezos-protocol-environment-shell:
|
||||
<<: *opam_definition
|
||||
variables:
|
||||
package: tezos-protocol-environment-shell
|
||||
|
||||
opam:31:tezos-baking-alpha:
|
||||
<<: *opam_definition
|
||||
variables:
|
||||
package: tezos-baking-alpha
|
||||
|
||||
opam:32:tezos-protocol-genesis:
|
||||
<<: *opam_definition
|
||||
variables:
|
||||
package: tezos-protocol-genesis
|
||||
|
||||
opam:33:ocplib-resto-json:
|
||||
<<: *opam_definition
|
||||
variables:
|
||||
package: ocplib-resto-json
|
||||
|
||||
opam:34:tezos-protocol-updater:
|
||||
<<: *opam_definition
|
||||
variables:
|
||||
package: tezos-protocol-updater
|
||||
|
||||
opam:35:tezos-p2p:
|
||||
<<: *opam_definition
|
||||
variables:
|
||||
package: tezos-p2p
|
||||
|
||||
opam:36:tezos-baking-alpha-commands:
|
||||
<<: *opam_definition
|
||||
variables:
|
||||
package: tezos-baking-alpha-commands
|
||||
|
||||
opam:37:tezos-client-alpha-commands:
|
||||
<<: *opam_definition
|
||||
variables:
|
||||
package: tezos-client-alpha-commands
|
||||
|
||||
opam:38:tezos-client-base-unix:
|
||||
<<: *opam_definition
|
||||
variables:
|
||||
package: tezos-client-base-unix
|
||||
|
||||
opam:39:tezos-client-genesis:
|
||||
<<: *opam_definition
|
||||
variables:
|
||||
package: tezos-client-genesis
|
||||
|
||||
opam:40:ocplib-ezresto:
|
||||
<<: *opam_definition
|
||||
variables:
|
||||
package: ocplib-ezresto
|
||||
|
||||
opam:41:tezos-embedded-protocol-alpha:
|
||||
<<: *opam_definition
|
||||
variables:
|
||||
package: tezos-embedded-protocol-alpha
|
||||
|
||||
opam:42:tezos-embedded-protocol-demo:
|
||||
<<: *opam_definition
|
||||
variables:
|
||||
package: tezos-embedded-protocol-demo
|
||||
|
||||
opam:43:tezos-embedded-protocol-genesis:
|
||||
<<: *opam_definition
|
||||
variables:
|
||||
package: tezos-embedded-protocol-genesis
|
||||
|
||||
opam:44:tezos-shell:
|
||||
<<: *opam_definition
|
||||
variables:
|
||||
package: tezos-shell
|
||||
|
||||
opam:45:tezos-client:
|
||||
<<: *opam_definition
|
||||
variables:
|
||||
package: tezos-client
|
||||
|
||||
opam:46:tezos-signer-services:
|
||||
opam:26:tezos-signer-services:
|
||||
<<: *opam_definition
|
||||
variables:
|
||||
package: tezos-signer-services
|
||||
|
||||
opam:47:ocplib-ezresto-directory:
|
||||
opam:27:tezos-protocol-alpha:
|
||||
<<: *opam_definition
|
||||
variables:
|
||||
package: ocplib-ezresto-directory
|
||||
package: tezos-protocol-alpha
|
||||
|
||||
opam:48:tezos-baker-alpha:
|
||||
opam:28:tezos-protocol-environment:
|
||||
<<: *opam_definition
|
||||
variables:
|
||||
package: tezos-baker-alpha
|
||||
package: tezos-protocol-environment
|
||||
|
||||
opam:49:tezos-protocol-demo:
|
||||
<<: *opam_definition
|
||||
variables:
|
||||
package: tezos-protocol-demo
|
||||
|
||||
opam:50:tezos-signer:
|
||||
<<: *opam_definition
|
||||
variables:
|
||||
package: tezos-signer
|
||||
|
||||
opam:51:tezos-signer-backends:
|
||||
opam:29:tezos-signer-backends:
|
||||
<<: *opam_definition
|
||||
variables:
|
||||
package: tezos-signer-backends
|
||||
|
||||
opam:52:tezos-node:
|
||||
opam:30:tezos-client-alpha:
|
||||
<<: *opam_definition
|
||||
variables:
|
||||
package: tezos-client-alpha
|
||||
|
||||
opam:31:tezos-client-commands:
|
||||
<<: *opam_definition
|
||||
variables:
|
||||
package: tezos-client-commands
|
||||
|
||||
opam:32:tezos-protocol-environment-shell:
|
||||
<<: *opam_definition
|
||||
variables:
|
||||
package: tezos-protocol-environment-shell
|
||||
|
||||
opam:33:tezos-baking-alpha:
|
||||
<<: *opam_definition
|
||||
variables:
|
||||
package: tezos-baking-alpha
|
||||
|
||||
opam:34:tezos-protocol-genesis:
|
||||
<<: *opam_definition
|
||||
variables:
|
||||
package: tezos-protocol-genesis
|
||||
|
||||
opam:35:ocplib-resto-json:
|
||||
<<: *opam_definition
|
||||
variables:
|
||||
package: ocplib-resto-json
|
||||
|
||||
opam:36:tezos-protocol-updater:
|
||||
<<: *opam_definition
|
||||
variables:
|
||||
package: tezos-protocol-updater
|
||||
|
||||
opam:37:tezos-p2p:
|
||||
<<: *opam_definition
|
||||
variables:
|
||||
package: tezos-p2p
|
||||
|
||||
opam:38:tezos-baking-alpha-commands:
|
||||
<<: *opam_definition
|
||||
variables:
|
||||
package: tezos-baking-alpha-commands
|
||||
|
||||
opam:39:tezos-client-alpha-commands:
|
||||
<<: *opam_definition
|
||||
variables:
|
||||
package: tezos-client-alpha-commands
|
||||
|
||||
opam:40:tezos-client-base-unix:
|
||||
<<: *opam_definition
|
||||
variables:
|
||||
package: tezos-client-base-unix
|
||||
|
||||
opam:41:tezos-client-genesis:
|
||||
<<: *opam_definition
|
||||
variables:
|
||||
package: tezos-client-genesis
|
||||
|
||||
opam:42:ocplib-ezresto:
|
||||
<<: *opam_definition
|
||||
variables:
|
||||
package: ocplib-ezresto
|
||||
|
||||
opam:43:lmdb:
|
||||
<<: *opam_definition
|
||||
variables:
|
||||
package: lmdb
|
||||
|
||||
opam:44:tezos-embedded-protocol-alpha:
|
||||
<<: *opam_definition
|
||||
variables:
|
||||
package: tezos-embedded-protocol-alpha
|
||||
|
||||
opam:45:tezos-embedded-protocol-demo:
|
||||
<<: *opam_definition
|
||||
variables:
|
||||
package: tezos-embedded-protocol-demo
|
||||
|
||||
opam:46:tezos-embedded-protocol-genesis:
|
||||
<<: *opam_definition
|
||||
variables:
|
||||
package: tezos-embedded-protocol-genesis
|
||||
|
||||
opam:47:tezos-shell:
|
||||
<<: *opam_definition
|
||||
variables:
|
||||
package: tezos-shell
|
||||
|
||||
opam:48:tezos-client:
|
||||
<<: *opam_definition
|
||||
variables:
|
||||
package: tezos-client
|
||||
|
||||
opam:49:ocplib-ezresto-directory:
|
||||
<<: *opam_definition
|
||||
variables:
|
||||
package: ocplib-ezresto-directory
|
||||
|
||||
opam:50:tezos-baker-alpha:
|
||||
<<: *opam_definition
|
||||
variables:
|
||||
package: tezos-baker-alpha
|
||||
|
||||
opam:51:tezos-protocol-demo:
|
||||
<<: *opam_definition
|
||||
variables:
|
||||
package: tezos-protocol-demo
|
||||
|
||||
opam:52:tezos-signer:
|
||||
<<: *opam_definition
|
||||
variables:
|
||||
package: tezos-signer
|
||||
|
||||
opam:53:tezos-node:
|
||||
<<: *opam_definition
|
||||
variables:
|
||||
package: tezos-node
|
||||
|
||||
opam:53:ocplib-json-typed-browser:
|
||||
opam:54:ocplib-json-typed-browser:
|
||||
<<: *opam_definition
|
||||
variables:
|
||||
package: ocplib-json-typed-browser
|
||||
|
47
vendors/ocaml-lmdb/LICENSE
vendored
Normal file
47
vendors/ocaml-lmdb/LICENSE
vendored
Normal file
@ -0,0 +1,47 @@
|
||||
The OpenLDAP Public License
|
||||
Version 2.8, 17 August 2003
|
||||
|
||||
Redistribution and use of this software and associated documentation
|
||||
("Software"), with or without modification, are permitted provided
|
||||
that the following conditions are met:
|
||||
|
||||
1. Redistributions in source form must retain copyright statements
|
||||
and notices,
|
||||
|
||||
2. Redistributions in binary form must reproduce applicable copyright
|
||||
statements and notices, this list of conditions, and the following
|
||||
disclaimer in the documentation and/or other materials provided
|
||||
with the distribution, and
|
||||
|
||||
3. Redistributions must contain a verbatim copy of this document.
|
||||
|
||||
The OpenLDAP Foundation may revise this license from time to time.
|
||||
Each revision is distinguished by a version number. You may use
|
||||
this Software under terms of this license revision or under the
|
||||
terms of any subsequent revision of the license.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE OPENLDAP FOUNDATION AND ITS
|
||||
CONTRIBUTORS ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
|
||||
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||
AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
SHALL THE OPENLDAP FOUNDATION, ITS CONTRIBUTORS, OR THE AUTHOR(S)
|
||||
OR OWNER(S) OF THE SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
The names of the authors and copyright holders must not be used in
|
||||
advertising or otherwise to promote the sale, use or other dealing
|
||||
in this Software without specific, written prior permission. Title
|
||||
to copyright in this Software shall at all times remain with copyright
|
||||
holders.
|
||||
|
||||
OpenLDAP is a registered trademark of the OpenLDAP Foundation.
|
||||
|
||||
Copyright 1999-2003 The OpenLDAP Foundation, Redwood City,
|
||||
California, USA. All Rights Reserved. Permission to copy and
|
||||
distribute verbatim copies of this document is granted.
|
4
vendors/ocaml-lmdb/config/discover.ml
vendored
Normal file
4
vendors/ocaml-lmdb/config/discover.ml
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
let () =
|
||||
let oc = open_out "c_flags.sexp" in
|
||||
output_string oc (if Sys.word_size = 32 then "(-DMDB_VL32)" else "()") ;
|
||||
close_out oc
|
4
vendors/ocaml-lmdb/config/jbuild
vendored
Normal file
4
vendors/ocaml-lmdb/config/jbuild
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
(jbuild_version 1)
|
||||
|
||||
(executable
|
||||
((name discover)))
|
21
vendors/ocaml-lmdb/lmdb.opam
vendored
Normal file
21
vendors/ocaml-lmdb/lmdb.opam
vendored
Normal file
@ -0,0 +1,21 @@
|
||||
opam-version: "1.2"
|
||||
name: "lmdb"
|
||||
version: "0.1"
|
||||
authors: "Vincent Bernardoff <vb@luminar.eu.org>"
|
||||
maintainer: "Vincent Bernardoff <vb@luminar.eu.org>"
|
||||
license: "ISC"
|
||||
homepage: "https://github.com/vbmithr/ocaml-lmdb"
|
||||
bug-reports: "https://github.com/vbmithr/ocaml-lmdb/issues"
|
||||
dev-repo: "git://github.com/vbmithr/ocaml-lmdb"
|
||||
|
||||
available: [
|
||||
ocaml-version >= "4.02.0"
|
||||
]
|
||||
|
||||
build: [ "jbuilder" "build" "-j" jobs "-p" name "@install" ]
|
||||
depends: [
|
||||
"jbuilder" {build & >= "1.0+beta18"}
|
||||
"rresult" {>= "0.5.0"}
|
||||
"cstruct" {test & >= "3.2.1"}
|
||||
"alcotest" {test & >= "0.8.1"}
|
||||
]
|
14
vendors/ocaml-lmdb/src/jbuild
vendored
Normal file
14
vendors/ocaml-lmdb/src/jbuild
vendored
Normal file
@ -0,0 +1,14 @@
|
||||
(jbuild_version 1)
|
||||
|
||||
(library
|
||||
((name lmdb)
|
||||
(public_name lmdb)
|
||||
(libraries (rresult))
|
||||
(c_names (mdb midl lmdb_stubs))
|
||||
(c_flags (:include c_flags.sexp))
|
||||
(c_library_flags (-lpthread))))
|
||||
|
||||
(rule
|
||||
((targets (c_flags.sexp))
|
||||
(deps (../config/discover.exe))
|
||||
(action (run ${<} -ocamlc ${OCAMLC}))))
|
1647
vendors/ocaml-lmdb/src/lmdb.h
vendored
Normal file
1647
vendors/ocaml-lmdb/src/lmdb.h
vendored
Normal file
File diff suppressed because it is too large
Load Diff
648
vendors/ocaml-lmdb/src/lmdb.ml
vendored
Normal file
648
vendors/ocaml-lmdb/src/lmdb.ml
vendored
Normal file
@ -0,0 +1,648 @@
|
||||
(*---------------------------------------------------------------------------
|
||||
Copyright (c) 2018 Vincent Bernardoff. All rights reserved.
|
||||
Distributed under the ISC license, see terms at the end of the file.
|
||||
---------------------------------------------------------------------------*)
|
||||
|
||||
module Option = struct
|
||||
let map ~f = function
|
||||
| None -> None
|
||||
| Some v -> Some (f v)
|
||||
end
|
||||
|
||||
let finalize ~final ~f =
|
||||
try
|
||||
let res = f () in
|
||||
final () ;
|
||||
res
|
||||
with exn ->
|
||||
final () ;
|
||||
raise exn
|
||||
|
||||
open Rresult
|
||||
|
||||
type error =
|
||||
| NoSuchFileOrDir
|
||||
| IOError
|
||||
| EnvironmentLocked
|
||||
| OutOfMemory
|
||||
| PermissionDenied
|
||||
| InvalidArgument
|
||||
| NoSpaceLeftOnDevice
|
||||
| KeyExist
|
||||
| KeyNotFound
|
||||
| PageNotFound
|
||||
| Corrupted
|
||||
| Panic
|
||||
| VersionMismatch
|
||||
| InvalidFile
|
||||
| MapFull
|
||||
| DbsFull
|
||||
| ReadersFull
|
||||
| TLSFull
|
||||
| TxnFull
|
||||
| CursorFull
|
||||
| PageFull
|
||||
| MapResized
|
||||
| Incompatible
|
||||
| BadRslot
|
||||
| BadTxn
|
||||
| BadValSize
|
||||
| BadDbi
|
||||
| TxnProblem
|
||||
|
||||
let int_of_error = function
|
||||
| NoSuchFileOrDir -> 2
|
||||
| IOError -> 5
|
||||
| EnvironmentLocked -> 11
|
||||
| OutOfMemory -> 12
|
||||
| PermissionDenied -> 13
|
||||
| InvalidArgument -> 22
|
||||
| NoSpaceLeftOnDevice -> 28
|
||||
| KeyExist -> -30799
|
||||
| KeyNotFound -> -30798
|
||||
| PageNotFound -> -30797
|
||||
| Corrupted -> -30796
|
||||
| Panic -> -30795
|
||||
| VersionMismatch -> -30794
|
||||
| InvalidFile -> -30793
|
||||
| MapFull -> -30792
|
||||
| DbsFull -> -30791
|
||||
| ReadersFull -> -30790
|
||||
| TLSFull -> -30789
|
||||
| TxnFull -> -30788
|
||||
| CursorFull -> -30787
|
||||
| PageFull -> -30786
|
||||
| MapResized -> -30785
|
||||
| Incompatible -> -30784
|
||||
| BadRslot -> -30783
|
||||
| BadTxn -> -30782
|
||||
| BadValSize -> -30781
|
||||
| BadDbi -> -30780
|
||||
| TxnProblem -> -30779
|
||||
|
||||
let error_of_int = function
|
||||
| 2 -> NoSuchFileOrDir
|
||||
| 5 -> IOError
|
||||
| 11 -> EnvironmentLocked
|
||||
| 12 -> OutOfMemory
|
||||
| 13 -> PermissionDenied
|
||||
| 22 -> InvalidArgument
|
||||
| 28 -> NoSpaceLeftOnDevice
|
||||
| -30799 -> KeyExist
|
||||
| -30798 -> KeyNotFound
|
||||
| -30797 -> PageNotFound
|
||||
| -30796 -> Corrupted
|
||||
| -30795 -> Panic
|
||||
| -30794 -> VersionMismatch
|
||||
| -30793 -> InvalidFile
|
||||
| -30792 -> MapFull
|
||||
| -30791 -> DbsFull
|
||||
| -30790 -> ReadersFull
|
||||
| -30789 -> TLSFull
|
||||
| -30788 -> TxnFull
|
||||
| -30787 -> CursorFull
|
||||
| -30786 -> PageFull
|
||||
| -30785 -> MapResized
|
||||
| -30784 -> Incompatible
|
||||
| -30783 -> BadRslot
|
||||
| -30782 -> BadTxn
|
||||
| -30781 -> BadValSize
|
||||
| -30780 -> BadDbi
|
||||
| -30779 -> TxnProblem
|
||||
| i -> invalid_arg (Printf.sprintf "error_of_int: %d" i)
|
||||
|
||||
type version = {
|
||||
major : int ;
|
||||
minor : int ;
|
||||
patch : int ;
|
||||
}
|
||||
|
||||
external version : unit -> version = "stub_mdb_version"
|
||||
external strerror : int -> string = "stub_mdb_strerror"
|
||||
|
||||
let string_of_error error =
|
||||
strerror (int_of_error error)
|
||||
|
||||
let pp_error ppf err =
|
||||
Format.fprintf ppf "%s" (string_of_error err)
|
||||
|
||||
let to_msg t = R.error_to_msg ~pp_error t
|
||||
|
||||
type t
|
||||
external create : unit -> (t, int) result = "stub_mdb_env_create"
|
||||
|
||||
type flag_env =
|
||||
| FixedMap
|
||||
| NoSubdir
|
||||
| NoSync
|
||||
| RdOnly
|
||||
| NoMetaSync
|
||||
| WriteMap
|
||||
| MapAsync
|
||||
| NoTLS
|
||||
| NoLock
|
||||
| NoRdAhead
|
||||
| NoMemInit
|
||||
| PrevMeta
|
||||
|
||||
let int_of_flag_env = function
|
||||
| FixedMap -> 0x01
|
||||
| NoSubdir -> 0x4000
|
||||
| NoSync -> 0x10_000
|
||||
| RdOnly -> 0x20_000
|
||||
| NoMetaSync -> 0x40_000
|
||||
| WriteMap -> 0x80_000
|
||||
| MapAsync -> 0x100_000
|
||||
| NoTLS -> 0x200_000
|
||||
| NoLock -> 0x400_000
|
||||
| NoRdAhead -> 0x800_000
|
||||
| NoMemInit -> 0x1_000_000
|
||||
| PrevMeta -> 0x2_000_000
|
||||
|
||||
let flags_env_of_int v =
|
||||
List.fold_left begin fun acc flag ->
|
||||
if v land (int_of_flag_env flag) <> 0 then flag :: acc else acc
|
||||
end []
|
||||
[ FixedMap ; NoSubdir ; NoSync ; RdOnly ; NoMetaSync ;
|
||||
WriteMap ; MapAsync ; NoTLS ; NoLock ; NoRdAhead ;
|
||||
NoMemInit ; PrevMeta ]
|
||||
|
||||
type flag_open =
|
||||
| ReverseKey
|
||||
| DupSort
|
||||
| IntegerKey
|
||||
| DupFixed
|
||||
| IntegerDup
|
||||
| ReverseDup
|
||||
| Create
|
||||
|
||||
let int_of_flag_open = function
|
||||
| ReverseKey -> 0x02
|
||||
| DupSort -> 0x04
|
||||
| IntegerKey -> 0x08
|
||||
| DupFixed -> 0x10
|
||||
| IntegerDup -> 0x20
|
||||
| ReverseDup -> 0x40
|
||||
| Create -> 0x40_000
|
||||
|
||||
let flags_open_of_int v =
|
||||
List.fold_left begin fun acc flag ->
|
||||
if v land (int_of_flag_open flag) <> 0 then flag :: acc else acc
|
||||
end []
|
||||
[ ReverseKey ; DupSort ; IntegerKey ; DupFixed ; IntegerDup ;
|
||||
ReverseDup ; Create ]
|
||||
|
||||
type flag_put =
|
||||
| NoOverwrite
|
||||
| NoDupData
|
||||
| Current
|
||||
| Reserve
|
||||
| Append
|
||||
| AppendDup
|
||||
| Multiple
|
||||
|
||||
let int_of_flag_put = function
|
||||
| NoOverwrite -> 0x10
|
||||
| NoDupData -> 0x20
|
||||
| Current -> 0x40
|
||||
| Reserve -> 0x10_000
|
||||
| Append -> 0x20_000
|
||||
| AppendDup -> 0x40_000
|
||||
| Multiple -> 0x80_000
|
||||
|
||||
let fold_flags int_of_flag flags =
|
||||
List.fold_left (fun a flag -> a lor (int_of_flag flag)) 0 flags
|
||||
|
||||
let int_of_flags_env = fold_flags int_of_flag_env
|
||||
let int_of_flags_open = fold_flags int_of_flag_open
|
||||
let int_of_flags_put = fold_flags int_of_flag_put
|
||||
|
||||
let return ?(on_error = fun () -> ()) ret v =
|
||||
if ret = 0 then
|
||||
Ok v
|
||||
else begin
|
||||
on_error () ;
|
||||
Error (error_of_int ret)
|
||||
end
|
||||
|
||||
external set_maxreaders : t -> int -> int = "stub_mdb_env_set_maxreaders" [@@noalloc]
|
||||
|
||||
let set_maxreaders t readers =
|
||||
let ret = set_maxreaders t readers in
|
||||
return ret ()
|
||||
|
||||
external set_maxdbs : t -> int -> int = "stub_mdb_env_set_maxdbs" [@@noalloc]
|
||||
|
||||
let set_maxdbs t dbs =
|
||||
let ret = set_maxdbs t dbs in
|
||||
return ret ()
|
||||
|
||||
external set_mapsize : t -> int64 -> int = "stub_mdb_env_set_mapsize" [@@noalloc]
|
||||
|
||||
let set_mapsize t size =
|
||||
let ret = set_mapsize t size in
|
||||
return ret ()
|
||||
|
||||
external opendir :
|
||||
t -> string -> int -> Unix.file_perm -> int = "stub_mdb_env_open" [@@noalloc]
|
||||
|
||||
external closedir :
|
||||
t -> unit = "stub_mdb_env_close" [@@noalloc]
|
||||
|
||||
let opendir ?maxreaders ?maxdbs ?mapsize ?(flags=[]) path mode =
|
||||
match create () with
|
||||
| Error v -> Error (error_of_int v)
|
||||
| Ok t ->
|
||||
begin match maxreaders with
|
||||
| None -> Ok ()
|
||||
| Some readers -> set_maxreaders t readers
|
||||
end >>= fun () ->
|
||||
begin match maxdbs with
|
||||
| None -> Ok ()
|
||||
| Some dbs -> set_maxdbs t dbs
|
||||
end >>= fun () ->
|
||||
begin match mapsize with
|
||||
| None -> Ok ()
|
||||
| Some size -> set_mapsize t size
|
||||
end >>= fun () ->
|
||||
let ret = opendir t path (int_of_flags_env flags) mode in
|
||||
return ret t ~on_error:(fun () -> closedir t)
|
||||
|
||||
external copy :
|
||||
t -> string -> int -> int = "stub_mdb_env_copy2" [@@noalloc]
|
||||
|
||||
let copy ?(compact=false) t path =
|
||||
let ret = copy t path (if compact then 0x01 else 0x00) in
|
||||
return ret ()
|
||||
|
||||
external copyfd :
|
||||
t -> Unix.file_descr -> int -> int = "stub_mdb_env_copyfd2" [@@noalloc]
|
||||
|
||||
let copyfd ?(compact=false) t fd =
|
||||
let ret = copyfd t fd (if compact then 0x01 else 0x00) in
|
||||
return ret ()
|
||||
|
||||
type stat = {
|
||||
psize : int ;
|
||||
depth : int ;
|
||||
branch_pages : int ;
|
||||
leaf_pages : int ;
|
||||
overflow_pages : int ;
|
||||
entries : int ;
|
||||
}
|
||||
|
||||
external stat : t -> stat = "stub_mdb_env_stat"
|
||||
|
||||
type envinfo = {
|
||||
mapsize : int ;
|
||||
last_pgno : int ;
|
||||
last_txnid : int ;
|
||||
maxreaders : int ;
|
||||
numreaders : int ;
|
||||
}
|
||||
|
||||
external envinfo : t -> envinfo = "stub_mdb_env_info"
|
||||
|
||||
external sync : t -> bool -> int = "stub_mdb_env_sync" [@@noalloc]
|
||||
|
||||
let sync ?(force=false) t =
|
||||
let ret = sync t force in
|
||||
return ret ()
|
||||
|
||||
external setclear_flags :
|
||||
t -> int -> bool -> int = "stub_mdb_env_set_flags" [@@noalloc]
|
||||
|
||||
let set_flags t flags =
|
||||
let ret = setclear_flags t (int_of_flags_env flags) true in
|
||||
return ret ()
|
||||
|
||||
let clear_flags t flags =
|
||||
let ret = setclear_flags t (int_of_flags_env flags) false in
|
||||
return ret ()
|
||||
|
||||
external get_flags : t -> int = "stub_mdb_env_get_flags" [@@noalloc]
|
||||
|
||||
let get_flags t =
|
||||
flags_env_of_int (get_flags t)
|
||||
|
||||
external get_path : t -> string = "stub_mdb_env_get_path"
|
||||
external get_fd : t -> Unix.file_descr = "stub_mdb_env_get_fd" [@@noalloc]
|
||||
external get_maxreaders : t -> int = "stub_mdb_env_get_maxreaders" [@@noalloc]
|
||||
external get_maxkeysize : t -> int = "stub_mdb_env_get_maxkeysize" [@@noalloc]
|
||||
|
||||
type rawtxn
|
||||
type ro
|
||||
type rw
|
||||
type _ txn =
|
||||
| Txn_ro : rawtxn -> ro txn
|
||||
| Txn_rw : rawtxn -> rw txn
|
||||
|
||||
let rawtxn_of_txn : type a. a txn -> rawtxn = function
|
||||
| Txn_ro rawtxn -> rawtxn
|
||||
| Txn_rw rawtxn -> rawtxn
|
||||
|
||||
external txn_begin :
|
||||
t -> int -> rawtxn option -> (rawtxn, int) result = "stub_mdb_txn_begin"
|
||||
|
||||
let create_rw_txn ?(sync=true) ?(metasync=true) ?parent t =
|
||||
let flags = match sync, metasync with
|
||||
| true, true -> int_of_flags_env [NoSync; NoMetaSync]
|
||||
| true, false -> int_of_flag_env NoSync
|
||||
| false, true -> int_of_flag_env NoMetaSync
|
||||
| _ -> 0 in
|
||||
match txn_begin t flags (Option.map ~f:rawtxn_of_txn parent) with
|
||||
| Error i -> Error (error_of_int i)
|
||||
| Ok tx -> Ok (Txn_rw tx)
|
||||
|
||||
let create_ro_txn ?(sync=true) ?(metasync=true) ?parent t =
|
||||
let flags = match sync, metasync with
|
||||
| true, true -> int_of_flags_env [RdOnly; NoSync; NoMetaSync]
|
||||
| true, false -> int_of_flags_env [RdOnly; NoSync]
|
||||
| false, true -> int_of_flags_env [RdOnly; NoMetaSync]
|
||||
| _ -> int_of_flag_env RdOnly in
|
||||
match txn_begin t flags (Option.map ~f:rawtxn_of_txn parent) with
|
||||
| Error i -> Error (error_of_int i)
|
||||
| Ok tx -> Ok (Txn_ro tx)
|
||||
|
||||
external get_txn_id : rawtxn -> int = "stub_mdb_txn_id" [@@noalloc]
|
||||
external get_txn_env : rawtxn -> t = "stub_mdb_txn_env"
|
||||
|
||||
let get_txn_id txn =
|
||||
get_txn_id (rawtxn_of_txn txn)
|
||||
|
||||
let get_txn_env txn =
|
||||
get_txn_env (rawtxn_of_txn txn)
|
||||
|
||||
external commit_txn : rawtxn -> int = "stub_mdb_txn_commit" [@@noalloc]
|
||||
external abort_txn : rawtxn -> unit = "stub_mdb_txn_abort" [@@noalloc]
|
||||
|
||||
let commit_txn txn =
|
||||
return (commit_txn (rawtxn_of_txn txn)) ()
|
||||
|
||||
let abort_txn txn =
|
||||
abort_txn (rawtxn_of_txn txn)
|
||||
|
||||
external reset_ro_txn : rawtxn -> unit = "stub_mdb_txn_reset" [@@noalloc]
|
||||
external renew_ro_txn : rawtxn -> int = "stub_mdb_txn_renew" [@@noalloc]
|
||||
|
||||
let reset_ro_txn (Txn_ro rawtxn) =
|
||||
reset_ro_txn rawtxn
|
||||
|
||||
let renew_ro_txn (Txn_ro rawtxn) =
|
||||
return (renew_ro_txn rawtxn) ()
|
||||
|
||||
type db = nativeint
|
||||
|
||||
external opendb :
|
||||
rawtxn -> string option -> int -> (db, int) result = "stub_mdb_dbi_open"
|
||||
|
||||
let opendb ?(flags=[]) ?name txn =
|
||||
R.reword_error error_of_int
|
||||
(opendb (rawtxn_of_txn txn) name (int_of_flags_open flags))
|
||||
|
||||
external db_stat :
|
||||
rawtxn -> db -> (stat, int) result = "stub_mdb_stat"
|
||||
|
||||
let db_stat txn dbi =
|
||||
R.reword_error error_of_int (db_stat (rawtxn_of_txn txn) dbi)
|
||||
|
||||
external db_flags :
|
||||
rawtxn -> db -> (int, int) result = "stub_mdb_dbi_flags"
|
||||
|
||||
let db_flags txn dbi =
|
||||
match db_flags (rawtxn_of_txn txn) dbi with
|
||||
| Error i -> Error (error_of_int i)
|
||||
| Ok v -> Ok (flags_open_of_int v)
|
||||
|
||||
external db_drop :
|
||||
rawtxn -> db -> bool -> int = "stub_mdb_drop" [@@noalloc]
|
||||
|
||||
let db_drop txn dbi =
|
||||
return (db_drop (rawtxn_of_txn txn) dbi false) ()
|
||||
|
||||
let with_ro_db ?sync ?metasync ?parent ?flags ?name t ~f =
|
||||
create_ro_txn ?sync ?metasync ?parent t >>= fun txn ->
|
||||
opendb ?flags ?name txn >>= fun db ->
|
||||
match f txn db with
|
||||
| exception exn ->
|
||||
abort_txn txn ;
|
||||
raise exn
|
||||
| Ok res ->
|
||||
commit_txn txn >>= fun () ->
|
||||
Ok res
|
||||
| Error err ->
|
||||
abort_txn txn ;
|
||||
Error err
|
||||
|
||||
let with_rw_db ?sync ?metasync ?parent ?flags ?name t ~f =
|
||||
create_rw_txn ?sync ?metasync ?parent t >>= fun txn ->
|
||||
opendb ?flags ?name txn >>= fun db ->
|
||||
match f txn db with
|
||||
| exception exn ->
|
||||
abort_txn txn ;
|
||||
raise exn
|
||||
| Ok res ->
|
||||
commit_txn txn >>= fun () ->
|
||||
Ok res
|
||||
| Error err ->
|
||||
abort_txn txn ;
|
||||
Error err
|
||||
|
||||
type buffer = (char, Bigarray.int8_unsigned_elt, Bigarray.c_layout) Bigarray.Array1.t
|
||||
|
||||
external get :
|
||||
rawtxn -> db -> string -> (buffer, int) result = "stub_mdb_get"
|
||||
|
||||
let get txn dbi k =
|
||||
R.reword_error error_of_int (get (rawtxn_of_txn txn) dbi k)
|
||||
|
||||
let mem txn dbi k =
|
||||
match get txn dbi k with
|
||||
| Ok _ -> Ok true
|
||||
| Error KeyNotFound -> Ok false
|
||||
| Error err -> Error err
|
||||
|
||||
external put :
|
||||
rawtxn -> db -> string -> buffer -> int -> int = "stub_mdb_put" [@@noalloc]
|
||||
external put_string :
|
||||
rawtxn -> db -> string -> string -> int -> int = "stub_mdb_put_string" [@@noalloc]
|
||||
|
||||
let put ?(flags=[]) txn dbi k v =
|
||||
let flags = int_of_flags_put flags in
|
||||
return (put (rawtxn_of_txn txn) dbi k v flags) ()
|
||||
|
||||
let put_string ?(flags=[]) txn dbi k v =
|
||||
let flags = int_of_flags_put flags in
|
||||
return (put_string (rawtxn_of_txn txn) dbi k v flags) ()
|
||||
|
||||
external del :
|
||||
rawtxn -> db -> string -> buffer option -> int = "stub_mdb_del" [@@noalloc]
|
||||
external del_string :
|
||||
rawtxn -> db -> string -> string option -> int = "stub_mdb_del_string" [@@noalloc]
|
||||
|
||||
let del ?data txn dbi k =
|
||||
return (del (rawtxn_of_txn txn) dbi k data) ()
|
||||
|
||||
let del_string ?data txn dbi k =
|
||||
return (del_string (rawtxn_of_txn txn) dbi k data) ()
|
||||
|
||||
type rawcursor
|
||||
type _ cursor =
|
||||
| Cursor_ro : rawcursor -> ro cursor
|
||||
| Cursor_rw : rawcursor -> rw cursor
|
||||
|
||||
let rawcursor_of_cursor : type a. a cursor -> rawcursor = function
|
||||
| Cursor_ro rawcursor -> rawcursor
|
||||
| Cursor_rw rawcursor -> rawcursor
|
||||
|
||||
let cursor_ro rawcursor = Cursor_ro rawcursor
|
||||
let cursor_rw rawcursor = Cursor_rw rawcursor
|
||||
|
||||
external opencursor :
|
||||
rawtxn -> db -> (rawcursor, int) result = "stub_mdb_cursor_open"
|
||||
|
||||
let opencursor :
|
||||
type a. a txn -> db -> (a cursor, error) result = fun txn dbi ->
|
||||
match txn with
|
||||
| Txn_ro rawtxn ->
|
||||
R.reword_error error_of_int (opencursor rawtxn dbi) |>
|
||||
R.map cursor_ro
|
||||
| Txn_rw rawtxn ->
|
||||
R.reword_error error_of_int (opencursor rawtxn dbi) |>
|
||||
R.map cursor_rw
|
||||
|
||||
external cursor_close :
|
||||
rawcursor -> unit = "stub_mdb_cursor_close" [@@noalloc]
|
||||
|
||||
external cursor_renew :
|
||||
rawtxn -> rawcursor -> int = "stub_mdb_cursor_renew" [@@noalloc]
|
||||
|
||||
let cursor_close cursor =
|
||||
cursor_close (rawcursor_of_cursor cursor)
|
||||
|
||||
let cursor_renew (Txn_ro rawtxn) (Cursor_ro rawcursor) =
|
||||
return (cursor_renew rawtxn rawcursor) ()
|
||||
|
||||
external cursor_txn :
|
||||
rawcursor -> rawtxn = "stub_mdb_cursor_txn"
|
||||
|
||||
let cursor_txn : type a. a cursor -> a txn = function
|
||||
| Cursor_ro rawcursor -> Txn_ro (cursor_txn rawcursor)
|
||||
| Cursor_rw rawcursor -> Txn_rw (cursor_txn rawcursor)
|
||||
|
||||
external cursor_db :
|
||||
rawcursor -> db = "stub_mdb_cursor_dbi" [@@noalloc]
|
||||
|
||||
let cursor_db cursor =
|
||||
cursor_db (rawcursor_of_cursor cursor)
|
||||
|
||||
type cursor_op =
|
||||
| First
|
||||
| First_dup
|
||||
| Get_both
|
||||
| Get_both_range
|
||||
| Get_current
|
||||
| Get_multiple
|
||||
| Last
|
||||
| Last_dup
|
||||
| Next
|
||||
| Next_dup
|
||||
| Next_multiple
|
||||
| Next_nodup
|
||||
| Prev
|
||||
| Prev_dup
|
||||
| Prev_nodup
|
||||
| Set
|
||||
| Set_key
|
||||
| Set_range
|
||||
| Prev_multiple
|
||||
|
||||
external cursor_get_op :
|
||||
rawcursor -> string option -> buffer option -> cursor_op ->
|
||||
(buffer * buffer, int) result = "stub_mdb_cursor_get"
|
||||
|
||||
let cursor_get_op ?key ?data cursor op =
|
||||
R.reword_error error_of_int
|
||||
(cursor_get_op (rawcursor_of_cursor cursor) key data op)
|
||||
|
||||
let cursor_first cursor =
|
||||
R.map ignore (cursor_get_op cursor First)
|
||||
let cursor_last cursor =
|
||||
R.map ignore (cursor_get_op cursor Last)
|
||||
let cursor_next cursor =
|
||||
R.map ignore (cursor_get_op cursor Next)
|
||||
let cursor_prev cursor =
|
||||
R.map ignore (cursor_get_op cursor Prev)
|
||||
let cursor_at cursor = function
|
||||
| "" -> cursor_first cursor
|
||||
| key -> R.map ignore (cursor_get_op ~key cursor Set_range)
|
||||
|
||||
let cursor_get cursor =
|
||||
cursor_get_op cursor Get_current
|
||||
|
||||
let cursor_fold_left ~f ~init cursor =
|
||||
let rec inner a =
|
||||
match cursor_get cursor with
|
||||
| Error KeyNotFound -> Ok a
|
||||
| Error err -> Error err
|
||||
| Ok kv ->
|
||||
f a kv >>= fun a ->
|
||||
match cursor_next cursor with
|
||||
| Error KeyNotFound -> Ok a
|
||||
| Error err -> Error err
|
||||
| Ok () -> inner a
|
||||
in
|
||||
inner init
|
||||
|
||||
let cursor_iter ~f cursor =
|
||||
cursor_fold_left ~init:() ~f:(fun () kv -> f kv) cursor
|
||||
|
||||
external cursor_put :
|
||||
rawcursor -> string -> buffer -> int -> int = "stub_mdb_cursor_put" [@@noalloc]
|
||||
external cursor_put_string :
|
||||
rawcursor -> string -> string -> int -> int = "stub_mdb_cursor_put_string" [@@noalloc]
|
||||
external cursor_del :
|
||||
rawcursor -> int -> int = "stub_mdb_cursor_del" [@@noalloc]
|
||||
external cursor_count :
|
||||
rawcursor -> (int, int) result = "stub_mdb_cursor_count"
|
||||
|
||||
let cursor_put ?(flags=[]) cursor k v =
|
||||
return
|
||||
(cursor_put (rawcursor_of_cursor cursor) k v (int_of_flags_put flags))
|
||||
()
|
||||
|
||||
let cursor_put_string ?(flags=[]) cursor k v =
|
||||
return
|
||||
(cursor_put_string (rawcursor_of_cursor cursor) k v (int_of_flags_put flags))
|
||||
()
|
||||
|
||||
let cursor_del ?(flags=[]) cursor =
|
||||
return
|
||||
(cursor_del (rawcursor_of_cursor cursor) (int_of_flags_put flags))
|
||||
()
|
||||
|
||||
let cursor_count cursor =
|
||||
R.reword_error error_of_int
|
||||
(cursor_count (rawcursor_of_cursor cursor))
|
||||
|
||||
let with_cursor txn db ~f =
|
||||
opencursor txn db >>= fun cursor ->
|
||||
finalize
|
||||
~final:(fun () -> cursor_close cursor)
|
||||
~f:(fun () -> f cursor)
|
||||
|
||||
(*---------------------------------------------------------------------------
|
||||
Copyright (c) 2018 Vincent Bernardoff
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
---------------------------------------------------------------------------*)
|
255
vendors/ocaml-lmdb/src/lmdb.mli
vendored
Normal file
255
vendors/ocaml-lmdb/src/lmdb.mli
vendored
Normal file
@ -0,0 +1,255 @@
|
||||
(*---------------------------------------------------------------------------
|
||||
Copyright (c) 2018 Vincent Bernardoff. All rights reserved.
|
||||
Distributed under the ISC license, see terms at the end of the file.
|
||||
---------------------------------------------------------------------------*)
|
||||
|
||||
open Rresult
|
||||
|
||||
type error =
|
||||
| NoSuchFileOrDir
|
||||
| IOError
|
||||
| EnvironmentLocked
|
||||
| OutOfMemory
|
||||
| PermissionDenied
|
||||
| InvalidArgument
|
||||
| NoSpaceLeftOnDevice
|
||||
| KeyExist
|
||||
| KeyNotFound
|
||||
| PageNotFound
|
||||
| Corrupted
|
||||
| Panic
|
||||
| VersionMismatch
|
||||
| InvalidFile
|
||||
| MapFull
|
||||
| DbsFull
|
||||
| ReadersFull
|
||||
| TLSFull
|
||||
| TxnFull
|
||||
| CursorFull
|
||||
| PageFull
|
||||
| MapResized
|
||||
| Incompatible
|
||||
| BadRslot
|
||||
| BadTxn
|
||||
| BadValSize
|
||||
| BadDbi
|
||||
| TxnProblem
|
||||
|
||||
val string_of_error : error -> string
|
||||
val pp_error : Format.formatter -> error -> unit
|
||||
val to_msg : ('a, error) result -> ('a, [> R.msg]) result
|
||||
|
||||
type version = {
|
||||
major : int ;
|
||||
minor : int ;
|
||||
patch : int ;
|
||||
}
|
||||
|
||||
val version : unit -> version
|
||||
|
||||
type ro
|
||||
type rw
|
||||
type t
|
||||
|
||||
type flag_env =
|
||||
| FixedMap
|
||||
| NoSubdir
|
||||
| NoSync
|
||||
| RdOnly
|
||||
| NoMetaSync
|
||||
| WriteMap
|
||||
| MapAsync
|
||||
| NoTLS
|
||||
| NoLock
|
||||
| NoRdAhead
|
||||
| NoMemInit
|
||||
| PrevMeta
|
||||
|
||||
val opendir :
|
||||
?maxreaders:int -> ?maxdbs:int -> ?mapsize:int64 -> ?flags:flag_env list ->
|
||||
string -> Unix.file_perm -> (t, error) result
|
||||
|
||||
val closedir : t -> unit
|
||||
|
||||
val copy : ?compact:bool -> t -> string -> (unit, error) result
|
||||
val copyfd : ?compact:bool -> t -> Unix.file_descr -> (unit, error) result
|
||||
|
||||
type stat = {
|
||||
psize : int ;
|
||||
depth : int ;
|
||||
branch_pages : int ;
|
||||
leaf_pages : int ;
|
||||
overflow_pages : int ;
|
||||
entries : int ;
|
||||
}
|
||||
|
||||
val stat : t -> stat
|
||||
|
||||
type envinfo = {
|
||||
mapsize : int ;
|
||||
last_pgno : int ;
|
||||
last_txnid : int ;
|
||||
maxreaders : int ;
|
||||
numreaders : int ;
|
||||
}
|
||||
|
||||
val envinfo : t -> envinfo
|
||||
|
||||
val sync : ?force:bool -> t -> (unit, error) result
|
||||
|
||||
val get_flags : t -> flag_env list
|
||||
val set_flags : t -> flag_env list -> (unit, error) result
|
||||
val clear_flags : t -> flag_env list -> (unit, error) result
|
||||
|
||||
val get_path : t -> string
|
||||
val get_fd : t -> Unix.file_descr
|
||||
|
||||
val get_maxreaders : t -> int
|
||||
val get_maxkeysize : t -> int
|
||||
|
||||
val set_mapsize : t -> int64 -> (unit, error) result
|
||||
|
||||
type _ txn
|
||||
|
||||
val create_rw_txn :
|
||||
?sync:bool -> ?metasync:bool ->
|
||||
?parent:rw txn -> t -> (rw txn, error) result
|
||||
|
||||
val create_ro_txn :
|
||||
?sync:bool -> ?metasync:bool ->
|
||||
?parent:_ txn -> t -> (ro txn, error) result
|
||||
|
||||
val get_txn_id : _ txn -> int
|
||||
val get_txn_env : _ txn -> t
|
||||
|
||||
val commit_txn : _ txn -> (unit, error) result
|
||||
val abort_txn : _ txn -> unit
|
||||
|
||||
val reset_ro_txn : ro txn -> unit
|
||||
val renew_ro_txn : ro txn -> (unit, error) result
|
||||
|
||||
type flag_open =
|
||||
| ReverseKey
|
||||
| DupSort
|
||||
| IntegerKey
|
||||
| DupFixed
|
||||
| IntegerDup
|
||||
| ReverseDup
|
||||
| Create
|
||||
|
||||
type db
|
||||
|
||||
val opendb :
|
||||
?flags:flag_open list -> ?name:string -> _ txn -> (db, error) result
|
||||
|
||||
val db_stat : _ txn -> db -> (stat, error) result
|
||||
val db_flags : _ txn -> db -> (flag_open list, error) result
|
||||
val db_drop : _ txn -> db -> (unit, error) result
|
||||
|
||||
val with_ro_db :
|
||||
?sync:bool -> ?metasync:bool ->
|
||||
?parent:_ txn -> ?flags:flag_open list ->
|
||||
?name:string -> t -> f:(ro txn -> db -> ('a, error) result) ->
|
||||
('a, error) result
|
||||
|
||||
val with_rw_db :
|
||||
?sync:bool -> ?metasync:bool ->
|
||||
?parent:rw txn -> ?flags:flag_open list ->
|
||||
?name:string -> t -> f:(rw txn -> db -> ('a, error) result) ->
|
||||
('a, error) result
|
||||
|
||||
type buffer = (char, Bigarray.int8_unsigned_elt, Bigarray.c_layout) Bigarray.Array1.t
|
||||
|
||||
val get : _ txn -> db -> string -> (buffer, error) result
|
||||
val mem : _ txn -> db -> string -> (bool, error) result
|
||||
|
||||
type flag_put =
|
||||
| NoOverwrite
|
||||
| NoDupData
|
||||
| Current
|
||||
| Reserve
|
||||
| Append
|
||||
| AppendDup
|
||||
| Multiple
|
||||
|
||||
val put : ?flags:flag_put list ->
|
||||
rw txn -> db -> string -> buffer -> (unit, error) result
|
||||
val put_string : ?flags:flag_put list ->
|
||||
rw txn -> db -> string -> string -> (unit, error) result
|
||||
|
||||
val del : ?data:buffer ->
|
||||
rw txn -> db -> string -> (unit, error) result
|
||||
val del_string : ?data:string ->
|
||||
rw txn -> db -> string -> (unit, error) result
|
||||
|
||||
type _ cursor
|
||||
|
||||
val opencursor : 'a txn -> db -> ('a cursor, error) result
|
||||
val cursor_close : _ cursor -> unit
|
||||
val cursor_renew : ro txn -> ro cursor -> (unit, error) result
|
||||
|
||||
val cursor_txn : 'a cursor -> 'a txn
|
||||
val cursor_db : _ cursor -> db
|
||||
|
||||
val cursor_first : _ cursor -> (unit, error) result
|
||||
val cursor_last : _ cursor -> (unit, error) result
|
||||
val cursor_prev : _ cursor -> (unit, error) result
|
||||
val cursor_next : _ cursor -> (unit, error) result
|
||||
val cursor_at : _ cursor -> string -> (unit, error) result
|
||||
|
||||
val cursor_get : _ cursor -> (buffer * buffer, error) result
|
||||
|
||||
val cursor_fold_left :
|
||||
f:('a -> (buffer * buffer) -> ('a, error) result) ->
|
||||
init:'a -> _ cursor -> ('a, error) result
|
||||
|
||||
val cursor_iter :
|
||||
f:(buffer * buffer -> (unit, error) result) -> _ cursor -> (unit, error) result
|
||||
|
||||
val with_cursor :
|
||||
'a txn -> db -> f:('a cursor -> ('b, error) result) ->
|
||||
('b, error) result
|
||||
|
||||
type cursor_op =
|
||||
| First
|
||||
| First_dup
|
||||
| Get_both
|
||||
| Get_both_range
|
||||
| Get_current
|
||||
| Get_multiple
|
||||
| Last
|
||||
| Last_dup
|
||||
| Next
|
||||
| Next_dup
|
||||
| Next_multiple
|
||||
| Next_nodup
|
||||
| Prev
|
||||
| Prev_dup
|
||||
| Prev_nodup
|
||||
| Set
|
||||
| Set_key
|
||||
| Set_range
|
||||
| Prev_multiple
|
||||
|
||||
val cursor_put : ?flags:flag_put list ->
|
||||
rw cursor -> string -> buffer -> (unit, error) result
|
||||
val cursor_put_string : ?flags:flag_put list ->
|
||||
rw cursor -> string -> string -> (unit, error) result
|
||||
val cursor_del : ?flags:flag_put list -> rw cursor -> (unit, error) result
|
||||
val cursor_count : _ cursor -> (int, error) result
|
||||
|
||||
(*---------------------------------------------------------------------------
|
||||
Copyright (c) 2018 Vincent Bernardoff
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
---------------------------------------------------------------------------*)
|
566
vendors/ocaml-lmdb/src/lmdb_stubs.c
vendored
Normal file
566
vendors/ocaml-lmdb/src/lmdb_stubs.c
vendored
Normal file
@ -0,0 +1,566 @@
|
||||
/* --------------------------------------------------------------------------
|
||||
Copyright (c) 2018 Vincent Bernardoff. All rights reserved.
|
||||
Distributed under the ISC license, see terms at the end of the file.
|
||||
--------------------------------------------------------------------------- */
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include <caml/mlvalues.h>
|
||||
#include <caml/alloc.h>
|
||||
#include <caml/memory.h>
|
||||
#include <caml/custom.h>
|
||||
#include <caml/bigarray.h>
|
||||
|
||||
#include "lmdb.h"
|
||||
|
||||
CAMLprim value stub_mdb_version(value unit) {
|
||||
CAMLparam1(unit);
|
||||
CAMLlocal1(result);
|
||||
|
||||
int major, minor, patch;
|
||||
mdb_version(&major, &minor, &patch);
|
||||
result = caml_alloc_tuple(3);
|
||||
Store_field(result, 0, Val_int(major));
|
||||
Store_field(result, 1, Val_int(minor));
|
||||
Store_field(result, 2, Val_int(patch));
|
||||
|
||||
CAMLreturn(result);
|
||||
}
|
||||
|
||||
CAMLprim value stub_mdb_strerror(value errno) {
|
||||
CAMLparam1(errno);
|
||||
CAMLlocal1(result);
|
||||
|
||||
char *errstr;
|
||||
errstr = mdb_strerror(Int_val(errno));
|
||||
result = caml_copy_string(errstr);
|
||||
|
||||
CAMLreturn(result);
|
||||
}
|
||||
|
||||
#define Env_val(v) (*((MDB_env **) Data_custom_val(v)))
|
||||
#define Txn_val(v) (*((MDB_txn **) Data_custom_val(v)))
|
||||
#define Cursor_val(v) (*((MDB_cursor **) Data_custom_val(v)))
|
||||
|
||||
#define Gen_custom_block(SNAME, CNAME, MNAME) \
|
||||
static int compare_##SNAME(value a, value b) { \
|
||||
CNAME *aa = MNAME(a), *bb = MNAME(b); \
|
||||
return (aa == bb ? 0 : (aa < bb ? -1 : 1)); \
|
||||
} \
|
||||
\
|
||||
static struct custom_operations lmdb_##SNAME##_ops = { \
|
||||
.identifier = "lmdb_" #SNAME, \
|
||||
.finalize = custom_finalize_default, \
|
||||
.compare = compare_##SNAME, \
|
||||
.compare_ext = custom_compare_ext_default, \
|
||||
.hash = custom_hash_default, \
|
||||
.serialize = custom_serialize_default, \
|
||||
.deserialize = custom_deserialize_default \
|
||||
}; \
|
||||
\
|
||||
static value alloc_##SNAME (CNAME *a) { \
|
||||
value custom = alloc_custom(&lmdb_##SNAME##_ops, sizeof(CNAME *), 0, 1); \
|
||||
MNAME(custom) = a; \
|
||||
return custom; \
|
||||
}
|
||||
|
||||
Gen_custom_block(env, MDB_env, Env_val)
|
||||
Gen_custom_block(txn, MDB_txn, Txn_val)
|
||||
Gen_custom_block(cursor, MDB_cursor, Cursor_val)
|
||||
|
||||
CAMLprim value stub_mdb_env_create(value unit) {
|
||||
CAMLparam1(unit);
|
||||
CAMLlocal2(result, ml_env);
|
||||
|
||||
int ret;
|
||||
MDB_env *env;
|
||||
|
||||
ret = mdb_env_create(&env);
|
||||
if (ret) {
|
||||
result = caml_alloc(1, 1);
|
||||
Store_field(result, 0, Val_int(ret));
|
||||
}
|
||||
else {
|
||||
result = caml_alloc(1, 0);
|
||||
ml_env = alloc_env(env);
|
||||
Store_field(result, 0, ml_env);
|
||||
}
|
||||
|
||||
CAMLreturn(result);
|
||||
}
|
||||
|
||||
CAMLprim value stub_mdb_env_open(value env, value path, value flags, value mode) {
|
||||
return Val_int(mdb_env_open(Env_val(env), String_val(path), Int_val(flags), Int_val(mode)));
|
||||
}
|
||||
|
||||
CAMLprim value stub_mdb_env_close(value env) {
|
||||
mdb_env_close(Env_val(env));
|
||||
return Val_unit;
|
||||
}
|
||||
|
||||
CAMLprim value stub_mdb_env_copy2(value env, value path, value flags) {
|
||||
return Val_int(mdb_env_copy2(Env_val(env), String_val(path), Int_val(flags)));
|
||||
}
|
||||
|
||||
CAMLprim value stub_mdb_env_copyfd2(value env, value fd, value flags) {
|
||||
return Val_int(mdb_env_copyfd2(Env_val(env), Int_val(fd), Int_val(flags)));
|
||||
}
|
||||
|
||||
static void caml_mdb_stat(value result, const MDB_stat *stat) {
|
||||
Store_field(result, 0, Val_int(stat->ms_psize));
|
||||
Store_field(result, 1, Val_int(stat->ms_depth));
|
||||
Store_field(result, 2, Val_long(stat->ms_branch_pages));
|
||||
Store_field(result, 3, Val_long(stat->ms_leaf_pages));
|
||||
Store_field(result, 4, Val_long(stat->ms_overflow_pages));
|
||||
Store_field(result, 5, Val_long(stat->ms_entries));
|
||||
}
|
||||
|
||||
CAMLprim value stub_mdb_env_stat(value env) {
|
||||
CAMLparam1(env);
|
||||
CAMLlocal1(result);
|
||||
|
||||
MDB_stat stat;
|
||||
mdb_env_stat(Env_val(env), &stat);
|
||||
result = caml_alloc_tuple(6);
|
||||
caml_mdb_stat(result, &stat);
|
||||
CAMLreturn(result);
|
||||
}
|
||||
|
||||
CAMLprim value stub_mdb_env_info(value env) {
|
||||
CAMLparam1(env);
|
||||
CAMLlocal1(result);
|
||||
|
||||
MDB_envinfo info;
|
||||
mdb_env_info(Env_val(env), &info);
|
||||
result = caml_alloc_tuple(5);
|
||||
|
||||
Store_field(result, 0, Val_long(info.me_mapsize));
|
||||
Store_field(result, 1, Val_long(info.me_last_pgno));
|
||||
Store_field(result, 2, Val_long(info.me_last_txnid));
|
||||
Store_field(result, 3, Val_int(info.me_maxreaders));
|
||||
Store_field(result, 4, Val_int(info.me_numreaders));
|
||||
|
||||
CAMLreturn(result);
|
||||
}
|
||||
|
||||
CAMLprim value stub_mdb_env_sync(value env, value force) {
|
||||
return Val_int(mdb_env_sync(Env_val(env), Bool_val(force)));
|
||||
}
|
||||
|
||||
CAMLprim value stub_mdb_env_set_flags(value env, value flags, value onoff) {
|
||||
return Val_int(mdb_env_set_flags(Env_val(env), Int_val(flags), Bool_val(onoff)));
|
||||
}
|
||||
|
||||
CAMLprim value stub_mdb_env_get_flags(value env) {
|
||||
int flags;
|
||||
mdb_env_get_flags(Env_val(env), &flags);
|
||||
return Val_int(flags);
|
||||
}
|
||||
|
||||
CAMLprim value stub_mdb_env_get_path(value env) {
|
||||
CAMLparam1(env);
|
||||
CAMLlocal1(result);
|
||||
|
||||
const char *path;
|
||||
mdb_env_get_path(Env_val(env), &path);
|
||||
result = caml_copy_string(path);
|
||||
|
||||
CAMLreturn(result);
|
||||
}
|
||||
|
||||
CAMLprim value stub_mdb_env_get_fd(value env) {
|
||||
mdb_filehandle_t fd;
|
||||
mdb_env_get_fd(Env_val(env), &fd);
|
||||
return Val_int(fd);
|
||||
}
|
||||
|
||||
CAMLprim value stub_mdb_env_set_mapsize(value env, value size) {
|
||||
return Val_int(mdb_env_set_mapsize(Env_val(env), Int64_val(size)));
|
||||
}
|
||||
|
||||
CAMLprim value stub_mdb_env_set_maxreaders(value env, value readers) {
|
||||
return Val_int(mdb_env_set_maxreaders(Env_val(env), Int_val(readers)));
|
||||
}
|
||||
|
||||
CAMLprim value stub_mdb_env_get_maxreaders(value env) {
|
||||
unsigned int readers;
|
||||
mdb_env_get_maxreaders(Env_val(env), &readers);
|
||||
return Val_int(readers);
|
||||
}
|
||||
|
||||
CAMLprim value stub_mdb_env_set_maxdbs(value env, value dbs) {
|
||||
return Val_int(mdb_env_set_maxdbs(Env_val(env), Int_val(dbs)));
|
||||
}
|
||||
|
||||
CAMLprim value stub_mdb_env_get_maxkeysize(value env) {
|
||||
return Val_int(mdb_env_get_maxkeysize(Env_val(env)));
|
||||
}
|
||||
|
||||
CAMLprim value stub_mdb_txn_begin(value env, value flags, value parent) {
|
||||
CAMLparam3(env, flags, parent);
|
||||
CAMLlocal2(result, ml_txn);
|
||||
|
||||
int ret;
|
||||
MDB_txn *parent_txn = Is_block(parent) ? Txn_val(Field(parent, 0)) : NULL;
|
||||
MDB_txn *new_txn;
|
||||
|
||||
ret = mdb_txn_begin(Env_val(env), parent_txn, Int_val(flags), &new_txn);
|
||||
|
||||
if (ret) {
|
||||
result = caml_alloc(1, 1);
|
||||
Store_field(result, 0, Val_int(ret));
|
||||
}
|
||||
else {
|
||||
result = caml_alloc(1, 0);
|
||||
ml_txn = alloc_txn(new_txn);
|
||||
Store_field(result, 0, ml_txn);
|
||||
}
|
||||
|
||||
CAMLreturn(result);
|
||||
}
|
||||
|
||||
CAMLprim value stub_mdb_txn_env(value txn) {
|
||||
CAMLparam1(txn);
|
||||
CAMLlocal1(result);
|
||||
MDB_env *env = mdb_txn_env(Txn_val(txn));
|
||||
result = alloc_env(env);
|
||||
CAMLreturn(result);
|
||||
}
|
||||
|
||||
CAMLprim value stub_mdb_txn_id(value txn) {
|
||||
return Val_long(mdb_txn_id(Txn_val(txn)));
|
||||
}
|
||||
|
||||
CAMLprim value stub_mdb_txn_commit(value txn) {
|
||||
return Val_int(mdb_txn_commit(Txn_val(txn)));
|
||||
}
|
||||
|
||||
CAMLprim value stub_mdb_txn_abort(value txn) {
|
||||
mdb_txn_abort(Txn_val(txn));
|
||||
return Val_unit;
|
||||
}
|
||||
|
||||
CAMLprim value stub_mdb_txn_reset(value txn) {
|
||||
mdb_txn_reset(Txn_val(txn));
|
||||
return Val_unit;
|
||||
}
|
||||
|
||||
CAMLprim value stub_mdb_txn_renew(value txn) {
|
||||
return Val_int(mdb_txn_renew(Txn_val(txn)));
|
||||
}
|
||||
|
||||
CAMLprim value stub_mdb_dbi_open(value txn, value name, value flags) {
|
||||
CAMLparam3(txn, name, flags);
|
||||
CAMLlocal2(result, ml_dbi);
|
||||
|
||||
MDB_dbi dbi;
|
||||
int ret;
|
||||
const char* db_name = NULL;
|
||||
|
||||
if (Is_block(name)) db_name = String_val(Field(name, 0));
|
||||
|
||||
ret = mdb_dbi_open(Txn_val(txn), db_name, Int_val(flags), &dbi);
|
||||
|
||||
if (ret) {
|
||||
result = caml_alloc(1, 1);
|
||||
Store_field(result, 0, Val_int(ret));
|
||||
}
|
||||
else {
|
||||
result = caml_alloc(1, 0);
|
||||
ml_dbi = caml_copy_nativeint(dbi);
|
||||
Store_field(result, 0, ml_dbi);
|
||||
}
|
||||
|
||||
CAMLreturn(result);
|
||||
}
|
||||
|
||||
CAMLprim value stub_mdb_stat(value txn, value dbi) {
|
||||
CAMLparam2(txn, dbi);
|
||||
CAMLlocal2(result, tuple);
|
||||
|
||||
MDB_stat stat;
|
||||
int ret;
|
||||
ret = mdb_stat(Txn_val(txn), Nativeint_val(dbi), &stat);
|
||||
|
||||
if (ret) {
|
||||
result = caml_alloc(1, 1);
|
||||
Store_field(result, 0, Val_int(ret));
|
||||
}
|
||||
else {
|
||||
result = caml_alloc(1, 0);
|
||||
tuple = caml_alloc_tuple(6);
|
||||
caml_mdb_stat(tuple, &stat);
|
||||
Store_field(result, 0, tuple);
|
||||
}
|
||||
|
||||
CAMLreturn(result);
|
||||
}
|
||||
|
||||
CAMLprim value stub_mdb_dbi_flags(value txn, value dbi) {
|
||||
CAMLparam2(txn, dbi);
|
||||
CAMLlocal1(result);
|
||||
|
||||
unsigned int flags;
|
||||
int ret;
|
||||
ret = mdb_dbi_flags(Txn_val(txn), Nativeint_val(dbi), &flags);
|
||||
|
||||
if (ret) {
|
||||
result = caml_alloc(1, 1);
|
||||
Store_field(result, 0, Val_int(ret));
|
||||
}
|
||||
else {
|
||||
result = caml_alloc(1, 0);
|
||||
Store_field(result, 0, Val_int(flags));
|
||||
}
|
||||
|
||||
CAMLreturn(result);
|
||||
}
|
||||
|
||||
CAMLprim value stub_mdb_dbi_close(value env, value dbi) {
|
||||
mdb_dbi_close(Env_val(env), Nativeint_val(dbi));
|
||||
return Val_unit;
|
||||
}
|
||||
|
||||
CAMLprim value stub_mdb_drop(value txn, value dbi, value del) {
|
||||
return Val_int(mdb_drop(Txn_val(txn), Nativeint_val(dbi), Bool_val(del)));
|
||||
}
|
||||
|
||||
static inline value alloc_mdb_val_ba (MDB_val *v) {
|
||||
return
|
||||
(v ?
|
||||
caml_ba_alloc_dims(CAML_BA_UINT8 | CAML_BA_C_LAYOUT, 1, v->mv_data, v->mv_size) :
|
||||
caml_ba_alloc_dims(CAML_BA_UINT8 | CAML_BA_C_LAYOUT, 1, NULL, 0));
|
||||
}
|
||||
|
||||
CAMLprim value stub_mdb_get(value txn, value dbi, value key) {
|
||||
CAMLparam3(txn, dbi, key);
|
||||
CAMLlocal1(result);
|
||||
|
||||
MDB_val k, v;
|
||||
int ret;
|
||||
|
||||
k.mv_size = caml_string_length(key);
|
||||
k.mv_data = String_val(key);
|
||||
|
||||
ret = mdb_get(Txn_val(txn), Nativeint_val(dbi), &k, &v);
|
||||
if (ret) {
|
||||
result = caml_alloc(1, 1);
|
||||
Store_field(result, 0, Val_int(ret));
|
||||
}
|
||||
else {
|
||||
result = caml_alloc(1, 0);
|
||||
Store_field(result, 0, alloc_mdb_val_ba(&v));
|
||||
}
|
||||
|
||||
CAMLreturn(result);
|
||||
}
|
||||
|
||||
CAMLprim value stub_mdb_put(value txn, value dbi,
|
||||
value key, value data, value flags) {
|
||||
MDB_val k, v;
|
||||
k.mv_size = caml_string_length(key);
|
||||
k.mv_data = String_val(key);
|
||||
v.mv_size = Caml_ba_array_val(data)->dim[0];
|
||||
v.mv_data = Caml_ba_data_val(data);
|
||||
return Val_int(mdb_put(Txn_val(txn), Nativeint_val(dbi), &k, &v, Int_val(flags)));
|
||||
}
|
||||
|
||||
CAMLprim value stub_mdb_put_string(value txn, value dbi,
|
||||
value key, value data, value flags) {
|
||||
MDB_val k, v;
|
||||
k.mv_size = caml_string_length(key);
|
||||
k.mv_data = String_val(key);
|
||||
v.mv_size = caml_string_length(data);
|
||||
v.mv_data = String_val(data);
|
||||
return Val_int(mdb_put(Txn_val(txn), Nativeint_val(dbi), &k, &v, Int_val(flags)));
|
||||
}
|
||||
|
||||
CAMLprim value stub_mdb_del(value txn, value dbi, value key, value data) {
|
||||
MDB_val k, v, *vp = NULL;
|
||||
k.mv_size = caml_string_length(key);
|
||||
k.mv_data = String_val(key);
|
||||
|
||||
if (Is_block(data)) {
|
||||
v.mv_size = Caml_ba_array_val(Field(data, 0))->dim[0];
|
||||
v.mv_data = Caml_ba_data_val(Field(data, 0));
|
||||
vp = &v;
|
||||
}
|
||||
|
||||
return Val_int(mdb_del(Txn_val(txn), Nativeint_val(dbi), &k, vp));
|
||||
}
|
||||
|
||||
CAMLprim value stub_mdb_del_string(value txn, value dbi, value key, value data) {
|
||||
MDB_val k, v, *vp = NULL;
|
||||
k.mv_size = caml_string_length(key);
|
||||
k.mv_data = String_val(key);
|
||||
|
||||
if (Is_block(data)) {
|
||||
v.mv_size = caml_string_length(Field(data, 0));
|
||||
v.mv_data = String_val(Field(data, 0));
|
||||
vp = &v;
|
||||
}
|
||||
|
||||
return Val_int(mdb_del(Txn_val(txn), Nativeint_val(dbi), &k, vp));
|
||||
}
|
||||
|
||||
CAMLprim value stub_mdb_cursor_open(value txn, value dbi) {
|
||||
CAMLparam2(txn, dbi);
|
||||
CAMLlocal2(result, ml_cursor);
|
||||
|
||||
MDB_cursor *cursor;
|
||||
int ret;
|
||||
ret = mdb_cursor_open(Txn_val(txn), Nativeint_val(dbi), &cursor);
|
||||
|
||||
if (ret) {
|
||||
result = caml_alloc(1, 1);
|
||||
Store_field(result, 0, Val_int(ret));
|
||||
}
|
||||
else {
|
||||
result = caml_alloc(1, 0);
|
||||
ml_cursor = alloc_cursor(cursor);
|
||||
Store_field(result, 0, ml_cursor);
|
||||
}
|
||||
|
||||
CAMLreturn(result);
|
||||
}
|
||||
|
||||
CAMLprim value stub_mdb_cursor_close(value cursor) {
|
||||
mdb_cursor_close(Cursor_val(cursor));
|
||||
return Val_unit;
|
||||
}
|
||||
|
||||
CAMLprim value stub_mdb_cursor_renew(value txn, value cursor) {
|
||||
return Val_int(mdb_cursor_renew(Txn_val(txn), Cursor_val(cursor)));
|
||||
}
|
||||
|
||||
CAMLprim value stub_mdb_cursor_txn(value cursor) {
|
||||
return (value) mdb_cursor_txn(Cursor_val(cursor));
|
||||
}
|
||||
|
||||
CAMLprim value stub_mdb_cursor_dbi(value cursor) {
|
||||
return Val_int(mdb_cursor_dbi(Cursor_val(cursor)));
|
||||
}
|
||||
|
||||
CAMLprim value stub_mdb_cursor_get(value cursor, value key, value data, value op) {
|
||||
CAMLparam4(cursor, key, data, op);
|
||||
CAMLlocal2(result, tuple);
|
||||
|
||||
MDB_val k, v;
|
||||
int ret;
|
||||
|
||||
if (Is_block(key)) {
|
||||
k.mv_size = caml_string_length(Field(key, 0));
|
||||
k.mv_data = String_val(Field(key, 0));
|
||||
}
|
||||
|
||||
if (Is_block(data)) {
|
||||
v.mv_size = Caml_ba_array_val(Field(data, 0))->dim[0];
|
||||
v.mv_data = Caml_ba_data_val(Field(data, 0));
|
||||
}
|
||||
|
||||
ret = mdb_cursor_get(Cursor_val(cursor), &k, &v, Int_val(op));
|
||||
if (ret) {
|
||||
result = caml_alloc(1, 1);
|
||||
Store_field(result, 0, Val_int(ret));
|
||||
}
|
||||
else {
|
||||
result = caml_alloc(1, 0);
|
||||
tuple = caml_alloc_tuple(2);
|
||||
Store_field(tuple, 0, alloc_mdb_val_ba(&k));
|
||||
Store_field(tuple, 1, alloc_mdb_val_ba(&v));
|
||||
Store_field(result, 0, tuple);
|
||||
}
|
||||
|
||||
CAMLreturn(result);
|
||||
}
|
||||
|
||||
CAMLprim value stub_mdb_cursor_get_string(value cursor, value key, value data, value op) {
|
||||
CAMLparam4(cursor, key, data, op);
|
||||
CAMLlocal2(result, tuple);
|
||||
|
||||
MDB_val k, v;
|
||||
int ret;
|
||||
|
||||
if (Is_block(key)) {
|
||||
k.mv_size = caml_string_length(Field(key, 0));
|
||||
k.mv_data = String_val(Field(key, 0));
|
||||
}
|
||||
|
||||
if (Is_block(data)) {
|
||||
v.mv_size = caml_string_length(Field(data, 0));
|
||||
v.mv_data = String_val(Field(data, 0));
|
||||
}
|
||||
|
||||
ret = mdb_cursor_get(Cursor_val(cursor), &k, &v, Int_val(op));
|
||||
if (ret) {
|
||||
result = caml_alloc(1, 1);
|
||||
Store_field(result, 0, Val_int(ret));
|
||||
}
|
||||
else {
|
||||
result = caml_alloc(1, 0);
|
||||
tuple = caml_alloc_tuple(2);
|
||||
Store_field(tuple, 0, alloc_mdb_val_ba(&k));
|
||||
Store_field(tuple, 1, alloc_mdb_val_ba(&v));
|
||||
Store_field(result, 0, tuple);
|
||||
}
|
||||
|
||||
CAMLreturn(result);
|
||||
}
|
||||
|
||||
CAMLprim value stub_mdb_cursor_put(value cursor, value key, value data, value flags) {
|
||||
MDB_val k, v;
|
||||
k.mv_size = caml_string_length(key);
|
||||
k.mv_data = String_val(key);
|
||||
v.mv_size = Caml_ba_array_val(data)->dim[0];
|
||||
v.mv_data = Caml_ba_data_val(data);
|
||||
return Val_int(mdb_cursor_put(Cursor_val(cursor), &k, &v, Int_val(flags)));
|
||||
}
|
||||
|
||||
CAMLprim value stub_mdb_cursor_put_string(value cursor, value key, value data, value flags) {
|
||||
MDB_val k, v;
|
||||
k.mv_size = caml_string_length(key);
|
||||
k.mv_data = String_val(key);
|
||||
v.mv_size = caml_string_length(data);
|
||||
v.mv_data = String_val(data);
|
||||
return Val_int(mdb_cursor_put(Cursor_val(cursor), &k, &v, Int_val(flags)));
|
||||
}
|
||||
|
||||
CAMLprim value stub_mdb_cursor_del(value cursor, value flags) {
|
||||
return Val_int(mdb_cursor_del(Cursor_val(cursor), Int_val(flags)));
|
||||
}
|
||||
|
||||
CAMLprim value stub_mdb_cursor_count(value cursor) {
|
||||
CAMLparam1(cursor);
|
||||
CAMLlocal1(result);
|
||||
|
||||
mdb_size_t count;
|
||||
int ret;
|
||||
|
||||
ret = mdb_cursor_count(Cursor_val(cursor), &count);
|
||||
if (ret) {
|
||||
result = caml_alloc(1, 1);
|
||||
Store_field(result, 0, Val_int(ret));
|
||||
}
|
||||
else {
|
||||
result = caml_alloc(1, 0);
|
||||
Store_field(result, 0, Val_long(count));
|
||||
}
|
||||
|
||||
CAMLreturn(result);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------
|
||||
Copyright (c) 2018 Vincent Bernardoff
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
--------------------------------------------------------------------------- */
|
11130
vendors/ocaml-lmdb/src/mdb.c
vendored
Normal file
11130
vendors/ocaml-lmdb/src/mdb.c
vendored
Normal file
File diff suppressed because it is too large
Load Diff
421
vendors/ocaml-lmdb/src/midl.c
vendored
Normal file
421
vendors/ocaml-lmdb/src/midl.c
vendored
Normal file
@ -0,0 +1,421 @@
|
||||
/** @file midl.c
|
||||
* @brief ldap bdb back-end ID List functions */
|
||||
/* $OpenLDAP$ */
|
||||
/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
|
||||
*
|
||||
* Copyright 2000-2016 The OpenLDAP Foundation.
|
||||
* Portions Copyright 2001-2017 Howard Chu, Symas Corp.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted only as authorized by the OpenLDAP
|
||||
* Public License.
|
||||
*
|
||||
* A copy of this license is available in the file LICENSE in the
|
||||
* top-level directory of the distribution or, alternatively, at
|
||||
* <http://www.OpenLDAP.org/license.html>.
|
||||
*/
|
||||
|
||||
#include <limits.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
#include <sys/types.h>
|
||||
#include "midl.h"
|
||||
|
||||
/** @defgroup internal LMDB Internals
|
||||
* @{
|
||||
*/
|
||||
/** @defgroup idls ID List Management
|
||||
* @{
|
||||
*/
|
||||
#define CMP(x,y) ( (x) < (y) ? -1 : (x) > (y) )
|
||||
|
||||
unsigned mdb_midl_search( MDB_IDL ids, MDB_ID id )
|
||||
{
|
||||
/*
|
||||
* binary search of id in ids
|
||||
* if found, returns position of id
|
||||
* if not found, returns first position greater than id
|
||||
*/
|
||||
unsigned base = 0;
|
||||
unsigned cursor = 1;
|
||||
int val = 0;
|
||||
unsigned n = ids[0];
|
||||
|
||||
while( 0 < n ) {
|
||||
unsigned pivot = n >> 1;
|
||||
cursor = base + pivot + 1;
|
||||
val = CMP( ids[cursor], id );
|
||||
|
||||
if( val < 0 ) {
|
||||
n = pivot;
|
||||
|
||||
} else if ( val > 0 ) {
|
||||
base = cursor;
|
||||
n -= pivot + 1;
|
||||
|
||||
} else {
|
||||
return cursor;
|
||||
}
|
||||
}
|
||||
|
||||
if( val > 0 ) {
|
||||
++cursor;
|
||||
}
|
||||
return cursor;
|
||||
}
|
||||
|
||||
#if 0 /* superseded by append/sort */
|
||||
int mdb_midl_insert( MDB_IDL ids, MDB_ID id )
|
||||
{
|
||||
unsigned x, i;
|
||||
|
||||
x = mdb_midl_search( ids, id );
|
||||
assert( x > 0 );
|
||||
|
||||
if( x < 1 ) {
|
||||
/* internal error */
|
||||
return -2;
|
||||
}
|
||||
|
||||
if ( x <= ids[0] && ids[x] == id ) {
|
||||
/* duplicate */
|
||||
assert(0);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ( ++ids[0] >= MDB_IDL_DB_MAX ) {
|
||||
/* no room */
|
||||
--ids[0];
|
||||
return -2;
|
||||
|
||||
} else {
|
||||
/* insert id */
|
||||
for (i=ids[0]; i>x; i--)
|
||||
ids[i] = ids[i-1];
|
||||
ids[x] = id;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
MDB_IDL mdb_midl_alloc(int num)
|
||||
{
|
||||
MDB_IDL ids = malloc((num+2) * sizeof(MDB_ID));
|
||||
if (ids) {
|
||||
*ids++ = num;
|
||||
*ids = 0;
|
||||
}
|
||||
return ids;
|
||||
}
|
||||
|
||||
void mdb_midl_free(MDB_IDL ids)
|
||||
{
|
||||
if (ids)
|
||||
free(ids-1);
|
||||
}
|
||||
|
||||
void mdb_midl_shrink( MDB_IDL *idp )
|
||||
{
|
||||
MDB_IDL ids = *idp;
|
||||
if (*(--ids) > MDB_IDL_UM_MAX &&
|
||||
(ids = realloc(ids, (MDB_IDL_UM_MAX+2) * sizeof(MDB_ID))))
|
||||
{
|
||||
*ids++ = MDB_IDL_UM_MAX;
|
||||
*idp = ids;
|
||||
}
|
||||
}
|
||||
|
||||
static int mdb_midl_grow( MDB_IDL *idp, int num )
|
||||
{
|
||||
MDB_IDL idn = *idp-1;
|
||||
/* grow it */
|
||||
idn = realloc(idn, (*idn + num + 2) * sizeof(MDB_ID));
|
||||
if (!idn)
|
||||
return ENOMEM;
|
||||
*idn++ += num;
|
||||
*idp = idn;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mdb_midl_need( MDB_IDL *idp, unsigned num )
|
||||
{
|
||||
MDB_IDL ids = *idp;
|
||||
num += ids[0];
|
||||
if (num > ids[-1]) {
|
||||
num = (num + num/4 + (256 + 2)) & -256;
|
||||
if (!(ids = realloc(ids-1, num * sizeof(MDB_ID))))
|
||||
return ENOMEM;
|
||||
*ids++ = num - 2;
|
||||
*idp = ids;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mdb_midl_append( MDB_IDL *idp, MDB_ID id )
|
||||
{
|
||||
MDB_IDL ids = *idp;
|
||||
/* Too big? */
|
||||
if (ids[0] >= ids[-1]) {
|
||||
if (mdb_midl_grow(idp, MDB_IDL_UM_MAX))
|
||||
return ENOMEM;
|
||||
ids = *idp;
|
||||
}
|
||||
ids[0]++;
|
||||
ids[ids[0]] = id;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mdb_midl_append_list( MDB_IDL *idp, MDB_IDL app )
|
||||
{
|
||||
MDB_IDL ids = *idp;
|
||||
/* Too big? */
|
||||
if (ids[0] + app[0] >= ids[-1]) {
|
||||
if (mdb_midl_grow(idp, app[0]))
|
||||
return ENOMEM;
|
||||
ids = *idp;
|
||||
}
|
||||
memcpy(&ids[ids[0]+1], &app[1], app[0] * sizeof(MDB_ID));
|
||||
ids[0] += app[0];
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mdb_midl_append_range( MDB_IDL *idp, MDB_ID id, unsigned n )
|
||||
{
|
||||
MDB_ID *ids = *idp, len = ids[0];
|
||||
/* Too big? */
|
||||
if (len + n > ids[-1]) {
|
||||
if (mdb_midl_grow(idp, n | MDB_IDL_UM_MAX))
|
||||
return ENOMEM;
|
||||
ids = *idp;
|
||||
}
|
||||
ids[0] = len + n;
|
||||
ids += len;
|
||||
while (n)
|
||||
ids[n--] = id++;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void mdb_midl_xmerge( MDB_IDL idl, MDB_IDL merge )
|
||||
{
|
||||
MDB_ID old_id, merge_id, i = merge[0], j = idl[0], k = i+j, total = k;
|
||||
idl[0] = (MDB_ID)-1; /* delimiter for idl scan below */
|
||||
old_id = idl[j];
|
||||
while (i) {
|
||||
merge_id = merge[i--];
|
||||
for (; old_id < merge_id; old_id = idl[--j])
|
||||
idl[k--] = old_id;
|
||||
idl[k--] = merge_id;
|
||||
}
|
||||
idl[0] = total;
|
||||
}
|
||||
|
||||
/* Quicksort + Insertion sort for small arrays */
|
||||
|
||||
#define SMALL 8
|
||||
#define MIDL_SWAP(a,b) { itmp=(a); (a)=(b); (b)=itmp; }
|
||||
|
||||
void
|
||||
mdb_midl_sort( MDB_IDL ids )
|
||||
{
|
||||
/* Max possible depth of int-indexed tree * 2 items/level */
|
||||
int istack[sizeof(int)*CHAR_BIT * 2];
|
||||
int i,j,k,l,ir,jstack;
|
||||
MDB_ID a, itmp;
|
||||
|
||||
ir = (int)ids[0];
|
||||
l = 1;
|
||||
jstack = 0;
|
||||
for(;;) {
|
||||
if (ir - l < SMALL) { /* Insertion sort */
|
||||
for (j=l+1;j<=ir;j++) {
|
||||
a = ids[j];
|
||||
for (i=j-1;i>=1;i--) {
|
||||
if (ids[i] >= a) break;
|
||||
ids[i+1] = ids[i];
|
||||
}
|
||||
ids[i+1] = a;
|
||||
}
|
||||
if (jstack == 0) break;
|
||||
ir = istack[jstack--];
|
||||
l = istack[jstack--];
|
||||
} else {
|
||||
k = (l + ir) >> 1; /* Choose median of left, center, right */
|
||||
MIDL_SWAP(ids[k], ids[l+1]);
|
||||
if (ids[l] < ids[ir]) {
|
||||
MIDL_SWAP(ids[l], ids[ir]);
|
||||
}
|
||||
if (ids[l+1] < ids[ir]) {
|
||||
MIDL_SWAP(ids[l+1], ids[ir]);
|
||||
}
|
||||
if (ids[l] < ids[l+1]) {
|
||||
MIDL_SWAP(ids[l], ids[l+1]);
|
||||
}
|
||||
i = l+1;
|
||||
j = ir;
|
||||
a = ids[l+1];
|
||||
for(;;) {
|
||||
do i++; while(ids[i] > a);
|
||||
do j--; while(ids[j] < a);
|
||||
if (j < i) break;
|
||||
MIDL_SWAP(ids[i],ids[j]);
|
||||
}
|
||||
ids[l+1] = ids[j];
|
||||
ids[j] = a;
|
||||
jstack += 2;
|
||||
if (ir-i+1 >= j-l) {
|
||||
istack[jstack] = ir;
|
||||
istack[jstack-1] = i;
|
||||
ir = j-1;
|
||||
} else {
|
||||
istack[jstack] = j-1;
|
||||
istack[jstack-1] = l;
|
||||
l = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
unsigned mdb_mid2l_search( MDB_ID2L ids, MDB_ID id )
|
||||
{
|
||||
/*
|
||||
* binary search of id in ids
|
||||
* if found, returns position of id
|
||||
* if not found, returns first position greater than id
|
||||
*/
|
||||
unsigned base = 0;
|
||||
unsigned cursor = 1;
|
||||
int val = 0;
|
||||
unsigned n = (unsigned)ids[0].mid;
|
||||
|
||||
while( 0 < n ) {
|
||||
unsigned pivot = n >> 1;
|
||||
cursor = base + pivot + 1;
|
||||
val = CMP( id, ids[cursor].mid );
|
||||
|
||||
if( val < 0 ) {
|
||||
n = pivot;
|
||||
|
||||
} else if ( val > 0 ) {
|
||||
base = cursor;
|
||||
n -= pivot + 1;
|
||||
|
||||
} else {
|
||||
return cursor;
|
||||
}
|
||||
}
|
||||
|
||||
if( val > 0 ) {
|
||||
++cursor;
|
||||
}
|
||||
return cursor;
|
||||
}
|
||||
|
||||
int mdb_mid2l_insert( MDB_ID2L ids, MDB_ID2 *id )
|
||||
{
|
||||
unsigned x, i;
|
||||
|
||||
x = mdb_mid2l_search( ids, id->mid );
|
||||
|
||||
if( x < 1 ) {
|
||||
/* internal error */
|
||||
return -2;
|
||||
}
|
||||
|
||||
if ( x <= ids[0].mid && ids[x].mid == id->mid ) {
|
||||
/* duplicate */
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ( ids[0].mid >= MDB_IDL_UM_MAX ) {
|
||||
/* too big */
|
||||
return -2;
|
||||
|
||||
} else {
|
||||
/* insert id */
|
||||
ids[0].mid++;
|
||||
for (i=(unsigned)ids[0].mid; i>x; i--)
|
||||
ids[i] = ids[i-1];
|
||||
ids[x] = *id;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mdb_mid2l_append( MDB_ID2L ids, MDB_ID2 *id )
|
||||
{
|
||||
/* Too big? */
|
||||
if (ids[0].mid >= MDB_IDL_UM_MAX) {
|
||||
return -2;
|
||||
}
|
||||
ids[0].mid++;
|
||||
ids[ids[0].mid] = *id;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef MDB_VL32
|
||||
unsigned mdb_mid3l_search( MDB_ID3L ids, MDB_ID id )
|
||||
{
|
||||
/*
|
||||
* binary search of id in ids
|
||||
* if found, returns position of id
|
||||
* if not found, returns first position greater than id
|
||||
*/
|
||||
unsigned base = 0;
|
||||
unsigned cursor = 1;
|
||||
int val = 0;
|
||||
unsigned n = (unsigned)ids[0].mid;
|
||||
|
||||
while( 0 < n ) {
|
||||
unsigned pivot = n >> 1;
|
||||
cursor = base + pivot + 1;
|
||||
val = CMP( id, ids[cursor].mid );
|
||||
|
||||
if( val < 0 ) {
|
||||
n = pivot;
|
||||
|
||||
} else if ( val > 0 ) {
|
||||
base = cursor;
|
||||
n -= pivot + 1;
|
||||
|
||||
} else {
|
||||
return cursor;
|
||||
}
|
||||
}
|
||||
|
||||
if( val > 0 ) {
|
||||
++cursor;
|
||||
}
|
||||
return cursor;
|
||||
}
|
||||
|
||||
int mdb_mid3l_insert( MDB_ID3L ids, MDB_ID3 *id )
|
||||
{
|
||||
unsigned x, i;
|
||||
|
||||
x = mdb_mid3l_search( ids, id->mid );
|
||||
|
||||
if( x < 1 ) {
|
||||
/* internal error */
|
||||
return -2;
|
||||
}
|
||||
|
||||
if ( x <= ids[0].mid && ids[x].mid == id->mid ) {
|
||||
/* duplicate */
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* insert id */
|
||||
ids[0].mid++;
|
||||
for (i=(unsigned)ids[0].mid; i>x; i--)
|
||||
ids[i] = ids[i-1];
|
||||
ids[x] = *id;
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif /* MDB_VL32 */
|
||||
|
||||
/** @} */
|
||||
/** @} */
|
204
vendors/ocaml-lmdb/src/midl.h
vendored
Normal file
204
vendors/ocaml-lmdb/src/midl.h
vendored
Normal file
@ -0,0 +1,204 @@
|
||||
/** @file midl.h
|
||||
* @brief LMDB ID List header file.
|
||||
*
|
||||
* This file was originally part of back-bdb but has been
|
||||
* modified for use in libmdb. Most of the macros defined
|
||||
* in this file are unused, just left over from the original.
|
||||
*
|
||||
* This file is only used internally in libmdb and its definitions
|
||||
* are not exposed publicly.
|
||||
*/
|
||||
/* $OpenLDAP$ */
|
||||
/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
|
||||
*
|
||||
* Copyright 2000-2016 The OpenLDAP Foundation.
|
||||
* Portions Copyright 2001-2017 Howard Chu, Symas Corp.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted only as authorized by the OpenLDAP
|
||||
* Public License.
|
||||
*
|
||||
* A copy of this license is available in the file LICENSE in the
|
||||
* top-level directory of the distribution or, alternatively, at
|
||||
* <http://www.OpenLDAP.org/license.html>.
|
||||
*/
|
||||
|
||||
#ifndef _MDB_MIDL_H_
|
||||
#define _MDB_MIDL_H_
|
||||
|
||||
#include "lmdb.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** @defgroup internal LMDB Internals
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @defgroup idls ID List Management
|
||||
* @{
|
||||
*/
|
||||
/** A generic unsigned ID number. These were entryIDs in back-bdb.
|
||||
* Preferably it should have the same size as a pointer.
|
||||
*/
|
||||
typedef mdb_size_t MDB_ID;
|
||||
|
||||
/** An IDL is an ID List, a sorted array of IDs. The first
|
||||
* element of the array is a counter for how many actual
|
||||
* IDs are in the list. In the original back-bdb code, IDLs are
|
||||
* sorted in ascending order. For libmdb IDLs are sorted in
|
||||
* descending order.
|
||||
*/
|
||||
typedef MDB_ID *MDB_IDL;
|
||||
|
||||
/* IDL sizes - likely should be even bigger
|
||||
* limiting factors: sizeof(ID), thread stack size
|
||||
*/
|
||||
#ifdef MDB_VL32
|
||||
#define MDB_IDL_LOGN 14 /* DB_SIZE is 2^14, UM_SIZE is 2^15 */
|
||||
#else
|
||||
#define MDB_IDL_LOGN 16 /* DB_SIZE is 2^16, UM_SIZE is 2^17 */
|
||||
#endif
|
||||
#define MDB_IDL_DB_SIZE (1<<MDB_IDL_LOGN)
|
||||
#define MDB_IDL_UM_SIZE (1<<(MDB_IDL_LOGN+1))
|
||||
|
||||
#define MDB_IDL_DB_MAX (MDB_IDL_DB_SIZE-1)
|
||||
#define MDB_IDL_UM_MAX (MDB_IDL_UM_SIZE-1)
|
||||
|
||||
#define MDB_IDL_SIZEOF(ids) (((ids)[0]+1) * sizeof(MDB_ID))
|
||||
#define MDB_IDL_IS_ZERO(ids) ( (ids)[0] == 0 )
|
||||
#define MDB_IDL_CPY( dst, src ) (memcpy( dst, src, MDB_IDL_SIZEOF( src ) ))
|
||||
#define MDB_IDL_FIRST( ids ) ( (ids)[1] )
|
||||
#define MDB_IDL_LAST( ids ) ( (ids)[(ids)[0]] )
|
||||
|
||||
/** Current max length of an #mdb_midl_alloc()ed IDL */
|
||||
#define MDB_IDL_ALLOCLEN( ids ) ( (ids)[-1] )
|
||||
|
||||
/** Append ID to IDL. The IDL must be big enough. */
|
||||
#define mdb_midl_xappend(idl, id) do { \
|
||||
MDB_ID *xidl = (idl), xlen = ++(xidl[0]); \
|
||||
xidl[xlen] = (id); \
|
||||
} while (0)
|
||||
|
||||
/** Search for an ID in an IDL.
|
||||
* @param[in] ids The IDL to search.
|
||||
* @param[in] id The ID to search for.
|
||||
* @return The index of the first ID greater than or equal to \b id.
|
||||
*/
|
||||
unsigned mdb_midl_search( MDB_IDL ids, MDB_ID id );
|
||||
|
||||
/** Allocate an IDL.
|
||||
* Allocates memory for an IDL of the given size.
|
||||
* @return IDL on success, NULL on failure.
|
||||
*/
|
||||
MDB_IDL mdb_midl_alloc(int num);
|
||||
|
||||
/** Free an IDL.
|
||||
* @param[in] ids The IDL to free.
|
||||
*/
|
||||
void mdb_midl_free(MDB_IDL ids);
|
||||
|
||||
/** Shrink an IDL.
|
||||
* Return the IDL to the default size if it has grown larger.
|
||||
* @param[in,out] idp Address of the IDL to shrink.
|
||||
*/
|
||||
void mdb_midl_shrink(MDB_IDL *idp);
|
||||
|
||||
/** Make room for num additional elements in an IDL.
|
||||
* @param[in,out] idp Address of the IDL.
|
||||
* @param[in] num Number of elements to make room for.
|
||||
* @return 0 on success, ENOMEM on failure.
|
||||
*/
|
||||
int mdb_midl_need(MDB_IDL *idp, unsigned num);
|
||||
|
||||
/** Append an ID onto an IDL.
|
||||
* @param[in,out] idp Address of the IDL to append to.
|
||||
* @param[in] id The ID to append.
|
||||
* @return 0 on success, ENOMEM if the IDL is too large.
|
||||
*/
|
||||
int mdb_midl_append( MDB_IDL *idp, MDB_ID id );
|
||||
|
||||
/** Append an IDL onto an IDL.
|
||||
* @param[in,out] idp Address of the IDL to append to.
|
||||
* @param[in] app The IDL to append.
|
||||
* @return 0 on success, ENOMEM if the IDL is too large.
|
||||
*/
|
||||
int mdb_midl_append_list( MDB_IDL *idp, MDB_IDL app );
|
||||
|
||||
/** Append an ID range onto an IDL.
|
||||
* @param[in,out] idp Address of the IDL to append to.
|
||||
* @param[in] id The lowest ID to append.
|
||||
* @param[in] n Number of IDs to append.
|
||||
* @return 0 on success, ENOMEM if the IDL is too large.
|
||||
*/
|
||||
int mdb_midl_append_range( MDB_IDL *idp, MDB_ID id, unsigned n );
|
||||
|
||||
/** Merge an IDL onto an IDL. The destination IDL must be big enough.
|
||||
* @param[in] idl The IDL to merge into.
|
||||
* @param[in] merge The IDL to merge.
|
||||
*/
|
||||
void mdb_midl_xmerge( MDB_IDL idl, MDB_IDL merge );
|
||||
|
||||
/** Sort an IDL.
|
||||
* @param[in,out] ids The IDL to sort.
|
||||
*/
|
||||
void mdb_midl_sort( MDB_IDL ids );
|
||||
|
||||
/** An ID2 is an ID/pointer pair.
|
||||
*/
|
||||
typedef struct MDB_ID2 {
|
||||
MDB_ID mid; /**< The ID */
|
||||
void *mptr; /**< The pointer */
|
||||
} MDB_ID2;
|
||||
|
||||
/** An ID2L is an ID2 List, a sorted array of ID2s.
|
||||
* The first element's \b mid member is a count of how many actual
|
||||
* elements are in the array. The \b mptr member of the first element is unused.
|
||||
* The array is sorted in ascending order by \b mid.
|
||||
*/
|
||||
typedef MDB_ID2 *MDB_ID2L;
|
||||
|
||||
/** Search for an ID in an ID2L.
|
||||
* @param[in] ids The ID2L to search.
|
||||
* @param[in] id The ID to search for.
|
||||
* @return The index of the first ID2 whose \b mid member is greater than or equal to \b id.
|
||||
*/
|
||||
unsigned mdb_mid2l_search( MDB_ID2L ids, MDB_ID id );
|
||||
|
||||
|
||||
/** Insert an ID2 into a ID2L.
|
||||
* @param[in,out] ids The ID2L to insert into.
|
||||
* @param[in] id The ID2 to insert.
|
||||
* @return 0 on success, -1 if the ID was already present in the ID2L.
|
||||
*/
|
||||
int mdb_mid2l_insert( MDB_ID2L ids, MDB_ID2 *id );
|
||||
|
||||
/** Append an ID2 into a ID2L.
|
||||
* @param[in,out] ids The ID2L to append into.
|
||||
* @param[in] id The ID2 to append.
|
||||
* @return 0 on success, -2 if the ID2L is too big.
|
||||
*/
|
||||
int mdb_mid2l_append( MDB_ID2L ids, MDB_ID2 *id );
|
||||
|
||||
#ifdef MDB_VL32
|
||||
typedef struct MDB_ID3 {
|
||||
MDB_ID mid; /**< The ID */
|
||||
void *mptr; /**< The pointer */
|
||||
unsigned int mcnt; /**< Number of pages */
|
||||
unsigned int mref; /**< Refcounter */
|
||||
} MDB_ID3;
|
||||
|
||||
typedef MDB_ID3 *MDB_ID3L;
|
||||
|
||||
unsigned mdb_mid3l_search( MDB_ID3L ids, MDB_ID id );
|
||||
int mdb_mid3l_insert( MDB_ID3L ids, MDB_ID3 *id );
|
||||
|
||||
#endif /* MDB_VL32 */
|
||||
/** @} */
|
||||
/** @} */
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif /* _MDB_MIDL_H_ */
|
10
vendors/ocaml-lmdb/test/jbuild
vendored
Normal file
10
vendors/ocaml-lmdb/test/jbuild
vendored
Normal file
@ -0,0 +1,10 @@
|
||||
(jbuild_version 1)
|
||||
|
||||
(executable
|
||||
((name test)
|
||||
(libraries (cstruct rresult lmdb alcotest))))
|
||||
|
||||
(alias
|
||||
((name runtest-lmdb)
|
||||
(deps (test.exe))
|
||||
(action (run ${<}))))
|
178
vendors/ocaml-lmdb/test/test.ml
vendored
Normal file
178
vendors/ocaml-lmdb/test/test.ml
vendored
Normal file
@ -0,0 +1,178 @@
|
||||
open Rresult
|
||||
open Lmdb
|
||||
|
||||
let assert_false v =
|
||||
assert (not v)
|
||||
|
||||
let assert_error err = function
|
||||
| Ok _ -> invalid_arg "assert_error"
|
||||
| Error e -> if e <> err then invalid_arg "assert_error"
|
||||
|
||||
let assert_equal_ba expected ba =
|
||||
assert (expected = Cstruct.(to_string (of_bigarray ba)))
|
||||
|
||||
let version () =
|
||||
let { major ; minor ; patch } = version () in
|
||||
assert (major = 0) ;
|
||||
assert (minor = 9) ;
|
||||
assert (patch = 70)
|
||||
|
||||
let test_string_of_error () =
|
||||
let errmsg = string_of_error KeyExist in
|
||||
assert (String.length errmsg > 0)
|
||||
|
||||
let cleanup () =
|
||||
let files = [ "/tmp/data.mdb" ; "/tmp/lock.mdb" ] in
|
||||
ListLabels.iter files ~f:begin fun fn ->
|
||||
Sys.(if file_exists fn then remove fn)
|
||||
end
|
||||
|
||||
let env () =
|
||||
cleanup () ;
|
||||
opendir ~maxreaders:34 ~maxdbs:1 "/tmp" 0o644 >>= fun env ->
|
||||
let _stat = stat env in
|
||||
let _envinfo = envinfo env in
|
||||
let _flags = get_flags env in
|
||||
let _path = get_path env in
|
||||
let _fd = get_fd env in
|
||||
let _maxreaders = get_maxreaders env in
|
||||
let _maxkeysize = get_maxkeysize env in
|
||||
sync env >>= fun () ->
|
||||
Ok ()
|
||||
|
||||
let txn () =
|
||||
cleanup () ;
|
||||
opendir ~maxdbs:1 "/tmp" 0o644 >>= fun env ->
|
||||
create_ro_txn env >>= fun rotxn ->
|
||||
reset_ro_txn rotxn ;
|
||||
create_rw_txn env >>= fun rwtxn ->
|
||||
assert (rwtxn = rwtxn) ;
|
||||
let env2 = get_txn_env rwtxn in
|
||||
assert (env = env2) ;
|
||||
opendb rwtxn >>= fun defaultdbi ->
|
||||
opendb ~flags:[Create] rwtxn ~name:"bleh" >>= fun dbi ->
|
||||
put_string rwtxn dbi "test" "test" >>= fun () ->
|
||||
get rwtxn dbi "test" >>= fun buffer ->
|
||||
assert_equal_ba "test" buffer ;
|
||||
assert_error KeyNotFound (del rwtxn dbi "bleh") ;
|
||||
del rwtxn dbi "test" >>= fun () ->
|
||||
db_stat rwtxn dbi >>= fun _stat ->
|
||||
db_flags rwtxn dbi >>= fun _flags ->
|
||||
db_drop rwtxn dbi >>= fun () ->
|
||||
closedir env ;
|
||||
Ok ()
|
||||
|
||||
let cursors () =
|
||||
cleanup () ;
|
||||
opendir "/tmp" 0o644 >>= fun env ->
|
||||
create_rw_txn env >>= fun txn ->
|
||||
opendb txn >>= fun db ->
|
||||
opencursor txn db >>= fun cursor ->
|
||||
assert_error KeyNotFound (cursor_first cursor) ;
|
||||
assert_error KeyNotFound (cursor_last cursor) ;
|
||||
cursor_put_string cursor "test" "test" >>= fun () ->
|
||||
cursor_put_string cursor "test2" "test2" >>= fun () ->
|
||||
sync env >>= fun () ->
|
||||
cursor_first cursor >>= fun () ->
|
||||
cursor_at cursor "" >>= fun () ->
|
||||
assert_error KeyNotFound (cursor_prev cursor) ;
|
||||
cursor_last cursor >>= fun () ->
|
||||
assert_error KeyNotFound (cursor_next cursor) ;
|
||||
cursor_prev cursor >>= fun () ->
|
||||
get txn db "test" >>= fun buf ->
|
||||
assert_equal_ba "test" buf ;
|
||||
cursor_get cursor >>= fun (k, v) ->
|
||||
assert_equal_ba "test" k ;
|
||||
assert_equal_ba "test" v ;
|
||||
closedir env ;
|
||||
Ok ()
|
||||
|
||||
let cursors_del () =
|
||||
cleanup () ;
|
||||
opendir "/tmp" 0o644 >>= fun env ->
|
||||
with_rw_db env ~f:begin fun txn db ->
|
||||
with_cursor txn db ~f:begin fun cursor ->
|
||||
cursor_put_string cursor "k1" "v1" >>= fun () ->
|
||||
cursor_first cursor >>= fun () ->
|
||||
cursor_fold_left cursor ~init:() ~f:begin fun acc (_k, _v) ->
|
||||
cursor_del cursor
|
||||
end >>= fun () ->
|
||||
assert_error KeyNotFound (cursor_first cursor) ;
|
||||
Ok ()
|
||||
end
|
||||
end
|
||||
|
||||
let cursors_del4 () =
|
||||
cleanup () ;
|
||||
opendir "/tmp" 0o644 >>= fun env ->
|
||||
with_rw_db env ~f:begin fun txn db ->
|
||||
with_cursor txn db ~f:begin fun cursor ->
|
||||
cursor_put_string cursor "k1" "v1" >>= fun () ->
|
||||
cursor_put_string cursor "k2" "v2" >>= fun () ->
|
||||
cursor_put_string cursor "k3" "v3" >>= fun () ->
|
||||
cursor_put_string cursor "k4" "v4" >>= fun () ->
|
||||
cursor_first cursor >>= fun () ->
|
||||
cursor_fold_left cursor ~init:() ~f:begin fun acc (_k, _v) ->
|
||||
cursor_del cursor
|
||||
end >>= fun () ->
|
||||
assert_error KeyNotFound (cursor_first cursor) ;
|
||||
Ok ()
|
||||
end
|
||||
end
|
||||
|
||||
let fold () =
|
||||
cleanup () ;
|
||||
opendir "/tmp" 0o644 >>= fun env ->
|
||||
with_rw_db env ~f:begin fun txn db ->
|
||||
opencursor txn db >>= fun cursor ->
|
||||
cursor_put_string cursor "k1" "v1" >>= fun () ->
|
||||
cursor_put_string cursor "k2" "v2" >>= fun () ->
|
||||
cursor_put_string cursor "k3" "v3" >>= fun () ->
|
||||
cursor_put_string cursor "k4" "v4" >>= fun () ->
|
||||
cursor_first cursor >>= fun () ->
|
||||
cursor_fold_left ~f:begin fun i (k, v) ->
|
||||
assert_equal_ba ("k" ^ (string_of_int i)) k ;
|
||||
assert_equal_ba ("v" ^ (string_of_int i)) v ;
|
||||
Ok (succ i)
|
||||
end ~init:1 cursor >>= fun _ ->
|
||||
Ok ()
|
||||
end >>= fun () ->
|
||||
closedir env ;
|
||||
Ok ()
|
||||
|
||||
let consistency () =
|
||||
cleanup () ;
|
||||
opendir "/tmp" 0o644 >>= fun env ->
|
||||
let v = Cstruct.(to_bigarray (of_string "bleh")) in
|
||||
with_rw_db env ~f:begin fun txn db ->
|
||||
put txn db "bleh" v
|
||||
end >>= fun () ->
|
||||
with_ro_db env ~f:begin fun txn db ->
|
||||
get txn db "bleh" >>= fun v' ->
|
||||
(* assert (v = v') ; *)
|
||||
assert_equal_ba "bleh" v' ;
|
||||
Ok ()
|
||||
end >>= fun () ->
|
||||
Ok ()
|
||||
|
||||
let fail_on_error f () =
|
||||
match f () with
|
||||
| Ok _ -> ()
|
||||
| Error err -> failwith (string_of_error err)
|
||||
|
||||
let basic = [
|
||||
"version", `Quick, version ;
|
||||
"string_of_error", `Quick, test_string_of_error ;
|
||||
"env", `Quick, fail_on_error env ;
|
||||
"txn", `Quick, fail_on_error txn ;
|
||||
"cursors", `Quick, fail_on_error cursors ;
|
||||
"cursors_del", `Quick, fail_on_error cursors_del ;
|
||||
"cursors_del4", `Quick, fail_on_error cursors_del4 ;
|
||||
"fold", `Quick, fail_on_error fold ;
|
||||
"consistency", `Quick, fail_on_error consistency ;
|
||||
]
|
||||
|
||||
let () =
|
||||
Alcotest.run "lmdb" [
|
||||
"basic", basic ;
|
||||
]
|
Loading…
Reference in New Issue
Block a user