template <class Func>
struct OpsExecuter::RollbackHelper {
void rollback_obc_if_modified();
- void rollback_obc_if_modified(const std::error_code& e);
OpsExecuter *ox;
Func func;
};
}
}
-template <class Func>
-void OpsExecuter::RollbackHelper<Func>::rollback_obc_if_modified(
- const std::error_code& e)
-{
- // Oops, an operation had failed. do_osd_ops() altogether with
- // OpsExecuter already dropped the ObjectStore::Transaction if
- // there was any. However, this is not enough to completely
- // rollback as we gave OpsExecuter the very single copy of `obc`
- // we maintain and we did it for both reading and writing.
- // Now all modifications must be reverted.
- //
- // The conditional's purpose is to efficiently handle hot errors
- // which may appear as a result of e.g. CEPH_OSD_OP_CMPXATTR or
- // CEPH_OSD_OP_OMAP_CMP. These are read-like ops and clients
- // typically append them before any write. If OpsExecuter hasn't
- // seen any modifying operation, `obc` is supposed to be kept
- // unchanged.
- assert(ox);
- const auto need_rollback = ox->has_seen_write();
- crimson::get_logger(ceph_subsys_osd).debug(
- "{}: object {} got error {}, need_rollback={}",
- __func__,
- ox->obc->get_oid(),
- e,
- need_rollback);
- if (need_rollback) {
- func(ox->obc);
- }
-}
-
// PgOpsExecuter -- a class for executing ops targeting a certain PG.
class PgOpsExecuter {
template <typename T = void>