summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ctdb/include/ctdb_private.h9
-rw-r--r--ctdb/server/ctdb_control.c6
-rw-r--r--ctdb/server/ctdb_daemon.c6
-rw-r--r--ctdb/server/ctdb_persistent.c48
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;
+}