Files
xen/tools/ocaml/xenstored/history.ml
T
Edwin Török ea250e81cf tools/ocaml: run 'make format' on OCaml files
`git log -p -1 -w` proves the change here is only whitespace.

No functional change.

Signed-off-by: Edwin Török <edwin.torok@cloud.com>
Acked-by: Christian Lindig <christian.lindig@citrix.com>
2023-02-06 10:22:12 +00:00

64 lines
2.6 KiB
OCaml

(*
* Copyright (c) 2017 Citrix Systems Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation; version 2.1 only. with the special
* exception on linking described in file LICENSE.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*)
type history_record = {
con: Connection.t; (* connection that made a change *)
tid: int; (* transaction id of the change (may be Transaction.none) *)
before: Store.t; (* the store before the change *)
after: Store.t; (* the store after the change *)
finish_count: int64; (* the commit-count at which the transaction finished *)
}
let history : history_record list ref = ref []
(* Keep only enough commit-history to protect the running transactions that we are still tracking *)
(* There is scope for optimisation here, replacing List.filter with something more efficient,
* probably on a different list-like structure. *)
let trim ?txn () =
Transaction.trim_short_running_transactions txn;
history := match Transaction.oldest_short_running_transaction () with
| None -> [] (* We have no open transaction, so no history is needed *)
| Some (_, txn) -> (
(* keep records with finish_count recent enough to be relevant *)
List.filter (fun r -> r.finish_count > txn.Transaction.start_count) !history
)
let end_transaction txn con tid commit =
let success = Connection.end_transaction con tid commit in
trim ~txn ();
success
let reconnect con =
trim ();
Connection.do_reconnect con
let push (x: history_record) =
let dom = x.con.Connection.dom in
match dom with
| None -> () (* treat socket connections as always free to conflict *)
| Some d -> if not (Domain.is_free_to_conflict d) then history := x :: !history
(* Find the connections from records since commit-count [since] for which [f record] returns [true] *)
let filter_connections ~ignore ~since ~f =
(* The "mem" call is an optimisation, to avoid calling f if we have picked con already. *)
(* Using a hash table rather than a list is to optimise the "mem" call. *)
List.fold_left (fun acc hist_rec ->
if hist_rec.finish_count > since
&& not (hist_rec.con == ignore)
&& not (Hashtbl.mem acc hist_rec.con)
&& f hist_rec
then Hashtbl.replace acc hist_rec.con ();
acc
) (Hashtbl.create 1023) !history