summaryrefslogtreecommitdiffstats
path: root/src/crimson/os/seastore/transaction.h
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/crimson/os/seastore/transaction.h145
1 files changed, 145 insertions, 0 deletions
diff --git a/src/crimson/os/seastore/transaction.h b/src/crimson/os/seastore/transaction.h
new file mode 100644
index 000000000..e189d1d32
--- /dev/null
+++ b/src/crimson/os/seastore/transaction.h
@@ -0,0 +1,145 @@
+// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
+// vim: ts=8 sw=2 smarttab
+
+#pragma once
+
+#include <iostream>
+
+#include "crimson/os/seastore/seastore_types.h"
+#include "crimson/os/seastore/cached_extent.h"
+#include "crimson/os/seastore/root_block.h"
+
+namespace crimson::os::seastore {
+
+/**
+ * Transaction
+ *
+ * Representation of in-progress mutation. Used exclusively through Cache methods.
+ */
+class Transaction {
+public:
+ using Ref = std::unique_ptr<Transaction>;
+ enum class get_extent_ret {
+ PRESENT,
+ ABSENT,
+ RETIRED
+ };
+ get_extent_ret get_extent(paddr_t addr, CachedExtentRef *out) {
+ if (retired_set.count(addr)) {
+ return get_extent_ret::RETIRED;
+ } else if (auto iter = write_set.find_offset(addr);
+ iter != write_set.end()) {
+ if (out)
+ *out = CachedExtentRef(&*iter);
+ return get_extent_ret::PRESENT;
+ } else if (
+ auto iter = read_set.find(addr);
+ iter != read_set.end()) {
+ if (out)
+ *out = CachedExtentRef(*iter);
+ return get_extent_ret::PRESENT;
+ } else {
+ return get_extent_ret::ABSENT;
+ }
+ }
+
+ void add_to_retired_set(CachedExtentRef ref) {
+ ceph_assert(!is_weak());
+ if (!ref->is_initial_pending()) {
+ // && retired_set.count(ref->get_paddr()) == 0
+ // If it's already in the set, insert here will be a noop,
+ // which is what we want.
+ retired_set.insert(ref);
+ } else {
+ ref->state = CachedExtent::extent_state_t::INVALID;
+ }
+ if (ref->is_pending()) {
+ write_set.erase(*ref);
+ }
+ }
+
+ void add_to_read_set(CachedExtentRef ref) {
+ if (is_weak()) return;
+
+ ceph_assert(read_set.count(ref) == 0);
+ read_set.insert(ref);
+ }
+
+ void add_fresh_extent(CachedExtentRef ref) {
+ ceph_assert(!is_weak());
+ fresh_block_list.push_back(ref);
+ ref->set_paddr(make_record_relative_paddr(offset));
+ offset += ref->get_length();
+ write_set.insert(*ref);
+ }
+
+ void add_mutated_extent(CachedExtentRef ref) {
+ ceph_assert(!is_weak());
+ mutated_block_list.push_back(ref);
+ write_set.insert(*ref);
+ }
+
+ void mark_segment_to_release(segment_id_t segment) {
+ assert(to_release == NULL_SEG_ID);
+ to_release = segment;
+ }
+
+ segment_id_t get_segment_to_release() const {
+ return to_release;
+ }
+
+ const auto &get_fresh_block_list() {
+ return fresh_block_list;
+ }
+
+ const auto &get_mutated_block_list() {
+ return mutated_block_list;
+ }
+
+ const auto &get_retired_set() {
+ return retired_set;
+ }
+
+ bool is_weak() const {
+ return weak;
+ }
+
+private:
+ friend class Cache;
+ friend Ref make_transaction();
+ friend Ref make_weak_transaction();
+
+ /**
+ * If set, *this may not be used to perform writes and will not provide
+ * consistentency allowing operations using to avoid maintaining a read_set.
+ */
+ const bool weak;
+
+ RootBlockRef root; ///< ref to root if read or written by transaction
+
+ segment_off_t offset = 0; ///< relative offset of next block
+
+ pextent_set_t read_set; ///< set of extents read by paddr
+ ExtentIndex write_set; ///< set of extents written by paddr
+
+ std::list<CachedExtentRef> fresh_block_list; ///< list of fresh blocks
+ std::list<CachedExtentRef> mutated_block_list; ///< list of mutated blocks
+
+ pextent_set_t retired_set; ///< list of extents mutated by this transaction
+
+ ///< if != NULL_SEG_ID, release this segment after completion
+ segment_id_t to_release = NULL_SEG_ID;
+
+ Transaction(bool weak) : weak(weak) {}
+};
+using TransactionRef = Transaction::Ref;
+
+inline TransactionRef make_transaction() {
+ return std::unique_ptr<Transaction>(new Transaction(false));
+}
+
+inline TransactionRef make_weak_transaction() {
+ return std::unique_ptr<Transaction>(new Transaction(true));
+}
+
+}