Module Tjr_plist.Plist_intf
Plist main types
The main plist types come in three groups:
plist_marshal_ops
, which becomes available with justplist_marshal_info
(and blk and buf ops)plist_extra_ops
, for operating on an on-disk plist; available withblk_dev_ops
plist_ops
, available once we decide how to store the plist state (via thewith_state
parameter)
type ('blk_id, 'buf) plist
=
{
hd : 'blk_id;
tl : 'blk_id;
buffer : 'buf;
off : int;
blk_len : int;
tl_dirty : bool;
tl may not have been written to disk
}
This is an internal implementation type. NOTE modifications take place in the tl block
NOTE we expect that the nxt pointer is set only for add, adv_tl, append
NOTE that the buffer contains the marshalled elts, but not necessarily the end-of-list marker
FIXME? including blk_len makes things a bit trickier since we have to store this in the root blk
module Pl_origin : sig ... end
This type is the standard information we need to persist in order to quickly restore the plist; we can also just follow the list from the hd block of course, but this is O(n).
type ('a, 'blk_id, 'blk) plist_marshal_ops
=
{
unmarshal : 'blk -> 'a list * 'blk_id option;
marshal : ('a list * 'blk_id option) -> 'blk;
}
Internal operations, for debugging FIXME this is just ('a list * blk_id,'blk) mshlr
type ('a, 'blk_id) adv_hd
=
{
old_hd : 'blk_id;
old_elts : 'a list;
new_hd : 'blk_id;
}
Information from the "advance head" operation
module Plist_ops : sig ... end
include Plist_ops
type ('a, 'buf, 'blk_id, 't) plist_ops
=
{
add : nxt:'blk_id -> elt:'a -> ('blk_id option, 't) Tjr_monad.m;
add_if_room : 'a -> (bool, 't) Tjr_monad.m;
sync_tl : unit -> (unit, 't) Tjr_monad.m;
adv_hd : unit -> (('a, 'blk_id) adv_hd or_error, 't) Tjr_monad.m;
adv_tl : 'blk_id -> (unit, 't) Tjr_monad.m;
blk_len : unit -> (int, 't) Tjr_monad.m;
get_origin : unit -> ('blk_id Pl_origin.pl_origin, 't) Tjr_monad.m;
read_hd : unit -> ('a list * 'blk_id option, 't) Tjr_monad.m;
append : ('blk_id, 'buf) plist -> (unit, 't) Tjr_monad.m;
}
plist operations which require the plist state from the monad
- add : The blk_id is returned if it is not used; another variant assumes an alloc function. We don't assume the nxt_blk is clean - we may write a single elt into the new blk then barrier, before updating the nxt pointer.
- add_if_room: returns a boolean to indicate if the element was added in the current tl
- sync : we automatically barrier before moving to a new tl (FIXME check); this is for partial blocks which we need to sync (eg for clean shutdown)
- adv_hd: return an error if no nxt pointer (iff blk_len = 1 iff hd=tl)
- adv_tl: write new empty tl, update old tl, and advance tl to new
- read_hd: assumes hd has been marshalled to disk; this likely won't be the case if hd=tl FIXME perhaps keep hd in mem? why do we need this?
- append: take a second plist, and adjust the "current" plist so that the hd is unchanged, but the tl points to the tl of the second plist (and the buf and offset etc are copied); an assumption is that the second plist is never used from this point onwards. FIXME clearly we need to remove the pl2 from the global state, or else we have a space leak
module Plist_marshal_info : sig ... end
include Plist_marshal_info
type ('a, 'blk_id, 'blk, 'buf) plist_marshal_info
=
{
elt_mshlr : ('a option, 'buf) Tjr_fs_shared.mshlr;
blk_id_mshlr : ('blk_id option, 'buf) Tjr_fs_shared.mshlr;
}
We write an elt e as "marshal(Some e)" and the end-of-list marker as "marshal(None)"
- max_elt_sz: max size of a marshalled elt option
- max_blk_id_sz: max size of a marshalled blk_id option
type ('a, 'blk_id, 'blk, 'buf, 't) plist_factory
= < monad_ops : 't Tjr_monad.monad_ops; buf_ops : 'buf Tjr_fs_shared.buf_ops; blk_ops : ('blk, 'buf) Tjr_fs_shared.blk_ops; plist_marshal_info : ('a, 'blk_id, 'blk, 'buf) plist_marshal_info; plist_marshal_ops : ('a, 'blk_id, 'blk) plist_marshal_ops; with_blk_dev_ops : blk_dev_ops:('blk_id, 'blk, 't) Tjr_fs_shared.blk_dev_ops -> barrier:(unit -> (unit, 't) Tjr_monad.m) -> < init : < create : 'blk_id -> (('blk_id, 'buf) plist, 't) Tjr_monad.m; read_from_hd : 'blk_id -> (('a list * 'blk_id option) list, 't) Tjr_monad.m; from_endpts : 'blk_id Pl_origin.pl_origin -> (('blk_id, 'buf) plist, 't) Tjr_monad.m; >; with_state : (('blk_id, 'buf) plist, 't) Tjr_monad.with_state -> ('a, 'buf, 'blk_id, 't) plist_ops; with_ref : ('blk_id, 'buf) plist -> < plist_ref : ('blk_id, 'buf) plist Stdlib.ref; with_plist : (('blk_id, 'buf) plist, 't) Tjr_monad.with_state; >; add_origin : < set_and_sync : 'blk_id Pl_origin.pl_origin -> (unit, 't) Tjr_monad.m; > -> ('a, 'buf, 'blk_id, 't) plist_ops -> ('a, 'buf, 'blk_id, 't) plist_ops; create : 'blk_id -> (< plist_ref : ('blk_id, 'buf) plist Stdlib.ref; with_plist : (('blk_id, 'buf) plist, 't) Tjr_monad.with_state; plist_ops : ('a, 'buf, 'blk_id, 't) plist_ops; >, 't) Tjr_monad.m; restore : 'blk_id Pl_origin.t -> (< plist_ref : ('blk_id, 'buf) plist Stdlib.ref; with_plist : (('blk_id, 'buf) plist, 't) Tjr_monad.with_state; plist_ops : ('a, 'buf, 'blk_id, 't) plist_ops; >, 't) Tjr_monad.m; >; >
type ('blk_id, 't) freelist_ops_af
= ('blk_id, 't) Tjr_fs_shared.blk_allocator_ops
=
{
blk_alloc : unit -> ('blk_id, 't) Tjr_monad.m;
blk_free : 'blk_id -> (unit, 't) Tjr_monad.m;
}
module Simple_plist_ops : sig ... end
include Simple_plist_ops
type ('a, 'blk_id, 't) simple_plist_ops
=
{
add : 'a -> (bool, 't) Tjr_monad.m;
Return value indicates whether we moved to a new block
sync_tl : unit -> (unit, 't) Tjr_monad.m;
blk_len : unit -> (int, 't) Tjr_monad.m;
get_origin : unit -> ('blk_id Pl_origin.pl_origin, 't) Tjr_monad.m;
}
type ('a, 'blk_id, 'blk, 'buf, 't) simple_plist_factory
= < plist_factory : ('a, 'blk_id, 'blk, 'buf, 't) plist_factory; convert_to_simple_plist : freelist_ops:('blk_id, 't) freelist_ops_af -> plist_ops:('a, 'buf, 'blk_id, 't) plist_ops -> ('a, 'blk_id, 't) simple_plist_ops; with_ : blk_dev_ops:('blk_id, 'blk, 't) Tjr_fs_shared.blk_dev_ops -> barrier:(unit -> (unit, 't) Tjr_monad.m) -> freelist_ops:('blk_id, 't) freelist_ops_af -> < create : 'blk_id -> (< plist_ref : ('blk_id, 'buf) plist Stdlib.ref; with_plist : (('blk_id, 'buf) plist, 't) Tjr_monad.with_state; plist_ops : ('a, 'buf, 'blk_id, 't) plist_ops; simple_plist_ops : ('a, 'blk_id, 't) simple_plist_ops; >, 't) Tjr_monad.m; restore : 'blk_id Pl_origin.t -> (< plist_ref : ('blk_id, 'buf) plist Stdlib.ref; with_plist : (('blk_id, 'buf) plist, 't) Tjr_monad.with_state; plist_ops : ('a, 'buf, 'blk_id, 't) plist_ops; simple_plist_ops : ('a, 'blk_id, 't) simple_plist_ops; >, 't) Tjr_monad.m; >; >