-// Close closes the files of the tree.
-func (t *Tree) Close() error {
- err := t.journal.Close()
- if t.order != nil {
- err = errors.Join(err, t.order.Close())
- t.order = nil
- }
-
- for level, index := range t.levels {
- err = errors.Join(err, index.Close())
-
- delete(t.levels, level)
- }
-
- return err
-}
-
-// Add writes a new node to the tree.
-func (t *Tree) Add(node Node) error {
- if t.failure != nil {
- return fmt.Errorf("tree needs a reopen after a failed write: %w", t.failure)
- }
-
- err := t.check(node)
- if err != nil {
- return err
- }
-
- line, err := json.Marshal(node)
- if err != nil {
- return fmt.Errorf("encode node: %w", err)
- }
-
- place, err := t.journal.Write(t.clock().Format(time.DateOnly), append(line, '\n'))
- if err == nil {
- err = t.addIndex(NodeKey{node.Level, node.Index}, place)
- }
-
- if err != nil {
- t.failure = err
- return fmt.Errorf("write node (%d, %d): %w", node.Level, node.Index, err)
- }
-
- return nil
-}
-
-// Built tells if the node (l, i) is built.
-func (t *Tree) Built(level, index int) (bool, error) {
- _, built, err := t.place(level, index)
- return built, err
-}
-
-// Node reads the node (l, i) if it is built.
-func (t *Tree) Node(level, index int) (Node, bool, error) {
- place, built, err := t.place(level, index)
- if err != nil || !built {
- return Node{}, false, err
- }
-
- line, err := t.journal.Read(place)
- if err != nil {
- return Node{}, false, fmt.Errorf("read node (%d, %d): %w", level, index, err)
- }
-
- var node Node
-
- err = json.Unmarshal(line, &node)
- if err != nil {
- return Node{}, false, fmt.Errorf("decode node (%d, %d): %w", level, index, err)
- }
-
- if node.Level != level || node.Index != index {
- return Node{}, false, fmt.Errorf("index of node (%d, %d) points to node (%d, %d)", level, index, node.Level, node.Index)
- }
-
- return node, true, nil
-}
-
-// Keys returns the keys of the built nodes, ordered by level and then by index.
-func (t *Tree) Keys() ([]NodeKey, error) {
- keys := make([]NodeKey, 0, t.order.count)
- for n := range t.order.count {
- record, _, err := t.order.Read(n)
- if err != nil {
- return nil, err
- }
-
- key, _ := treeDecodeRecord(record)
- keys = append(keys, key)
- }
-
- slices.SortFunc(keys, func(a, b NodeKey) int {
- return cmp.Or(cmp.Compare(a.level, b.level), cmp.Compare(a.index, b.index))
- })
-
- return keys, nil
-}
-