2 * Example program to demonstrate the libctdb api
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 3 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, see <http://www.gnu.org/licenses/>.
19 * This program needs to be linked with libtdb and libctdb
20 * (You need these packages installed: libtdb libtdb-devel
21 * ctdb and ctdb-devel)
23 * This program can then be compiled using
24 * gcc -o tst tst.c -ltdb -lctdb
39 #include <ctdb_protocol.h>
44 char *ctdb_addr_to_str(ctdb_sock_addr *addr)
46 static char cip[128] = "";
48 switch (addr->sa.sa_family) {
50 inet_ntop(addr->ip.sin_family, &addr->ip.sin_addr, cip, sizeof(cip));
53 inet_ntop(addr->ip6.sin6_family, &addr->ip6.sin6_addr, cip, sizeof(cip));
56 printf("ERROR, unknown family %u\n", addr->sa.sa_family);
62 void print_nodemap(struct ctdb_node_map *nodemap)
66 printf("number of nodes:%d\n", nodemap->num);
67 for (i=0;i<nodemap->num;i++) {
68 printf("Node:%d Address:%s Flags:%s%s%s%s%s%s\n",
69 nodemap->nodes[i].pnn,
70 ctdb_addr_to_str(&nodemap->nodes[i].addr),
71 nodemap->nodes[i].flags&NODE_FLAGS_DISCONNECTED?"DISCONNECTED ":"",
72 nodemap->nodes[i].flags&NODE_FLAGS_UNHEALTHY?"UNHEALTHY ":"",
73 nodemap->nodes[i].flags&NODE_FLAGS_PERMANENTLY_DISABLED?"ADMIN DISABLED ":"",
74 nodemap->nodes[i].flags&NODE_FLAGS_BANNED?"BANNED ":"",
75 nodemap->nodes[i].flags&NODE_FLAGS_DELETED?"DELETED ":"",
76 nodemap->nodes[i].flags&NODE_FLAGS_STOPPED?"STOPPED ":"");
80 void msg_h(struct ctdb_connection *ctdb, uint64_t srvid, TDB_DATA data, void *private_data)
82 printf("Message received on port %llx : %s\n", srvid, data.dptr);
85 void rip_h(struct ctdb_connection *ctdb, uint64_t srvid, TDB_DATA data, void *private_data)
87 printf("RELEASE IP message for %s\n", data.dptr);
90 void tip_h(struct ctdb_connection *ctdb, uint64_t srvid, TDB_DATA data, void *private_data)
92 printf("TAKE IP message for %s\n", data.dptr);
95 static void gnm_cb(struct ctdb_connection *ctdb,
96 struct ctdb_request *req, void *private)
99 struct ctdb_node_map *nodemap;
101 status = ctdb_getnodemap_recv(ctdb, req, &nodemap);
102 ctdb_request_free(ctdb, req);
104 printf("Error reading NODEMAP\n");
107 printf("ASYNC response to getnodemap:\n");
108 print_nodemap(nodemap);
109 ctdb_free_nodemap(nodemap);
112 void print_ips(struct ctdb_all_public_ips *ips)
116 printf("Num public ips:%d\n", ips->num);
117 for (i=0; i<ips->num;i++) {
118 printf("%s hosted on node %d\n",
119 ctdb_addr_to_str(&ips->ips[i].addr),
124 static void ips_cb(struct ctdb_connection *ctdb,
125 struct ctdb_request *req, void *private)
128 struct ctdb_all_public_ips *ips;
130 status = ctdb_getpublicips_recv(ctdb, req, &ips);
131 ctdb_request_free(ctdb, req);
133 printf("Error reading PUBLIC IPS\n");
136 printf("ASYNC response to getpublicips:\n");
138 ctdb_free_publicips(ips);
141 static void pnn_cb(struct ctdb_connection *ctdb,
142 struct ctdb_request *req, void *private)
147 status = ctdb_getpnn_recv(ctdb, req, &pnn);
148 ctdb_request_free(ctdb, req);
150 printf("Error reading PNN\n");
153 printf("ASYNC RESPONSE TO GETPNN: pnn:%d\n", pnn);
156 static void rm_cb(struct ctdb_connection *ctdb,
157 struct ctdb_request *req, void *private)
162 status = ctdb_getrecmaster_recv(ctdb, req, &rm);
163 ctdb_request_free(ctdb, req);
165 printf("Error reading RECMASTER\n");
169 printf("GETRECMASTER ASYNC: recmaster:%d\n", rm);
173 * example on how to first read(non-existing recortds are implicitely created
174 * on demand) a record and change it in the callback.
175 * This forms the atom for the read-modify-write cycle.
177 * Pure read, or pure write are just special cases of this cycle.
179 static void rrl_cb(struct ctdb_db *ctdb_db,
180 struct ctdb_lock *lock, TDB_DATA outdata, void *private)
184 bool *rrl_cb_called = private;
186 *rrl_cb_called = true;
189 printf("rrl_cb returned error\n");
193 printf("rrl size:%d data:%.*s\n", outdata.dsize,
194 outdata.dsize, outdata.dptr);
195 if (outdata.dsize == 0) {
198 strcpy(tmp, outdata.dptr);
203 data.dsize = strlen(tmp) + 1;
204 if (!ctdb_writerecord(ctdb_db, lock, data))
205 printf("Error writing data!\n");
207 /* Release the lock as quickly as possible */
208 ctdb_release_lock(ctdb_db, lock);
210 printf("Wrote new record : %s\n", tmp);
214 static bool registered = false;
215 void message_handler_cb(struct ctdb_connection *ctdb,
216 struct ctdb_request *req, void *private)
218 if (!ctdb_set_message_handler_recv(ctdb, req)) {
219 err(1, "registering message");
221 ctdb_request_free(ctdb, req);
222 printf("Message handler registered\n");
226 int main(int argc, char *argv[])
228 struct ctdb_connection *ctdb_connection;
229 struct ctdb_request *handle;
230 struct ctdb_db *ctdb_db_context;
231 struct ctdb_node_map *nodemap;
235 bool rrl_cb_called = false;
238 ctdb_log_level = LOG_DEBUG;
239 ctdb_connection = ctdb_connect("/tmp/ctdb.socket",
240 ctdb_log_file, stderr);
241 if (!ctdb_connection)
242 err(1, "Connecting to /tmp/ctdb.socket");
244 pfd.fd = ctdb_get_fd(ctdb_connection);
246 srvid = CTDB_SRVID_TEST_RANGE|55;
247 handle = ctdb_set_message_handler_send(ctdb_connection, srvid,
249 message_handler_cb, &srvid);
250 if (handle == NULL) {
251 printf("Failed to register message port\n");
255 /* Hack for testing: this makes sure registrations went out. */
256 while (!registered) {
257 ctdb_service(ctdb_connection, POLLIN|POLLOUT);
260 handle = ctdb_set_message_handler_send(ctdb_connection,
261 CTDB_SRVID_RELEASE_IP,
263 message_handler_cb, NULL);
264 if (handle == NULL) {
265 printf("Failed to register message port for RELEASE IP\n");
269 handle = ctdb_set_message_handler_send(ctdb_connection,
272 message_handler_cb, NULL);
273 if (handle == NULL) {
274 printf("Failed to register message port for TAKE IP\n");
278 msg.dptr="HelloWorld";
279 msg.dsize = strlen(msg.dptr);
281 srvid = CTDB_SRVID_TEST_RANGE|55;
282 if (!ctdb_send_message(ctdb_connection, 0, srvid, msg)) {
283 printf("Failed to send message. Aborting\n");
287 handle = ctdb_getrecmaster_send(ctdb_connection, 0, rm_cb, NULL);
288 if (handle == NULL) {
289 printf("Failed to send get_recmaster control\n");
293 ctdb_db_context = ctdb_attachdb(ctdb_connection, "test_test.tdb",
295 if (!ctdb_db_context) {
296 printf("Failed to attach to database\n");
301 * SYNC call with callback to read the recmaster
302 * calls the blocking sync function.
303 * Avoid this mode for performance critical tasks
305 if (!ctdb_getrecmaster(ctdb_connection, CTDB_CURRENT_NODE, &recmaster)) {
306 printf("Failed to receive response to getrecmaster\n");
309 printf("GETRECMASTER SYNC: recmaster:%d\n", recmaster);
312 handle = ctdb_getpnn_send(ctdb_connection, CTDB_CURRENT_NODE,
314 if (handle == NULL) {
315 printf("Failed to send get_pnn control\n");
319 /* In the non-contended case the callback might be invoked
320 * immediately, before ctdb_readrecordlock_async() returns.
321 * In the contended case the callback will be invoked later.
323 * Normally an application would not care whether the callback
324 * has already been invoked here or not, but if the application
325 * needs to know, it can use the *private_data pointer
326 * to pass data through to the callback and back.
328 if (!ctdb_readrecordlock_async(ctdb_db_context, key,
329 rrl_cb, &rrl_cb_called)) {
330 printf("Failed to send READRECORDLOCK\n");
333 if (!rrl_cb_called) {
334 printf("READRECORDLOCK is async\n");
338 * Read the nodemap from a node (async)
340 handle = ctdb_getnodemap_send(ctdb_connection, CTDB_CURRENT_NODE,
342 if (handle == NULL) {
343 printf("Failed to send get_nodemap control\n");
348 * Read the list of public ips from a node (async)
350 handle = ctdb_getpublicips_send(ctdb_connection, CTDB_CURRENT_NODE,
352 if (handle == NULL) {
353 printf("Failed to send getpublicips control\n");
358 * Read the nodemap from a node (sync)
360 if (!ctdb_getnodemap(ctdb_connection, CTDB_CURRENT_NODE,
362 printf("Failed to receive response to getrecmaster\n");
365 printf("SYNC response to getnodemap:\n");
366 print_nodemap(nodemap);
367 ctdb_free_nodemap(nodemap);
371 pfd.events = ctdb_which_events(ctdb_connection);
372 if (poll(&pfd, 1, -1) < 0) {
373 printf("Poll failed");
376 if (ctdb_service(ctdb_connection, pfd.revents) < 0) {
377 err(1, "Failed to service");