summaryrefslogtreecommitdiffstats
path: root/src/crimson/os/seastore/onode_manager/staged-fltree/node_extent_mutable.h
blob: 52f10a013003093d786ca3a5b90a7df96dfd428b (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
// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:nil -*-
// vim: ts=8 sw=2 smarttab

#include <cstring>

#include "fwd.h"

#pragma once

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

class NodeExtent;

/**
 * NodeExtentMutable
 *
 * A thin wrapper of NodeExtent to make sure that only the newly allocated
 * or the duplicated NodeExtent is mutable, and the memory modifications are
 * safe within the extent range.
 */
class NodeExtentMutable {
 public:
  void copy_in_absolute(void* dst, const void* src, extent_len_t len) {
    assert((char*)dst >= get_write());
    assert((char*)dst + len <= buf_upper_bound());
    std::memcpy(dst, src, len);
  }
  template <typename T>
  void copy_in_absolute(void* dst, const T& src) {
    copy_in_absolute(dst, &src, sizeof(T));
  }

  const void* copy_in_relative(
      extent_len_t dst_offset, const void* src, extent_len_t len) {
    auto dst = get_write() + dst_offset;
    copy_in_absolute(dst, src, len);
    return dst;
  }
  template <typename T>
  const T* copy_in_relative(
      extent_len_t dst_offset, const T& src) {
    auto dst = copy_in_relative(dst_offset, &src, sizeof(T));
    return static_cast<const T*>(dst);
  }

  void shift_absolute(const void* src, extent_len_t len, int offset) {
    assert((const char*)src >= get_write());
    assert((const char*)src + len <= buf_upper_bound());
    char* to = (char*)src + offset;
    assert(to >= get_write());
    assert(to + len <= buf_upper_bound());
    if (len != 0) {
      std::memmove(to, src, len);
    }
  }
  void shift_relative(extent_len_t src_offset, extent_len_t len, int offset) {
    shift_absolute(get_write() + src_offset, len, offset);
  }

  template <typename T>
  void validate_inplace_update(const T& updated) {
    assert((const char*)&updated >= get_write());
    assert((const char*)&updated + sizeof(T) <= buf_upper_bound());
  }

  const char* get_read() const;
  char* get_write();
  extent_len_t get_length() const;
  laddr_t get_laddr() const;

 private:
  explicit NodeExtentMutable(NodeExtent&);
  const char* buf_upper_bound() const;

  NodeExtent& extent;

  friend class NodeExtent;
};

}