let maxwatch = ref (50)
let maxtransaction = ref (20)
+let maxrequests = ref (-1) (* maximum requests per transaction *)
let domid_self = 0x7FF0
quota-maxsize = 2048
quota-maxwatch = 100
quota-transaction = 10
+quota-maxrequests = 1024
# Activate filed base backend
persistent = false
if not success then
raise Transaction_again;
if commit then
- process_watch (List.rev (Transaction.get_ops t)) cons
+ process_watch (List.rev (Transaction.get_paths t)) cons
let do_introduce con t domains cons data =
if not (Connection.is_dom0 con)
fct con t doms cons data;
Packet.Ack (fun () ->
if Transaction.get_id t = Transaction.none then
- process_watch (Transaction.get_ops t) cons
+ process_watch (Transaction.get_paths t) cons
)
let reply_data fct con t doms cons data =
in
let response = input_handle_error ~cons ~doms ~fct ~con ~t ~req in
+ let response = try
+ if tid <> Transaction.none then
+ (* Remember the request and response for this operation in case we need to replay the transaction *)
+ Transaction.add_operation ~perm:(Connection.get_perm con) t req response;
+ response
+ with Quota.Limit_reached ->
+ Packet.Error "EQUOTA"
+ in
+
(* Put the response on the wire *)
send_response ty con t rid response
with exn ->
ty: ty;
store: Store.t;
quota: Quota.t;
- mutable ops: (Xenbus.Xb.Op.operation * Store.Path.t) list;
+ mutable paths: (Xenbus.Xb.Op.operation * Store.Path.t) list;
+ mutable operations: (Packet.request * Packet.response) list;
mutable read_lowpath: Store.Path.t option;
mutable write_lowpath: Store.Path.t option;
}
ty = ty;
store = if id = none then store else Store.copy store;
quota = Quota.copy store.Store.quota;
- ops = [];
+ 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_ops t = t.ops
-
-let add_wop t ty path = t.ops <- (ty, path) :: t.ops
+let get_paths t = t.paths
+
+let add_wop t ty path = t.paths <- (ty, path) :: t.paths
+let add_operation ~perm t request response =
+ if !Define.maxrequests >= 0
+ && not (Perms.Connection.is_dom0 perm)
+ && List.length t.operations >= !Define.maxrequests
+ then raise Quota.Limit_reached;
+ 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
r
let commit ~con t =
- let has_write_ops = List.length t.ops > 0 in
+ let has_write_ops = List.length t.paths > 0 in
let has_coalesced = ref false in
let has_commited =
match t.ty with
("quota-transaction", Config.Set_int Define.maxtransaction);
("quota-maxentity", Config.Set_int Quota.maxent);
("quota-maxsize", Config.Set_int Quota.maxsize);
+ ("quota-maxrequests", Config.Set_int Define.maxrequests);
("test-eagain", Config.Set_bool Transaction.test_eagain);
("persistent", Config.Set_bool Disk.enable);
("xenstored-log-file", Config.String Logging.set_xenstored_log_destination);