}
friend class crimson::os::seastore::SeaStore;
+ friend class TransactionConflictCondition;
};
using TransactionRef = Transaction::Ref;
);
}
+struct TransactionConflictCondition {
+ class transaction_conflict final : public std::exception {
+ public:
+ const char* what() const noexcept final {
+ return "transaction conflict detected";
+ }
+ };
+
+public:
+ TransactionConflictCondition(Transaction &t) : t(t) {}
+
+ template <typename Fut>
+ std::pair<bool, std::optional<Fut>> may_interrupt() {
+ if (t.conflicted) {
+ return {
+ true,
+ seastar::futurize<Fut>::make_exception_future(
+ transaction_conflict())};
+ } else {
+ return {false, std::optional<Fut>()};
+ }
+ }
+
+ template <typename T>
+ static constexpr bool is_interruption_v =
+ std::is_same_v<T, transaction_conflict>;
+
+
+ static bool is_interruption(std::exception_ptr& eptr) {
+ return *eptr.__cxa_exception_type() == typeid(transaction_conflict);
+ }
+
+private:
+ Transaction &t;
+};
+
+using trans_intr = crimson::interruptible::interruptor<
+ TransactionConflictCondition
+ >;
+
+template <typename E>
+using trans_iertr =
+ crimson::interruptible::interruptible_errorator<
+ TransactionConflictCondition,
+ E
+ >;
+
+template <typename F, typename... Args>
+auto with_trans_intr(Transaction &t, F &&f, Args&&... args) {
+ return trans_intr::with_interruption_to_error<crimson::ct_error::eagain>(
+ std::move(f),
+ TransactionConflictCondition(t),
+ t,
+ std::forward<Args>(args)...);
+}
+
+template <typename T>
+using with_trans_ertr = typename T::base_ertr::template extend<crimson::ct_error::eagain>;
+
}