Permalink
Browse files

bugfix: special treatment for log_update in case of empty transactions

  • Loading branch information...
1 parent 3cc4c02 commit 82967cb9eaaecac05efe770924fe98aa323c76f0 Romain Slootmaekers committed Feb 6, 2013
Showing with 55 additions and 17 deletions.
  1. +43 −17 src/dbx.ml
  2. +12 −0 src/dbx_test.ml
View
@@ -126,36 +126,62 @@ module DBX(L:LOG) = struct
| NOK k -> failwith (Printf.sprintf "delete_prefix: %s" k)
let log_update (log:L.t) ?(diff = true) (f: tx -> ('a,'b) result L.m) =
+ let previous = L.last log in
let _find_lookup () =
- let pp = L.last log in
- L.read log pp >>= function
+ L.read log previous >>= function
| Commit lc ->
- let lu = if diff
- then Commit.get_pos lc
- else Commit.get_lookup lc
- in return lu
- | NIL -> return pp
+ let lu = if diff
+ then Commit.get_pos lc
+ else Commit.get_lookup lc
+ in return lu
+ | NIL -> return previous
| e -> failwith (Printf.sprintf "log_update: %s is not commit" (entry2s e))
in
let now = L.now log in
let fut = if diff then Time.next_major now else now in
-
+
let slab = Slab.make fut in
let tx = {log;slab; cactions = []} in
_find_lookup () >>= fun lookup ->
f tx >>= function
| OK x ->
begin
- let root = Slab.length tx.slab -1 in
- let previous = L.last log in
- let pos = Inner root in
- let commit = make_commit ~pos ~previous ~lookup fut (List.rev tx.cactions) false in
- let c = Commit commit in
- let _ = Slab.add tx.slab c in
- let slab' = Slab.compact tx.slab in
- L.write log slab' >>= fun () ->
- return (OK x)
+ let sl = Slab.length tx.slab in
+ if sl > 0
+ then
+ begin
+ let root = sl - 1 in
+ let pos = Inner root in
+ let commit = make_commit ~pos ~previous ~lookup fut (List.rev tx.cactions) false in
+ let c = Commit commit in
+ let _ = Slab.add tx.slab c in
+ let slab' = Slab.compact tx.slab in
+ L.write log slab' >>= fun () ->
+ return (OK x)
+ end
+ else (* This is an empty transaction *)
+ begin
+ L.read log previous >>=
+ begin function
+ | Commit lc -> return (Commit.get_pos lc)
+ | NIL -> return (Inner (-1))
+ | e -> failwith (Printf.sprintf "log_update %s is not a commit" (entry2s e))
+ end
+ >>= fun ppos ->
+ let commit = make_commit
+ ~pos:ppos
+ ~previous
+ ~lookup fut
+ []
+ false
+ in
+ let c = Commit commit in
+ let _ = Slab.add tx.slab c in
+ let slab' = Slab.compact tx.slab in
+ L.write log slab' >>= fun () ->
+ return (OK x)
+ end
end
| NOK k -> return (NOK k)
View
@@ -125,6 +125,17 @@ let log_bug2() =
let ok2 = MDBX.log_update mlog (fun tx -> Mlog.return ok) in
()
+let log_bug3() =
+ let mlog = _setup () in
+ let _ = MDBX.log_update mlog ~diff:true (fun tx -> _ok_set tx "x" "X") in
+ let _ = MDBX.log_update mlog ~diff:true (fun tx -> Mlog.return (OK ())) in
+ MDBX.commit_last mlog >>= fun () ->
+ Mlog.dump mlog;
+ MDB.get mlog "x" >>= fun r ->
+ OUnit.assert_equal r (OK "X");
+ ()
+
+
let suite = "DBX" >::: [
"get_after_delete" >:: get_after_delete;
"get_after_log_update" >:: get_after_log_update;
@@ -134,4 +145,5 @@ let suite = "DBX" >::: [
"delete_prefix" >:: delete_prefix;
"log_nothing" >:: log_nothing;
"log_bug2" >:: log_bug2;
+ "log_bug3" >:: log_bug3;
]

0 comments on commit 82967cb

Please sign in to comment.