smbd/nmbd: Remove HAVE_LONGLONG
[Samba.git] / ctdb / utils / ping_pong / ping_pong.c
blob16f58d8af2b6dc76ca318ec80abf38a53a922434
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>
43 static struct timeval tp1,tp2;
45 static int do_reads, do_writes, use_mmap, do_check;
47 static void start_timer(void)
49 gettimeofday(&tp1,NULL);
52 static double end_timer(void)
54 gettimeofday(&tp2,NULL);
55 return (tp2.tv_sec + (tp2.tv_usec*1.0e-6)) -
56 (tp1.tv_sec + (tp1.tv_usec*1.0e-6));
59 /* lock a byte range in a open file */
60 static int lock_range(int fd, int offset, int len)
62 struct flock lock;
64 lock.l_type = F_WRLCK;
65 lock.l_whence = SEEK_SET;
66 lock.l_start = offset;
67 lock.l_len = len;
68 lock.l_pid = 0;
70 return fcntl(fd,F_SETLKW,&lock);
73 /* check whether we could place a lock */
74 int check_lock(int fd, int offset, int len)
76 struct flock lock;
77 int ret;
79 lock.l_type = F_WRLCK;
80 lock.l_whence = SEEK_SET;
81 lock.l_start = offset;
82 lock.l_len = len;
83 lock.l_pid = 0;
85 ret = fcntl(fd, F_GETLK, &lock);
86 if (ret != 0) {
87 printf("error calling fcntl F_GETLCK: %s\n", strerror(errno));
88 return -1;
91 if (lock.l_type == F_UNLCK) {
92 /* we would be able to place the lock */
93 return 0;
96 /* we would not be able to place lock */
97 printf("check_lock failed: lock held: "
98 "pid='%d', type='%d', start='%d', len='%d'\n",
99 (int)lock.l_pid, (int)lock.l_type, (int)lock.l_start, (int)lock.l_len);
100 return 1;
103 /* unlock a byte range in a open file */
104 static int unlock_range(int fd, int offset, int len)
106 struct flock lock;
108 lock.l_type = F_UNLCK;
109 lock.l_whence = SEEK_SET;
110 lock.l_start = offset;
111 lock.l_len = len;
112 lock.l_pid = 0;
114 return fcntl(fd,F_SETLKW,&lock);
117 /* run the ping pong test on fd */
118 static void ping_pong(int fd, int num_locks)
120 unsigned count = 0;
121 int i=0, loops=0;
122 unsigned char *val;
123 unsigned char incr=0, last_incr=0;
124 unsigned char *p = NULL;
125 int ret;
127 ret = ftruncate(fd, num_locks+1);
128 if (ret == -1) {
129 printf("ftruncate failed: %s\n", strerror(errno));
130 return;
133 if (use_mmap) {
134 p = mmap(NULL, num_locks+1, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
135 if (p == MAP_FAILED) {
136 printf("mmap failed: %s\n", strerror(errno));
137 return;
141 val = (unsigned char *)calloc(num_locks+1, sizeof(unsigned char));
142 if (val == NULL) {
143 printf("calloc failed\n");
144 return;
147 start_timer();
149 lock_range(fd, 0, 1);
150 i = 0;
152 while (1) {
153 if (lock_range(fd, (i+1) % num_locks, 1) != 0) {
154 printf("lock at %d failed! - %s\n",
155 (i+1) % num_locks, strerror(errno));
157 if (do_check) {
158 ret = check_lock(fd, i, 1);
160 if (do_reads) {
161 unsigned char c;
162 if (use_mmap) {
163 c = p[i];
164 } else if (pread(fd, &c, 1, i) != 1) {
165 printf("read failed at %d\n", i);
167 incr = c - val[i];
168 val[i] = c;
170 if (do_writes) {
171 char c = val[i] + 1;
172 if (use_mmap) {
173 p[i] = c;
174 } else if (pwrite(fd, &c, 1, i) != 1) {
175 printf("write failed at %d\n", i);
178 if (unlock_range(fd, i, 1) != 0) {
179 printf("unlock at %d failed! - %s\n",
180 i, strerror(errno));
182 i = (i+1) % num_locks;
183 count++;
184 if (loops > num_locks && incr != last_incr) {
185 last_incr = incr;
186 printf("data increment = %u\n", incr);
187 fflush(stdout);
189 if (end_timer() > 1.0) {
190 printf("%8u locks/sec\r",
191 (unsigned)(2*count/end_timer()));
192 fflush(stdout);
193 start_timer();
194 count=0;
196 loops++;
200 int main(int argc, char *argv[])
202 char *fname;
203 int fd, num_locks;
204 int c;
206 while ((c = getopt(argc, argv, "rwmc")) != -1) {
207 switch (c){
208 case 'w':
209 do_writes = 1;
210 break;
211 case 'r':
212 do_reads = 1;
213 break;
214 case 'm':
215 use_mmap = 1;
216 break;
217 case 'c':
218 do_check = 1;
219 break;
220 default:
221 fprintf(stderr, "Unknown option '%c'\n", c);
222 exit(1);
226 argv += optind;
227 argc -= optind;
229 if (argc < 2) {
230 printf("ping_pong [options] <file> <num_locks>\n");
231 printf(" -r do reads\n");
232 printf(" -w do writes\n");
233 printf(" -m use mmap\n");
234 printf(" -c check locks\n");
235 exit(1);
238 fname = argv[0];
239 num_locks = atoi(argv[1]);
240 if (num_locks <= 0) {
241 printf("num_locks should be > 0\n");
242 exit(1);
245 fd = open(fname, O_CREAT|O_RDWR, 0600);
246 if (fd == -1) exit(1);
248 ping_pong(fd, num_locks);
250 return 0;