ntvfs: Simplify rap_netshareenum()
[samba4-gss.git] / ctdb / utils / ping_pong / ping_pong.c
blob3d28f34982d523b78b3e6704037b39617e36e7f5
1 /*
2 A ping-pong fcntl byte range lock test
4 Copyright (C) Andrew Tridgell 2002
5 Copyright (C) Michael Adam 2012
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, see <http://www.gnu.org/licenses/>.
22 This measures the ping-pong byte range lock latency. It is
23 especially useful on a cluster of nodes sharing a common lock
24 manager as it will give some indication of the lock managers
25 performance under stress.
27 tridge@samba.org, February 2002
31 #define _XOPEN_SOURCE 500
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <sys/time.h>
36 #include <time.h>
37 #include <errno.h>
38 #include <string.h>
39 #include <unistd.h>
40 #include <fcntl.h>
41 #include <sys/mman.h>
42 #include <stdbool.h>
44 static struct timeval tp1,tp2;
46 static int do_reads, do_writes, use_mmap, do_check, do_brl_test;
48 static void start_timer(void)
50 gettimeofday(&tp1,NULL);
53 static double end_timer(void)
55 gettimeofday(&tp2,NULL);
56 return (tp2.tv_sec + (tp2.tv_usec*1.0e-6)) -
57 (tp1.tv_sec + (tp1.tv_usec*1.0e-6));
60 /* lock a byte range in a open file */
61 static int lock_range(int fd, int offset, int len, bool wait)
63 struct flock lock;
65 lock.l_type = F_WRLCK;
66 lock.l_whence = SEEK_SET;
67 lock.l_start = offset;
68 lock.l_len = len;
69 lock.l_pid = 0;
71 return fcntl(fd, wait ? F_SETLKW : F_SETLK, &lock);
74 /* check whether we could place a lock */
75 static int check_lock(int fd, int offset, int len)
77 struct flock lock;
78 int ret;
80 lock.l_type = F_WRLCK;
81 lock.l_whence = SEEK_SET;
82 lock.l_start = offset;
83 lock.l_len = len;
84 lock.l_pid = 0;
86 ret = fcntl(fd, F_GETLK, &lock);
87 if (ret != 0) {
88 printf("error calling fcntl F_GETLCK: %s\n", strerror(errno));
89 return -1;
92 if (lock.l_type == F_UNLCK) {
93 /* we would be able to place the lock */
94 return 0;
97 /* we would not be able to place lock */
98 printf("check_lock failed: lock held: "
99 "pid='%d', type='%d', start='%d', len='%d'\n",
100 (int)lock.l_pid, (int)lock.l_type, (int)lock.l_start, (int)lock.l_len);
101 return 1;
104 /* unlock a byte range in a open file */
105 static int unlock_range(int fd, int offset, int len)
107 struct flock lock;
109 lock.l_type = F_UNLCK;
110 lock.l_whence = SEEK_SET;
111 lock.l_start = offset;
112 lock.l_len = len;
113 lock.l_pid = 0;
115 return fcntl(fd,F_SETLKW,&lock);
118 /* run the ping pong test on fd */
119 static void ping_pong(int fd, int num_locks)
121 unsigned count = 0;
122 int i=0, loops=0;
123 unsigned char *val;
124 unsigned char incr=0, last_incr=0;
125 unsigned char *p = NULL;
126 int ret;
128 ret = ftruncate(fd, num_locks+1);
129 if (ret == -1) {
130 printf("ftruncate failed: %s\n", strerror(errno));
131 return;
134 if (use_mmap) {
135 p = mmap(NULL, num_locks+1, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
136 if (p == MAP_FAILED) {
137 printf("mmap failed: %s\n", strerror(errno));
138 return;
142 val = (unsigned char *)calloc(num_locks+1, sizeof(unsigned char));
143 if (val == NULL) {
144 printf("calloc failed\n");
145 if (use_mmap) {
146 munmap(p, num_locks+1);
148 return;
151 start_timer();
153 ret = lock_range(fd, 0, 1, true);
154 if (ret != 0) {
155 printf("initial lock at 0 failed! - %s\n", strerror(errno));
156 goto done;
159 i = 0;
161 while (1) {
162 if (lock_range(fd, (i+1) % num_locks, 1, true) != 0) {
163 printf("lock at %d failed! - %s\n",
164 (i+1) % num_locks, strerror(errno));
166 if (do_check) {
167 ret = check_lock(fd, i, 1);
168 if (ret != 0) {
169 goto done;
172 if (do_reads) {
173 unsigned char c;
174 if (use_mmap) {
175 c = p[i];
176 } else if (pread(fd, &c, 1, i) != 1) {
177 printf("read failed at %d\n", i);
179 incr = c - val[i];
180 val[i] = c;
182 if (do_writes) {
183 char c = val[i] + 1;
184 if (use_mmap) {
185 p[i] = c;
186 } else if (pwrite(fd, &c, 1, i) != 1) {
187 printf("write failed at %d\n", i);
190 if (unlock_range(fd, i, 1) != 0) {
191 printf("unlock at %d failed! - %s\n",
192 i, strerror(errno));
194 i = (i+1) % num_locks;
195 count++;
196 if (loops > num_locks && incr != last_incr) {
197 last_incr = incr;
198 printf("data increment = %u\n", incr);
199 fflush(stdout);
201 if (end_timer() > 1.0) {
202 printf("%8u locks/sec\r",
203 (unsigned)(2*count/end_timer()));
204 fflush(stdout);
205 start_timer();
206 count=0;
208 loops++;
211 done:
212 if (use_mmap) {
213 munmap(p, num_locks+1);
215 free(val);
218 static void usage(void)
220 printf("ping_pong -rwmc <file> <num_locks>\n");
221 printf("ping_pong -l <file>\n\n");
222 printf("Options\n");
223 printf(" -r do reads\n");
224 printf(" -w do writes\n");
225 printf(" -m use mmap\n");
226 printf(" -c check locks\n");
227 printf(" -l test for working byte range locks\n");
230 int main(int argc, char *argv[])
232 char *fname;
233 int fd, num_locks;
234 int c;
236 while ((c = getopt(argc, argv, "rwmcl")) != -1) {
237 switch (c){
238 case 'w':
239 do_writes = 1;
240 break;
241 case 'r':
242 do_reads = 1;
243 break;
244 case 'm':
245 use_mmap = 1;
246 break;
247 case 'c':
248 do_check = 1;
249 break;
250 case 'l':
251 do_brl_test = 1;
252 break;
253 default:
254 fprintf(stderr, "Unknown option '%c'\n", c);
255 exit(1);
259 argv += optind;
260 argc -= optind;
262 if (argc < 1) {
263 usage();
264 exit(1);
267 fname = argv[0];
269 fd = open(fname, O_CREAT|O_RDWR, 0600);
270 if (fd == -1) {
271 exit(1);
274 if (do_brl_test) {
275 if (lock_range(fd, 0, 0, false) != 0) {
276 printf("file already locked, calling check_lock to tell us who has it locked:\n");
277 (void)check_lock(fd, 0, 0);
278 printf("Working POSIX byte range locks\n");
279 exit(0);
282 printf("Holding lock, press any key to continue...\n");
283 printf("You should run the same command on another node now.\n");
284 (void)getchar();
285 printf("Good bye.\n");
286 exit(0);
289 if (argc < 2) {
290 usage();
291 exit(1);
294 num_locks = atoi(argv[1]);
295 if (num_locks <= 0) {
296 printf("num_locks should be > 0\n");
297 exit(1);
300 ping_pong(fd, num_locks);
302 return 0;