test structure too
[tridge/junkcode.git] / ping_pong.c
1 /*
2   this measures the ping-pong byte range lock latency. It is
3   especially useful on a cluster of nodes sharing a common lock
4   manager as it will give some indication of the lock managers
5   performance under stress
6
7   tridge@samba.org, February 2002
8
9 */
10
11 #include <stdio.h>
12 #include <stdlib.h>
13 #include <sys/time.h>
14 #include <time.h>
15 #include <errno.h>
16 #include <string.h>
17 #include <unistd.h>
18 #include <fcntl.h>
19 #include <getopt.h>
20 #include <sys/mman.h>
21
22 static struct timeval tp1,tp2;
23
24 static int do_reads, do_writes, use_mmap;
25
26 static void start_timer()
27 {
28         gettimeofday(&tp1,NULL);
29 }
30
31 static double end_timer()
32 {
33         gettimeofday(&tp2,NULL);
34         return (tp2.tv_sec + (tp2.tv_usec*1.0e-6)) - 
35                 (tp1.tv_sec + (tp1.tv_usec*1.0e-6));
36 }
37
38 /* lock a byte range in a open file */
39 static int lock_range(int fd, int offset, int len)
40 {
41         struct flock lock;
42
43         lock.l_type = F_WRLCK;
44         lock.l_whence = SEEK_SET;
45         lock.l_start = offset;
46         lock.l_len = len;
47         lock.l_pid = 0;
48         
49         return fcntl(fd,F_SETLKW,&lock);
50 }
51
52 /* unlock a byte range in a open file */
53 static int unlock_range(int fd, int offset, int len)
54 {
55         struct flock lock;
56
57         lock.l_type = F_UNLCK;
58         lock.l_whence = SEEK_SET;
59         lock.l_start = offset;
60         lock.l_len = len;
61         lock.l_pid = 0;
62         
63         return fcntl(fd,F_SETLKW,&lock);
64 }
65
66 /* run the ping pong test on fd */
67 static void ping_pong(int fd, int num_locks)
68 {
69         unsigned count = 0;
70         int i=0, loops=0;
71         unsigned char *val;
72         unsigned char incr=0, last_incr=0;
73         unsigned char *p = NULL;
74
75         ftruncate(fd, num_locks+1);
76
77         if (use_mmap) {
78                 p = mmap(NULL, num_locks+1, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
79         }
80
81         val = (unsigned char *)calloc(num_locks+1, sizeof(unsigned char));
82
83         start_timer();  
84
85         lock_range(fd, 0, 1);
86         i = 0;
87
88         while (1) {
89                 if (lock_range(fd, (i+1) % num_locks, 1) != 0) {
90                         printf("lock at %d failed! - %s\n",
91                                (i+1) % num_locks, strerror(errno));
92                 }
93                 if (do_reads) {
94                         unsigned char c;
95                         if (use_mmap) {
96                                 c = p[i];
97                         } else if (pread(fd, &c, 1, i) != 1) {
98                                 printf("read failed at %d\n", i);
99                         }
100                         incr = c - val[i];
101                         val[i] = c;
102                 }
103                 if (do_writes) {
104                         char c = val[i] + 1;
105                         if (use_mmap) {
106                                 p[i] = c;
107                         } else if (pwrite(fd, &c, 1, i) != 1) {
108                                 printf("write failed at %d\n", i);
109                         }
110                 }
111                 if (unlock_range(fd, i, 1) != 0) {
112                         printf("unlock at %d failed! - %s\n",
113                                i, strerror(errno));
114                 }
115                 i = (i+1) % num_locks;
116                 count++;
117                 if (loops > num_locks && incr != last_incr) {
118                         last_incr = incr;
119                         printf("data increment = %u\n", incr);
120                         fflush(stdout);
121                 }
122                 if (end_timer() > 1.0) {
123                         printf("%8u locks/sec\r", 
124                                (unsigned)(2*count/end_timer()));
125                         fflush(stdout);
126                         start_timer();
127                         count=0;
128                 }
129                 loops++;
130         }
131 }
132
133 int main(int argc, char *argv[])
134 {
135         char *fname;
136         int fd, num_locks;
137         int c;
138
139         while ((c = getopt(argc, argv, "rwm")) != -1) {
140                 switch (c){
141                 case 'w':
142                         do_writes = 1;
143                         break;
144                 case 'r':
145                         do_reads = 1;
146                         break;
147                 case 'm':
148                         use_mmap = 1;
149                         break;
150                 default:
151                         fprintf(stderr, "Unknown option '%c'\n", c);
152                         exit(1);
153                 }
154         }
155
156         argv += optind;
157         argc -= optind;
158
159         if (argc < 2) {
160                 printf("ping_pong [options] <file> <num_locks>\n");
161                 printf("           -r    do reads\n");
162                 printf("           -w    do writes\n");
163                 printf("           -m    use mmap\n");
164                 exit(1);
165         }
166
167         fname = argv[0];
168         num_locks = atoi(argv[1]);
169
170         fd = open(fname, O_CREAT|O_RDWR, 0600);
171         if (fd == -1) exit(1);
172
173         ping_pong(fd, num_locks);
174
175         return 0;
176 }