ctdb-tests: Replace ctdb_logging.h with common/logging.h
[vlendec/samba-autobuild/.git] / ctdb / tests / src / ctdb_randrec.c
1 /* 
2    create a lot of random records, both current records and deleted records
3
4    Copyright (C) Andrew Tridgell  2008
5         Ronnie sahlberg 2007
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
21 #include "replace.h"
22 #include "system/filesys.h"
23 #include "system/network.h"
24 #include "system/time.h"
25
26 #include <popt.h>
27 #include <talloc.h>
28 #include <tevent.h>
29
30 #include "lib/util/debug.h"
31 #include "lib/util/time.h"
32
33 #include "ctdb_private.h"
34 #include "ctdb_client.h"
35
36 #include "common/cmdline.h"
37 #include "common/common.h"
38 #include "common/logging.h"
39
40 static struct timeval tp1,tp2;
41
42 static void start_timer(void)
43 {
44         gettimeofday(&tp1,NULL);
45 }
46
47 static double end_timer(void)
48 {
49         gettimeofday(&tp2,NULL);
50         return (tp2.tv_sec + (tp2.tv_usec*1.0e-6)) - 
51                 (tp1.tv_sec + (tp1.tv_usec*1.0e-6));
52 }
53
54 static int num_records = 10;
55 static int delete_pct = 75;
56 static int base_rec;
57
58 static void store_records(struct ctdb_context *ctdb, struct tevent_context *ev)
59 {
60         TDB_DATA key, data;
61         struct ctdb_db_context *ctdb_db;
62         TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
63         int ret;
64         struct ctdb_record_handle *h;
65         uint32_t i=0;
66         
67         ctdb_db = ctdb_db_handle(ctdb, "test.tdb");
68
69         srandom(time(NULL) ^ getpid());
70
71         start_timer();
72
73         printf("working with %d records\n", num_records);
74         while (1) {
75                 unsigned r = random() % num_records;
76                 key.dptr = (uint8_t *)&r;
77                 key.dsize = sizeof(r); 
78
79                 h = ctdb_fetch_lock(ctdb_db, tmp_ctx, key, &data);
80                 if (h == NULL) {
81                         printf("Failed to fetch record '%s' on node %d\n", 
82                                (const char *)key.dptr, ctdb_get_pnn(ctdb));
83                         talloc_free(tmp_ctx);
84                         return;
85                 }
86
87                 if (random() % 100 < delete_pct) {
88                         data.dptr = NULL;
89                         data.dsize = 0;
90                 } else {
91                         data.dptr = talloc_zero_size(h, data.dsize + sizeof(r));
92                         data.dsize += sizeof(r);
93                 }
94
95                 ret = ctdb_record_store(h, data);
96                 if (ret != 0) {
97                         printf("Failed to store record\n");
98                 }
99
100                 if (data.dptr == NULL && data.dsize == 0) {
101                         struct ctdb_control_schedule_for_deletion *dd;
102                         TDB_DATA indata;
103                         int32_t status;
104
105                         indata.dsize = offsetof(struct ctdb_control_schedule_for_deletion, key) + key.dsize;
106                         indata.dptr = talloc_zero_array(ctdb, uint8_t, indata.dsize);
107                         if (indata.dptr == NULL) {
108                                 printf("out of memory\n");
109                                 exit(1);
110                         }
111                         dd = (struct ctdb_control_schedule_for_deletion *)(void *)indata.dptr;
112                         dd->db_id = ctdb_db->db_id;
113                         dd->hdr = *ctdb_header_from_record_handle(h);
114                         dd->keylen = key.dsize;
115                         memcpy(dd->key, key.dptr, key.dsize);
116
117                         ret = ctdb_control(ctdb,
118                                            CTDB_CURRENT_NODE,
119                                            ctdb_db->db_id,
120                                            CTDB_CONTROL_SCHEDULE_FOR_DELETION,
121                                            0, /* flags */
122                                            indata,
123                                            NULL, /* mem_ctx */
124                                            NULL, /* outdata */
125                                            &status,
126                                            NULL, /* timeout : NULL == wait forever */
127                                            NULL); /* error message */
128
129                         talloc_free(indata.dptr);
130
131                         if (ret != 0 || status != 0) {
132                                 DEBUG(DEBUG_ERR, (__location__ " Error sending "
133                                                   "SCHEDULE_FOR_DELETION "
134                                                   "control.\n"));
135                         }
136                 }
137
138                 talloc_free(h);
139
140                 if (i % 1000 == 0) {
141                         printf("%7.0f recs/second   %u total\r", 1000.0 / end_timer(), i);
142                         fflush(stdout);
143                         start_timer();
144                 }
145                 i++;
146         }
147
148         talloc_free(tmp_ctx);
149 }
150
151 /*
152   main program
153 */
154 int main(int argc, const char *argv[])
155 {
156         struct ctdb_context *ctdb;
157         struct ctdb_db_context *ctdb_db;
158
159         struct poptOption popt_options[] = {
160                 POPT_AUTOHELP
161                 POPT_CTDB_CMDLINE
162                 { "num-records", 'r', POPT_ARG_INT, &num_records, 0, "num_records", "integer" },
163                 { "base-rec", 'b', POPT_ARG_INT, &base_rec, 0, "base_rec", "integer" },
164                 { "delete-pct", 'p', POPT_ARG_INT, &delete_pct, 0, "delete_pct", "integer" },
165                 POPT_TABLEEND
166         };
167         int opt;
168         const char **extra_argv;
169         int extra_argc = 0;
170         poptContext pc;
171         struct tevent_context *ev;
172
173         pc = poptGetContext(argv[0], argc, argv, popt_options, POPT_CONTEXT_KEEP_FIRST);
174
175         while ((opt = poptGetNextOpt(pc)) != -1) {
176                 switch (opt) {
177                 default:
178                         fprintf(stderr, "Invalid option %s: %s\n", 
179                                 poptBadOption(pc, 0), poptStrerror(opt));
180                         exit(1);
181                 }
182         }
183
184         /* setup the remaining options for the main program to use */
185         extra_argv = poptGetArgs(pc);
186         if (extra_argv) {
187                 extra_argv++;
188                 while (extra_argv[extra_argc]) extra_argc++;
189         }
190
191         ev = tevent_context_init(NULL);
192
193         ctdb = ctdb_cmdline_client(ev, timeval_current_ofs(3, 0));
194
195         if (ctdb == NULL) {
196                 printf("failed to connect to daemon\n");
197                 exit(1);
198         }
199
200         /* attach to a specific database */
201         ctdb_db = ctdb_attach(ctdb, timeval_current_ofs(2, 0), "test.tdb",
202                               false, 0);
203         if (!ctdb_db) {
204                 printf("ctdb_attach failed - %s\n", ctdb_errstr(ctdb));
205                 exit(1);
206         }
207
208         store_records(ctdb, ev);
209
210         return 0;
211 }