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
42 void msg_h(struct ctdb_connection *ctdb, uint64_t srvid, TDB_DATA data, void *private_data)
44 printf("Message received on port %d : %s\n", (int)srvid, data.dptr);
47 static void pnn_cb(struct ctdb_connection *ctdb,
48 struct ctdb_request *req, void *private)
53 status = ctdb_getpnn_recv(ctdb, req, &pnn);
54 ctdb_request_free(ctdb, req);
56 printf("Error reading PNN\n");
59 printf("pnn:%d\n", pnn);
62 static void rm_cb(struct ctdb_connection *ctdb,
63 struct ctdb_request *req, void *private)
68 status = ctdb_getrecmaster_recv(ctdb, req, &rm);
69 ctdb_request_free(ctdb, req);
71 printf("Error reading RECMASTER\n");
75 printf("GETRECMASTER ASYNC: recmaster:%d\n", rm);
79 * example on how to first read(non-existing recortds are implicitely created
80 * on demand) a record and change it in the callback.
81 * This forms the atom for the read-modify-write cycle.
83 * Pure read, or pure write are just special cases of this cycle.
85 static void rrl_cb(struct ctdb_db *ctdb_db,
86 struct ctdb_lock *lock, TDB_DATA outdata, void *private)
90 bool *rrl_cb_called = private;
92 *rrl_cb_called = true;
95 printf("rrl_cb returned error\n");
99 printf("rrl size:%d data:%.*s\n", outdata.dsize,
100 outdata.dsize, outdata.dptr);
101 if (outdata.dsize == 0) {
104 strcpy(tmp, outdata.dptr);
109 data.dsize = strlen(tmp) + 1;
110 if (!ctdb_writerecord(ctdb_db, lock, data))
111 printf("Error writing data!\n");
113 /* Release the lock as quickly as possible */
114 ctdb_release_lock(ctdb_db, lock);
116 printf("Wrote new record : %s\n", tmp);
120 static bool registered = false;
121 void message_handler_cb(struct ctdb_connection *ctdb,
122 struct ctdb_request *req, void *private)
124 if (!ctdb_set_message_handler_recv(ctdb, req)) {
125 err(1, "registering message");
127 ctdb_request_free(ctdb, req);
128 printf("Message handler registered\n");
132 int main(int argc, char *argv[])
134 struct ctdb_connection *ctdb_connection;
135 struct ctdb_request *handle;
136 struct ctdb_db *ctdb_db_context;
140 bool rrl_cb_called = false;
142 ctdb_log_level = LOG_DEBUG;
143 ctdb_connection = ctdb_connect("/tmp/ctdb.socket",
144 ctdb_log_file, stderr);
145 if (!ctdb_connection)
146 err(1, "Connecting to /tmp/ctdb.socket");
148 pfd.fd = ctdb_get_fd(ctdb_connection);
150 handle = ctdb_set_message_handler_send(ctdb_connection, 55,
152 message_handler_cb, NULL);
153 if (handle == NULL) {
154 printf("Failed to register message port\n");
158 /* Hack for testing: this makes sure registration goes out. */
159 while (!registered) {
160 ctdb_service(ctdb_connection, POLLIN|POLLOUT);
163 msg.dptr="HelloWorld";
164 msg.dsize = strlen(msg.dptr);
166 if (!ctdb_send_message(ctdb_connection, 0, 55, msg)) {
167 printf("Failed to send message. Aborting\n");
171 handle = ctdb_getrecmaster_send(ctdb_connection, 0, rm_cb, NULL);
172 if (handle == NULL) {
173 printf("Failed to send get_recmaster control\n");
177 ctdb_db_context = ctdb_attachdb(ctdb_connection, "test_test.tdb",
179 if (!ctdb_db_context) {
180 printf("Failed to attach to database\n");
185 * SYNC call with callback to read the recmaster
186 * calls the blocking sync function.
187 * Avoid this mode for performance critical tasks
189 if (!ctdb_getrecmaster(ctdb_connection, CTDB_CURRENT_NODE, &recmaster)) {
190 printf("Failed to receive response to getrecmaster\n");
193 printf("GETRECMASTER SYNC: recmaster:%d\n", recmaster);
196 handle = ctdb_getpnn_send(ctdb_connection, CTDB_CURRENT_NODE,
198 if (handle == NULL) {
199 printf("Failed to send get_pnn control\n");
203 /* In the non-contended case the callback might be invoked
204 * immediately, before ctdb_readrecordlock_async() returns.
205 * In the contended case the callback will be invoked later.
207 * Normally an application would not care whether the callback
208 * has already been invoked here or not, but if the application
209 * needs to know, it can use the *private_data pointer
210 * to pass data through to the callback and back.
212 if (!ctdb_readrecordlock_async(ctdb_db_context, key,
213 rrl_cb, &rrl_cb_called)) {
214 printf("Failed to send READRECORDLOCK\n");
217 if (!rrl_cb_called) {
218 printf("READRECORDLOCK is async\n");
222 pfd.events = ctdb_which_events(ctdb_connection);
223 if (poll(&pfd, 1, -1) < 0) {
224 printf("Poll failed");
227 if (ctdb_service(ctdb_connection, pfd.revents) < 0) {
228 err(1, "Failed to service");