Module Tjr_plist.Plist_intf

Plist main types

The main plist types come in three groups:

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

type 'a or_error = ('a, unit) Stdlib.result
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; >; >