summaryrefslogtreecommitdiffstats
path: root/src/crimson/os/seastore/onode_manager/staged-fltree/tree.h
blob: 7ee618cb3ff5b748b8ac1fb3598e11c3855696c9 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:nil -*-
// vim: ts=8 sw=2 smarttab

#pragma once

#include <ostream>

#include "common/hobject.h"
#include "crimson/common/type_helpers.h"

#include "fwd.h"
#include "tree_types.h"

/**
 * tree.h
 *
 * An example implementation to expose tree interfaces to users. The current
 * interface design is based on:
 * - ceph::os::Transaction::create/touch/remove()
 * - ceph::ObjectStore::collection_list()
 * - ceph::BlueStore::get_onode()
 * - db->get_iterator(PREFIIX_OBJ) by ceph::BlueStore::fsck()
 *
 * TODO: Redesign the interfaces based on real onode manager requirements.
 */

namespace crimson::os::seastore::onode {

class Node;
class Btree {
 public:
  using btree_ertr = crimson::errorator<
    crimson::ct_error::input_output_error,
    crimson::ct_error::invarg,
    crimson::ct_error::enoent,
    crimson::ct_error::erange>;
  template <class ValueT=void>
  using btree_future = btree_ertr::future<ValueT>;

  Btree(NodeExtentManagerURef&& nm);
  Btree(const Btree&) = delete;
  Btree(Btree&&) = delete;
  Btree& operator=(const Btree&) = delete;
  Btree& operator=(Btree&&) = delete;
  ~Btree();

  btree_future<> mkfs(Transaction&);

  class Cursor;
  // lookup
  btree_future<Cursor> begin(Transaction&);
  btree_future<Cursor> last(Transaction&);
  Cursor end();
  btree_future<bool> contains(Transaction&, const ghobject_t&);
  btree_future<Cursor> find(Transaction&, const ghobject_t&);
  btree_future<Cursor> lower_bound(Transaction&, const ghobject_t&);

  // modifiers
  // TODO: replace onode_t
  btree_future<std::pair<Cursor, bool>>
  insert(Transaction&, const ghobject_t&, const onode_t&);
  btree_future<size_t> erase(Transaction&, const ghobject_t& key);
  btree_future<Cursor> erase(Cursor& pos);
  btree_future<Cursor> erase(Cursor& first, Cursor& last);

  // stats
  btree_future<size_t> height(Transaction&);
  btree_future<tree_stats_t> get_stats_slow(Transaction&);
  std::ostream& dump(Transaction&, std::ostream&);
  std::ostream& print(std::ostream& os) const;

  // test_only
  bool test_is_clean() const;
  btree_future<> test_clone_from(Transaction& t, Transaction& t_from, Btree& from);

 private:
  context_t get_context(Transaction& t) { return {*nm, t}; }
  btree_future<Ref<Node>> get_root(Transaction& t);

  NodeExtentManagerURef nm;
  RootNodeTrackerURef root_tracker;

  friend class DummyChildPool;
};
inline std::ostream& operator<<(std::ostream& os, const Btree& tree) {
  return tree.print(os);
}

class tree_cursor_t;
class Btree::Cursor {
 public:
  Cursor(const Cursor&);
  Cursor(Cursor&&) noexcept;
  Cursor& operator=(const Cursor&);
  Cursor& operator=(Cursor&&);
  ~Cursor();

  bool is_end() const;
  // XXX: return key_view_t to avoid unecessary ghobject_t constructions
  ghobject_t get_ghobj() const;
  const onode_t* value() const;
  bool operator==(const Cursor& x) const;
  bool operator!=(const Cursor& x) const { return !(*this == x); }
  Cursor& operator++();
  Cursor operator++(int);

 private:
  Cursor(Btree*, Ref<tree_cursor_t>);
  Cursor(Btree*);

  static Cursor make_end(Btree*);

  Btree* p_tree;
  Ref<tree_cursor_t> p_cursor;

  friend class Btree;
};

}