add a gplv3 boilerplate to the example application for libctdb
[sahlberg/ctdb.git] / libctdb / tst.c
1 /*
2  * Example program to demonstrate the libctdb api
3  *
4  * This program needs to be linked with libtdb.
5  * (libtdb and libtdb-devel packages)
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 3 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, see <http://www.gnu.org/licenses/>.
19  */
20 #include <stdio.h>
21 #include <stdint.h>
22 #include <poll.h>
23 #include <fcntl.h>
24 #include <string.h>
25 #include <stdlib.h>
26 #include <err.h>
27 #include <stdbool.h>
28 #include "lib/tdb/include/tdb.h"
29 #include "include/ctdb.h"
30
31 TDB_DATA key;
32
33 void msg_h(struct ctdb_connection *ctdb, uint64_t srvid, TDB_DATA data, void *private_data)
34 {
35         printf("Message received on port %d : %s\n", (int)srvid, data.dptr);
36 }
37
38 static void pnn_cb(struct ctdb_connection *ctdb,
39                    struct ctdb_request *req, void *private)
40 {
41         int status;
42         uint32_t pnn;
43
44         status = ctdb_getpnn_recv(req, &pnn);
45         if (status != 0) {
46                 printf("Error reading PNN\n");
47                 return;
48         }
49         printf("status:%d pnn:%d\n", status, pnn);
50 }
51
52 static void rm_cb(struct ctdb_connection *ctdb,
53                   struct ctdb_request *req, void *private)
54 {
55         int status;
56         uint32_t rm;
57
58         status = ctdb_getrecmaster_recv(req, &rm);
59         if (status != 0) {
60                 printf("Error reading RECMASTER\n");
61                 return;
62         }
63
64         printf("GETRECMASTER ASYNC: status:%d recmaster:%d\n", status, rm);
65 }
66
67 /*
68  * example on how to first read(non-existing recortds are implicitely created
69  * on demand) a record and change it in the callback.
70  * This forms the atom for the read-modify-write cycle.
71  *
72  * Pure read, or pure write are just special cases of this cycle.
73  */
74 static void rrl_cb(struct ctdb_connection *ctdb,
75                   struct ctdb_request *req, void *private)
76 {
77         struct ctdb_lock *lock;
78         TDB_DATA outdata;
79         TDB_DATA data;
80         char tmp[256];
81
82         lock = ctdb_readrecordlock_recv(private, req, &outdata);
83         if (!lock) {
84                 printf("rrl_cb returned error\n");
85                 return;
86         }
87
88         printf("rrl size:%d data:%.*s\n", outdata.dsize,
89                outdata.dsize, outdata.dptr);
90         if (outdata.dsize == 0) {
91                 tmp[0] = 0;
92         } else {
93                 strcpy(tmp, outdata.dptr);
94         }
95         strcat(tmp, "*");
96
97         data.dptr  = tmp;
98         data.dsize = strlen(tmp) + 1;
99         ctdb_writerecord(lock, data);
100
101         printf("Wrote new record : %s\n", tmp);
102
103         ctdb_release_lock(lock);
104 }
105
106 static bool registered = false;
107 void message_handler_cb(struct ctdb_connection *ctdb,
108                         struct ctdb_request *req, void *private)
109 {
110         if (ctdb_set_message_handler_recv(ctdb, req) != 0) {
111                 err(1, "registering message");
112         }
113         printf("Message handler registered\n");
114         registered = true;
115 }
116
117 int main(int argc, char *argv[])
118 {
119         struct ctdb_connection *ctdb_connection;
120         struct ctdb_request *handle;
121         struct ctdb_db *ctdb_db_context;
122         struct pollfd pfd;
123         uint32_t recmaster;
124         int ret;
125         TDB_DATA msg;
126
127         ctdb_connection = ctdb_connect("/tmp/ctdb.socket");
128         if (!ctdb_connection)
129                 err(1, "Connecting to /tmp/ctdb.socket");
130
131         pfd.fd = ctdb_get_fd(ctdb_connection);
132
133         handle = ctdb_set_message_handler_send(ctdb_connection, 55, msg_h,
134                                                message_handler_cb, NULL);
135         if (handle == NULL) {
136                 printf("Failed to register message port\n");
137                 exit(10);
138         }
139
140         /* Hack for testing: this makes sure registration goes out. */
141         while (!registered) {
142                 ctdb_service(ctdb_connection, POLLIN|POLLOUT);
143         }
144
145         msg.dptr="HelloWorld";
146         msg.dsize = strlen(msg.dptr);
147
148         ret = ctdb_send_message(ctdb_connection, 0, 55, msg);
149         if (ret != 0) {
150                 printf("Failed to send message. Aborting\n");
151                 exit(10);
152         }
153
154         handle = ctdb_getrecmaster_send(ctdb_connection, 0, rm_cb, NULL);
155         if (handle == NULL) {
156                 printf("Failed to send get_recmaster control\n");
157                 exit(10);
158         }
159
160         ctdb_db_context = ctdb_attachdb(ctdb_connection, "test_test.tdb", 0, 0);
161         if (!ctdb_db_context) {
162                 printf("Failed to attach to database\n");
163                 exit(10);
164         }
165
166         /*
167          * SYNC call with callback to read the recmaster
168          * calls the blocking sync function.
169          * Avoid this mode for performance critical tasks
170          */
171         ret = ctdb_getrecmaster(ctdb_connection, CTDB_CURRENT_NODE, &recmaster);
172         if (ret != 0) {
173                 printf("Failed to receive response to getrecmaster\n");
174                 exit(10);
175         }
176         printf("GETRECMASTER SYNC: status:%d recmaster:%d\n", ret, recmaster);
177
178
179         handle = ctdb_getpnn_send(ctdb_connection, CTDB_CURRENT_NODE,
180                                   pnn_cb, NULL);
181         if (handle == NULL) {
182                 printf("Failed to send get_pnn control\n");
183                 exit(10);
184         }
185
186         if (!ctdb_readrecordlock_send(ctdb_db_context, key, &handle,
187                                       rrl_cb, ctdb_db_context)) {
188                 printf("Failed to send READRECORDLOCK\n");
189                 exit(10);
190         }
191         if (handle) {
192                 printf("READRECORDLOCK is async\n");
193         }
194         for (;;) {
195
196           pfd.events = ctdb_which_events(ctdb_connection);
197           if (poll(&pfd, 1, -1) < 0) {
198             printf("Poll failed");
199             exit(10);
200           }
201           if (ctdb_service(ctdb_connection, pfd.revents) < 0) {
202                   err(1, "Failed to service");
203           }
204         }
205
206         return 0;
207 }