break;
}
if (oi.is_dirty()) {
- result = start_flush(ctx->op, ctx->obc, false, NULL, NULL);
+ result = start_flush(ctx->op, ctx->obc, false, NULL, boost::none);
if (result == -EINPROGRESS)
result = -EAGAIN;
} else {
}
hobject_t missing;
if (oi.is_dirty()) {
- result = start_flush(ctx->op, ctx->obc, true, &missing, NULL);
+ result = start_flush(ctx->op, ctx->obc, true, &missing, boost::none);
if (result == -EINPROGRESS)
result = -EAGAIN;
} else {
int ReplicatedPG::start_flush(
OpRequestRef op, ObjectContextRef obc,
bool blocking, hobject_t *pmissing,
- Context *on_flush)
+ boost::optional<std::function<void()>> &&on_flush)
{
const object_info_t& oi = obc->obs.oi;
const hobject_t& soid = oi.soid;
fop->obc = obc;
fop->flushed_version = oi.user_version;
fop->blocking = blocking;
- fop->on_flush = on_flush;
+ fop->on_flush = std::move(on_flush);
fop->op = op;
ObjectOperation o;
requeue_ops(fop->dup_ops);
}
if (fop->on_flush) {
- Context *on_flush = fop->on_flush;
- fop->on_flush = NULL;
- on_flush->complete(-EBUSY);
+ (*(fop->on_flush))();
+ fop->on_flush = boost::none;
}
flush_ops.erase(oid);
return;
requeue_ops(fop->dup_ops);
}
if (fop->on_flush) {
- Context *on_flush = fop->on_flush;
- fop->on_flush = NULL;
- on_flush->complete(-EBUSY);
+ (*(fop->on_flush))();
+ fop->on_flush = boost::none;
}
flush_ops.erase(oid);
if (fop->blocking)
agent_maybe_evict(obc, true)) {
osd->logger->inc(l_osd_tier_clean);
if (fop->on_flush) {
- Context *on_flush = fop->on_flush;
- fop->on_flush = NULL;
- on_flush->complete(0);
+ (*(fop->on_flush))();
+ fop->on_flush = boost::none;
}
flush_ops.erase(oid);
return 0;
dout(10) << __func__ << " clearing DIRTY flag for " << oid << dendl;
OpContextUPtr ctx = simple_opc_create(fop->obc);
- ctx->on_finish = fop->on_flush;
- fop->on_flush = NULL;
+ ctx->register_on_finish(*(fop->on_flush));
+ fop->on_flush = boost::none;
ctx->lock_to_release = OpContext::W_LOCK; // we took it above
ctx->at_version = get_next_version();
requeue_ops(fop->dup_ops);
}
if (fop->on_flush) {
- Context *on_flush = fop->on_flush;
- fop->on_flush = NULL;
- on_flush->complete(-ECANCELED);
+ (*(fop->on_flush))();
+ fop->on_flush = boost::none;
}
flush_ops.erase(fop->obc->obs.oi.soid);
}
}
}
-struct C_AgentFlushStartStop : public Context {
- ReplicatedPGRef pg;
- hobject_t oid;
- C_AgentFlushStartStop(ReplicatedPG *p, hobject_t o) : pg(p), oid(o) {
- pg->osd->agent_start_op(oid);
- }
- void finish(int r) {
- pg->osd->agent_finish_op(oid);
- }
-};
-
bool ReplicatedPG::agent_maybe_flush(ObjectContextRef& obc)
{
if (!obc->obs.oi.is_dirty()) {
// FIXME: flush anything dirty, regardless of what distribution of
// ages we expect.
- Context *on_flush = new C_AgentFlushStartStop(this, obc->obs.oi.soid);
+ hobject_t oid = obc->obs.oi.soid;
+ osd->agent_start_op(oid);
+ // no need to capture a pg ref, can't outlive fop or ctx
+ std::function<void()> on_flush = [this, oid]() {
+ osd->agent_finish_op(oid);
+ };
+
int result = start_flush(
OpRequestRef(), obc, false, NULL,
on_flush);
if (result != -EINPROGRESS) {
- on_flush->complete(result);
+ on_flush();
dout(10) << __func__ << " start_flush() failed " << obc->obs.oi
<< " with " << result << dendl;
osd->logger->inc(l_osd_agent_skip);
return true;
}
-struct C_AgentEvictStartStop : public Context {
- ReplicatedPGRef pg;
- explicit C_AgentEvictStartStop(ReplicatedPG *p) : pg(p) {
- pg->osd->agent_start_evict_op();
- }
- void finish(int r) {
- pg->osd->agent_finish_evict_op();
- }
-};
-
bool ReplicatedPG::agent_maybe_evict(ObjectContextRef& obc, bool after_flush)
{
const hobject_t& soid = obc->obs.oi.soid;
dout(10) << __func__ << " evicting " << obc->obs.oi << dendl;
OpContextUPtr ctx = simple_opc_create(obc);
- Context *on_evict = new C_AgentEvictStartStop(this);
- ctx->on_finish = on_evict;
+
+ osd->agent_start_evict_op();
+ ctx->register_on_finish(
+ [this]() {
+ osd->agent_finish_evict_op();
+ });
+
ctx->lock_to_release = OpContext::W_LOCK;
ctx->at_version = get_next_version();
assert(ctx->new_obs.exists);
int rval; ///< copy-from result
bool blocking; ///< whether we are blocking updates
bool removal; ///< we are removing the backend object
- Context *on_flush; ///< callback, may be null
+ boost::optional<std::function<void()>> on_flush; ///< callback, may be null
FlushOp()
: flushed_version(0), objecter_tid(0), rval(0),
- blocking(false), removal(false),
- on_flush(NULL) {}
+ blocking(false), removal(false) {}
~FlushOp() { assert(!on_flush); }
};
typedef boost::shared_ptr<FlushOp> FlushOpRef;
int start_flush(
OpRequestRef op, ObjectContextRef obc,
bool blocking, hobject_t *pmissing,
- Context *on_flush);
+ boost::optional<std::function<void()>> &&on_flush);
void finish_flush(hobject_t oid, ceph_tid_t tid, int r);
int try_flush_mark_clean(FlushOpRef fop);
void cancel_flush(FlushOpRef fop, bool requeue);