c5f71a02a2459b3172a49a6aecd9ede55ebb7d28
[sahlberg/ctdb.git] / tests / src / ctdb_update_record.c
1 /* 
2    simple ctdb test tool
3    This test just fetch_locks a record bumps the RSN and then writes new content
4
5    Copyright (C) Ronnie Sahlberg 2009
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 "includes.h"
22 #include "lib/tevent/tevent.h"
23 #include "system/filesys.h"
24 #include "popt.h"
25 #include "cmdline.h"
26 #include "ctdb_private.h"
27
28 static struct ctdb_db_context *ctdb_db;
29
30 #define TESTKEY "testkey"
31
32
33 /*
34         Just try locking/unlocking a single record once
35 */
36 static void fetch_lock_once(struct ctdb_context *ctdb, struct event_context *ev, uint32_t generation)
37 {
38         TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
39         TDB_DATA key, data;
40         struct ctdb_record_handle *h;
41         struct ctdb_ltdb_header *header;
42         int ret;
43
44         key.dptr = discard_const(TESTKEY);
45         key.dsize = strlen(TESTKEY);
46
47         printf("Trying to fetch lock the record ...\n");
48
49         h = ctdb_fetch_readonly_lock(ctdb_db, tmp_ctx, key, &data, false);
50         if (h == NULL) {
51                 printf("Failed to fetch record '%s' on node %d\n", 
52                         (const char *)key.dptr, ctdb_get_pnn(ctdb));
53                 talloc_free(tmp_ctx);
54                 exit(10);
55         }
56
57         printf("Record fetchlocked.\n");
58         header = talloc_memdup(tmp_ctx, ctdb_header_from_record_handle(h), sizeof(*header));
59         printf("RSN:%d\n", (int)header->rsn);
60         talloc_free(h);
61         printf("Record released.\n");
62
63         printf("Write new record with RSN+10\n");
64         header->rsn += 10;
65         data.dptr = (void *)talloc_asprintf(tmp_ctx, "%d", (int)header->rsn);
66         data.dsize = strlen((char *)data.dptr);
67
68         ret = ctdb_ctrl_updaterecord(ctdb, ctdb, timeval_zero(), CTDB_CURRENT_NODE, ctdb_db, key, header, data);
69         if (ret != 0) {
70                 printf("Failed to writerecord,  ret==%d\n", ret);       
71                 exit(1);
72         }
73
74         printf("re-fetch the record\n");
75         h = ctdb_fetch_lock(ctdb_db, tmp_ctx, key, &data);
76         if (h == NULL) {
77                 printf("Failed to fetch record '%s' on node %d\n", 
78                         (const char *)key.dptr, ctdb_get_pnn(ctdb));
79                 talloc_free(tmp_ctx);
80                 exit(10);
81         }
82
83         printf("Record fetchlocked.\n");
84         header = talloc_memdup(tmp_ctx, ctdb_header_from_record_handle(h), sizeof(*header));
85         printf("RSN:%d\n", (int)header->rsn);
86         talloc_free(h);
87         printf("Record released.\n");
88
89         talloc_free(tmp_ctx);
90 }
91
92 /*
93   main program
94 */
95 int main(int argc, const char *argv[])
96 {
97         struct ctdb_context *ctdb;
98
99         struct poptOption popt_options[] = {
100                 POPT_AUTOHELP
101                 POPT_CTDB_CMDLINE
102                 POPT_TABLEEND
103         };
104         int opt;
105         const char **extra_argv;
106         int extra_argc = 0;
107         poptContext pc;
108         struct event_context *ev;
109         struct ctdb_vnn_map *vnnmap=NULL;
110
111         pc = poptGetContext(argv[0], argc, argv, popt_options, POPT_CONTEXT_KEEP_FIRST);
112
113         while ((opt = poptGetNextOpt(pc)) != -1) {
114                 switch (opt) {
115                 default:
116                         fprintf(stderr, "Invalid option %s: %s\n", 
117                                 poptBadOption(pc, 0), poptStrerror(opt));
118                         exit(1);
119                 }
120         }
121
122         /* setup the remaining options for the main program to use */
123         extra_argv = poptGetArgs(pc);
124         if (extra_argv) {
125                 extra_argv++;
126                 while (extra_argv[extra_argc]) extra_argc++;
127         }
128
129         ev = event_context_init(NULL);
130
131         ctdb = ctdb_cmdline_client(ev, timeval_current_ofs(5, 0));
132
133         /* attach to a specific database */
134         ctdb_db = ctdb_attach(ctdb, timeval_current_ofs(5, 0), "test.tdb", false, 0);
135         if (!ctdb_db) {
136                 printf("ctdb_attach failed - %s\n", ctdb_errstr(ctdb));
137                 exit(1);
138         }
139
140         printf("Waiting for cluster\n");
141         while (1) {
142                 uint32_t recmode=1;
143                 ctdb_ctrl_getrecmode(ctdb, ctdb, timeval_zero(), CTDB_CURRENT_NODE, &recmode);
144                 if (recmode == 0) break;
145                 event_loop_once(ev);
146         }
147
148
149         if (ctdb_ctrl_getvnnmap(ctdb, timeval_zero(), CTDB_CURRENT_NODE, ctdb, &vnnmap) != 0) {
150                 printf("Unable to get vnnmap from local node\n");
151                 exit(1);
152         }
153         printf("Current Generation %d\n", (int)vnnmap->generation);
154
155         fetch_lock_once(ctdb, ev, vnnmap->generation);
156
157         return 0;
158 }