Commit beb6d93e by Dwight Engen Committed by Serge Hallyn

add arguments with getopt to concurrent tester

- add ability to run for multiple iterations - can also run non-threaded for comparison to threaded case Signed-off-by: 's avatarDwight Engen <dwight.engen@oracle.com> Acked-by: 's avatarSerge Hallyn <serge.hallyn@ubuntu.com> Signed-off-by: 's avatarSerge Hallyn <serge.hallyn@ubuntu.com>
parent 72899b34
...@@ -15,14 +15,46 @@ ...@@ -15,14 +15,46 @@
* with this program; if not, write to the Free Software Foundation, Inc., * with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/ */
#include <limits.h>
#include <stdio.h> #include <stdio.h>
#include <pthread.h> #include <pthread.h>
#include <unistd.h>
#define _GNU_SOURCE
#include <getopt.h>
#include "../lxc/lxccontainer.h" #include "../lxc/lxccontainer.h"
#define NTHREADS 5 static int nthreads = 5;
static int iterations = 1;
static int quiet = 0;
static int delay = 0;
static const char *template = "busybox";
static struct option options[] = {
{ "threads", required_argument, NULL, 'j' },
{ "iterations", required_argument, NULL, 'i' },
{ "template", required_argument, NULL, 't' },
{ "delay", required_argument, NULL, 'd' },
{ "quiet", no_argument, NULL, 'q' },
{ "help", no_argument, NULL, '?' },
{ 0, 0, 0, 0 },
};
char *template = "busybox"; static void usage(void) {
fprintf(stderr, "Usage: lxc-test-concurrent [OPTION]...\n\n"
"Common options :\n"
" -j, --threads=N Threads to run concurrently\n"
" (default: 5, use 1 for no threading)\n"
" -i, --iterations=N Number times to run the test (default: 1)\n"
" -t, --template=t Template to use (default: busybox)\n"
" -d, --delay=N Delay in seconds between start and stop\n"
" -q, --quiet Don't produce any output\n"
" -?, --help Give this help list\n"
"\n"
"Mandatory or optional arguments to long options are also mandatory or optional\n"
"for any corresponding short options.\n\n");
}
struct thread_args { struct thread_args {
int thread_id; int thread_id;
...@@ -30,16 +62,21 @@ struct thread_args { ...@@ -30,16 +62,21 @@ struct thread_args {
char *mode; char *mode;
}; };
void * concurrent(void *arguments) { static void do_function(void *arguments)
char name[4]; {
char name[NAME_MAX+1];
struct thread_args *args = arguments; struct thread_args *args = arguments;
struct lxc_container *c; struct lxc_container *c;
sprintf(name, "%d", args->thread_id); sprintf(name, "lxc-test-concurrent-%d", args->thread_id);
args->return_code = 1;
c = lxc_container_new(name, NULL); c = lxc_container_new(name, NULL);
if (!c) {
fprintf(stderr, "Unable to instantiate container (%s)\n", name);
return;
}
args->return_code = 1;
if (strcmp(args->mode, "create") == 0) { if (strcmp(args->mode, "create") == 0) {
if (!c->is_defined(c)) { if (!c->is_defined(c)) {
if (!c->create(c, template, NULL, NULL, 1, NULL)) { if (!c->create(c, template, NULL, NULL, 1, NULL)) {
...@@ -58,6 +95,7 @@ void * concurrent(void *arguments) { ...@@ -58,6 +95,7 @@ void * concurrent(void *arguments) {
fprintf(stderr, "Waiting the container (%s) to start failed...\n", name); fprintf(stderr, "Waiting the container (%s) to start failed...\n", name);
goto out; goto out;
} }
sleep(delay);
} }
} else if(strcmp(args->mode, "stop") == 0) { } else if(strcmp(args->mode, "stop") == 0) {
if (c->is_defined(c) && c->is_running(c)) { if (c->is_defined(c) && c->is_running(c)) {
...@@ -81,49 +119,95 @@ void * concurrent(void *arguments) { ...@@ -81,49 +119,95 @@ void * concurrent(void *arguments) {
args->return_code = 0; args->return_code = 0;
out: out:
lxc_container_put(c); lxc_container_put(c);
pthread_exit(NULL);
} }
static void *concurrent(void *arguments)
{
do_function(arguments);
pthread_exit(NULL);
}
int main(int argc, char *argv[]) { int main(int argc, char *argv[]) {
int i, j; int i, j, iter, opt;
pthread_attr_t attr; pthread_attr_t attr;
pthread_t threads[NTHREADS]; pthread_t *threads;
struct thread_args args[NTHREADS]; struct thread_args *args;
char *modes[] = {"create", "start", "stop", "destroy", NULL}; char *modes[] = {"create", "start", "stop", "destroy", NULL};
if (argc > 1)
template = argv[1];
pthread_attr_init(&attr); pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
while ((opt = getopt_long(argc, argv, "j:i:t:d:q", options, NULL)) != -1) {
switch(opt) {
case 'j':
nthreads = atoi(optarg);
break;
case 'i':
iterations = atoi(optarg);
break;
case 't':
template = optarg;
break;
case 'd':
delay = atoi(optarg);
break;
case 'q':
quiet = 1;
break;
default: /* '?' */
usage();
exit(EXIT_FAILURE);
}
}
threads = malloc(sizeof(*threads) * nthreads);
args = malloc(sizeof(*args) * nthreads);
if (threads == NULL || args == NULL) {
fprintf(stderr, "Unable malloc enough memory for %d threads\n", nthreads);
exit(EXIT_FAILURE);
}
for (iter = 1; iter <= iterations; iter++) {
int fd;
fd = open("/", O_RDONLY);
if (!quiet)
printf("\nIteration %d/%d maxfd:%d\n", iter, iterations, fd);
close(fd);
for (i = 0; modes[i];i++) { for (i = 0; modes[i];i++) {
printf("Executing (%s) for %d containers...\n", modes[i], NTHREADS); if (!quiet)
for (j = 0; j < NTHREADS; j++) { printf("Executing (%s) for %d containers...\n", modes[i], nthreads);
for (j = 0; j < nthreads; j++) {
args[j].thread_id = j; args[j].thread_id = j;
args[j].mode = modes[i]; args[j].mode = modes[i];
if (nthreads > 1) {
if (pthread_create(&threads[j], &attr, concurrent, (void *) &args[j]) != 0) { if (pthread_create(&threads[j], &attr, concurrent, (void *) &args[j]) != 0) {
perror("pthread_create() error"); perror("pthread_create() error");
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
} else {
do_function(&args[j]);
}
} }
for (j = 0; j < NTHREADS; j++) { for (j = 0; j < nthreads; j++) {
if ( pthread_join(threads[j], NULL) != 0) { if (nthreads > 1) {
if (pthread_join(threads[j], NULL) != 0) {
perror("pthread_join() error"); perror("pthread_join() error");
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
}
if (args[j].return_code) { if (args[j].return_code) {
perror("thread returned an error"); fprintf(stderr, "thread returned error %d", args[j].return_code);
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
} }
printf("\n"); }
} }
free(args);
free(threads);
pthread_attr_destroy(&attr); pthread_attr_destroy(&attr);
exit(EXIT_SUCCESS); exit(EXIT_SUCCESS);
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment