package xenstore
Xenstore protocol in pure OCam
Install
Dune Dependency
github.com
Readme
Changelog
LGPL-2.1-only WITH OCaml-LGPL-linking-exception License
Edit opam file
Versions (2)
Authors
Maintainers
Sources
xenstore-2.4.0.tbz
sha256=11b63bb2a5a8bc487d36f36ecb195b2a2135aa13ab401cbc73da67505c08faa4
sha512=b921aa4265503677f4984007efee6865461a18031dc49583be040781307cc6cbfcd84bc11e9ebc0a23e9b0cf281bd94528c475624bc30471ad8ff70607e0732f
doc/src/xenstore.server/transaction.ml.html
Source file transaction.ml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210
(* * Copyright (C) Citrix Systems Inc. * * 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. *) let debug fmt = Logging.debug "transaction" fmt open Junk let none = 0l let test_eagain = ref false let check_parents_perms_identical root1 root2 path = let hierarch = Store.Path.get_hierarchy path in let permdiff = List.fold_left (fun acc path -> let n1 = Store.lookup root1 path and n2 = Store.lookup root2 path in match (n1, n2) with | Some n1, Some n2 -> Store.Node.get_perms n1 <> Store.Node.get_perms n2 || acc | _ -> true || acc) false hierarch in not permdiff let get_lowest path1 path2 = match path2 with | None -> Some path1 | Some path2 -> Some (Store.Path.get_common_prefix path1 path2) let test_coalesce oldroot currentroot path = let oldnode = Store.lookup oldroot path and currentnode = Store.lookup currentroot path in match (oldnode, currentnode) with | Some oldnode, Some currentnode -> if oldnode == currentnode then check_parents_perms_identical oldroot currentroot path else false | None, None -> ( (* ok then it doesn't exists in the old version and the current version, just sneak it in as a child of the parent node if it exists, or else fail *) let pnode = Store.lookup currentroot (Store.Path.get_parent path) in match pnode with | None -> false (* ok it doesn't exists, just bail out. *) | Some _pnode -> true) | _ -> false let can_coalesce oldroot currentroot path = try test_coalesce oldroot currentroot path with _ -> false type ty = No | Full of (int32 * Store.Node.t * Store.t) type t = { ty : ty ; store : Store.t ; quota : Quota.t ; mutable paths : (Xs_protocol.Op.t * Store.Name.t) list ; mutable operations : (Xs_protocol.Request.payload * Xs_protocol.Response.payload) list ; mutable read_lowpath : Store.Path.t option ; mutable write_lowpath : Store.Path.t option } let make id store = let ty = if id = none then No else Full (id, store.Store.root, store) in { ty ; store = (if id = none then store else Store.copy store) ; quota = Quota.copy store.Store.quota ; paths = [] ; operations = [] ; read_lowpath = None ; write_lowpath = None } let get_id t = match t.ty with No -> none | Full (id, _, _) -> id let get_store t = t.store let get_paths t = t.paths let add_wop t ty path = t.paths <- (ty, Store.Path.to_name path) :: t.paths let add_operation t request response = t.operations <- (request, response) :: t.operations let get_operations t = List.rev t.operations let set_read_lowpath t path = t.read_lowpath <- get_lowest path t.read_lowpath let set_write_lowpath t path = t.write_lowpath <- get_lowest path t.write_lowpath let exists t _perms path = Store.exists t.store path let write t creator perm path value = let path_existed = exists t perm path in Store.write t.store creator perm path value; if path_existed then set_write_lowpath t path else set_write_lowpath t (Store.Path.get_parent path); add_wop t Xs_protocol.Op.Write path let mkdir ?(with_watch = true) t creator perm path = Store.mkdir t.store creator perm path; set_write_lowpath t path; if with_watch then add_wop t Xs_protocol.Op.Mkdir path let setperms t perm path perms = Store.setperms t.store perm path perms; set_write_lowpath t path; add_wop t Xs_protocol.Op.Setperms path let rm t perm path = Store.rm t.store perm path; set_write_lowpath t (Store.Path.get_parent path); add_wop t Xs_protocol.Op.Rm path let list t perm path = let r = Store.ls t.store perm path in set_read_lowpath t path; r let read t perm path = let r = Store.read t.store perm path in set_read_lowpath t path; r let getperms t perm path = let r = Store.getperms t.store perm path in set_read_lowpath t path; r let commit ~con t = let has_write_ops = List.length t.paths > 0 in let has_coalesced = ref false in let has_commited = match t.ty with | No -> true | Full (_id, oldroot, cstore) -> let commit_partial oldroot cstore store = (* get the lowest path of the query and verify that it hasn't been modified by others transactions. *) let readpath_ok = match t.read_lowpath with | None -> true (* no reads recorded *) | Some path -> can_coalesce oldroot cstore.Store.root path in let writepath_ok = match t.write_lowpath with | None -> true (* no writes recorded *) | Some path -> can_coalesce oldroot cstore.Store.root path in if readpath_ok && writepath_ok then ( maybe (fun p -> let n = Store.lookup store.Store.root p in (* it has to be in the store, otherwise it means bugs in the lowpath registration. we don't need to handle none. *) maybe (fun n -> Store.set_node cstore p n t.quota store.Store.quota) n; Logging.write_coalesce ~tid:(get_id t) ~con (Store.Path.to_string p)) t.write_lowpath; maybe (fun p -> Logging.read_coalesce ~tid:(get_id t) ~con (Store.Path.to_string p)) t.read_lowpath; has_coalesced := true; cstore.Store.stat_transaction_coalesce <- cstore.Store.stat_transaction_coalesce + 1; true) else ( (* cannot do anything simple, just discard the queries, and the client need to redo it later *) cstore.Store.stat_transaction_abort <- cstore.Store.stat_transaction_abort + 1; false) in let try_commit oldroot cstore store = if oldroot == cstore.Store.root then ( (* move the new root to the current store, if the oldroot has not been modified *) if has_write_ops then ( Store.set_root cstore store.Store.root; Store.set_quota cstore store.Store.quota); true) else (* we try a partial commit if possible *) commit_partial oldroot cstore store in if !test_eagain && Random.int 3 = 0 then false else try_commit oldroot cstore t.store in (* if has_commited && has_write_ops then Disk.write t.store; *) if not has_commited then Logging.conflict ~tid:(get_id t) ~con else if not !has_coalesced then Logging.commit ~tid:(get_id t) ~con; has_commited
sectionYPositions = computeSectionYPositions($el), 10)"
x-init="setTimeout(() => sectionYPositions = computeSectionYPositions($el), 10)"
>