source: trunk/packages/xen-3.1/xen-3.1/tools/xenstore/xs_stress.c @ 34

Last change on this file since 34 was 34, checked in by hartmans, 18 years ago

Add xen and xen-common

File size: 4.4 KB
Line 
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>
12
13#define NUM_HANDLES 2
14#define DIR_FANOUT 3
15#define DIR_DEPTH 3
16
17/* How often to print progress */
18static int print;
19
20/* Layout looks like /<num>/<num>/count. */
21static void work(unsigned int cycles, unsigned int childnum)
22{
23        unsigned int i;
24        struct xs_handle *handles[NUM_HANDLES];
25        char id;
26
27        if (childnum < 10)
28                id = '0' + childnum;
29        else
30                id = 'A' + childnum - 10;
31
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        }
37
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];
44
45                for (j = 0; j < DIR_DEPTH; j++)
46                        sprintf(file + strlen(file), "/%li",
47                                random()%DIR_FANOUT);
48
49                if (!xs_transaction_start(h))
50                        barf_perror("%i: starting transaction %i",
51                                    childnum, i);
52
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);
62
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}
86
87static void create_dirs(struct xs_handle *h, const char *base, int togo)
88{
89        unsigned int i;
90        char filename[100];
91
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        }
98
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}
106
107static unsigned int add_count(struct xs_handle *h, const char *base, int togo)
108{
109        unsigned int i, count;
110        char filename[100];
111
112        if (togo == 0) {
113                char *answer;
114                unsigned int len;
115
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        }
124
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}
132
133static void setup(void)
134{
135        struct xs_handle *h;
136
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}
144
145static unsigned int tally_counts(void)
146{
147        struct xs_handle *h;
148        unsigned int ret;
149       
150        h = xs_daemon_open();
151        if (!h)
152                barf_perror("Contacting daemon");
153
154        ret = add_count(h, "", DIR_DEPTH);
155        xs_daemon_close(h);
156        return ret;
157}       
158
159int main(int argc, char *argv[])
160{
161        unsigned int i;
162        bool failed = false;
163        int kids[10];
164
165        if (argc != 2)
166                barf("Usage: xs_stress <iterations>");
167
168        printf("Setting up directories...\n");
169        setup();
170
171        print = atoi(argv[1]) / 76;
172        if (!print)
173                print = 1;
174
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        }
185
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);
200
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}
Note: See TracBrowser for help on using the repository browser.