1998-02-23 04:42:23 -08:00
|
|
|
(***********************************************************************)
|
|
|
|
(* *)
|
|
|
|
(* Objective Caml *)
|
|
|
|
(* *)
|
|
|
|
(* Francois Rouaix, projet Cristal, INRIA Rocquencourt *)
|
|
|
|
(* *)
|
|
|
|
(* Copyright 1996 Institut National de Recherche en Informatique et *)
|
1999-11-17 10:59:06 -08:00
|
|
|
(* en Automatique. All rights reserved. This file is distributed *)
|
|
|
|
(* under the terms of the GNU Library General Public License. *)
|
1998-02-23 04:42:23 -08:00
|
|
|
(* *)
|
|
|
|
(***********************************************************************)
|
|
|
|
|
1999-11-17 11:25:38 -08:00
|
|
|
(* $Id$ *)
|
1998-02-23 04:42:23 -08:00
|
|
|
|
|
|
|
(* Module [Db]: interface to the DB databases *)
|
|
|
|
|
|
|
|
(* this collides with Unix *)
|
|
|
|
type open_flag =
|
|
|
|
O_CREAT
|
|
|
|
| O_EXCL
|
|
|
|
| O_RDONLY
|
|
|
|
| O_RDWR
|
|
|
|
| O_TRUNC
|
|
|
|
|
|
|
|
type routine_flag =
|
|
|
|
R_CURSOR
|
|
|
|
| R_FIRST
|
|
|
|
| R_LAST
|
|
|
|
| R_NEXT
|
|
|
|
| R_NOOVERWRITE
|
|
|
|
| R_PREV
|
|
|
|
| R_SETCURSOR
|
|
|
|
|
1998-03-16 01:45:37 -08:00
|
|
|
|
|
|
|
(* All other fields have default values *)
|
|
|
|
type btree_flag =
|
|
|
|
Duplicates (* means R_DUP *)
|
|
|
|
| Cachesize of int
|
|
|
|
|
|
|
|
|
1998-02-23 04:42:23 -08:00
|
|
|
type file_perm = int
|
|
|
|
|
|
|
|
exception DB_error of string
|
|
|
|
(* Raised by the following functions when an error is encountered. *)
|
|
|
|
|
|
|
|
external caml_db_init : unit -> unit
|
|
|
|
= "caml_db_init"
|
|
|
|
|
|
|
|
let _ = Callback.register_exception "dberror" (DB_error "")
|
|
|
|
let _ = caml_db_init()
|
|
|
|
|
|
|
|
type key = string
|
|
|
|
type data = string
|
|
|
|
type t
|
|
|
|
|
|
|
|
(* Raw access *)
|
1998-03-16 01:45:37 -08:00
|
|
|
external dbopen : string -> open_flag list -> file_perm -> btree_flag list -> t
|
1998-02-23 04:42:23 -08:00
|
|
|
= "caml_db_open"
|
|
|
|
(* [dbopen file flags mode dupentries] *)
|
|
|
|
|
|
|
|
(* The common subset of available primitives *)
|
|
|
|
external close : t -> unit
|
|
|
|
= "caml_db_close"
|
|
|
|
|
|
|
|
external del : t -> key -> routine_flag list -> unit
|
|
|
|
= "caml_db_del"
|
|
|
|
(* raise Not_found if the key was not in the file *)
|
|
|
|
|
|
|
|
external get : t -> key -> routine_flag list -> data
|
|
|
|
= "caml_db_get"
|
|
|
|
(* raise Not_found if the key was not in the file *)
|
|
|
|
|
|
|
|
external put : t -> key -> data -> routine_flag list -> unit
|
|
|
|
= "caml_db_put"
|
|
|
|
|
|
|
|
external seq : t -> key -> routine_flag list -> (key * data)
|
|
|
|
= "caml_db_seq"
|
|
|
|
|
|
|
|
external sync : t -> unit
|
|
|
|
= "caml_db_sync"
|
|
|
|
|
|
|
|
|
|
|
|
(* Wrap-up as for other table-like types *)
|
|
|
|
let add db x v = put db x v [R_NOOVERWRITE]
|
|
|
|
let find db x = get db x []
|
1999-11-29 11:04:56 -08:00
|
|
|
let find_all db x =
|
1998-02-23 04:42:23 -08:00
|
|
|
try
|
|
|
|
match seq db x [R_CURSOR] with
|
|
|
|
k, v when k = x ->
|
1999-11-29 11:04:56 -08:00
|
|
|
let l = ref [v] in
|
|
|
|
begin
|
|
|
|
try
|
|
|
|
while true do
|
|
|
|
let k, v = seq db x [R_NEXT] in
|
|
|
|
if k = x then l := v :: !l
|
|
|
|
else raise Exit
|
|
|
|
done;
|
|
|
|
!l
|
|
|
|
with
|
|
|
|
Exit | Not_found -> !l
|
|
|
|
end
|
1998-02-23 04:42:23 -08:00
|
|
|
| _ -> (* its greater than x *) []
|
|
|
|
with
|
|
|
|
Not_found -> []
|
|
|
|
|
|
|
|
let remove db x = del db x []
|
|
|
|
|
1999-11-29 11:04:56 -08:00
|
|
|
let iter f db =
|
2000-04-02 19:21:07 -07:00
|
|
|
let rec walk = function
|
|
|
|
None -> ()
|
|
|
|
| Some(k, v) ->
|
|
|
|
f k v;
|
|
|
|
walk (try Some(seq db k [R_NEXT]) with Not_found -> None)
|
1998-02-23 04:42:23 -08:00
|
|
|
in
|
2000-04-02 19:21:07 -07:00
|
|
|
walk (try Some(seq db "" [R_FIRST]) with Not_found -> None)
|