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