summaryrefslogtreecommitdiffstats
path: root/src/crimson/os/seastore/extentmap_manager/btree/extentmap_btree_node.h
blob: 3937bd049c9a1fd7bd123c987b7ea2b5ce5bf139 (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
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
// vim: ts=8 sw=2 smarttab


#pragma once

#include <boost/iterator/counting_iterator.hpp>

#include "crimson/common/log.h"
#include "crimson/os/seastore/seastore_types.h"
#include "crimson/os/seastore/transaction_manager.h"
#include "crimson/os/seastore/extentmap_manager.h"

namespace crimson::os::seastore::extentmap_manager{

struct ext_context_t {
  TransactionManager &tm;
  Transaction &t;
};

struct extmap_node_meta_t {
  depth_t depth = 0;

  std::pair<extmap_node_meta_t, extmap_node_meta_t> split_into(objaddr_t pivot) const {
    return std::make_pair(
           extmap_node_meta_t{depth},
           extmap_node_meta_t{depth});
  }

  static extmap_node_meta_t merge_from(
    const extmap_node_meta_t &lhs, const extmap_node_meta_t &rhs) {
    assert(lhs.depth == rhs.depth);
    return extmap_node_meta_t{lhs.depth};
  }

  static std::pair<extmap_node_meta_t, extmap_node_meta_t>
  rebalance(const extmap_node_meta_t &lhs, const extmap_node_meta_t &rhs, laddr_t pivot) {
    assert(lhs.depth == rhs.depth);
    return std::make_pair(
           extmap_node_meta_t{lhs.depth},
           extmap_node_meta_t{lhs.depth});
  }
};

struct ExtMapNode : LogicalCachedExtent {
  using ExtMapNodeRef = TCachedExtentRef<ExtMapNode>;

  ExtMapNode(ceph::bufferptr &&ptr) : LogicalCachedExtent(std::move(ptr)) {}
  ExtMapNode(const ExtMapNode &other)
  : LogicalCachedExtent(other) {}

  using find_lextent_ertr = ExtentMapManager::find_lextent_ertr;
  using find_lextent_ret = ExtentMapManager::find_lextent_ret;
  virtual find_lextent_ret find_lextent(ext_context_t ec,
		                        objaddr_t lo, extent_len_t len) = 0;

  using insert_ertr = TransactionManager::read_extent_ertr;
  using insert_ret = insert_ertr::future<extent_mapping_t>;
  virtual insert_ret insert(ext_context_t ec, objaddr_t lo, lext_map_val_t val) = 0;

  using rm_lextent_ertr = TransactionManager::read_extent_ertr;
  using rm_lextent_ret = rm_lextent_ertr::future<bool>;
  virtual rm_lextent_ret rm_lextent(ext_context_t ec, objaddr_t lo, lext_map_val_t val) = 0;

  using split_children_ertr = TransactionManager::alloc_extent_ertr;
  using split_children_ret = split_children_ertr::future
 	                           <std::tuple<ExtMapNodeRef, ExtMapNodeRef, uint32_t>>;
  virtual split_children_ret make_split_children(ext_context_t ec) = 0;

  using full_merge_ertr = TransactionManager::alloc_extent_ertr;
  using full_merge_ret = full_merge_ertr::future<ExtMapNodeRef>;
  virtual full_merge_ret make_full_merge(ext_context_t ec, ExtMapNodeRef right) = 0;

  using make_balanced_ertr = TransactionManager::alloc_extent_ertr;
  using make_balanced_ret = make_balanced_ertr::future
	                           <std::tuple<ExtMapNodeRef, ExtMapNodeRef, uint32_t>>;
  virtual make_balanced_ret
    make_balanced(ext_context_t ec, ExtMapNodeRef right, bool prefer_left) = 0;

  virtual extmap_node_meta_t get_node_meta() const = 0;

  virtual bool at_max_capacity() const = 0;
  virtual bool at_min_capacity() const = 0;
  virtual unsigned get_node_size() const = 0;
  virtual ~ExtMapNode() = default;

  using alloc_ertr = TransactionManager::alloc_extent_ertr;
  template<class T>
  alloc_ertr::future<TCachedExtentRef<T>>
  extmap_alloc_extent(ext_context_t ec, extent_len_t len) {
    return ec.tm.alloc_extent<T>(ec.t, L_ADDR_MIN, len).safe_then(
      [](auto&& extent) {
      return alloc_ertr::make_ready_future<TCachedExtentRef<T>>(std::move(extent));
    });
  }

  template<class T>
  alloc_ertr::future<std::pair<TCachedExtentRef<T>, TCachedExtentRef<T>>>
  extmap_alloc_2extents(ext_context_t ec, extent_len_t len) {
    return seastar::do_with(std::pair<TCachedExtentRef<T>, TCachedExtentRef<T>>(),
      [ec, len] (auto &extents) {
      return crimson::do_for_each(boost::make_counting_iterator(0),
                                  boost::make_counting_iterator(2),
                                  [ec, len, &extents] (auto i) {
        return ec.tm.alloc_extent<T>(ec.t, L_ADDR_MIN, len).safe_then(
          [i, &extents](auto &&node) {
	         if (i == 0)
	           extents.first = node;
	         if (i == 1)
	           extents.second = node;
	       });
      }).safe_then([&extents] {
        return alloc_ertr::make_ready_future
	         <std::pair<TCachedExtentRef<T>, TCachedExtentRef<T>>>(std::move(extents));
      });
    });
  }

  using retire_ertr = crimson::errorator<
                      crimson::ct_error::enoent,
                      crimson::ct_error::input_output_error>;
  using retire_ret = retire_ertr::future<std::list<unsigned>>;
  retire_ret
  extmap_retire_node(ext_context_t ec, std::list<laddr_t> dec_laddrs) {
    return seastar::do_with(std::move(dec_laddrs), std::list<unsigned>(),
      [ec] (auto &&dec_laddrs, auto &refcnt) {
      return crimson::do_for_each(dec_laddrs.begin(), dec_laddrs.end(),
        [ec, &refcnt] (auto &laddr) {
        return ec.tm.dec_ref(ec.t, laddr).safe_then([&refcnt] (auto ref) {
          refcnt.push_back(ref);
        });
      }).safe_then([&refcnt] {
        return retire_ertr::make_ready_future<std::list<unsigned>>(std::move(refcnt));
      });
    });
  }

};

using ExtMapNodeRef = ExtMapNode::ExtMapNodeRef;

TransactionManager::read_extent_ertr::future<ExtMapNodeRef>
extmap_load_extent(ext_context_t ec, laddr_t laddr, depth_t depth);

}