]> git.proxmox.com Git - mirror_lxc.git/blame - src/tests/concurrent.c
spelling: timeout
[mirror_lxc.git] / src / tests / concurrent.c
CommitLineData
f209d63a
ÇO
1/* concurrent.c
2 *
3 * Copyright © 2013 S.Çağlar Onur <caglar@10ur.org>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2, as
7 * published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License along
15 * with this program; if not, write to the Free Software Foundation, Inc.,
16 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17 */
beb6d93e 18
eab15c1e 19#define _GNU_SOURCE
beb6d93e 20#include <limits.h>
f209d63a
ÇO
21#include <stdio.h>
22#include <pthread.h>
beb6d93e 23#include <unistd.h>
95ee490b
SG
24#include <string.h>
25#include <fcntl.h>
beb6d93e 26#include <getopt.h>
f209d63a 27
948955a2 28#include <lxc/lxccontainer.h>
f209d63a 29
beb6d93e
DE
30static int nthreads = 5;
31static int iterations = 1;
36eaa694 32static int debug = 0;
beb6d93e
DE
33static int quiet = 0;
34static int delay = 0;
35static const char *template = "busybox";
36
0b98289e 37static const struct option options[] = {
fbeb7a1a 38 { "threads", required_argument, NULL, 'j' },
39 { "iterations", required_argument, NULL, 'i' },
40 { "template", required_argument, NULL, 't' },
41 { "delay", required_argument, NULL, 'd' },
42 { "modes", required_argument, NULL, 'm' },
43 { "quiet", no_argument, NULL, 'q' },
44 { "debug", no_argument, NULL, 'D' },
45 { "help", no_argument, NULL, '?' },
46 { 0, 0, 0, 0 },
beb6d93e 47};
f209d63a 48
beb6d93e 49static void usage(void) {
fbeb7a1a 50 fprintf(stderr, "Usage: lxc-test-concurrent [OPTION]...\n\n"
51 "Common options :\n"
52 " -j, --threads=N Threads to run concurrently\n"
53 " (default: 5, use 1 for no threading)\n"
54 " -i, --iterations=N Number times to run the test (default: 1)\n"
55 " -t, --template=t Template to use (default: busybox)\n"
56 " -d, --delay=N Delay in seconds between start and stop\n"
57 " -m, --modes=<mode,mode,...> Modes to run (create, start, stop, destroy)\n"
58 " -q, --quiet Don't produce any output\n"
59 " -D, --debug Create a debug log\n"
60 " -?, --help Give this help list\n"
61 "\n"
62 "Mandatory or optional arguments to long options are also mandatory or optional\n"
63 "for any corresponding short options.\n\n");
beb6d93e 64}
103a2fc0 65
f209d63a 66struct thread_args {
fbeb7a1a 67 int thread_id;
68 int return_code;
69 const char *mode;
f209d63a
ÇO
70};
71
beb6d93e
DE
72static void do_function(void *arguments)
73{
fbeb7a1a 74 char name[NAME_MAX + 1];
75 struct thread_args *args = arguments;
76 struct lxc_container *c;
77
78 sprintf(name, "lxc-test-concurrent-%d", args->thread_id);
79
80 args->return_code = 1;
81
82 c = lxc_container_new(name, NULL);
83 if (!c) {
84 fprintf(stderr, "Unable to instantiate container (%s)\n", name);
85 return;
86 }
87
88 if (debug)
89 c->set_config_item(c, "lxc.log.level", "DEBUG");
90
91 if (strcmp(args->mode, "create") == 0) {
92 if (!c->is_defined(c)) {
93 if (!c->create(c, template, NULL, NULL, 1, NULL)) {
94 fprintf(stderr, "Creating the container (%s) failed...\n", name);
95 goto out;
96 }
97 }
98 } else if(strcmp(args->mode, "start") == 0) {
99 if (c->is_defined(c) && !c->is_running(c)) {
100 c->want_daemonize(c, true);
101
102 if (!c->start(c, false, NULL)) {
103 fprintf(stderr, "Starting the container (%s) failed...\n", name);
104 goto out;
105 }
106
107 if (!c->wait(c, "RUNNING", 15)) {
108 fprintf(stderr, "Waiting the container (%s) to start failed...\n", name);
109 goto out;
110 }
111
112 sleep(delay);
113 }
114 } else if(strcmp(args->mode, "stop") == 0) {
115 if (c->is_defined(c) && c->is_running(c)) {
116 if (!c->stop(c)) {
117 fprintf(stderr, "Stopping the container (%s) failed...\n", name);
118 goto out;
119 }
120
121 if (!c->wait(c, "STOPPED", 15)) {
122 fprintf(stderr, "Waiting the container (%s) to stop failed...\n", name);
123 goto out;
124 }
125 }
126 } else if(strcmp(args->mode, "destroy") == 0) {
127 if (c->is_defined(c) && !c->is_running(c)) {
128 if (!c->destroy(c)) {
129 fprintf(stderr, "Destroying the container (%s) failed...\n", name);
130 goto out;
131 }
132 }
133 }
134
135 args->return_code = 0;
136
f209d63a 137out:
fbeb7a1a 138 lxc_container_put(c);
139
140 if (debug)
141 lxc_log_close();
f209d63a
ÇO
142}
143
beb6d93e
DE
144static void *concurrent(void *arguments)
145{
fbeb7a1a 146 do_function(arguments);
147 pthread_exit(NULL);
4012c891 148
fbeb7a1a 149 return NULL;
beb6d93e 150}
f209d63a
ÇO
151
152int main(int argc, char *argv[]) {
fbeb7a1a 153 int i, j, iter, opt;
154 pthread_attr_t attr;
155 pthread_t *threads;
156 struct thread_args *args;
157
158 char *modes_default[] = {"create", "start", "stop", "destroy", NULL};
159 char **modes = modes_default;
160
161 pthread_attr_init(&attr);
162
163 while ((opt = getopt_long(argc, argv, "j:i:t:d:m:qD", options, NULL)) != -1) {
164 switch(opt) {
165 case 'j':
166 nthreads = atoi(optarg);
167 break;
168 case 'i':
169 iterations = atoi(optarg);
170 break;
171 case 't':
172 template = optarg;
173 break;
174 case 'd':
175 delay = atoi(optarg);
176 break;
177 case 'q':
178 quiet = 1;
179 break;
180 case 'D':
181 debug = 1;
182 break;
183 case 'm': {
184 char *mode_tok, *tok, *saveptr = NULL;
185
186 if (!optarg)
187 continue;
188
189 modes = NULL;
190 for (i = 0, mode_tok = optarg;
191 (tok = strtok_r(mode_tok, ",", &saveptr));
192 i++, mode_tok = NULL) {
193 modes = realloc(modes, sizeof(*modes) * (i+2));
194 if (!modes) {
195 perror("realloc");
196 exit(EXIT_FAILURE);
197 }
198 modes[i] = tok;
199 }
200
201 if (modes)
202 modes[i] = NULL;
203 break;
204 }
205 default: /* '?' */
206 usage();
207 exit(EXIT_FAILURE);
208 }
209 }
210
211 threads = malloc(sizeof(*threads) * nthreads);
212 args = malloc(sizeof(*args) * nthreads);
213 if (threads == NULL || args == NULL) {
214 fprintf(stderr, "Unable malloc enough memory for %d threads\n", nthreads);
215 exit(EXIT_FAILURE);
216 }
217
218 for (iter = 1; iter <= iterations; iter++) {
219 int fd;
220
221 fd = open("/", O_RDONLY);
222 if (fd < 0) {
223 fprintf(stderr, "Failed to open /\n");
224 continue;
225 }
226
227 if (!quiet)
228 printf("\nIteration %d/%d maxfd:%d\n", iter, iterations, fd);
229
230 close(fd);
231
232 for (i = 0; modes[i];i++) {
233 if (!quiet)
234 printf("Executing (%s) for %d containers...\n", modes[i], nthreads);
235
236 for (j = 0; j < nthreads; j++) {
237 args[j].thread_id = j;
238 args[j].mode = modes[i];
239
240 if (nthreads > 1) {
241 if (pthread_create(&threads[j], &attr, concurrent, (void *) &args[j]) != 0) {
242 perror("pthread_create() error");
243 exit(EXIT_FAILURE);
244 }
245 } else {
246 do_function(&args[j]);
247 }
248 }
249
250 for (j = 0; j < nthreads; j++) {
251 if (nthreads > 1) {
252 if (pthread_join(threads[j], NULL) != 0) {
253 perror("pthread_join() error");
254 exit(EXIT_FAILURE);
255 }
256 }
257
258 if (args[j].return_code) {
259 fprintf(stderr, "thread returned error %d\n", args[j].return_code);
260 exit(EXIT_FAILURE);
261 }
262 }
263 }
264 }
265
266 free(args);
267 free(threads);
268 pthread_attr_destroy(&attr);
269 exit(EXIT_SUCCESS);
f209d63a 270}