mirror of
https://github.com/samba-team/samba.git
synced 2025-03-27 22:50:26 +03:00
torture3: Test ctdb_req_send/recv
Signed-off-by: Volker Lendecke <vl@samba.org> Reviewed-by: Ralph Boehme <slow@samba.org>
This commit is contained in:
parent
e1418589b0
commit
7a7d56c562
@ -1067,6 +1067,7 @@ for test in CLUSTERED_TESTS:
|
||||
planclusteredmembertestsuite(test, "$PREFIX")
|
||||
|
||||
CLUSTERED_LOCAL_TESTS = [
|
||||
"ctdbd-conn1",
|
||||
"local-dbwrap-ctdb1"
|
||||
]
|
||||
|
||||
@ -1080,4 +1081,4 @@ for t in CLUSTERED_LOCAL_TESTS:
|
||||
'""',
|
||||
'""',
|
||||
smbtorture3,
|
||||
""])
|
||||
"-N 1000 -o 2000"])
|
||||
|
@ -145,5 +145,6 @@ bool run_local_namemap_cache1(int dummy);
|
||||
bool run_local_idmap_cache1(int dummy);
|
||||
bool run_hidenewfiles(int dummy);
|
||||
bool run_readdir_timestamp(int dummy);
|
||||
bool run_ctdbd_conn1(int dummy);
|
||||
|
||||
#endif /* __TORTURE_H__ */
|
||||
|
312
source3/torture/test_ctdbd_conn.c
Normal file
312
source3/torture/test_ctdbd_conn.c
Normal file
@ -0,0 +1,312 @@
|
||||
/*
|
||||
* Unix SMB/CIFS implementation.
|
||||
* Test async ctdb_req_send/recv
|
||||
* Copyright (C) Volker Lendecke 2020
|
||||
*
|
||||
* 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 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* 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, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
#include "torture/proto.h"
|
||||
#include "ctdbd_conn.h"
|
||||
#include "lib/cluster_support.h"
|
||||
#include "ctdb/include/ctdb_protocol.h"
|
||||
#include "lib/util/tevent_unix.h"
|
||||
|
||||
extern int torture_nprocs;
|
||||
extern int torture_numops;
|
||||
|
||||
struct ctdb_echo_state {
|
||||
struct ctdb_req_control_old req;
|
||||
struct iovec iov[2];
|
||||
TDB_DATA echodata;
|
||||
};
|
||||
|
||||
static void ctdb_echo_done(struct tevent_req *subreq);
|
||||
|
||||
static struct tevent_req *ctdb_echo_send(
|
||||
TALLOC_CTX *mem_ctx,
|
||||
struct tevent_context *ev,
|
||||
struct ctdbd_connection *conn,
|
||||
uint32_t delay)
|
||||
{
|
||||
struct tevent_req *req = NULL, *subreq = NULL;
|
||||
struct ctdb_echo_state *state = NULL;
|
||||
struct ctdb_req_header *hdr = NULL;
|
||||
uint32_t datalen;
|
||||
|
||||
req = tevent_req_create(
|
||||
mem_ctx, &state, struct ctdb_echo_state);
|
||||
if (req == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
hdr = &state->req.hdr;
|
||||
ctdbd_prep_hdr_next_reqid(conn, hdr);
|
||||
hdr->operation = CTDB_REQ_CONTROL;
|
||||
state->req.opcode = CTDB_CONTROL_ECHO_DATA;
|
||||
|
||||
state->iov[0] = (struct iovec) {
|
||||
.iov_base = &state->req,
|
||||
.iov_len = offsetof(struct ctdb_req_control_old, data),
|
||||
};
|
||||
|
||||
datalen = generate_random() % 1024;
|
||||
|
||||
state->echodata.dptr = talloc_array(state, uint8_t, datalen+8);
|
||||
if (tevent_req_nomem(state->echodata.dptr, req)) {
|
||||
return tevent_req_post(req, ev);
|
||||
}
|
||||
state->echodata.dsize = talloc_get_size(state->echodata.dptr);
|
||||
generate_random_buffer(
|
||||
state->echodata.dptr, state->echodata.dsize);
|
||||
|
||||
memcpy(state->echodata.dptr, &delay, sizeof(delay));
|
||||
memcpy(state->echodata.dptr+4, &datalen, sizeof(datalen));
|
||||
|
||||
state->req.datalen = state->echodata.dsize;
|
||||
|
||||
state->iov[1] = (struct iovec) {
|
||||
.iov_base = state->echodata.dptr,
|
||||
.iov_len = state->echodata.dsize,
|
||||
};
|
||||
|
||||
hdr->length =
|
||||
offsetof(struct ctdb_req_control_old, data) +
|
||||
state->req.datalen;
|
||||
|
||||
subreq = ctdbd_req_send(
|
||||
state, ev, conn, state->iov, ARRAY_SIZE(state->iov));
|
||||
if (tevent_req_nomem(subreq, req)) {
|
||||
return tevent_req_post(req, ev);
|
||||
}
|
||||
tevent_req_set_callback(subreq, ctdb_echo_done, req);
|
||||
|
||||
return req;
|
||||
}
|
||||
|
||||
static void ctdb_echo_done(struct tevent_req *subreq)
|
||||
{
|
||||
struct tevent_req *req = tevent_req_callback_data(
|
||||
subreq, struct tevent_req);
|
||||
struct ctdb_echo_state *state = tevent_req_data(
|
||||
req, struct ctdb_echo_state);
|
||||
struct ctdb_req_header *hdr = NULL;
|
||||
struct ctdb_reply_control_old *reply = NULL;
|
||||
int cmp, ret;
|
||||
|
||||
ret = ctdbd_req_recv(subreq, state, &hdr);
|
||||
TALLOC_FREE(subreq);
|
||||
if (tevent_req_error(req, ret)) {
|
||||
printf("ctdbd_req_recv(%"PRIu32") returned %d (%s)\n",
|
||||
state->req.hdr.reqid,
|
||||
ret,
|
||||
strerror(ret));
|
||||
return;
|
||||
}
|
||||
if (hdr->operation != CTDB_REPLY_CONTROL) {
|
||||
printf("Expected CTDB_REPLY_CONTROL, got %"PRIu32"\n",
|
||||
hdr->operation);
|
||||
tevent_req_error(req, EIO);
|
||||
return;
|
||||
}
|
||||
reply = (struct ctdb_reply_control_old *)hdr;
|
||||
if (reply->status != 0) {
|
||||
printf("reply->status = %"PRIi32"\n", reply->status);
|
||||
tevent_req_error(req, EIO);
|
||||
return;
|
||||
}
|
||||
if (reply->datalen != state->req.datalen) {
|
||||
printf("state->echodata.dsize=%zu datalen=%"PRIu32"\n",
|
||||
state->echodata.dsize,
|
||||
reply->datalen);
|
||||
tevent_req_error(req, EIO);
|
||||
return;
|
||||
}
|
||||
cmp = memcmp(reply->data,
|
||||
state->echodata.dptr,
|
||||
state->echodata.dsize);
|
||||
if (cmp != 0) {
|
||||
printf("data mismatch\n");
|
||||
tevent_req_error(req, EIO);
|
||||
return;
|
||||
}
|
||||
TALLOC_FREE(reply);
|
||||
tevent_req_done(req);
|
||||
}
|
||||
|
||||
static int ctdb_echo_recv(struct tevent_req *req)
|
||||
{
|
||||
return tevent_req_simple_recv_unix(req);
|
||||
}
|
||||
|
||||
struct ctdb_ping_flood_state {
|
||||
struct tevent_context *ev;
|
||||
struct ctdbd_connection *conn;
|
||||
size_t num_running;
|
||||
bool done;
|
||||
};
|
||||
|
||||
static void ctdb_ping_flood_next(struct tevent_req *subreq);
|
||||
static void ctdb_ping_flood_done(struct tevent_req *subreq);
|
||||
|
||||
static struct tevent_req *ctdb_ping_flood_send(
|
||||
TALLOC_CTX *mem_ctx,
|
||||
struct tevent_context *ev,
|
||||
struct ctdbd_connection *conn,
|
||||
size_t num_parallel,
|
||||
unsigned usecs)
|
||||
{
|
||||
struct tevent_req *req = NULL, *subreq = NULL;
|
||||
struct ctdb_ping_flood_state *state = NULL;
|
||||
size_t i;
|
||||
|
||||
req = tevent_req_create(
|
||||
mem_ctx, &state, struct ctdb_ping_flood_state);
|
||||
if (req == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
state->ev = ev;
|
||||
state->conn = conn;
|
||||
|
||||
for (i=0; i<num_parallel; i++) {
|
||||
subreq = ctdb_echo_send(
|
||||
state,
|
||||
state->ev,
|
||||
state->conn,
|
||||
generate_random() % 10);
|
||||
if (tevent_req_nomem(subreq, req)) {
|
||||
return tevent_req_post(req, ev);
|
||||
}
|
||||
tevent_req_set_callback(subreq, ctdb_ping_flood_next, req);
|
||||
}
|
||||
state->num_running = num_parallel;
|
||||
|
||||
subreq = tevent_wakeup_send(
|
||||
state,
|
||||
ev,
|
||||
tevent_timeval_current_ofs(0, usecs));
|
||||
if (tevent_req_nomem(subreq, req)) {
|
||||
return tevent_req_post(req, ev);
|
||||
}
|
||||
tevent_req_set_callback(subreq, ctdb_ping_flood_done, req);
|
||||
|
||||
return req;
|
||||
}
|
||||
|
||||
static void ctdb_ping_flood_next(struct tevent_req *subreq)
|
||||
{
|
||||
struct tevent_req *req = tevent_req_callback_data(
|
||||
subreq, struct tevent_req);
|
||||
struct ctdb_ping_flood_state *state = tevent_req_data(
|
||||
req, struct ctdb_ping_flood_state);
|
||||
int ret;
|
||||
|
||||
ret = ctdb_echo_recv(subreq);
|
||||
TALLOC_FREE(subreq);
|
||||
if (tevent_req_error(req, ret)) {
|
||||
return;
|
||||
}
|
||||
state->num_running -= 1;
|
||||
|
||||
if (state->done) {
|
||||
if (state->num_running == 0) {
|
||||
tevent_req_done(req);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
subreq = ctdb_echo_send(
|
||||
state,
|
||||
state->ev,
|
||||
state->conn,
|
||||
generate_random() % 10);
|
||||
if (tevent_req_nomem(subreq, req)) {
|
||||
return;
|
||||
}
|
||||
tevent_req_set_callback(subreq, ctdb_ping_flood_next, req);
|
||||
state->num_running += 1;
|
||||
}
|
||||
|
||||
static void ctdb_ping_flood_done(struct tevent_req *subreq)
|
||||
{
|
||||
struct tevent_req *req = tevent_req_callback_data(
|
||||
subreq, struct tevent_req);
|
||||
struct ctdb_ping_flood_state *state = tevent_req_data(
|
||||
req, struct ctdb_ping_flood_state);
|
||||
bool ok;
|
||||
|
||||
ok = tevent_wakeup_recv(subreq);
|
||||
TALLOC_FREE(subreq);
|
||||
if (!ok) {
|
||||
tevent_req_oom(req);
|
||||
return;
|
||||
}
|
||||
state->done = true;
|
||||
}
|
||||
|
||||
static int ctdb_ping_flood_recv(struct tevent_req *req)
|
||||
{
|
||||
return tevent_req_simple_recv_unix(req);
|
||||
}
|
||||
|
||||
bool run_ctdbd_conn1(int dummy)
|
||||
{
|
||||
struct ctdbd_connection *conn = NULL;
|
||||
struct tevent_context *ev = NULL;
|
||||
struct tevent_req *req = NULL;
|
||||
int ret;
|
||||
bool ok;
|
||||
bool result = false;
|
||||
|
||||
ev = samba_tevent_context_init(talloc_tos());
|
||||
if (ev == NULL) {
|
||||
printf("samba_tevent_context_init failed\n");
|
||||
goto done;
|
||||
}
|
||||
|
||||
ret = ctdbd_init_async_connection(
|
||||
ev, lp_ctdbd_socket(), 0, &conn);
|
||||
if (ret != 0) {
|
||||
printf("ctdbd_init_async_connection failed: %s\n",
|
||||
strerror(ret));
|
||||
goto done;
|
||||
}
|
||||
|
||||
req = ctdb_ping_flood_send(
|
||||
ev, ev, conn, torture_nprocs, torture_numops * 1000);
|
||||
if (req == NULL) {
|
||||
printf("ctdb_ping_flood_send failed\n");
|
||||
goto done;
|
||||
}
|
||||
|
||||
ok = tevent_req_poll_unix(req, ev, &ret);
|
||||
if (!ok) {
|
||||
printf("tevent_req_poll_unix failed: %s\n",
|
||||
strerror(ret));
|
||||
goto done;
|
||||
}
|
||||
|
||||
ret = ctdb_ping_flood_recv(req);
|
||||
TALLOC_FREE(req);
|
||||
if (ret != 0) {
|
||||
printf("ctdb_ping_flood failed: %s\n", strerror(ret));
|
||||
goto done;
|
||||
}
|
||||
|
||||
result = true;
|
||||
done:
|
||||
TALLOC_FREE(conn);
|
||||
return result;
|
||||
}
|
@ -14995,6 +14995,12 @@ static struct {
|
||||
.name = "hide-new-files-timeout",
|
||||
.fn = run_hidenewfiles,
|
||||
},
|
||||
#ifdef CLUSTER_SUPPORT
|
||||
{
|
||||
.name = "ctdbd-conn1",
|
||||
.fn = run_ctdbd_conn1,
|
||||
},
|
||||
#endif
|
||||
{
|
||||
.name = "readdir-timestamp",
|
||||
.fn = run_readdir_timestamp,
|
||||
|
@ -1181,6 +1181,11 @@ bld.SAMBA3_BINARY('locktest2',
|
||||
''',
|
||||
for_selftest=True)
|
||||
|
||||
TORTURE3_ADDITIONAL_SOURCE=""
|
||||
|
||||
if bld.env.with_ctdb:
|
||||
TORTURE3_ADDITIONAL_SOURCE += ' torture/test_ctdbd_conn.c'
|
||||
|
||||
bld.SAMBA3_BINARY('smbtorture' + bld.env.suffix3,
|
||||
source='''
|
||||
torture/torture.c
|
||||
@ -1221,7 +1226,7 @@ bld.SAMBA3_BINARY('smbtorture' + bld.env.suffix3,
|
||||
torture/test_idmap_cache.c
|
||||
torture/test_hidenewfiles.c
|
||||
torture/test_readdir_timestamp.c
|
||||
''',
|
||||
''' + TORTURE3_ADDITIONAL_SOURCE,
|
||||
deps='''
|
||||
talloc
|
||||
smbconf
|
||||
|
Loading…
x
Reference in New Issue
Block a user