Version 8.2.1.
[libpwmd.git] / contrib / pwmd-stress-test.c
blobf98ba40a794496389e905f03e4fd58fae9d1adfe
1 /*
2 Copyright (C) 2016-2018 Ben Kibbey <bjk@luxsci.net>
4 This file is part of libpwmd.
6 Libpwmd 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 2 of the License, or
9 (at your option) any later version.
11 Libpwmd 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.
16 You should have received a copy of the GNU General Public License
17 along with Libpwmd. If not, see <http://www.gnu.org/licenses/>.
19 #ifdef HAVE_CONFIG_H
20 #include <config.h>
21 #endif
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <unistd.h>
25 #include <libpwmd.h>
26 #include <pthread.h>
27 #include <string.h>
29 static char *socket, *file, *cmd;
30 static int remaining;
31 static pthread_mutex_t count_mutex = PTHREAD_MUTEX_INITIALIZER;
32 static int lock;
33 static int states;
34 static int lock_timeout;
35 static int quiet;
37 static gpg_error_t
38 status_cb (void *data, const char *line)
40 pthread_t tid = pthread_self ();
42 if (quiet < 1)
43 fprintf(stdout, "STATUS: %p: %s\n", (pthread_t *)tid, line);
44 return 0;
47 void *
48 start (void *data)
50 pwm_t *pwm = NULL;
51 gpg_error_t rc;
52 pthread_t tid = pthread_self ();
53 char *result;
55 if (quiet < 2)
56 fprintf(stdout, "START: %p\n", (pthread_t *)tid);
57 rc = pwmd_new ("test-client", &pwm);
58 if (rc)
59 goto fail;
61 pwmd_setopt (pwm, PWMD_OPTION_LOCK_ON_OPEN, lock);
62 pwmd_setopt (pwm, PWMD_OPTION_STATUS_CB, status_cb);
64 rc = pwmd_connect (pwm, socket, NULL);
65 if (rc)
66 goto fail;
68 if (lock_timeout)
70 rc = pwmd_command (pwm, NULL, NULL, NULL, NULL, "OPTION lock-timeout=%i",
71 lock_timeout);
72 if (rc)
73 goto fail;
76 if (states)
78 rc = pwmd_command (pwm, NULL, NULL, NULL, NULL, "OPTION client-state=%i",
79 states);
80 if (rc)
81 goto fail;
84 rc = pwmd_process (pwm);
85 if (rc)
86 goto fail;
88 if (file)
90 rc = pwmd_open (pwm, file, NULL, NULL);
91 if (rc)
92 goto fail;
95 rc = pwmd_process (pwm);
96 if (rc)
97 goto fail;
99 rc = pwmd_command (pwm, &result, NULL, NULL, NULL, cmd);
100 if (rc)
101 goto fail;
103 if (quiet < 1)
104 fprintf(stdout, "RESULT: %p: '%s'\n", (pthread_t *) tid, result);
105 pwmd_free (result);
106 rc = pwmd_process (pwm);
108 fail:
109 pwmd_close (pwm);
111 if (rc && quiet < 3)
112 fprintf(stdout, "ERROR: %p: %u: %s\n", (pthread_t *)tid, rc,
113 gpg_strerror(rc));
115 pthread_mutex_lock (&count_mutex);
116 remaining--;
117 pthread_mutex_unlock (&count_mutex);
118 if (quiet < 2)
119 fprintf(stdout, "END: %p\n", (pthread_t *)tid);
120 pthread_exit (NULL);
121 return NULL;
124 static void
125 usage (const char *pn, int status)
127 fprintf(status == EXIT_SUCCESS ? stdout : stderr,
128 "Usage: %s [-hsnq] [-l N] <clients> <socket> [<datafile>] '<command_with_args>'\n", pn);
129 fprintf(status == EXIT_SUCCESS ? stdout : stderr,
130 " -n don't lock data file mutex\n"
131 " -l N lock timeout in tenths of a second\n"
132 " -q quiet (can be used more than once)\n"
133 " -s receive client state status messages\n"
134 " -h this help text\n");
135 exit (status);
138 int main(int argc, char **argv)
140 int i;
141 pthread_attr_t attr;
142 unsigned nclients;
143 int opt;
145 lock = 1;
147 while ((opt = getopt (argc, argv, "hnsl:q")) != -1)
149 switch (opt)
151 case 'q':
152 quiet++;
153 break;
154 case 'l':
155 lock_timeout = atoi (optarg);
156 break;
157 case 'n':
158 lock = 0;
159 break;
160 case 's':
161 states = 1;
162 break;
163 case 'h':
164 usage (argv[0], EXIT_SUCCESS);
165 break;
169 if (argc - optind < 3)
170 usage (argv[0], EXIT_FAILURE);
172 nclients = atoi (argv[optind++]);
173 socket = strdup (argv[optind++]);
175 if ((argc-optind) > 1)
176 file = strdup (argv[optind++]);
178 cmd = strdup (argv[optind++]);
179 if (quiet < 2)
180 fprintf(stdout, "Doing: '%s'\n", cmd);
181 pwmd_init ();
182 pthread_attr_init (&attr);
183 pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED);
185 for (i = 0; i < nclients; i++)
187 pthread_t tid;
188 int e = pthread_create (&tid, NULL, start, NULL);
190 if (e)
192 if (quiet < 3)
193 fprintf(stdout, "%s\n", strerror (e));
194 continue;
197 pthread_mutex_lock (&count_mutex);
198 remaining++;
199 pthread_mutex_unlock (&count_mutex);
202 pthread_attr_destroy (&attr);
204 for (; remaining;)
206 int n;
208 pthread_mutex_lock (&count_mutex);
209 n = remaining;
210 pthread_mutex_unlock (&count_mutex);
212 if (quiet < 2)
213 fprintf(stdout, "%i clients remain ...\n", n);
214 usleep (100000);
217 pwmd_deinit ();
218 exit (EXIT_SUCCESS);