~zulcss/samba/server-dailies-3.4

« back to all changes in this revision

Viewing changes to source4/torture/raw/tconrate.c

  • Committer: Chuck Short
  • Date: 2010-09-28 20:38:39 UTC
  • Revision ID: zulcss@ubuntu.com-20100928203839-pgjulytsi9ue63x1
Initial version

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
   SMB tree connection rate test
 
3
 
 
4
   Copyright (C) 2006-2007 James Peach
 
5
 
 
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.
 
10
 
 
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.
 
15
 
 
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/>.
 
18
*/
 
19
 
 
20
#include "includes.h"
 
21
#include "libcli/libcli.h"
 
22
#include "libcli/resolve/resolve.h"
 
23
#include "torture/smbtorture.h"
 
24
#include "lib/cmdline/popt_common.h"
 
25
#include "param/param.h"
 
26
 
 
27
#include "system/filesys.h"
 
28
#include "system/shmem.h"
 
29
 
 
30
#define TIME_LIMIT_SECS 30
 
31
#define usec_to_sec(s) ((s) / 1000000)
 
32
 
 
33
/* Map a shared memory buffer of at least nelem counters. */
 
34
static void * map_count_buffer(unsigned nelem, size_t elemsz)
 
35
{
 
36
        void * buf;
 
37
        size_t bufsz;
 
38
        size_t pagesz = getpagesize();
 
39
 
 
40
        bufsz = nelem * elemsz;
 
41
        bufsz = (bufsz + pagesz) % pagesz; /* round up to pagesz */
 
42
 
 
43
#ifdef MAP_ANON
 
44
        /* BSD */
 
45
        buf = mmap(NULL, bufsz, PROT_READ|PROT_WRITE, MAP_ANON|MAP_SHARED,
 
46
                        -1 /* fd */, 0 /* offset */);
 
47
#else
 
48
        buf = mmap(NULL, bufsz, PROT_READ|PROT_WRITE, MAP_FILE|MAP_SHARED,
 
49
                        open("/dev/zero", O_RDWR), 0 /* offset */);
 
50
#endif
 
51
 
 
52
        if (buf == MAP_FAILED) {
 
53
                printf("failed to map count buffer: %s\n",
 
54
                                strerror(errno));
 
55
                return NULL;
 
56
        }
 
57
 
 
58
        return buf;
 
59
 
 
60
}
 
61
 
 
62
static int fork_tcon_client(struct torture_context *tctx,
 
63
                int *tcon_count, unsigned tcon_timelimit,
 
64
                const char *host, const char *share)
 
65
{
 
66
        pid_t child;
 
67
        struct smbcli_state *cli;
 
68
        struct timeval end;
 
69
        struct timeval now;
 
70
        struct smbcli_options options;
 
71
        struct smbcli_session_options session_options;
 
72
 
 
73
        lp_smbcli_options(tctx->lp_ctx, &options);
 
74
        lp_smbcli_session_options(tctx->lp_ctx, &session_options);
 
75
 
 
76
        child = fork();
 
77
        if (child == -1) {
 
78
                printf("failed to fork child: %s\n,", strerror(errno));
 
79
                return -1;
 
80
        } else if (child != 0) {
 
81
                /* Parent, just return. */
 
82
                return 0;
 
83
        }
 
84
 
 
85
        /* Child. Just make as many connections as possible within the
 
86
         * time limit. Don't bother synchronising the child start times
 
87
         * because it's probably not work the effort, and a bit of startup
 
88
         * jitter is probably a more realistic test.
 
89
         */
 
90
 
 
91
 
 
92
        end = timeval_current();
 
93
        now = timeval_current();
 
94
        end.tv_sec += tcon_timelimit;
 
95
        *tcon_count = 0;
 
96
 
 
97
        while (timeval_compare(&now, &end) == -1) {
 
98
                NTSTATUS status;
 
99
 
 
100
                status = smbcli_full_connection(NULL, &cli,
 
101
                                host, lp_smb_ports(tctx->lp_ctx), share,
 
102
                                NULL, lp_socket_options(tctx->lp_ctx), cmdline_credentials,
 
103
                                lp_resolve_context(tctx->lp_ctx),
 
104
                                tctx->ev, &options, &session_options,
 
105
                                lp_iconv_convenience(tctx->lp_ctx),
 
106
                                lp_gensec_settings(tctx, tctx->lp_ctx));
 
107
 
 
108
                if (!NT_STATUS_IS_OK(status)) {
 
109
                        printf("failed to connect to //%s/%s: %s\n",
 
110
                                host, share, nt_errstr(status));
 
111
                        goto done;
 
112
                }
 
113
 
 
114
                smbcli_tdis(cli);
 
115
 
 
116
                *tcon_count = *tcon_count + 1;
 
117
                now = timeval_current();
 
118
        }
 
119
 
 
120
done:
 
121
        exit(0);
 
122
}
 
123
 
 
124
static bool children_remain(void)
 
125
{
 
126
        /* Reap as many children as possible. */
 
127
        for (;;) {
 
128
                pid_t ret = waitpid(-1, NULL, WNOHANG);
 
129
                if (ret == 0) {
 
130
                        /* no children ready */
 
131
                        return true;
 
132
                }
 
133
                if (ret == -1) {
 
134
                        /* no children left. maybe */
 
135
                        return errno == ECHILD ? false : true;
 
136
                }
 
137
        }
 
138
 
 
139
        /* notreached */
 
140
        return false;
 
141
}
 
142
 
 
143
static double rate_convert_secs(unsigned count,
 
144
                const struct timeval *start, const struct timeval *end)
 
145
{
 
146
        return (double)count /
 
147
                usec_to_sec((double)usec_time_diff(end, start));
 
148
}
 
149
 
 
150
/* Test the rate at which the server will accept connections.  */
 
151
bool torture_bench_treeconnect(struct torture_context *tctx)
 
152
{
 
153
        const char *host = torture_setting_string(tctx, "host", NULL);
 
154
        const char *share = torture_setting_string(tctx, "share", NULL);
 
155
 
 
156
        int timelimit = torture_setting_int(tctx, "timelimit",
 
157
                                        TIME_LIMIT_SECS);
 
158
        int nprocs = torture_setting_int(tctx, "nprocs", 4);
 
159
 
 
160
        int *curr_counts = map_count_buffer(nprocs, sizeof(int));
 
161
        int *last_counts = talloc_array(NULL, int, nprocs);
 
162
 
 
163
        struct timeval now, last, start;
 
164
        int i, delta;
 
165
 
 
166
        torture_assert(tctx, nprocs > 0, "bad proc count");
 
167
        torture_assert(tctx, timelimit > 0, "bad timelimit");
 
168
        torture_assert(tctx, curr_counts, "allocation failure");
 
169
        torture_assert(tctx, last_counts, "allocation failure");
 
170
 
 
171
        start = last = timeval_current();
 
172
        for (i = 0; i < nprocs; ++i) {
 
173
                fork_tcon_client(tctx, &curr_counts[i], timelimit, host, share);
 
174
        }
 
175
 
 
176
        while (children_remain()) {
 
177
 
 
178
                sleep(1);
 
179
                now = timeval_current();
 
180
 
 
181
                for (i = 0, delta = 0; i < nprocs; ++i) {
 
182
                        delta += curr_counts[i] - last_counts[i];
 
183
                }
 
184
 
 
185
                printf("%u connections/sec\n",
 
186
                        (unsigned)rate_convert_secs(delta, &last, &now));
 
187
 
 
188
                memcpy(last_counts, curr_counts, nprocs * sizeof(int));
 
189
                last = timeval_current();
 
190
        }
 
191
 
 
192
        now = timeval_current();
 
193
 
 
194
        for (i = 0, delta = 0; i < nprocs; ++i) {
 
195
                delta += curr_counts[i];
 
196
        }
 
197
 
 
198
        printf("TOTAL: %u connections/sec over %u secs\n",
 
199
                        (unsigned)rate_convert_secs(delta, &start, &now),
 
200
                        timelimit);
 
201
        return true;
 
202
}
 
203
 
 
204
/* vim: set sts=8 sw=8 : */