r22226: move discard_const macros to librelace
[Samba.git] / source / cluster / ctdb / tests / ctdb_test.c
blob908a2eaac750385d957ebb7d2bc339844a33ae74
1 /*
2 ctdb test harness
4 Copyright (C) Andrew Tridgell 2006
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 "includes.h"
22 #include "lib/events/events.h"
23 #include "system/filesys.h"
24 #include "popt.h"
26 enum my_functions {FUNC_SORT=1, FUNC_FETCH=2};
28 static int int_compare(int *i1, int *i2)
30 return *i1 - *i2;
34 add an integer into a record in sorted order
36 static int sort_func(struct ctdb_call_info *call)
38 if (call->call_data == NULL ||
39 call->call_data->dsize != sizeof(int)) {
40 return CTDB_ERR_INVALID;
42 call->new_data = talloc(call, TDB_DATA);
43 if (call->new_data == NULL) {
44 return CTDB_ERR_NOMEM;
46 call->new_data->dptr = talloc_size(call,
47 call->record_data.dsize +
48 call->call_data->dsize);
49 if (call->new_data->dptr == NULL) {
50 return CTDB_ERR_NOMEM;
52 call->new_data->dsize = call->record_data.dsize + call->call_data->dsize;
53 memcpy(call->new_data->dptr,
54 call->record_data.dptr, call->record_data.dsize);
55 memcpy(call->new_data->dptr+call->record_data.dsize,
56 call->call_data->dptr, call->call_data->dsize);
58 qsort(call->new_data->dptr, call->new_data->dsize / sizeof(int),
59 sizeof(int), (comparison_fn_t)int_compare);
61 return 0;
65 ctdb call function to fetch a record
67 static int fetch_func(struct ctdb_call_info *call)
69 call->reply_data = &call->record_data;
70 return 0;
74 main program
76 int main(int argc, const char *argv[])
78 struct ctdb_context *ctdb;
79 struct ctdb_db_context *ctdb_db;
80 const char *nlist = NULL;
81 const char *transport = "tcp";
82 const char *myaddress = NULL;
83 int self_connect=0;
85 struct poptOption popt_options[] = {
86 POPT_AUTOHELP
87 { "nlist", 0, POPT_ARG_STRING, &nlist, 0, "node list file", "filename" },
88 { "listen", 0, POPT_ARG_STRING, &myaddress, 0, "address to listen on", "address" },
89 { "transport", 0, POPT_ARG_STRING, &transport, 0, "protocol transport", NULL },
90 { "self-connect", 0, POPT_ARG_NONE, &self_connect, 0, "enable self connect", "boolean" },
91 POPT_TABLEEND
93 int opt;
94 const char **extra_argv;
95 int extra_argc = 0;
96 int i, ret;
97 poptContext pc;
98 struct event_context *ev;
99 struct ctdb_call call;
101 pc = poptGetContext(argv[0], argc, argv, popt_options, POPT_CONTEXT_KEEP_FIRST);
103 while ((opt = poptGetNextOpt(pc)) != -1) {
104 switch (opt) {
105 default:
106 fprintf(stderr, "Invalid option %s: %s\n",
107 poptBadOption(pc, 0), poptStrerror(opt));
108 exit(1);
112 /* setup the remaining options for the main program to use */
113 extra_argv = poptGetArgs(pc);
114 if (extra_argv) {
115 extra_argv++;
116 while (extra_argv[extra_argc]) extra_argc++;
119 if (nlist == NULL || myaddress == NULL) {
120 printf("You must provide a node list with --nlist and an address with --listen\n");
121 exit(1);
124 ev = event_context_init(NULL);
126 /* initialise ctdb */
127 ctdb = ctdb_init(ev);
128 if (ctdb == NULL) {
129 printf("Failed to init ctdb\n");
130 exit(1);
133 if (self_connect) {
134 ctdb_set_flags(ctdb, CTDB_FLAG_SELF_CONNECT);
137 ret = ctdb_set_transport(ctdb, transport);
138 if (ret == -1) {
139 printf("ctdb_set_transport failed - %s\n", ctdb_errstr(ctdb));
140 exit(1);
143 /* tell ctdb what address to listen on */
144 ret = ctdb_set_address(ctdb, myaddress);
145 if (ret == -1) {
146 printf("ctdb_set_address failed - %s\n", ctdb_errstr(ctdb));
147 exit(1);
150 /* tell ctdb what nodes are available */
151 ret = ctdb_set_nlist(ctdb, nlist);
152 if (ret == -1) {
153 printf("ctdb_set_nlist failed - %s\n", ctdb_errstr(ctdb));
154 exit(1);
157 /* attach to a specific database */
158 ctdb_db = ctdb_attach(ctdb, "test.tdb", TDB_DEFAULT, O_RDWR|O_CREAT|O_TRUNC, 0666);
159 if (!ctdb_db) {
160 printf("ctdb_attach failed - %s\n", ctdb_errstr(ctdb));
161 exit(1);
164 /* setup a ctdb call function */
165 ret = ctdb_set_call(ctdb_db, sort_func, FUNC_SORT);
166 ret = ctdb_set_call(ctdb_db, fetch_func, FUNC_FETCH);
168 /* start the protocol running */
169 ret = ctdb_start(ctdb);
171 /* wait until all nodes are connected (should not be needed
172 outide of test code) */
173 ctdb_connect_wait(ctdb);
175 ZERO_STRUCT(call);
176 call.key.dptr = discard_const("test");
177 call.key.dsize = strlen("test")+1;
179 /* add some random data */
180 for (i=0;i<10;i++) {
181 int v = random() % 1000;
183 call.call_id = FUNC_SORT;
184 call.call_data.dptr = (uint8_t *)&v;
185 call.call_data.dsize = sizeof(v);
187 ret = ctdb_call(ctdb_db, &call);
188 if (ret == -1) {
189 printf("ctdb_call FUNC_SORT failed - %s\n", ctdb_errstr(ctdb));
190 exit(1);
194 /* fetch the record */
195 call.call_id = FUNC_FETCH;
196 call.call_data.dptr = NULL;
197 call.call_data.dsize = 0;
199 ret = ctdb_call(ctdb_db, &call);
200 if (ret == -1) {
201 printf("ctdb_call FUNC_FETCH failed - %s\n", ctdb_errstr(ctdb));
202 exit(1);
205 for (i=0;i<call.reply_data.dsize/sizeof(int);i++) {
206 printf("%3d\n", ((int *)call.reply_data.dptr)[i]);
208 talloc_free(call.reply_data.dptr);
210 /* go into a wait loop to allow other nodes to complete */
211 ctdb_wait_loop(ctdb);
213 /* shut it down */
214 talloc_free(ctdb);
215 return 0;