ia64/xen-unstable

view tools/xenstore/xs_stress.c @ 6946:e703abaf6e3d

Add behaviour to the remove methods to remove the transaction's path itself. This allows us to write Remove(path) to remove the specified path rather than having to slice the path ourselves.
author emellor@ewan
date Sun Sep 18 14:42:13 2005 +0100 (2005-09-18)
parents 999293916aa7
children f7a7f8f2e6e4 872cf6ee0594 06d84bf87159
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>
12 #define NUM_HANDLES 2
13 #define DIR_FANOUT 3
14 #define DIR_DEPTH 3
16 /* How often to print progress */
17 static int print;
19 /* Layout looks like /<num>/<num>/count. */
20 static void work(unsigned int cycles, unsigned int childnum)
21 {
22 unsigned int i;
23 struct xs_handle *handles[NUM_HANDLES];
24 char id;
26 if (childnum < 10)
27 id = '0' + childnum;
28 else
29 id = 'A' + childnum - 10;
31 for (i = 0; i < NUM_HANDLES; i++) {
32 handles[i] = xs_daemon_open();
33 if (!handles[i])
34 barf_perror("Opening handle %i", i);
35 }
37 srandom(childnum);
38 for (i = 0; i < cycles; i++) {
39 unsigned int lockdepth, j, len;
40 char file[100] = "", lockdir[100];
41 char *contents, tmp[100];
42 struct xs_handle *h = handles[random() % NUM_HANDLES];
44 lockdepth = random() % DIR_DEPTH;
45 for (j = 0; j < DIR_DEPTH; j++) {
46 if (j == lockdepth)
47 strcpy(lockdir, file);
48 sprintf(file + strlen(file), "/%li",
49 random()%DIR_FANOUT);
50 }
51 if (streq(lockdir, ""))
52 strcpy(lockdir, "/");
54 if (!xs_transaction_start(h, lockdir))
55 barf_perror("%i: starting transaction %i on %s",
56 childnum, i, lockdir);
58 sprintf(file + strlen(file), "/count");
59 contents = xs_read(h, file, &len);
60 if (!contents)
61 barf_perror("%i: can't read %s iter %i",
62 childnum, file, i);
63 sprintf(tmp, "%i", atoi(contents) + 1);
64 if (!xs_write(h, file, tmp, strlen(tmp)+1, 0))
65 barf_perror("%i: can't write %s iter %i",
66 childnum, file, i);
68 /* Abandon 1 in 10 */
69 if (random() % 10 == 0) {
70 if (!xs_transaction_end(h, true))
71 barf_perror("%i: can't abort transact %s",
72 childnum, lockdir);
73 i--;
74 } else {
75 if (!xs_transaction_end(h, false))
76 barf_perror("%i: can't commit transact %s",
77 childnum, lockdir);
79 /* Offset when we print . so kids don't all
80 * print at once. */
81 if ((i + print/(childnum+1)) % print == 0)
82 write(STDOUT_FILENO, &id, 1);
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", 2, O_EXCL|O_CREAT))
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, atoi(argv[1]));
205 printf("Success!\n");
206 exit(0);
207 }