trans.find(i->shard);
assert(iter != trans.end());
bool should_send = get_parent()->should_send_op(*i, op->hoid);
+ if (should_send) {
+ dout(10) << __func__ << ": sending transaction for object "
+ << op->hoid << " to shard " << *i << dendl;
+ } else {
+ dout(10) << __func__ << ": NOT sending transaction for object "
+ << op->hoid << " to shard " << *i << dendl;
+ }
pg_stat_t stats =
should_send ?
get_info().stats :
for (vector<pg_log_entry_t>::const_iterator p = logv.begin();
p != logv.end();
++p) {
+ // we might get log entries for missing objects since we can write to
+ // degraded objects
+ if (!transaction_applied) {
+ if (p->is_delete())
+ t.remove(coll, p->soid);
+
+ assert(
+ p->soid > info.last_backfill ||
+ pg_log.get_missing().is_missing(p->soid) ||
+ (p->is_clone() || p->is_promote() ||
+ (p->is_modify() && (p->prior_version == eversion_t())))
+ );
+
+ if (p->soid <= info.last_backfill) {
+ dout(10) << __func__ << ": transaction empty, adding event "
+ << *p << " to missing"
+ << dendl;
+ pg_log.missing_add_event(*p);
+ } else {
+ dout(10) << __func__ << ": transaction empty, backfill, "
+ << "not adding event " << *p << " to missing"
+ << dendl;
+ }
+ }
add_log_entry(*p, keys[p->get_key_name()]);
}
assert(needs_recovery(hoid));
needs_recovery_map[hoid].need = need;
}
+ void rebuild_object_location(
+ const hobject_t &hoid,
+ const set<pg_shard_t> &actingbackfill,
+ const map<pg_shard_t, const pg_missing_t *> &all_missing,
+ const map<pg_shard_t, const pg_info_t *> &all_info) {
+ needs_recovery_map.erase(hoid);
+ missing_loc.erase(hoid);
+ eversion_t need;
+ for (set<pg_shard_t>::const_iterator peer = actingbackfill.begin();
+ peer != actingbackfill.end();
+ ++peer) {
+ map<pg_shard_t, const pg_missing_t *>::const_iterator pm =
+ all_missing.find(*peer);
+ assert(pm != all_missing.end());
+ if (pm->second->is_missing(hoid)) {
+ need = pm->second->missing.find(hoid)->second.need;
+ break;
+ }
+ }
+ if (need == eversion_t())
+ return;
+
+ set<pg_shard_t> have;
+ for (map<pg_shard_t, const pg_missing_t *>::const_iterator pm =
+ all_missing.begin();
+ pm != all_missing.end();
+ ++pm) {
+ map<pg_shard_t, const pg_info_t *>::const_iterator pi =
+ all_info.find(pm->first);
+ assert(pi != all_info.end());
+ if (pi->second->last_update >= need &&
+ !pm->second->is_missing(hoid)) {
+ have.insert(pm->first);
+ }
+ }
+ missing_loc[hoid].swap(have);
+ add_missing(hoid, need, eversion_t());
+ }
/// Adds info about a possible recovery source
bool add_source_info(
repop->ctx->reqid,
repop->ctx->op);
repop->ctx->op_t = NULL;
+
+ if (is_degraded_object(soid)) {
+ dout(10) << __func__ << ": " << soid
+ << " degraded, maintaining missing sets"
+ << dendl;
+ assert(!is_missing_object(soid));
+ for (vector<pg_log_entry_t>::iterator j = repop->ctx->log.begin();
+ j != repop->ctx->log.end();
+ ++j) {
+ for (set<pg_shard_t>::const_iterator peer = actingbackfill.begin();
+ peer != actingbackfill.end();
+ ++peer) {
+ if (*peer == pg_whoami) {
+ assert(!is_missing_object(j->soid));
+ continue;
+ }
+ map<pg_shard_t, pg_missing_t>::iterator pm = peer_missing.find(*peer);
+ assert(pm != peer_missing.end());
+ if (!pm->second.is_missing(soid)) {
+ assert(!pm->second.is_missing(j->soid));
+ continue;
+ }
+ dout(10) << __func__ << ": " << soid << " missing on "
+ << *peer << ", adding event " << *j << " to missing"
+ << dendl;
+ pm->second.add_next_event(*j);
+ }
+ missing_loc.rebuild_object_location(
+ j->soid,
+ actingbackfill,
+ get_all_missing(),
+ get_all_info());
+ }
+ }
}
template<typename T, int MSGTYPE>
const pg_pool_t &get_pool() const {
return pool.info;
}
+ map<pg_shard_t, const pg_missing_t *> get_all_missing() const {
+ map<pg_shard_t, const pg_missing_t *> all_missing;
+ all_missing[pg_whoami] = &(pg_log.get_missing());
+ for (map<pg_shard_t, pg_missing_t>::const_iterator i = peer_missing.begin();
+ i != peer_missing.end();
+ ++i) {
+ all_missing[i->first] = &(i->second);
+ }
+ return all_missing;
+ }
+ const map<pg_shard_t, const pg_info_t *> get_all_info() const {
+ map<pg_shard_t, const pg_info_t *> all_info;
+ all_info[pg_whoami] = &info;
+ for (map<pg_shard_t, pg_info_t>::const_iterator i = peer_info.begin();
+ i != peer_info.end();
+ ++i) {
+ all_info[i->first] = &(i->second);
+ }
+ return all_info;
+ }
ObjectContextRef get_obc(
const hobject_t &hoid,
map<string, bufferlist> &attrs) {