[functional tests] more work on decoding btrees
This commit is contained in:
parent
d0040a169d
commit
5e6ffbbd3a
@ -1,9 +1,20 @@
|
|||||||
(library
|
(library
|
||||||
(binary-format)
|
(binary-format)
|
||||||
(export size-type binary-format le32 le64 bytes)
|
|
||||||
(import (rnrs)
|
(export unpack-type
|
||||||
|
size-type
|
||||||
|
binary-format
|
||||||
|
binary-format-names
|
||||||
|
le32
|
||||||
|
le64
|
||||||
|
bytes)
|
||||||
|
|
||||||
|
(import (chezscheme)
|
||||||
|
(fmt fmt)
|
||||||
(list-utils))
|
(list-utils))
|
||||||
|
|
||||||
|
;;;-----------------------------------------
|
||||||
|
|
||||||
(define-syntax size-type
|
(define-syntax size-type
|
||||||
(syntax-rules (le32 le64 bytes)
|
(syntax-rules (le32 le64 bytes)
|
||||||
((_ le32) 4)
|
((_ le32) 4)
|
||||||
@ -23,23 +34,66 @@
|
|||||||
(bytevector-copy! bv offset copy 0 count)
|
(bytevector-copy! bv offset copy 0 count)
|
||||||
copy))))
|
copy))))
|
||||||
|
|
||||||
(define-syntax binary-format
|
#|
|
||||||
|
(define-syntax ordered-funcall
|
||||||
|
(lambda (form)
|
||||||
|
(let ((form^ (cdr (syntax->list form))))
|
||||||
|
(let ((gens (map (lambda (_) (datum->syntax #'* (gensym "t"))) form^)))
|
||||||
|
#`(let* #,(map list gens form^)
|
||||||
|
#,gens)))))
|
||||||
|
|#
|
||||||
|
|
||||||
|
(define-syntax ordered-funcall
|
||||||
|
(lambda (x)
|
||||||
|
(syntax-case x ()
|
||||||
|
((k f v ...)
|
||||||
|
(with-syntax
|
||||||
|
([(t ...) (map (lambda (_)
|
||||||
|
(datum->syntax #'k (gensym)))
|
||||||
|
#'(v ...))])
|
||||||
|
#'(let* ([t v] ...)
|
||||||
|
(f t ...)))))))
|
||||||
|
|
||||||
|
(define-syntax binary-format-names
|
||||||
(syntax-rules ()
|
(syntax-rules ()
|
||||||
((_ (name pack-name unpack-name) (field type) ...)
|
((_ (name pack-name unpack-name size-name) (field type) ...)
|
||||||
(begin
|
(begin
|
||||||
(define-record-type name (fields field ...))
|
(define-record-type name (fields field ...))
|
||||||
|
|
||||||
(define (unpack-name bv offset)
|
(define size-name
|
||||||
(let ((offset offset))
|
(+ (size-type type) ...))
|
||||||
|
|
||||||
(define (inc-offset n v)
|
(define (unpack-name bv offset)
|
||||||
(set! offset (+ offset n))
|
(let ((offset offset))
|
||||||
v)
|
|
||||||
|
|
||||||
((record-constructor (record-constructor-descriptor name))
|
(define (inc-offset n v)
|
||||||
(inc-offset (size-type type) (unpack-type bv offset type)) ...)))))))
|
(set! offset (+ offset n))
|
||||||
|
v)
|
||||||
|
|
||||||
;;; since le32, le64 and bytes are used as auxiliary keywords, we must export
|
(ordered-funcall
|
||||||
|
(record-constructor (record-constructor-descriptor name))
|
||||||
|
(inc-offset (size-type type) (unpack-type bv offset type)) ...)))))))
|
||||||
|
|
||||||
|
(define-syntax binary-format
|
||||||
|
(lambda (x)
|
||||||
|
;;; FIXME: we don't need multiple args
|
||||||
|
(define (gen-id template-id . args)
|
||||||
|
(datum->syntax template-id
|
||||||
|
(string->symbol
|
||||||
|
(apply string-append
|
||||||
|
(map (lambda (x)
|
||||||
|
(if (string? x)
|
||||||
|
x
|
||||||
|
(symbol->string (syntax->datum x))))
|
||||||
|
args)))))
|
||||||
|
(syntax-case x ()
|
||||||
|
((_ name field ...)
|
||||||
|
(with-syntax ((pack-name (gen-id #'name #'name "-pack"))
|
||||||
|
(unpack-name (gen-id #'name #'name "-unpack"))
|
||||||
|
(size-name (gen-id #'name #'name "-size")))
|
||||||
|
#'(binary-format-names (name pack-name unpack-name size-name) field ...))))))
|
||||||
|
|
||||||
|
;;; Since le32, le64 and bytes are used as auxiliary keywords, we must export
|
||||||
;;; definitions of them as well.
|
;;; definitions of them as well.
|
||||||
;;; FIXME: use a macro to remove duplication
|
;;; FIXME: use a macro to remove duplication
|
||||||
(define-syntax le32
|
(define-syntax le32
|
||||||
|
@ -1,7 +1,10 @@
|
|||||||
(library
|
(library
|
||||||
(btree)
|
(btree)
|
||||||
|
|
||||||
(export btree-open
|
(export btree-value-type
|
||||||
|
btree-dev
|
||||||
|
btree-root
|
||||||
|
btree-open
|
||||||
btree-lookup
|
btree-lookup
|
||||||
btree-each
|
btree-each
|
||||||
le64-type)
|
le64-type)
|
||||||
@ -13,9 +16,7 @@
|
|||||||
|
|
||||||
;;; Unlike the kernel or c++ versions, I'm going to leave it to the hiogher
|
;;; Unlike the kernel or c++ versions, I'm going to leave it to the hiogher
|
||||||
;;; levels to handle multi level btrees.
|
;;; levels to handle multi level btrees.
|
||||||
(binary-format
|
(binary-format node-header
|
||||||
(node-header pack-btree-node unpack-btree-node)
|
|
||||||
|
|
||||||
(csum le32)
|
(csum le32)
|
||||||
(flags le32)
|
(flags le32)
|
||||||
(blocknr le64)
|
(blocknr le64)
|
||||||
@ -24,33 +25,34 @@
|
|||||||
(value-size le32)
|
(value-size le32)
|
||||||
(padding le32))
|
(padding le32))
|
||||||
|
|
||||||
|
;;; (unpacker bv offset)
|
||||||
(define-record-type value-type (fields size unpacker))
|
(define-record-type value-type (fields size unpacker))
|
||||||
|
|
||||||
(define (max-entries vt)
|
(define (max-entries vt)
|
||||||
(/ (- metadata-block-size node-header-size)
|
(/ (- metadata-block-size node-header-size)
|
||||||
(+ (size-of 'le64)
|
(+ (size-type le64)
|
||||||
(value-type-size vt))))
|
(value-type-size vt))))
|
||||||
|
|
||||||
(define (key-offset index)
|
(define (key-offset index)
|
||||||
(+ node-header-size (* (size-of 'le64 index))))
|
(+ node-header-size (* (size-type le64) index)))
|
||||||
|
|
||||||
(define (value-base vt)
|
(define (value-base header)
|
||||||
(+ node-header-size
|
(+ node-header-size
|
||||||
(* (max-entries vt)
|
(* (node-header-max-entries header)
|
||||||
(size-of 'le64))))
|
(size-type le64))))
|
||||||
|
|
||||||
(define (value-offset vt index)
|
(define (value-offset header vt index)
|
||||||
(+ (value-base vt)
|
(+ (value-base header)
|
||||||
(* (value-type-size vt) index)))
|
(* (value-type-size vt) index)))
|
||||||
|
|
||||||
(define-record-type btree
|
(define-record-type btree
|
||||||
(fields value-type dev root))
|
(fields value-type dev root))
|
||||||
|
|
||||||
(define (btree-open vt dev root)
|
(define (btree-open vt dev root)
|
||||||
(make-btree value-type dev root))
|
(make-btree vt dev root))
|
||||||
|
|
||||||
(define le64-type
|
(define le64-type
|
||||||
(make-value-type (size-of 'le64)
|
(make-value-type (size-type le64)
|
||||||
(lambda (bv offset)
|
(lambda (bv offset)
|
||||||
(unpack-type bv offset le64))))
|
(unpack-type bv offset le64))))
|
||||||
|
|
||||||
@ -61,10 +63,10 @@
|
|||||||
(bitwise-bit-set? 1 (node-header-flags header)))
|
(bitwise-bit-set? 1 (node-header-flags header)))
|
||||||
|
|
||||||
(define (key-at node index)
|
(define (key-at node index)
|
||||||
(unpack-type node (key-offset index le64)))
|
(unpack-type node (key-offset index) le64))
|
||||||
|
|
||||||
(define (value-at node index vt)
|
(define (value-at header node index vt)
|
||||||
((value-type-unpacker vt) node (value-offset vt index)))
|
((value-type-unpacker vt) node (value-offset header vt index)))
|
||||||
|
|
||||||
;;; Performs a binary search looking for the key and returns the index of the
|
;;; Performs a binary search looking for the key and returns the index of the
|
||||||
;;; lower bound.
|
;;; lower bound.
|
||||||
@ -90,12 +92,12 @@
|
|||||||
(define (lookup root fail-k)
|
(define (lookup root fail-k)
|
||||||
(let loop ((root root))
|
(let loop ((root root))
|
||||||
(let* ((node (read-block dev root))
|
(let* ((node (read-block dev root))
|
||||||
(header (unpack-node-header node 0))
|
(header (node-header-unpack node 0))
|
||||||
(index (lower-bound node header key fail-k)))
|
(index (lower-bound node header key)))
|
||||||
(if (internal-node? header)
|
(if (internal-node? header)
|
||||||
(loop (unpack-value node index le64-type))
|
(loop (value-at header node index le64-type))
|
||||||
(if (= key (key-at node index))
|
(if (= key (key-at node index))
|
||||||
(value-at node index vt)
|
(value-at header node index vt)
|
||||||
(fail-k default))))))
|
(fail-k default))))))
|
||||||
|
|
||||||
(call/cc
|
(call/cc
|
||||||
@ -113,26 +115,19 @@
|
|||||||
(define (visit-leaf node header)
|
(define (visit-leaf node header)
|
||||||
(let loop ((index 0))
|
(let loop ((index 0))
|
||||||
(when (< index (node-header-nr-entries header))
|
(when (< index (node-header-nr-entries header))
|
||||||
(fn (key-at node index) (value-at node index vt))
|
(fn (key-at node index) (value-at header node index vt))
|
||||||
(loop (+ 1 index)))))
|
(loop (+ 1 index)))))
|
||||||
|
|
||||||
(define (visit-internal node header)
|
(define (visit-internal node header)
|
||||||
(let loop ((index 0))
|
(let loop ((index 0))
|
||||||
(when (< index (node-header-nr-entries header))
|
(when (< index (node-header-nr-entries header))
|
||||||
(visit-node (value-at node index le64-type))
|
(visit-node (value-at header node index le64-type))
|
||||||
(loop (+ 1 index)))))
|
(loop (+ 1 index)))))
|
||||||
|
|
||||||
(define (visit-node root)
|
(define (visit-node root)
|
||||||
(let* ((node (read-block root))
|
(let* ((node (read-block (btree-dev tree) root))
|
||||||
(header (unpack-node-header node 0)))
|
(header (node-header-unpack node 0)))
|
||||||
((if (internal-node? header) visit-internal visit-leaf) node header)))
|
((if (internal-node? header) visit-internal visit-leaf) node header)))
|
||||||
|
|
||||||
(visit-node (btree-root tree)))
|
(visit-node (btree-root tree)))))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
))
|
|
||||||
|
@ -1,8 +1,10 @@
|
|||||||
(import
|
(import
|
||||||
(binary-format)
|
(binary-format)
|
||||||
(block-io)
|
(block-io)
|
||||||
|
(btree)
|
||||||
(fmt fmt)
|
(fmt fmt)
|
||||||
(matchable)
|
(matchable)
|
||||||
|
(mapping-tree)
|
||||||
(rnrs))
|
(rnrs))
|
||||||
|
|
||||||
;;;;---------------------------------------------------
|
;;;;---------------------------------------------------
|
||||||
@ -17,18 +19,18 @@
|
|||||||
(define $uuid-size 16)
|
(define $uuid-size 16)
|
||||||
(define $space-map-root-size 128)
|
(define $space-map-root-size 128)
|
||||||
|
|
||||||
(binary-format (superblock pack-superblock unpack-superblock)
|
(binary-format superblock
|
||||||
(csum le32)
|
(csum le32)
|
||||||
(flags le32)
|
(flags le32)
|
||||||
(block-nr le64)
|
(block-nr le64)
|
||||||
(uuid (bytes 16))
|
(uuid (bytes $uuid-size))
|
||||||
(magic le64)
|
(magic le64)
|
||||||
(version le32)
|
(version le32)
|
||||||
(time le32)
|
(time le32)
|
||||||
(trans-id le64)
|
(trans-id le64)
|
||||||
(metadata-snap le64)
|
(metadata-snap le64)
|
||||||
(data-space-map-root (bytes 128))
|
(data-space-map-root (bytes $space-map-root-size))
|
||||||
(metadata-space-map-root (bytes 128))
|
(metadata-space-map-root (bytes $space-map-root-size))
|
||||||
(data-mapping-root le64)
|
(data-mapping-root le64)
|
||||||
(device-details-root le64)
|
(device-details-root le64)
|
||||||
(data-block-size le32)
|
(data-block-size le32)
|
||||||
@ -49,7 +51,34 @@
|
|||||||
|
|
||||||
(define (read-superblock)
|
(define (read-superblock)
|
||||||
(with-metadata (md (current-metadata))
|
(with-metadata (md (current-metadata))
|
||||||
(unpack-superblock (read-block md 0) 0)))
|
(superblock-unpack (read-block md 0) 0)))
|
||||||
|
|
||||||
|
(define (dump-dev-tree)
|
||||||
|
(with-metadata (md (current-metadata))
|
||||||
|
(let ((sb (superblock-unpack (read-block md 0) 0)))
|
||||||
|
(btree-each (btree-open le64-type md (superblock-data-mapping-root sb))
|
||||||
|
(lambda (k v)
|
||||||
|
(fmt #t (dsp "dev-id: ") (num k)
|
||||||
|
(dsp ", mapping root: ") (num v) nl))))))
|
||||||
|
|
||||||
|
(define (dump-mappings root)
|
||||||
|
(with-metadata (md (current-metadata))
|
||||||
|
(btree-each (btree-open le64-type md root)
|
||||||
|
(lambda (k v)
|
||||||
|
(fmt #t (dsp "vblock: ") (num k)
|
||||||
|
(dsp ", pblock: ") (num v) nl)))))
|
||||||
|
|
||||||
|
(define (dump-all-mappings)
|
||||||
|
(with-metadata (md (current-metadata))
|
||||||
|
(let ((sb (superblock-unpack (read-block md 0) 0)))
|
||||||
|
(let ((mappings (mapping-tree-open md (superblock-data-mapping-root sb))))
|
||||||
|
(mapping-tree-each mappings
|
||||||
|
(lambda (dev-id vblock pblock)
|
||||||
|
(fmt #t
|
||||||
|
(dsp "thin dev ") (num dev-id)
|
||||||
|
(dsp ", vblock ") (num vblock)
|
||||||
|
(dsp ", pblock ") (num pblock)
|
||||||
|
nl)))))))
|
||||||
|
|
||||||
(define (check-superblock)
|
(define (check-superblock)
|
||||||
(with-metadata (md (current-metadata))
|
(with-metadata (md (current-metadata))
|
||||||
|
34
functional-tests/mapping-tree.scm
Normal file
34
functional-tests/mapping-tree.scm
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
(library
|
||||||
|
(mapping-tree)
|
||||||
|
|
||||||
|
(export mapping-tree-open
|
||||||
|
mapping-tree-lookup
|
||||||
|
mapping-tree-each)
|
||||||
|
|
||||||
|
(import (btree)
|
||||||
|
(chezscheme)
|
||||||
|
(binary-format))
|
||||||
|
|
||||||
|
(define-record-type mapping-tree (fields dev-tree))
|
||||||
|
|
||||||
|
(define (mapping-tree-open dev root)
|
||||||
|
(make-mapping-tree (btree-open le64-type dev root)))
|
||||||
|
|
||||||
|
(define (mapping-tree-lookup mtree dev-id vblock default)
|
||||||
|
(let* ((unique (gensym))
|
||||||
|
(dev-tree (mapping-tree-dev-tree mtree))
|
||||||
|
(root2 (btree-lookup dev-tree dev-id unique)))
|
||||||
|
(if (eq? unique root2)
|
||||||
|
default
|
||||||
|
(btree-lookup (btree-open le64-type (btree-dev dev-tree) root2) vblock default))))
|
||||||
|
|
||||||
|
;;; Visits every entry in the mapping tree calling (fn dev-id vblock mapping).
|
||||||
|
(define (mapping-tree-each mtree fn)
|
||||||
|
(let ((dev-tree (mapping-tree-dev-tree mtree)))
|
||||||
|
|
||||||
|
(define (visit-dev dev-id mapping-root)
|
||||||
|
(btree-each (btree-open le64-type (btree-dev dev-tree) mapping-root)
|
||||||
|
(lambda (vblock mapping)
|
||||||
|
(fn dev-id vblock mapping))))
|
||||||
|
|
||||||
|
(btree-each dev-tree visit-dev))))
|
Loading…
Reference in New Issue
Block a user