}
}
- if (!any_up) {
+ if (info.history.last_epoch_started < info.history.same_since &&
+ !any_up) {
dout(10) << "build_prior no osds are up from the last epoch started, PG is down for now." << dendl;
state_set(PG_STATE_DOWN);
}
for (map<int,Info>::iterator it = peer_info.begin();
it != peer_info.end();
it++) {
- if (it->second.last_update > newest_update) {
+ if (it->second.last_update > newest_update ||
+ (it->second.last_update == newest_update && // prefer osds in the prior set
+ prior_set.count(newest_update_osd) == 0)) {
newest_update = it->second.last_update;
newest_update_osd = it->first;
}
peers_complete_thru = it->second.last_complete;
}
}
+ if (newest_update == info.last_update) // or just me, if nobody better.
+ newest_update_osd = osd->whoami;
// gather log(+missing) from that person!
if (newest_update_osd != osd->whoami) {
// twiddle pg state
state_set(PG_STATE_ACTIVE);
state_clear(PG_STATE_STRAY);
+ state_clear(PG_STATE_DOWN);
if (is_crashed()) {
//assert(is_replay()); // HELP.. not on replica?
state_clear(PG_STATE_CRASHED);
void set_role(int r) { role = r; }
bool is_primary() const { return role == PG_ROLE_HEAD; }
+ bool is_replica() const { return role > 0; }
bool is_acker() const {
if (g_conf.osd_rep == OSD_REP_PRIMARY)
return is_primary();
bool is_complete() const { return info.last_complete == info.last_update; }
+ int get_state() const { return state; }
bool is_active() const { return state_test(PG_STATE_ACTIVE); }
bool is_crashed() const { return state_test(PG_STATE_CRASHED); }
bool is_down() const { return state_test(PG_STATE_DOWN); }
out << " pct " << pg.peers_complete_thru;
if (!pg.have_master_log) out << " !hml";
}
- if (pg.is_active()) out << " active";
- if (pg.is_crashed()) out << " crashed";
- if (pg.is_replay()) out << " replay";
- if (pg.is_clean()) out << " clean";
- if (pg.is_stray()) out << " stray";
+
+ out << " " << pg_state_string(pg.get_state());
+
//out << " (" << pg.log.bottom << "," << pg.log.top << "]";
if (pg.missing.num_missing()) out << " m=" << pg.missing.num_missing();
if (pg.missing.num_lost()) out << " l=" << pg.missing.num_lost();
<< " v " << nv
<< " " << op->get_offset() << "~" << op->get_length()
<< dendl;
+
+ // sanity checks
+ if (op->get_map_epoch() < info.history.same_primary_since) {
+ dout(10) << "sub_op_modify discarding old sub_op from "
+ << op->get_map_epoch() << " < " << info.history.same_primary_since << dendl;
+ delete op;
+ return;
+ }
+ if (!is_active()) {
+ dout(10) << "sub_op_modify not active" << dendl;
+ delete op;
+ return;
+ }
+ assert(is_replica());
// note peer's stat
int fromosd = op->get_source().num();
{
const pobject_t poid = op->get_poid();
const eversion_t v = op->get_version();
- int from = op->get_source().num();
dout(7) << "op_pull " << poid << " v " << op->get_version()
<< " from " << op->get_source()
<< dendl;
- // is a replica asking? are they missing it?
- if (is_primary()) {
- // primary
- assert(peer_missing.count(from)); // we had better know this, from the peering process.
+ if (op->get_map_epoch() < info.history.same_primary_since) {
+ dout(10) << "sub_op_pull discarding old sub_op from "
+ << op->get_map_epoch() << " < " << info.history.same_primary_since << dendl;
+ delete op;
+ return;
+ }
- if (!peer_missing[from].is_missing(poid.oid)) {
- dout(7) << "op_pull replica isn't actually missing it, we must have already pushed to them" << dendl;
- delete op;
- return;
- }
+ assert(!is_primary()); // we should be a replica or stray.
- // do we have it yet?
- if (is_missing_object(poid.oid)) {
- wait_for_missing_object(poid.oid, op);
- return;
- }
- } else {
- // non-primary
- if (missing.is_missing(poid.oid)) {
- dout(7) << "op_pull not primary, and missing " << poid << ", ignoring" << dendl;
- delete op;
- return;
- }
- }
-
// push it back!
push(poid, op->get_source().num());
}
pobject_t poid = op->get_poid();
eversion_t v = op->get_version();
+ dout(7) << "op_push "
+ << poid
+ << " v " << v
+ << " size " << op->get_length() << " " << op->get_data().length()
+ << dendl;
+
+ if (is_replica()) {
+ // replica should only accept pushes from the current primary.
+ if (op->get_map_epoch() < info.history.same_primary_since) {
+ dout(10) << "sub_op_push discarding old sub_op from "
+ << op->get_map_epoch() << " < " << info.history.same_primary_since << dendl;
+ delete op;
+ return;
+ }
+ // FIXME: actually, no, what i really want here is a personal "same_role_since"
+ if (!is_active()) {
+ dout(10) << "sub_op_push not active" << dendl;
+ delete op;
+ return;
+ }
+ } else {
+ // primary will accept pushes anytime.
+ }
+
// are we missing (this specific version)?
// (if version is wrong, it is either old (we don't want it) or
// newer (peering is buggy))
return;
}
- dout(7) << "op_push "
- << poid
- << " v " << v
- << " size " << op->get_length() << " " << op->get_data().length()
- << dendl;
-
assert(op->get_data().length() == op->get_length());
// write object and add it to the PG