This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
+ the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "includes.h"
#include "lib/cmdline/popt_common.h"
#include "libcli/composite/composite.h"
#include "libcli/smb_composite/smb_composite.h"
+#include "param/param.h"
#define BASEDIR "\\benchopen"
static int open_retries;
static char **fnames;
static int num_connected;
-
-enum open_stage {OPEN_INITIAL, OPEN_OPEN, OPEN_CLOSE};
+static struct timed_event *report_te;
struct benchopen_state {
TALLOC_CTX *mem_ctx;
struct event_context *ev;
struct smbcli_state *cli;
struct smbcli_tree *tree;
- enum open_stage stage;
int client_num;
int old_fnum;
int fnum;
struct smbcli_request *req_open;
struct smbcli_request *req_close;
struct smb_composite_connect reconnect;
+ struct timed_event *te;
/* these are used for reconnections */
int dest_port;
};
static void next_open(struct benchopen_state *state);
-static void next_operation(struct benchopen_state *state);
static void reopen_connection(struct event_context *ev, struct timed_event *te,
struct timeval t, void *private_data);
status = smb_composite_connect_recv(ctx, state->mem_ctx);
if (!NT_STATUS_IS_OK(status)) {
- event_add_timed(state->ev, state->mem_ctx,
- timeval_current_ofs(1,0),
- reopen_connection, state);
+ talloc_free(state->te);
+ state->te = event_add_timed(state->ev, state->mem_ctx,
+ timeval_current_ofs(1,0),
+ reopen_connection, state);
return;
}
DEBUG(0,("reconnect to %s finished (%u connected)\n", state->dest_host,
num_connected));
- state->stage = OPEN_INITIAL;
state->fnum = -1;
- next_operation(state);
+ state->old_fnum = -1;
+ next_open(state);
}
struct smb_composite_connect *io = &state->reconnect;
char *host, *share;
+ state->te = NULL;
+
if (!torture_get_conn_index(state->client_num, state->mem_ctx, &host, &share)) {
DEBUG(0,("Can't find host/share for reconnect?!\n"));
exit(1);
{
state->count++;
- state->file_num = (state->file_num+1) % (nprocs+1);
+ state->file_num = (state->file_num+1) % (3*nprocs);
+
+ DEBUG(2,("[%d] opening %u\n", state->client_num, state->file_num));
state->open_parms.ntcreatex.level = RAW_OPEN_NTCREATEX;
state->open_parms.ntcreatex.in.flags = 0;
state->open_parms.ntcreatex.in.root_fid = 0;
static void next_close(struct benchopen_state *state)
{
+ DEBUG(2,("[%d] closing %d\n", state->client_num, state->old_fnum));
+ if (state->old_fnum == -1) {
+ return;
+ }
state->close_parms.close.level = RAW_CLOSE_CLOSE;
state->close_parms.close.in.file.fnum = state->old_fnum;
state->close_parms.close.in.write_time = 0;
state->req_close = smb_raw_close_send(state->tree, &state->close_parms);
state->req_close->async.fn = close_completed;
state->req_close->async.private = state;
+ state->old_fnum = -1;
}
/*
TALLOC_CTX *tmp_ctx = talloc_new(state->mem_ctx);
NTSTATUS status;
- state->old_fnum = state->fnum;
-
status = smb_raw_open_recv(req, tmp_ctx, &state->open_parms);
talloc_free(tmp_ctx);
state->cli = NULL;
num_connected--;
DEBUG(0,("reopening connection to %s\n", state->dest_host));
- event_add_timed(state->ev, state->mem_ctx,
- timeval_current_ofs(1,0),
- reopen_connection, state);
+ talloc_free(state->te);
+ state->te = event_add_timed(state->ev, state->mem_ctx,
+ timeval_current_ofs(1,0),
+ reopen_connection, state);
return;
}
if (NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
+ DEBUG(2,("[%d] retrying open\n", state->client_num));
open_retries++;
state->req_open = smb_raw_open_send(state->tree, &state->open_parms);
state->req_open->async.fn = open_completed;
return;
}
+ state->old_fnum = state->fnum;
state->fnum = state->open_parms.ntcreatex.out.file.fnum;
- next_operation(state);
+ DEBUG(2,("[%d] open completed: fnum=%d old_fnum=%d\n",
+ state->client_num, state->fnum, state->old_fnum));
+
+ if (state->old_fnum != -1) {
+ next_close(state);
+ }
+
+ next_open(state);
}
/*
state->cli = NULL;
num_connected--;
DEBUG(0,("reopening connection to %s\n", state->dest_host));
- event_add_timed(state->ev, state->mem_ctx,
- timeval_current_ofs(1,0),
- reopen_connection, state);
+ talloc_free(state->te);
+ state->te = event_add_timed(state->ev, state->mem_ctx,
+ timeval_current_ofs(1,0),
+ reopen_connection, state);
return;
}
return;
}
- next_operation(state);
+ DEBUG(2,("[%d] close completed: fnum=%d old_fnum=%d\n",
+ state->client_num, state->fnum, state->old_fnum));
}
-static void next_operation(struct benchopen_state *state)
+static void echo_completion(struct smbcli_request *req)
{
- switch (state->stage) {
- case OPEN_INITIAL:
- next_open(state);
- state->stage = OPEN_OPEN;
- break;
- case OPEN_OPEN:
- next_open(state);
- state->stage = OPEN_CLOSE;
- break;
- case OPEN_CLOSE:
- next_close(state);
- state->stage = OPEN_OPEN;
- break;
+ struct benchopen_state *state = (struct benchopen_state *)req->async.private;
+ NTSTATUS status = smbcli_request_simple_recv(req);
+ if (NT_STATUS_EQUAL(status, NT_STATUS_END_OF_FILE) ||
+ NT_STATUS_EQUAL(status, NT_STATUS_LOCAL_DISCONNECT)) {
+ talloc_free(state->tree);
+ state->tree = NULL;
+ num_connected--;
+ DEBUG(0,("reopening connection to %s\n", state->dest_host));
+ talloc_free(state->te);
+ state->te = event_add_timed(state->ev, state->mem_ctx,
+ timeval_current_ofs(1,0),
+ reopen_connection, state);
}
}
}
printf("\r");
fflush(stdout);
- event_add_timed(ev, state, timeval_current_ofs(1, 0), report_rate, state);
+ report_te = event_add_timed(ev, state, timeval_current_ofs(1, 0),
+ report_rate, state);
+
+ /* send an echo on each interface to ensure it stays alive - this helps
+ with IP takeover */
+ for (i=0;i<nprocs;i++) {
+ struct smb_echo p;
+ struct smbcli_request *req;
+
+ if (!state[i].tree) {
+ continue;
+ }
+
+ p.in.repeat_count = 1;
+ p.in.size = 0;
+ p.in.data = NULL;
+ req = smb_raw_echo_send(state[i].tree->session->transport, &p);
+ req->async.private = &state[i];
+ req->async.fn = echo_completion;
+ }
}
/*
struct event_context *ev = event_context_find(mem_ctx);
struct benchopen_state *state;
int total = 0, minops=0;
- bool progress;
+ bool progress=False;
progress = torture_setting_bool(torture, "progress", true);
- nprocs = lp_parm_int(-1, "torture", "nprocs", 4);
+ nprocs = torture_setting_int(torture, "nprocs", 4);
state = talloc_zero_array(mem_ctx, struct benchopen_state, nprocs);
goto failed;
}
- fnames = talloc_array(mem_ctx, char *, nprocs+1);
- for (i=0;i<nprocs+1;i++) {
+ fnames = talloc_array(mem_ctx, char *, 3*nprocs);
+ for (i=0;i<3*nprocs;i++) {
fnames[i] = talloc_asprintf(fnames, "%s\\file%d.dat", BASEDIR, i);
}
state[i].fnum = smbcli_open(state[i].tree,
fnames[state->file_num],
O_RDWR|O_CREAT, DENY_ALL);
- state[i].stage = OPEN_OPEN;
- next_operation(&state[i]);
+ state[i].old_fnum = -1;
+ next_open(&state[i]);
}
tv = timeval_current();
if (progress) {
- event_add_timed(ev, state, timeval_current_ofs(1, 0), report_rate, state);
+ report_te = event_add_timed(ev, state, timeval_current_ofs(1, 0),
+ report_rate, state);
}
printf("Running for %d seconds\n", timelimit);
}
}
+ talloc_free(report_te);
+
printf("%.2f ops/second (%d retries)\n",
total/timeval_elapsed(&tv), open_retries);
minops = state[0].count;