Module Tjr_plist

A persistent (on-disk) list. The freelist based on this is concurrent-safe (multiple writers are allowed, but only a single thread interacts with disk), but this code is not.

NOTE the freelist code has moved to the imp_fs repo.

Look at Plist_intf for the main types.

A persistent list is an on-disk list, where elements can be added at the tail. The "origin block" stores the hd blkid, the tl blkid and the length of the list. From this, the in-memory state of the list can be reconstructed after a system crash. The hd is expected not to change (much). The tl may change (as new elts get added and the tl block gets full, the tl advances) but since we can follow links from the hd (or the old tl) we don't have to modify the origin block when the tl changes. Thus, we can add elements to the end of the list, and make the changes persistent with a single sync.

We also have an additional operation of "adv_hd", which moves the hd pointer to the next blk. This does require an update to the origin block before the new hd is made visible to the rest of the system.

The adv_hd operation is used by the freelist. For the freelist, each block on disk stores a list of (free) blkids. To avoid repeated disk access, free blkids are typically transferred to memory as a batch using a single blk read (via the adv_hd operation). Sync behaviour: There are at least 2 choices (in addition to respecting explicit syncs):

The current implementation syncs when moving to a new tail, not on every add. Thus, some elements that have been added, but not synced, may be lost on a system crash. If needed, you can avoid this by explicitly syncing after each add (with the commensurate loss of performance). The sequence of operations is:

include Tjr_plist__.Summary
module Plist_intf : sig ... end

Plist main types

module Pl_origin = Plist_intf.Pl_origin
module Plist_ops = Plist_intf.Plist_ops
type ('a, 'buf, 'blk_id, 't) plist_ops = ('a'buf'blk_id't) Plist_intf.plist_ops
type ('a, 'blk_id, 'blk, 'buf, 't) plist_factory = ('a'blk_id'blk'buf't) Plist_intf.plist_factory
type ('blk_id, 't) freelist_ops_af = ('blk_id't) Plist_intf.freelist_ops_af
type ('a, 'blk_id, 'blk, 'buf, 't) simple_plist_factory = ('a'blk_id'blk'buf't) Plist_intf.simple_plist_factory
module Simple_plist_ops = Plist_intf.Simple_plist_ops
type ('a, 'blk_id, 't) simple_plist_ops = ('a'blk_id't) Plist_intf.simple_plist_ops
module Make_1 : sig ... end

Construct a persistent list (most generic version, not concurrent-safe).

val pl_examples : < for_blk_id : Tjr_fs_shared.Shared_ctxt.r Pl_type_abbrevs.plist_factory; for_int : int Pl_type_abbrevs.plist_factory; for_int_int_kvop : (int, int) Tjr_fs_shared.kvop Pl_type_abbrevs.plist_factory; >
module Make_simple_plist = Tjr_plist__.Make_2
val simple_pl_examples : < for_int : (int, Pl_type_abbrevs.blk_id, Pl_type_abbrevs.blk, Tjr_fs_shared.ba_buf, Tjr_monad.With_lwt.lwt) Plist_intf.simple_plist_factory; for_int_int_kvop : ((int, int) Tjr_fs_shared.kvopPl_type_abbrevs.blk_id, Pl_type_abbrevs.blk, Tjr_fs_shared.ba_buf, Tjr_monad.With_lwt.lwt) Plist_intf.simple_plist_factory; >