5963f2a91f9be5cfc7e7b8f0be6612c9f916fc71
[abartlet/samba.git/.git] / source4 / cluster / ctdb / tests / ctdb_test.c
1 /* 
2    ctdb test harness
3
4    Copyright (C) Andrew Tridgell  2006
5
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 3 of the License, or (at your option) any later version.
10
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.
15
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
19 */
20
21 #include "includes.h"
22 #include "lib/events/events.h"
23 #include "system/filesys.h"
24 #include "popt.h"
25 #include "cmdline.h"
26
27 enum my_functions {FUNC_SORT=1, FUNC_FETCH=2};
28
29 static int int_compare(int *i1, int *i2)
30 {
31         return *i1 - *i2;
32 }
33
34 /*
35   add an integer into a record in sorted order
36 */
37 static int sort_func(struct ctdb_call_info *call)
38 {
39         if (call->call_data == NULL ||
40             call->call_data->dsize != sizeof(int)) {
41                 return CTDB_ERR_INVALID;
42         }
43         call->new_data = talloc(call, TDB_DATA);
44         if (call->new_data == NULL) {
45                 return CTDB_ERR_NOMEM;
46         }
47         call->new_data->dptr = talloc_size(call, 
48                                            call->record_data.dsize + 
49                                            call->call_data->dsize);
50         if (call->new_data->dptr == NULL) {
51                 return CTDB_ERR_NOMEM;
52         }
53         call->new_data->dsize = call->record_data.dsize + call->call_data->dsize;
54         memcpy(call->new_data->dptr,
55                call->record_data.dptr, call->record_data.dsize);
56         memcpy(call->new_data->dptr+call->record_data.dsize,
57                call->call_data->dptr, call->call_data->dsize);
58
59         qsort(call->new_data->dptr, call->new_data->dsize / sizeof(int),
60               sizeof(int), (comparison_fn_t)int_compare);
61
62         return 0;
63 }
64
65 /*
66   ctdb call function to fetch a record
67 */
68 static int fetch_func(struct ctdb_call_info *call)
69 {
70         call->reply_data = &call->record_data;
71         return 0;
72 }
73
74 /*
75   main program
76 */
77 int main(int argc, const char *argv[])
78 {
79         struct ctdb_context *ctdb;
80         struct ctdb_db_context *ctdb_db;
81
82         struct poptOption popt_options[] = {
83                 POPT_AUTOHELP
84                 POPT_CTDB_CMDLINE
85                 POPT_TABLEEND
86         };
87         int opt;
88         const char **extra_argv;
89         int extra_argc = 0;
90         int i, ret;
91         poptContext pc;
92         struct event_context *ev;
93         struct ctdb_call call;
94
95         pc = poptGetContext(argv[0], argc, argv, popt_options, POPT_CONTEXT_KEEP_FIRST);
96
97         while ((opt = poptGetNextOpt(pc)) != -1) {
98                 switch (opt) {
99                 default:
100                         fprintf(stderr, "Invalid option %s: %s\n", 
101                                 poptBadOption(pc, 0), poptStrerror(opt));
102                         exit(1);
103                 }
104         }
105
106         /* setup the remaining options for the main program to use */
107         extra_argv = poptGetArgs(pc);
108         if (extra_argv) {
109                 extra_argv++;
110                 while (extra_argv[extra_argc]) extra_argc++;
111         }
112
113         ev = event_context_init(NULL);
114
115         /* initialise ctdb */
116         ctdb = ctdb_cmdline_init(ev);
117         if (ctdb == NULL) {
118                 printf("Failed to init ctdb\n");
119                 exit(1);
120         }
121
122         /* attach to a specific database */
123         ctdb_db = ctdb_attach(ctdb, "test.tdb", TDB_DEFAULT, O_RDWR|O_CREAT|O_TRUNC, 0666);
124         if (!ctdb_db) {
125                 printf("ctdb_attach failed - %s\n", ctdb_errstr(ctdb));
126                 exit(1);
127         }
128
129         /* setup a ctdb call function */
130         ret = ctdb_set_call(ctdb_db, sort_func,  FUNC_SORT);
131         ret = ctdb_set_call(ctdb_db, fetch_func, FUNC_FETCH);
132
133         /* start the protocol running */
134         ret = ctdb_start(ctdb);
135
136         ctdb_connect_wait(ctdb);
137
138         ZERO_STRUCT(call);
139         call.key.dptr = discard_const("test");
140         call.key.dsize = strlen("test")+1;
141
142         /* add some random data */
143         for (i=0;i<10;i++) {
144                 int v = random() % 1000;
145
146                 call.call_id = FUNC_SORT;
147                 call.call_data.dptr = (uint8_t *)&v;
148                 call.call_data.dsize = sizeof(v);
149
150                 ret = ctdb_call(ctdb_db, &call);
151                 if (ret == -1) {
152                         printf("ctdb_call FUNC_SORT failed - %s\n", ctdb_errstr(ctdb));
153                         exit(1);
154                 }
155         }
156
157         /* fetch the record */
158         call.call_id = FUNC_FETCH;
159         call.call_data.dptr = NULL;
160         call.call_data.dsize = 0;
161
162         ret = ctdb_call(ctdb_db, &call);
163         if (ret == -1) {
164                 printf("ctdb_call FUNC_FETCH failed - %s\n", ctdb_errstr(ctdb));
165                 exit(1);
166         }
167
168         for (i=0;i<call.reply_data.dsize/sizeof(int);i++) {
169                 printf("%3d\n", ((int *)call.reply_data.dptr)[i]);
170         }
171         talloc_free(call.reply_data.dptr);
172
173         /* go into a wait loop to allow other nodes to complete */
174         ctdb_shutdown(ctdb);
175
176         return 0;
177 }