s3: Fix build file due to file move. Use the new path of iniparser
[Samba/ekacnet.git] / source4 / torture / raw / offline.c
blob3b8bbdd53a0ae3840c36906acae6ea75c639934f
1 /*
2 Unix SMB/CIFS implementation.
4 Copyright (C) Andrew Tridgell 2008
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3 of the License, or
9 (at your option) any later version.
11 This program 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
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program. If not, see <http://www.gnu.org/licenses/>.
21 test offline files
24 #include "includes.h"
25 #include "system/time.h"
26 #include "system/filesys.h"
27 #include "libcli/libcli.h"
28 #include "torture/util.h"
29 #include "lib/events/events.h"
30 #include "libcli/composite/composite.h"
31 #include "libcli/smb_composite/smb_composite.h"
33 #define BASEDIR "\\testoffline"
35 static int nconnections;
36 static int numstates;
37 static int num_connected;
38 static int test_failed;
39 extern int torture_numops;
40 extern int torture_entries;
41 static bool test_finished;
43 enum offline_op {OP_LOADFILE, OP_SAVEFILE, OP_SETOFFLINE, OP_GETOFFLINE, OP_ENDOFLIST};
45 static double latencies[OP_ENDOFLIST];
46 static double worst_latencies[OP_ENDOFLIST];
48 #define FILE_SIZE 8192
51 struct offline_state {
52 struct torture_context *tctx;
53 struct tevent_context *ev;
54 struct smbcli_tree *tree;
55 TALLOC_CTX *mem_ctx;
56 int client;
57 int fnum;
58 uint32_t count;
59 uint32_t lastcount;
60 uint32_t fnumber;
61 uint32_t offline_count;
62 uint32_t online_count;
63 char *fname;
64 struct smb_composite_loadfile *loadfile;
65 struct smb_composite_savefile *savefile;
66 struct smbcli_request *req;
67 enum offline_op op;
68 struct timeval tv_start;
71 static void test_offline(struct offline_state *state);
74 static char *filename(TALLOC_CTX *ctx, int i)
76 char *s = talloc_asprintf(ctx, BASEDIR "\\file%u.dat", i);
77 return s;
82 called when a loadfile completes
84 static void loadfile_callback(struct composite_context *ctx)
86 struct offline_state *state = ctx->async.private_data;
87 NTSTATUS status;
88 int i;
90 status = smb_composite_loadfile_recv(ctx, state->mem_ctx);
91 if (!NT_STATUS_IS_OK(status)) {
92 printf("Failed to read file '%s' - %s\n",
93 state->loadfile->in.fname, nt_errstr(status));
94 test_failed++;
97 /* check the data is correct */
98 if (state->loadfile->out.size != FILE_SIZE) {
99 printf("Wrong file size %u - expected %u\n",
100 state->loadfile->out.size, FILE_SIZE);
101 test_failed++;
102 return;
105 for (i=0;i<FILE_SIZE;i++) {
106 if (state->loadfile->out.data[i] != 1+(state->fnumber % 255)) {
107 printf("Bad data in file %u (got %u expected %u)\n",
108 state->fnumber,
109 state->loadfile->out.data[i],
110 1+(state->fnumber % 255));
111 test_failed++;
112 return;
116 talloc_steal(state->loadfile, state->loadfile->out.data);
118 state->count++;
119 talloc_free(state->loadfile);
120 state->loadfile = NULL;
122 if (!test_finished) {
123 test_offline(state);
129 called when a savefile completes
131 static void savefile_callback(struct composite_context *ctx)
133 struct offline_state *state = ctx->async.private_data;
134 NTSTATUS status;
136 status = smb_composite_savefile_recv(ctx);
137 if (!NT_STATUS_IS_OK(status)) {
138 printf("Failed to save file '%s' - %s\n",
139 state->savefile->in.fname, nt_errstr(status));
140 test_failed++;
143 state->count++;
144 talloc_free(state->savefile);
145 state->savefile = NULL;
147 if (!test_finished) {
148 test_offline(state);
154 called when a setoffline completes
156 static void setoffline_callback(struct smbcli_request *req)
158 struct offline_state *state = req->async.private_data;
159 NTSTATUS status;
161 status = smbcli_request_simple_recv(req);
162 if (!NT_STATUS_IS_OK(status)) {
163 printf("Failed to set offline file '%s' - %s\n",
164 state->fname, nt_errstr(status));
165 test_failed++;
168 state->req = NULL;
169 state->count++;
171 if (!test_finished) {
172 test_offline(state);
178 called when a getoffline completes
180 static void getoffline_callback(struct smbcli_request *req)
182 struct offline_state *state = req->async.private_data;
183 NTSTATUS status;
184 union smb_fileinfo io;
186 io.getattr.level = RAW_FILEINFO_GETATTR;
188 status = smb_raw_pathinfo_recv(req, state->mem_ctx, &io);
189 if (!NT_STATUS_IS_OK(status)) {
190 printf("Failed to get offline file '%s' - %s\n",
191 state->fname, nt_errstr(status));
192 test_failed++;
195 if (io.getattr.out.attrib & FILE_ATTRIBUTE_OFFLINE) {
196 state->offline_count++;
197 } else {
198 state->online_count++;
201 state->req = NULL;
202 state->count++;
204 if (!test_finished) {
205 test_offline(state);
211 send the next offline file fetch request
213 static void test_offline(struct offline_state *state)
215 struct composite_context *ctx;
216 double lat;
218 lat = timeval_elapsed(&state->tv_start);
219 if (latencies[state->op] < lat) {
220 latencies[state->op] = lat;
223 state->op = (enum offline_op) (random() % OP_ENDOFLIST);
225 state->fnumber = random() % torture_numops;
226 talloc_free(state->fname);
227 state->fname = filename(state->mem_ctx, state->fnumber);
229 state->tv_start = timeval_current();
231 switch (state->op) {
232 case OP_LOADFILE:
233 state->loadfile = talloc_zero(state->mem_ctx, struct smb_composite_loadfile);
234 state->loadfile->in.fname = state->fname;
236 ctx = smb_composite_loadfile_send(state->tree, state->loadfile);
237 if (ctx == NULL) {
238 printf("Failed to setup loadfile for %s\n", state->fname);
239 test_failed = true;
242 talloc_steal(state->loadfile, ctx);
244 ctx->async.fn = loadfile_callback;
245 ctx->async.private_data = state;
246 break;
248 case OP_SAVEFILE:
249 state->savefile = talloc_zero(state->mem_ctx, struct smb_composite_savefile);
251 state->savefile->in.fname = state->fname;
252 state->savefile->in.data = talloc_size(state->savefile, FILE_SIZE);
253 state->savefile->in.size = FILE_SIZE;
254 memset(state->savefile->in.data, 1+(state->fnumber%255), FILE_SIZE);
256 ctx = smb_composite_savefile_send(state->tree, state->savefile);
257 if (ctx == NULL) {
258 printf("Failed to setup savefile for %s\n", state->fname);
259 test_failed = true;
262 talloc_steal(state->savefile, ctx);
264 ctx->async.fn = savefile_callback;
265 ctx->async.private_data = state;
266 break;
268 case OP_SETOFFLINE: {
269 union smb_setfileinfo io;
270 ZERO_STRUCT(io);
271 io.setattr.level = RAW_SFILEINFO_SETATTR;
272 io.setattr.in.attrib = FILE_ATTRIBUTE_OFFLINE;
273 io.setattr.in.file.path = state->fname;
274 /* make the file 1 hour old, to get past mininum age restrictions
275 for HSM systems */
276 io.setattr.in.write_time = time(NULL) - 60*60;
278 state->req = smb_raw_setpathinfo_send(state->tree, &io);
279 if (state->req == NULL) {
280 printf("Failed to setup setoffline for %s\n", state->fname);
281 test_failed = true;
284 state->req->async.fn = setoffline_callback;
285 state->req->async.private_data = state;
286 break;
289 case OP_GETOFFLINE: {
290 union smb_fileinfo io;
291 ZERO_STRUCT(io);
292 io.getattr.level = RAW_FILEINFO_GETATTR;
293 io.getattr.in.file.path = state->fname;
295 state->req = smb_raw_pathinfo_send(state->tree, &io);
296 if (state->req == NULL) {
297 printf("Failed to setup getoffline for %s\n", state->fname);
298 test_failed = true;
301 state->req->async.fn = getoffline_callback;
302 state->req->async.private_data = state;
303 break;
306 default:
307 printf("bad operation??\n");
308 break;
315 static void echo_completion(struct smbcli_request *req)
317 struct offline_state *state = (struct offline_state *)req->async.private_data;
318 NTSTATUS status = smbcli_request_simple_recv(req);
319 if (NT_STATUS_EQUAL(status, NT_STATUS_END_OF_FILE) ||
320 NT_STATUS_EQUAL(status, NT_STATUS_LOCAL_DISCONNECT) ||
321 NT_STATUS_EQUAL(status, NT_STATUS_CONNECTION_RESET)) {
322 talloc_free(state->tree);
323 state->tree = NULL;
324 num_connected--;
325 DEBUG(0,("lost connection\n"));
326 test_failed++;
330 static void report_rate(struct tevent_context *ev, struct tevent_timer *te,
331 struct timeval t, void *private_data)
333 struct offline_state *state = talloc_get_type(private_data,
334 struct offline_state);
335 int i;
336 uint32_t total=0, total_offline=0, total_online=0;
337 for (i=0;i<numstates;i++) {
338 total += state[i].count - state[i].lastcount;
339 if (timeval_elapsed(&state[i].tv_start) > latencies[state[i].op]) {
340 latencies[state[i].op] = timeval_elapsed(&state[i].tv_start);
342 state[i].lastcount = state[i].count;
343 total_online += state[i].online_count;
344 total_offline += state[i].offline_count;
346 printf("ops/s=%4u offline=%5u online=%4u set_lat=%.1f/%.1f get_lat=%.1f/%.1f save_lat=%.1f/%.1f load_lat=%.1f/%.1f\n",
347 total, total_offline, total_online,
348 latencies[OP_SETOFFLINE],
349 worst_latencies[OP_SETOFFLINE],
350 latencies[OP_GETOFFLINE],
351 worst_latencies[OP_GETOFFLINE],
352 latencies[OP_SAVEFILE],
353 worst_latencies[OP_SAVEFILE],
354 latencies[OP_LOADFILE],
355 worst_latencies[OP_LOADFILE]);
356 fflush(stdout);
357 event_add_timed(ev, state, timeval_current_ofs(1, 0), report_rate, state);
359 for (i=0;i<OP_ENDOFLIST;i++) {
360 if (latencies[i] > worst_latencies[i]) {
361 worst_latencies[i] = latencies[i];
363 latencies[i] = 0;
366 /* send an echo on each interface to ensure it stays alive - this helps
367 with IP takeover */
368 for (i=0;i<numstates;i++) {
369 struct smb_echo p;
370 struct smbcli_request *req;
372 if (!state[i].tree) {
373 continue;
376 p.in.repeat_count = 1;
377 p.in.size = 0;
378 p.in.data = NULL;
379 req = smb_raw_echo_send(state[i].tree->session->transport, &p);
380 req->async.private_data = &state[i];
381 req->async.fn = echo_completion;
386 test offline file handling
388 bool torture_test_offline(struct torture_context *torture)
390 bool ret = true;
391 TALLOC_CTX *mem_ctx = talloc_new(torture);
392 int i;
393 int timelimit = torture_setting_int(torture, "timelimit", 10);
394 struct timeval tv;
395 struct offline_state *state;
396 struct smbcli_state *cli;
397 bool progress;
398 progress = torture_setting_bool(torture, "progress", true);
400 nconnections = torture_setting_int(torture, "nprocs", 4);
401 numstates = nconnections * torture_entries;
403 state = talloc_zero_array(mem_ctx, struct offline_state, numstates);
405 printf("Opening %d connections with %d simultaneous operations and %u files\n", nconnections, numstates, torture_numops);
406 for (i=0;i<nconnections;i++) {
407 state[i].tctx = torture;
408 state[i].mem_ctx = talloc_new(state);
409 state[i].ev = torture->ev;
410 if (!torture_open_connection_ev(&cli, i, torture, torture->ev)) {
411 return false;
413 state[i].tree = cli->tree;
414 state[i].client = i;
415 /* allow more time for offline files */
416 state[i].tree->session->transport->options.request_timeout = 200;
419 /* the others are repeats on the earlier connections */
420 for (i=nconnections;i<numstates;i++) {
421 state[i].tctx = torture;
422 state[i].mem_ctx = talloc_new(state);
423 state[i].ev = torture->ev;
424 state[i].tree = state[i % nconnections].tree;
425 state[i].client = i;
428 num_connected = i;
430 if (!torture_setup_dir(cli, BASEDIR)) {
431 goto failed;
434 /* pre-create files */
435 printf("Pre-creating %u files ....\n", torture_numops);
436 for (i=0;i<torture_numops;i++) {
437 int fnum;
438 char *fname = filename(mem_ctx, i);
439 char buf[FILE_SIZE];
440 NTSTATUS status;
442 memset(buf, 1+(i % 255), sizeof(buf));
444 fnum = smbcli_open(state[0].tree, fname, O_RDWR|O_CREAT, DENY_NONE);
445 if (fnum == -1) {
446 printf("Failed to open %s on connection %d\n", fname, i);
447 goto failed;
450 if (smbcli_write(state[0].tree, fnum, 0, buf, 0, sizeof(buf)) != sizeof(buf)) {
451 printf("Failed to write file of size %u\n", FILE_SIZE);
452 goto failed;
455 status = smbcli_close(state[0].tree, fnum);
456 if (!NT_STATUS_IS_OK(status)) {
457 printf("Close failed - %s\n", nt_errstr(status));
458 goto failed;
461 talloc_free(fname);
464 /* start the async ops */
465 for (i=0;i<numstates;i++) {
466 state[i].tv_start = timeval_current();
467 test_offline(&state[i]);
470 tv = timeval_current();
472 if (progress) {
473 event_add_timed(torture->ev, state, timeval_current_ofs(1, 0), report_rate, state);
476 printf("Running for %d seconds\n", timelimit);
477 while (timeval_elapsed(&tv) < timelimit) {
478 event_loop_once(torture->ev);
480 if (test_failed) {
481 DEBUG(0,("test failed\n"));
482 goto failed;
486 printf("\nWaiting for completion\n");
487 test_finished = true;
488 for (i=0;i<numstates;i++) {
489 while (state[i].loadfile ||
490 state[i].savefile ||
491 state[i].req) {
492 event_loop_once(torture->ev);
496 printf("worst latencies: set_lat=%.1f get_lat=%.1f save_lat=%.1f load_lat=%.1f\n",
497 worst_latencies[OP_SETOFFLINE],
498 worst_latencies[OP_GETOFFLINE],
499 worst_latencies[OP_SAVEFILE],
500 worst_latencies[OP_LOADFILE]);
502 smbcli_deltree(state[0].tree, BASEDIR);
503 talloc_free(mem_ctx);
504 printf("\n");
505 return ret;
507 failed:
508 talloc_free(mem_ctx);
509 return false;