diff options
-rw-r--r-- | ctdb/include/ctdb_private.h | 9 | ||||
-rw-r--r-- | ctdb/server/ctdb_control.c | 6 | ||||
-rw-r--r-- | ctdb/server/ctdb_daemon.c | 6 | ||||
-rw-r--r-- | ctdb/server/ctdb_persistent.c | 48 |
4 files changed, 69 insertions, 0 deletions
diff --git a/ctdb/include/ctdb_private.h b/ctdb/include/ctdb_private.h index 4124f649fc..66e7709312 100644 --- a/ctdb/include/ctdb_private.h +++ b/ctdb/include/ctdb_private.h @@ -161,6 +161,7 @@ struct ctdb_client { uint32_t client_id; pid_t pid; struct ctdb_tcp_list *tcp_list; + uint32_t num_persistent_updates; }; @@ -544,6 +545,8 @@ enum ctdb_controls {CTDB_CONTROL_PROCESS_EXISTS = 0, CTDB_CONTROL_DEL_PUBLIC_IP = 78, CTDB_CONTROL_RUN_EVENTSCRIPTS = 79, CTDB_CONTROL_GET_CAPABILITIES = 80, + CTDB_CONTROL_START_PERSISTENT_UPDATE = 81, + CTDB_CONTROL_CANCEL_PERSISTENT_UPDATE= 82, }; /* @@ -812,6 +815,12 @@ int ctdb_ltdb_store(struct ctdb_db_context *ctdb_db, TDB_DATA key, struct ctdb_ltdb_header *header, TDB_DATA data); int ctdb_ltdb_persistent_store(struct ctdb_db_context *ctdb_db, TDB_DATA key, struct ctdb_ltdb_header *header, TDB_DATA data); +int32_t ctdb_control_start_persistent_update(struct ctdb_context *ctdb, + struct ctdb_req_control *c, + TDB_DATA recdata); +int32_t ctdb_control_cancel_persistent_update(struct ctdb_context *ctdb, + struct ctdb_req_control *c, + TDB_DATA recdata); void ctdb_queue_packet(struct ctdb_context *ctdb, struct ctdb_req_header *hdr); void ctdb_queue_packet_opcode(struct ctdb_context *ctdb, struct ctdb_req_header *hdr, unsigned opcode); int ctdb_ltdb_lock_requeue(struct ctdb_db_context *ctdb_db, diff --git a/ctdb/server/ctdb_control.c b/ctdb/server/ctdb_control.c index aaadbaee0a..1ae8e85cac 100644 --- a/ctdb/server/ctdb_control.c +++ b/ctdb/server/ctdb_control.c @@ -394,6 +394,12 @@ static int32_t ctdb_control_dispatch(struct ctdb_context *ctdb, case CTDB_CONTROL_GET_CAPABILITIES: return ctdb_control_get_capabilities(ctdb, outdata); + case CTDB_CONTROL_START_PERSISTENT_UPDATE: + return ctdb_control_start_persistent_update(ctdb, c, indata); + + case CTDB_CONTROL_CANCEL_PERSISTENT_UPDATE: + return ctdb_control_cancel_persistent_update(ctdb, c, indata); + default: DEBUG(DEBUG_CRIT,(__location__ " Unknown CTDB control opcode %u\n", opcode)); return -1; diff --git a/ctdb/server/ctdb_daemon.c b/ctdb/server/ctdb_daemon.c index c153a97570..aeb0cbde38 100644 --- a/ctdb/server/ctdb_daemon.c +++ b/ctdb/server/ctdb_daemon.c @@ -210,6 +210,12 @@ static int ctdb_client_destructor(struct ctdb_client *client) ctdb_takeover_client_destructor_hook(client); ctdb_reqid_remove(client->ctdb, client->client_id); client->ctdb->statistics.num_clients--; + + if (client->num_persistent_updates != 0) { + DEBUG(DEBUG_ERR,(__location__ " Client disconnecting with %u persistent updates in flight. Starting recovery\n", client->num_persistent_updates)); + client->ctdb->recovery_mode = CTDB_RECOVERY_ACTIVE; + } + return 0; } diff --git a/ctdb/server/ctdb_persistent.c b/ctdb/server/ctdb_persistent.c index 713950a0c9..66311a9f89 100644 --- a/ctdb/server/ctdb_persistent.c +++ b/ctdb/server/ctdb_persistent.c @@ -81,9 +81,16 @@ int32_t ctdb_control_persistent_store(struct ctdb_context *ctdb, struct ctdb_req_control *c, TDB_DATA recdata, bool *async_reply) { + struct ctdb_client *client = ctdb_reqid_find(ctdb, c->client_id, struct ctdb_client); struct ctdb_persistent_state *state; int i; + if (client == NULL) { + DEBUG(DEBUG_ERR,(__location__ " can not match persistent_store to a client. Returning error\n")); + return -1; + } + client->num_persistent_updates--; + state = talloc_zero(ctdb, struct ctdb_persistent_state); CTDB_NO_MEMORY(ctdb, state); @@ -410,3 +417,44 @@ int32_t ctdb_control_update_record(struct ctdb_context *ctdb, return 0; } + + + +/* + start a persistent store operation. passing both the key, header and + data to the daemon. If the client disconnects before it has issued + a persistent_update call to the daemon we trigger a full recovery + to ensure the databases are brought back in sync. + for now we ignore the recdata that the client has passed to us. + */ +int32_t ctdb_control_start_persistent_update(struct ctdb_context *ctdb, + struct ctdb_req_control *c, + TDB_DATA recdata) +{ + struct ctdb_client *client = ctdb_reqid_find(ctdb, c->client_id, struct ctdb_client); + + if (client == NULL) { + DEBUG(DEBUG_ERR,(__location__ " can not match start_persistent_update to a client. Returning error\n")); + return -1; + } + + client->num_persistent_updates++; + + return 0; +} + +int32_t ctdb_control_cancel_persistent_update(struct ctdb_context *ctdb, + struct ctdb_req_control *c, + TDB_DATA recdata) +{ + struct ctdb_client *client = ctdb_reqid_find(ctdb, c->client_id, struct ctdb_client); + + if (client == NULL) { + DEBUG(DEBUG_ERR,(__location__ " can not match cancel_persistent_update to a client. Returning error\n")); + return -1; + } + + client->num_persistent_updates--; + + return 0; +} |