pstore2
diff.hpp
Go to the documentation of this file.
1 //===- include/pstore/core/diff.hpp -----------------------*- mode: C++ -*-===//
2 //* _ _ __ __ *
3 //* __| (_)/ _|/ _| *
4 //* / _` | | |_| |_ *
5 //* | (_| | | _| _| *
6 //* \__,_|_|_| |_| *
7 //* *
8 //===----------------------------------------------------------------------===//
9 //
10 // Part of the pstore project, under the Apache License v2.0 with LLVM Exceptions.
11 // See https://github.com/SNSystems/pstore/blob/master/LICENSE.txt for license
12 // information.
13 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
14 //
15 //===----------------------------------------------------------------------===//
18 #ifndef PSTORE_CORE_DIFF_HPP
19 #define PSTORE_CORE_DIFF_HPP
20 
21 #include "pstore/core/hamt_set.hpp"
22 
23 namespace pstore {
24 
25  namespace diff_details {
26 
27  template <typename Index>
28  class traverser {
31 
32  public:
36  constexpr traverser (database const & db, Index const & index,
37  address threshold) noexcept
38  : db_{db}
39  , index_{index}
40  , threshold_{threshold} {}
41 
45  template <typename OutputIterator>
46  OutputIterator operator() (OutputIterator out) const;
47 
48  private:
54  template <typename OutputIterator>
55  OutputIterator visit_node (index_pointer node, unsigned shifts,
56  OutputIterator out) const;
57 
66  template <typename Node, typename OutputIterator>
67  OutputIterator visit_intermediate (index_pointer node, unsigned shifts,
68  OutputIterator out) const;
69 
70  bool is_new (index_pointer const node) const noexcept {
71  return node.is_heap () ||
72  node.untag_address<internal_node> ().to_address () >= threshold_;
73  }
74 
75  database const & db_;
76  Index const & index_;
77  address const threshold_;
78  };
79 
80  // operator()
81  // ~~~~~~~~~~
82  template <typename Index>
83  template <typename OutputIterator>
84  OutputIterator traverser<Index>::operator() (OutputIterator out) const {
85  if (auto const root = index_.root ()) {
86  out = this->visit_node (root, 0U, out);
87  }
88  return out;
89  }
90 
91  // visit node
92  // ~~~~~~~~~~
93  template <typename Index>
94  template <typename OutputIterator>
95  OutputIterator traverser<Index>::visit_node (index_pointer node, unsigned shifts,
96  OutputIterator out) const {
97  if (node.is_leaf ()) {
98  PSTORE_ASSERT (node.is_address ());
99  // If this leaf is not in the "old" byte range then add it to the output
100  // collection.
101  if (this->is_new (node)) {
102  *out = node.to_address ();
103  ++out;
104  }
105  return out;
106  }
107 
108  if (index::details::depth_is_internal_node (shifts)) {
109  return this->visit_intermediate<index::details::internal_node> (node, shifts,
110  out);
111  }
112 
113  return this->visit_intermediate<index::details::linear_node> (node, shifts, out);
114  }
115 
116  // visit intermediate
117  // ~~~~~~~~~~~~~~~~~~
118  template <typename Index>
119  template <typename Node, typename OutputIterator>
120  OutputIterator
122  unsigned const shifts, OutputIterator out) const {
123  std::pair<std::shared_ptr<void const>, Node const *> const p =
124  Node::get_node (db_, node);
125  PSTORE_ASSERT (std::get<Node const *> (p) != nullptr);
126  for (auto child : *std::get<Node const *> (p)) {
127  if (this->is_new (node)) {
128  out = this->visit_node (index_pointer{child},
129  shifts + index::details::hash_index_bits, out);
130  }
131  }
132  return out;
133  }
134 
135  } // end namespace diff_details
136 
137 
147  template <typename Index, typename OutputIterator>
148  OutputIterator diff (database const & db, Index const & index, revision_number const old,
149  OutputIterator out) {
150  if (old == pstore::head_revision || old > db.get_current_revision ()) {
151  return out;
152  }
153  // addresses less than the threshold value are "old".
154  diff_details::traverser<Index> t{db, index, (db.older_revision_footer_pos (old) + 1).to_address ()};
155  return t (out);
156  }
157 
158 } // end namespace pstore
159 
160 #endif // PSTORE_CORE_DIFF_HPP
OutputIterator diff(database const &db, Index const &index, revision_number const old, OutputIterator out)
Write a series of addresses to an output iterator of the objects that were added to an index between ...
Definition: diff.hpp:148
typed_address< trailer > older_revision_footer_pos(unsigned revision) const
Returns the address of the footer of a specified revision.
Definition: database.cpp:147
Definition: address.hpp:81
bool is_address() const noexcept
Returns true if the index_pointer is pointing to a store node, false otherwise.
Definition: hamt_map_types.hpp:221
constexpr traverser(database const &db, Index const &index, address threshold) noexcept
Definition: diff.hpp:36
bool is_heap() const noexcept
Returns true if the index_pointer is pointing to a heap node, false otherwise.
Definition: hamt_map_types.hpp:215
OutputIterator operator()(OutputIterator out) const
Definition: diff.hpp:84
bool is_leaf() const noexcept
Returns true if the index_pointer contains the address of a value in the store, false otherwise...
Definition: hamt_map_types.hpp:211
unsigned get_current_revision() const
Returns the generation number to which the database is synced.
Definition: database.hpp:262
An internal trie node.
Definition: hamt_map_types.hpp:508
Definition: nonpod2.cpp:40
Definition: database.hpp:40
An index pointer is either a database address or a pointer to volatile RAM.
Definition: hamt_map_types.hpp:132
Definition: diff.hpp:28