2 ctdb_control protocol code
4 Copyright (C) Andrew Tridgell 2007
6 This library is free software; you can redistribute it and/or
7 modify it under the terms of the GNU Lesser General Public
8 License as published by the Free Software Foundation; either
9 version 2 of the License, or (at your option) any later version.
11 This library is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Lesser General Public License for more details.
16 You should have received a copy of the GNU Lesser General Public
17 License along with this library; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 #include "lib/events/events.h"
22 #include "lib/tdb/include/tdb.h"
23 #include "system/network.h"
24 #include "system/filesys.h"
25 #include "system/wait.h"
26 #include "../include/ctdb_private.h"
27 #include "lib/util/dlinklist.h"
29 struct ctdb_control_state {
30 struct ctdb_context *ctdb;
32 ctdb_control_callback_fn_t callback;
36 #define CHECK_CONTROL_DATA_SIZE(size) do { \
37 if (indata.dsize != size) { \
38 DEBUG(0,(__location__ " Invalid data size in opcode %u. Got %u expected %u\n", \
39 opcode, indata.dsize, size)); \
45 process a control request
47 static int32_t ctdb_control_dispatch(struct ctdb_context *ctdb,
48 uint32_t opcode, TDB_DATA indata,
52 case CTDB_CONTROL_PROCESS_EXISTS: {
54 CHECK_CONTROL_DATA_SIZE(sizeof(pid));
55 pid = *(pid_t *)indata.dptr;
59 case CTDB_CONTROL_SET_DEBUG: {
60 CHECK_CONTROL_DATA_SIZE(sizeof(uint32_t));
61 LogLevel = *(uint32_t *)indata.dptr;
65 case CTDB_CONTROL_GET_DEBUG: {
66 CHECK_CONTROL_DATA_SIZE(0);
67 outdata->dptr = (uint8_t *)&LogLevel;
68 outdata->dsize = sizeof(LogLevel);
72 case CTDB_CONTROL_STATUS: {
73 CHECK_CONTROL_DATA_SIZE(0);
74 outdata->dptr = (uint8_t *)&ctdb->status;
75 outdata->dsize = sizeof(ctdb->status);
79 case CTDB_CONTROL_GETVNNMAP: {
81 CHECK_CONTROL_DATA_SIZE(0);
82 len = 2+ctdb->vnn_map->size;
83 outdata->dsize = 4*len;
84 outdata->dptr = (unsigned char *)talloc_array(outdata, uint32_t, len);
86 ((uint32_t *)outdata->dptr)[0] = ctdb->vnn_map->generation;
87 ((uint32_t *)outdata->dptr)[1] = ctdb->vnn_map->size;
88 for (i=0;i<ctdb->vnn_map->size;i++) {
89 ((uint32_t *)outdata->dptr)[i+2] = ctdb->vnn_map->map[i];
95 case CTDB_CONTROL_SETVNNMAP: {
98 ptr = (uint32_t *)(&indata.dptr[0]);
99 ctdb->vnn_map->generation = ptr[0];
100 ctdb->vnn_map->size = ptr[1];
101 if (ctdb->vnn_map->map) {
102 talloc_free(ctdb->vnn_map->map);
103 ctdb->vnn_map->map = NULL;
105 ctdb->vnn_map->map = talloc_array(ctdb->vnn_map, uint32_t, ctdb->vnn_map->size);
106 if (ctdb->vnn_map->map == NULL) {
107 DEBUG(0,(__location__ " Unable to allocate vnn_map->map structure\n"));
110 for (i=0;i<ctdb->vnn_map->size;i++) {
111 ctdb->vnn_map->map[i] = ptr[i+2];
116 case CTDB_CONTROL_CONFIG: {
117 CHECK_CONTROL_DATA_SIZE(0);
118 outdata->dptr = (uint8_t *)ctdb;
119 outdata->dsize = sizeof(*ctdb);
123 case CTDB_CONTROL_PING:
124 CHECK_CONTROL_DATA_SIZE(0);
127 case CTDB_CONTROL_GETDBPATH: {
129 struct ctdb_db_context *ctdb_db;
131 CHECK_CONTROL_DATA_SIZE(sizeof(db_id));
132 db_id = *(uint32_t *)indata.dptr;
133 ctdb_db = find_ctdb_db(ctdb, db_id);
134 if (ctdb_db == NULL) return -1;
135 outdata->dptr = discard_const(ctdb_db->db_path);
136 outdata->dsize = strlen(ctdb_db->db_path)+1;
141 DEBUG(0,(__location__ " Unknown CTDB control opcode %u\n", opcode));
147 called when a CTDB_REQ_CONTROL packet comes in
149 void ctdb_request_control(struct ctdb_context *ctdb, struct ctdb_req_header *hdr)
151 struct ctdb_req_control *c = (struct ctdb_req_control *)hdr;
152 TDB_DATA data, *outdata;
153 struct ctdb_reply_control *r;
157 data.dptr = &c->data[0];
158 data.dsize = c->datalen;
160 outdata = talloc_zero(c, TDB_DATA);
161 status = ctdb_control_dispatch(ctdb, c->opcode, data, outdata);
163 len = offsetof(struct ctdb_reply_control, data) + outdata->dsize;
164 r = ctdb->methods->allocate_pkt(ctdb, len);
165 CTDB_NO_MEMORY_VOID(ctdb, r);
166 talloc_set_name_const(r, "ctdb_reply_control packet");
169 r->hdr.ctdb_magic = CTDB_MAGIC;
170 r->hdr.ctdb_version = CTDB_VERSION;
171 r->hdr.operation = CTDB_REPLY_CONTROL;
172 r->hdr.destnode = hdr->srcnode;
173 r->hdr.srcnode = ctdb->vnn;
174 r->hdr.reqid = hdr->reqid;
176 r->datalen = outdata->dsize;
177 if (outdata->dsize) {
178 memcpy(&r->data[0], outdata->dptr, outdata->dsize);
181 ctdb_queue_packet(ctdb, &r->hdr);
187 called when a CTDB_REPLY_CONTROL packet comes in
189 void ctdb_reply_control(struct ctdb_context *ctdb, struct ctdb_req_header *hdr)
191 struct ctdb_reply_control *c = (struct ctdb_reply_control *)hdr;
193 struct ctdb_control_state *state;
195 state = ctdb_reqid_find(ctdb, hdr->reqid, struct ctdb_control_state);
200 if (hdr->reqid != state->reqid) {
201 /* we found a record but it was the wrong one */
202 DEBUG(0, ("Dropped orphaned control reply with reqid:%d\n", hdr->reqid));
206 data.dptr = &c->data[0];
207 data.dsize = c->datalen;
209 state->callback(ctdb, c->status, data, state->private_data);
213 static int ctdb_control_destructor(struct ctdb_control_state *state)
215 ctdb_reqid_remove(state->ctdb, state->reqid);
220 send a control message to a node
222 int ctdb_daemon_send_control(struct ctdb_context *ctdb, uint32_t destnode,
223 uint32_t srvid, uint32_t opcode, TDB_DATA data,
224 ctdb_control_callback_fn_t callback,
227 struct ctdb_req_control *c;
228 struct ctdb_control_state *state;
231 state = talloc(ctdb, struct ctdb_control_state);
232 CTDB_NO_MEMORY(ctdb, state);
234 state->reqid = ctdb_reqid_new(ctdb, state);
235 state->callback = callback;
236 state->private_data = private_data;
239 talloc_set_destructor(state, ctdb_control_destructor);
241 len = offsetof(struct ctdb_req_control, data) + data.dsize;
242 c = ctdb->methods->allocate_pkt(state, len);
243 CTDB_NO_MEMORY(ctdb, c);
244 talloc_set_name_const(c, "ctdb_req_control packet");
247 c->hdr.ctdb_magic = CTDB_MAGIC;
248 c->hdr.ctdb_version = CTDB_VERSION;
249 c->hdr.operation = CTDB_REQ_CONTROL;
250 c->hdr.destnode = destnode;
251 c->hdr.srcnode = ctdb->vnn;
252 c->hdr.reqid = state->reqid;
255 c->datalen = data.dsize;
257 memcpy(&c->data[0], data.dptr, data.dsize);
260 ctdb_queue_packet(ctdb, &c->hdr);
263 event_add_timed(ctdb->ev, state, timeval_current_ofs(CTDB_REQ_TIMEOUT, 0),
264 ctdb_control_timeout, state);