diff --git a/src/box/box.cc b/src/box/box.cc index 1321e324fdbe910e7c1890bb5c2c0a58983022fd..51ac718c7a2bee7083317881f5b985bd045066a5 100644 --- a/src/box/box.cc +++ b/src/box/box.cc @@ -1848,20 +1848,21 @@ static void box_issue_promote(uint32_t prev_leader_id, int64_t promote_lsn) { struct raft *raft = box_raft(); - assert(raft->volatile_term == raft->term); + uint64_t term = raft->term; + assert(raft->volatile_term == term); assert(promote_lsn >= 0); + txn_limbo_begin(&txn_limbo); - txn_limbo_write_promote(&txn_limbo, promote_lsn, - raft->term); - struct synchro_request req = { - .type = IPROTO_RAFT_PROMOTE, - .replica_id = prev_leader_id, - .origin_id = instance_id, - .lsn = promote_lsn, - .term = raft->term, - }; - txn_limbo_req_commit(&txn_limbo, &req); + /* + * XXX: 'begin' takes time. Conditions could change and it is not + * handled anyhow except for these assertions. + */ + assert(raft->volatile_term == term); + assert(txn_limbo.owner_id == prev_leader_id); + (void)prev_leader_id; + txn_limbo_write_promote(&txn_limbo, promote_lsn, term); txn_limbo_commit(&txn_limbo); + assert(txn_limbo_is_empty(&txn_limbo)); } @@ -1872,20 +1873,22 @@ static bool is_in_box_promote = false; static void box_issue_demote(uint32_t prev_leader_id, int64_t promote_lsn) { - assert(box_raft()->volatile_term == box_raft()->term); + struct raft *raft = box_raft(); + uint64_t term = raft->term; + assert(raft->volatile_term == term); assert(promote_lsn >= 0); + txn_limbo_begin(&txn_limbo); - txn_limbo_write_demote(&txn_limbo, promote_lsn, - box_raft()->term); - struct synchro_request req = { - .type = IPROTO_RAFT_DEMOTE, - .replica_id = prev_leader_id, - .origin_id = instance_id, - .lsn = promote_lsn, - .term = box_raft()->term, - }; - txn_limbo_req_commit(&txn_limbo, &req); + /* + * XXX: 'begin' takes time. Conditions could change and it is not + * handled anyhow except for these assertions. + */ + assert(raft->volatile_term == term); + assert(txn_limbo.owner_id == prev_leader_id); + (void)prev_leader_id; + txn_limbo_write_demote(&txn_limbo, promote_lsn, term); txn_limbo_commit(&txn_limbo); + assert(txn_limbo_is_empty(&txn_limbo)); } diff --git a/src/box/txn_limbo.c b/src/box/txn_limbo.c index 207744a9a2b6ff496a4cb5c4f28a20933cf15499..921d538d4293cd10aad4c6f714c06330522917b5 100644 --- a/src/box/txn_limbo.c +++ b/src/box/txn_limbo.c @@ -312,19 +312,10 @@ txn_limbo_checkpoint(const struct txn_limbo *limbo, req->term = limbo->promote_greatest_term; } +/** Write a request to WAL. */ static void -txn_limbo_write_synchro(struct txn_limbo *limbo, uint16_t type, int64_t lsn, - uint64_t term) +synchro_request_write(const struct synchro_request *req) { - assert(lsn >= 0); - - struct synchro_request req = { - .type = type, - .replica_id = limbo->owner_id, - .lsn = lsn, - .term = term, - }; - /* * This is a synchronous commit so we can * allocate everything on a stack. @@ -337,7 +328,7 @@ txn_limbo_write_synchro(struct txn_limbo *limbo, uint16_t type, int64_t lsn, struct journal_entry *entry = (struct journal_entry *)buf; entry->rows[0] = &row; - xrow_encode_synchro(&row, body, &req); + xrow_encode_synchro(&row, body, req); journal_entry_create(entry, 1, xrow_approx_len(&row), journal_entry_fiber_wakeup_cb, fiber()); @@ -359,8 +350,23 @@ txn_limbo_write_synchro(struct txn_limbo *limbo, uint16_t type, int64_t lsn, * problems are fixed. Or retry automatically with some period. */ panic("Could not write a synchro request to WAL: lsn = %lld, " - "type = %s\n", (long long)lsn, iproto_type_name(type)); + "type = %s\n", (long long)req->lsn, iproto_type_name(req->type)); +} +/** Create a request for a specific limbo and write it to WAL. */ +static void +txn_limbo_write_synchro(struct txn_limbo *limbo, uint16_t type, int64_t lsn, + uint64_t term) +{ + assert(lsn >= 0); + + struct synchro_request req = { + .type = type, + .replica_id = limbo->owner_id, + .lsn = lsn, + .term = term, + }; + synchro_request_write(&req); } /** @@ -490,8 +496,7 @@ txn_limbo_read_rollback(struct txn_limbo *limbo, int64_t lsn) void txn_limbo_write_promote(struct txn_limbo *limbo, int64_t lsn, uint64_t term) { - limbo->confirmed_lsn = lsn; - limbo->is_in_rollback = true; + assert(latch_is_locked(&limbo->promote_latch)); /* * We make sure that promote is only written once everything this * instance has may be confirmed. @@ -499,7 +504,17 @@ txn_limbo_write_promote(struct txn_limbo *limbo, int64_t lsn, uint64_t term) struct txn_limbo_entry *e = txn_limbo_last_synchro_entry(limbo); assert(e == NULL || e->lsn <= lsn); (void) e; - txn_limbo_write_synchro(limbo, IPROTO_RAFT_PROMOTE, lsn, term); + struct synchro_request req = { + .type = IPROTO_RAFT_PROMOTE, + .replica_id = limbo->owner_id, + .origin_id = instance_id, + .lsn = lsn, + .term = term, + }; + limbo->confirmed_lsn = lsn; + limbo->is_in_rollback = true; + synchro_request_write(&req); + txn_limbo_req_commit(limbo, &req); limbo->is_in_rollback = false; } @@ -522,12 +537,21 @@ txn_limbo_read_promote(struct txn_limbo *limbo, uint32_t replica_id, void txn_limbo_write_demote(struct txn_limbo *limbo, int64_t lsn, uint64_t term) { - limbo->confirmed_lsn = lsn; - limbo->is_in_rollback = true; + assert(latch_is_locked(&limbo->promote_latch)); struct txn_limbo_entry *e = txn_limbo_last_synchro_entry(limbo); assert(e == NULL || e->lsn <= lsn); (void)e; - txn_limbo_write_synchro(limbo, IPROTO_RAFT_DEMOTE, lsn, term); + struct synchro_request req = { + .type = IPROTO_RAFT_DEMOTE, + .replica_id = limbo->owner_id, + .origin_id = instance_id, + .lsn = lsn, + .term = term, + }; + limbo->confirmed_lsn = lsn; + limbo->is_in_rollback = true; + synchro_request_write(&req); + txn_limbo_req_commit(limbo, &req); limbo->is_in_rollback = false; }