ia64/xen-unstable

view tools/xenstore/xs_stress.c @ 7238:971e7c7411b3

Raise an exception if an error appears on the pipes to our children, and make
sure that the child's pipes are closed even under that exception. Move the
handling of POLLHUP to the end of the loop, so that we guarantee to read any
remaining data from the child if POLLHUP and POLLIN appear at the same time.

Signed-off-by: Ewan Mellor <ewan@xensource.com>
author emellor@ewan
date Thu Oct 06 10:13:11 2005 +0100 (2005-10-06)
parents ef9591d03fdd
children 93e27f7ca8a8 61b3b357d827
line source
1 /* Stress test for Xen Store: multiple people hammering transactions */
2 #include "xs.h"
3 #include "utils.h"
4 #include <stdlib.h>
5 #include <stdio.h>
6 #include <sys/types.h>
7 #include <sys/wait.h>
8 #include <sys/stat.h>
9 #include <fcntl.h>
10 #include <unistd.h>
11 #include <errno.h>
13 #define NUM_HANDLES 2
14 #define DIR_FANOUT 3
15 #define DIR_DEPTH 3
17 /* How often to print progress */
18 static int print;
20 /* Layout looks like /<num>/<num>/count. */
21 static void work(unsigned int cycles, unsigned int childnum)
22 {
23 unsigned int i;
24 struct xs_handle *handles[NUM_HANDLES];
25 char id;
27 if (childnum < 10)
28 id = '0' + childnum;
29 else
30 id = 'A' + childnum - 10;
32 for (i = 0; i < NUM_HANDLES; i++) {
33 handles[i] = xs_daemon_open();
34 if (!handles[i])
35 barf_perror("Opening handle %i", i);
36 }
38 srandom(childnum);
39 for (i = 0; i < cycles; i++) {
40 unsigned int j, len;
41 char file[100] = "";
42 char *contents, tmp[100];
43 struct xs_handle *h = handles[random() % NUM_HANDLES];
45 for (j = 0; j < DIR_DEPTH; j++)
46 sprintf(file + strlen(file), "/%li",
47 random()%DIR_FANOUT);
49 if (!xs_transaction_start(h))
50 barf_perror("%i: starting transaction %i",
51 childnum, i);
53 sprintf(file + strlen(file), "/count");
54 contents = xs_read(h, file, &len);
55 if (!contents)
56 barf_perror("%i: can't read %s iter %i",
57 childnum, file, i);
58 sprintf(tmp, "%i", atoi(contents) + 1);
59 if (!xs_write(h, file, tmp, strlen(tmp)+1))
60 barf_perror("%i: can't write %s iter %i",
61 childnum, file, i);
63 /* Abandon 1 in 10 */
64 if (random() % 10 == 0) {
65 if (!xs_transaction_end(h, true))
66 barf_perror("%i: can't abort transact",
67 childnum);
68 i--;
69 } else {
70 if (!xs_transaction_end(h, false)) {
71 if (errno == EAGAIN) {
72 write(STDOUT_FILENO, "!", 1);
73 i--;
74 } else
75 barf_perror("%i: can't commit trans",
76 childnum);
77 } else {
78 /* Offset when we print . so kids don't all
79 * print at once. */
80 if ((i + print/(childnum+1)) % print == 0)
81 write(STDOUT_FILENO, &id, 1);
82 }
83 }
84 }
85 }
87 static void create_dirs(struct xs_handle *h, const char *base, int togo)
88 {
89 unsigned int i;
90 char filename[100];
92 if (togo == 0) {
93 sprintf(filename, "%s/count", base);
94 if (!xs_write(h, filename, "0", 1))
95 barf_perror("Writing to %s", filename);
96 return;
97 }
99 for (i = 0; i < DIR_FANOUT; i++) {
100 sprintf(filename, "%s/%i", base, i);
101 if (!xs_mkdir(h, filename))
102 barf_perror("xs_mkdir %s", filename);
103 create_dirs(h, filename, togo-1);
104 }
105 }
107 static unsigned int add_count(struct xs_handle *h, const char *base, int togo)
108 {
109 unsigned int i, count;
110 char filename[100];
112 if (togo == 0) {
113 char *answer;
114 unsigned int len;
116 sprintf(filename, "%s/count", base);
117 answer = xs_read(h, filename, &len);
118 if (!answer)
119 barf_perror("Reading %s", filename);
120 count = atoi(answer);
121 free(answer);
122 return count;
123 }
125 count = 0;
126 for (i = 0; i < DIR_FANOUT; i++) {
127 sprintf(filename, "%s/%i", base, i);
128 count += add_count(h, filename, togo-1);
129 }
130 return count;
131 }
133 static void setup(void)
134 {
135 struct xs_handle *h;
137 /* Do setup. */
138 h = xs_daemon_open();
139 if (!h)
140 barf_perror("Contacting daemon");
141 create_dirs(h, "", DIR_DEPTH);
142 xs_daemon_close(h);
143 }
145 static unsigned int tally_counts(void)
146 {
147 struct xs_handle *h;
148 unsigned int ret;
150 h = xs_daemon_open();
151 if (!h)
152 barf_perror("Contacting daemon");
154 ret = add_count(h, "", DIR_DEPTH);
155 xs_daemon_close(h);
156 return ret;
157 }
159 int main(int argc, char *argv[])
160 {
161 unsigned int i;
162 bool failed = false;
163 int kids[10];
165 if (argc != 2)
166 barf("Usage: xs_stress <iterations>");
168 printf("Setting up directories...\n");
169 setup();
171 print = atoi(argv[1]) / 76;
172 if (!print)
173 print = 1;
175 printf("Running %i children...\n", ARRAY_SIZE(kids));
176 for (i = 0; i < ARRAY_SIZE(kids); i++) {
177 kids[i] = fork();
178 if (kids[i] == -1)
179 barf_perror("fork");
180 if (kids[i] == 0) {
181 work(atoi(argv[1]) / ARRAY_SIZE(kids), i);
182 exit(0);
183 }
184 }
186 for (i = 0; i < ARRAY_SIZE(kids); i++) {
187 int status;
188 if (waitpid(kids[i], &status, 0) == -1)
189 barf_perror("waitpid");
190 if (!WIFEXITED(status))
191 barf("Kid %i died via signal %i\n",
192 i, WTERMSIG(status));
193 if (WEXITSTATUS(status) != 0) {
194 printf("Child %i exited %i\n", i, WEXITSTATUS(status));
195 failed = true;
196 }
197 }
198 if (failed)
199 exit(1);
201 printf("\nCounting results...\n");
202 i = tally_counts();
203 if (i != (unsigned)atoi(argv[1]))
204 barf("Total counts %i not %s", i, argv[1]);
205 printf("Success!\n");
206 exit(0);
207 }