uint32_t *pnn_list;
int count;
uint32_t *caps;
+ uint32_t *ban_credits;
uint32_t db_id;
struct recdb_context *recdb;
uint32_t max_pnn;
struct tevent_context *ev,
struct ctdb_client_context *client,
uint32_t *pnn_list, int count, uint32_t *caps,
- uint32_t db_id, struct recdb_context *recdb)
+ uint32_t *ban_credits, uint32_t db_id,
+ struct recdb_context *recdb)
{
struct tevent_req *req, *subreq;
struct collect_highseqnum_db_state *state;
state->pnn_list = pnn_list;
state->count = count;
state->caps = caps;
+ state->ban_credits = ban_credits;
state->db_id = db_id;
state->recdb = recdb;
{
struct tevent_req *req = tevent_req_callback_data(
subreq, struct tevent_req);
+ struct collect_highseqnum_db_state *state = tevent_req_data(
+ req, struct collect_highseqnum_db_state);
int ret;
bool status;
status = pull_database_recv(subreq, &ret);
TALLOC_FREE(subreq);
if (! status) {
+ state->ban_credits[state->max_pnn] += 1;
tevent_req_error(req, ret);
return;
}
uint32_t *pnn_list;
int count;
uint32_t *caps;
+ uint32_t *ban_credits;
uint32_t db_id;
struct recdb_context *recdb;
struct ctdb_pulldb pulldb;
struct tevent_context *ev,
struct ctdb_client_context *client,
uint32_t *pnn_list, int count, uint32_t *caps,
- uint32_t db_id, struct recdb_context *recdb)
+ uint32_t *ban_credits, uint32_t db_id,
+ struct recdb_context *recdb)
{
struct tevent_req *req, *subreq;
struct collect_all_db_state *state;
status = pull_database_recv(subreq, &ret);
TALLOC_FREE(subreq);
if (! status) {
+ pnn = state->pnn_list[state->index];
+ state->ban_credits[pnn] += 1;
tevent_req_error(req, ret);
return;
}
uint32_t *pnn_list;
int count;
uint32_t *caps;
+ uint32_t *ban_credits;
uint32_t db_id;
bool persistent;
struct ctdb_tunable_list *tun_list,
uint32_t *pnn_list, int count,
uint32_t *caps,
+ uint32_t *ban_credits,
uint32_t generation,
uint32_t db_id, bool persistent)
{
state->pnn_list = pnn_list;
state->count = count;
state->caps = caps;
+ state->ban_credits = ban_credits;
state->db_id = db_id;
state->persistent = persistent;
subreq = collect_highseqnum_db_send(
state, state->ev, state->client,
state->pnn_list, state->count, state->caps,
- state->db_id, state->recdb);
+ state->ban_credits, state->db_id,
+ state->recdb);
} else {
subreq = collect_all_db_send(
state, state->ev, state->client,
state->pnn_list, state->count, state->caps,
- state->db_id, state->recdb);
+ state->ban_credits, state->db_id,
+ state->recdb);
}
if (tevent_req_nomem(subreq, req)) {
return;
uint32_t *pnn_list;
int count;
uint32_t *caps;
+ uint32_t *ban_credits;
uint32_t generation;
uint32_t db_id;
bool persistent;
struct ctdb_tunable_list *tun_list,
uint32_t *pnn_list, int count,
uint32_t *caps,
+ uint32_t *ban_credits,
uint32_t generation)
{
struct tevent_req *req, *subreq;
substate->pnn_list = pnn_list;
substate->count = count;
substate->caps = caps;
+ substate->ban_credits = ban_credits;
substate->generation = generation;
substate->db_id = dbmap->dbs[i].db_id;
substate->persistent = dbmap->dbs[i].flags &
CTDB_DB_FLAGS_PERSISTENT;
subreq = recover_db_send(state, ev, client, tun_list,
- pnn_list, count, caps,
+ pnn_list, count, caps, ban_credits,
generation, substate->db_id,
substate->persistent);
if (tevent_req_nomem(subreq, req)) {
subreq = recover_db_send(state, state->ev, substate->client,
substate->tun_list,
substate->pnn_list, substate->count,
- substate->caps,
+ substate->caps, substate->ban_credits,
substate->generation, substate->db_id,
substate->persistent);
if (tevent_req_nomem(subreq, req)) {
uint32_t destnode;
struct ctdb_node_map *nodemap;
uint32_t *caps;
+ uint32_t *ban_credits;
struct ctdb_tunable_list *tun_list;
struct ctdb_vnn_map *vnnmap;
struct ctdb_dbid_map *dbmap;
static void recovery_start_recovery_done(struct tevent_req *subreq);
static void recovery_vnnmap_update_done(struct tevent_req *subreq);
static void recovery_db_recovery_done(struct tevent_req *subreq);
+static void recovery_failed_done(struct tevent_req *subreq);
static void recovery_normal_done(struct tevent_req *subreq);
static void recovery_end_recovery_done(struct tevent_req *subreq);
return;
}
+ state->ban_credits = talloc_zero_array(state, uint32_t,
+ state->nodemap->num);
+ if (tevent_req_nomem(state->ban_credits, req)) {
+ return;
+ }
+
ctdb_req_control_getvnnmap(&request);
subreq = ctdb_client_control_send(state, state->ev, state->client,
state->destnode, TIMEOUT(),
subreq = db_recovery_send(state, state->ev, state->client,
state->dbmap, state->tun_list,
state->pnn_list, state->count,
- state->caps, state->vnnmap->generation);
+ state->caps, state->ban_credits,
+ state->vnnmap->generation);
if (tevent_req_nomem(subreq, req)) {
return;
}
LOG("%d of %d databases recovered\n", count, state->dbmap->num);
if (! status) {
- tevent_req_error(req, EIO);
+ uint32_t max_pnn = CTDB_UNKNOWN_PNN, max_credits = 0;
+ int i;
+
+ /* Bans are not enabled */
+ if (state->tun_list->enable_bans == 0) {
+ tevent_req_error(req, EIO);
+ return;
+ }
+
+ for (i=0; i<state->count; i++) {
+ uint32_t pnn;
+ pnn = state->pnn_list[i];
+ if (state->ban_credits[pnn] > max_credits) {
+ max_pnn = pnn;
+ max_credits = state->ban_credits[pnn];
+ }
+ }
+
+ /* If pulling database fails multiple times */
+ if (max_credits >= NUM_RETRIES) {
+ struct ctdb_req_message message;
+
+ LOG("Assigning banning credits to node %u\n", max_pnn);
+
+ message.srvid = CTDB_SRVID_BANNING;
+ message.data.pnn = max_pnn;
+
+ subreq = ctdb_client_message_send(
+ state, state->ev, state->client,
+ ctdb_client_pnn(state->client),
+ &message);
+ if (tevent_req_nomem(subreq, req)) {
+ return;
+ }
+ tevent_req_set_callback(subreq, recovery_failed_done,
+ req);
+ }
return;
}
tevent_req_set_callback(subreq, recovery_normal_done, req);
}
+static void recovery_failed_done(struct tevent_req *subreq)
+{
+ struct tevent_req *req = tevent_req_callback_data(
+ subreq, struct tevent_req);
+ int ret;
+ bool status;
+
+ status = ctdb_client_message_recv(subreq, &ret);
+ TALLOC_FREE(subreq);
+ if (! status) {
+ LOG("failed to assign banning credits, ret=%d\n", ret);
+ }
+
+ tevent_req_error(req, EIO);
+}
+
static void recovery_normal_done(struct tevent_req *subreq)
{
struct tevent_req *req = tevent_req_callback_data(