[dbench @ cvs-1:tridge-20010812182557-rkvm3a5cqeobpai7]
[tridge/dbench.git] / fileio.c
1 /* 
2    dbench version 1.2
3    Copyright (C) 1999 by Andrew Tridgell <tridge@samba.org>
4    Copyright (C) 2001 by Martin Pool <mbp@samba.org>
5    
6    This program is free software; you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation; either version 2 of the License, or
9    (at your option) any later version.
10    
11    This program is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15    
16    You should have received a copy of the GNU General Public License
17    along with this program; if not, write to the Free Software
18    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 */
20
21 #include "dbench.h"
22
23 #define MAX_FILES 1000
24
25 static char buf[70000];
26 extern int line_count;
27
28 char *server = NULL;
29 extern int sync_open, sync_dirs;
30
31 static struct {
32         int fd;
33         int handle;
34 } ftable[MAX_FILES];
35
36
37 /* Find the directory holding a file, and flush it to disk.  We do
38    this in -S mode after a directory-modifying mode, to simulate the
39    way knfsd tries to flush directories.  MKDIR and similar operations
40    are meant to be synchronous on NFSv2. */
41 void sync_parent(char *fname)
42 {
43         char *copy_name;
44         int dir_fd;
45         char *slash;
46
47         if (strchr(fname, '/')) {
48                 copy_name = strdup(fname);
49                 slash = strrchr(copy_name, '/');
50                 *slash = '\0';
51         } else {
52                 copy_name = strdup(".");
53         } 
54         
55         dir_fd = open(copy_name, O_RDONLY);
56         if (dir_fd == -1) {
57                 printf("open directory \"%s\" for sync failed: %s\n",
58                        copy_name,
59                        strerror(errno));
60         } else {
61                 if (fdatasync(dir_fd) == -1) {
62                         printf("datasync directory \"%s\" failed: %s\n",
63                                copy_name,
64                                strerror(errno));
65                 }
66                 if (close(dir_fd) == -1) {
67                         printf("close directory failed: %s\n",
68                                strerror(errno));
69                 }
70         }
71         free(copy_name);
72 }
73
74
75 void nb_setup(int client)
76 {
77         /* nothing to do */
78 }
79
80 void nb_unlink(char *fname)
81 {
82         strupper(fname);
83
84         if (unlink(fname) != 0) {
85                 printf("(%d) unlink %s failed (%s)\n", 
86                        line_count, fname, strerror(errno));
87         }
88         if (sync_dirs)
89                 sync_parent(fname);
90 }
91
92 void expand_file(int fd, int size)
93 {
94         int s;
95         while (size) {
96                 s = MIN(sizeof(buf), size);
97                 write(fd, buf, s);
98                 size -= s;
99         }
100 }
101
102 void nb_open(char *fname, int handle, int size)
103 {
104         int fd, i;
105         int flags = O_RDWR|O_CREAT;
106         struct stat st;
107         static int count;
108
109         strupper(fname);
110
111         if (size == 0) flags |= O_TRUNC;
112
113         if (sync_open)
114                 flags |= O_SYNC;
115         
116         fd = open(fname, flags, 0600);
117         if (fd == -1) {
118                 printf("(%d) open %s failed for handle %d (%s)\n", 
119                        line_count, fname, handle, strerror(errno));
120                 return;
121         }
122         fstat(fd, &st);
123         if (size > st.st_size) {
124 #if DEBUG
125                 printf("(%d) expanding %s to %d from %d\n", 
126                        line_count, fname, size, (int)st.st_size);
127 #endif
128                 expand_file(fd, size - st.st_size);
129         } else if (size < st.st_size) {
130                 printf("truncating %s to %d from %d\n", 
131                        fname, size, (int)st.st_size);
132                 ftruncate(fd, size);
133         }
134         for (i=0;i<MAX_FILES;i++) {
135                 if (ftable[i].handle == 0) break;
136         }
137         if (i == MAX_FILES) {
138                 printf("file table full for %s\n", fname);
139                 exit(1);
140         }
141         ftable[i].handle = handle;
142         ftable[i].fd = fd;
143         if (count++ % 100 == 0) {
144                 printf(".");
145         }
146 }
147
148 void nb_write(int handle, int size, int offset)
149 {
150         int i;
151
152         if (buf[0] == 0) memset(buf, 1, sizeof(buf));
153
154         for (i=0;i<MAX_FILES;i++) {
155                 if (ftable[i].handle == handle) break;
156         }
157         if (i == MAX_FILES) {
158 #if 1
159                 printf("(%d) nb_write: handle %d was not open size=%d ofs=%d\n", 
160                        line_count, handle, size, offset);
161 #endif
162                 return;
163         }
164         lseek(ftable[i].fd, offset, SEEK_SET);
165         if (write(ftable[i].fd, buf, size) != size) {
166                 printf("write failed on handle %d\n", handle);
167         }
168 }
169
170 void nb_read(int handle, int size, int offset)
171 {
172         int i;
173         for (i=0;i<MAX_FILES;i++) {
174                 if (ftable[i].handle == handle) break;
175         }
176         if (i == MAX_FILES) {
177                 printf("(%d) nb_read: handle %d was not open size=%d ofs=%d\n", 
178                        line_count, handle, size, offset);
179                 return;
180         }
181         lseek(ftable[i].fd, offset, SEEK_SET);
182         read(ftable[i].fd, buf, size);
183 }
184
185 void nb_close(int handle)
186 {
187         int i;
188         for (i=0;i<MAX_FILES;i++) {
189                 if (ftable[i].handle == handle) break;
190         }
191         if (i == MAX_FILES) {
192                 printf("(%d) nb_close: handle %d was not open\n", 
193                        line_count, handle);
194                 return;
195         }
196         close(ftable[i].fd);
197         ftable[i].handle = 0;
198 }
199
200 void nb_mkdir(char *fname)
201 {
202         strupper(fname);
203
204         if (mkdir(fname, 0700) != 0) {
205 #if DEBUG
206                 printf("mkdir %s failed (%s)\n", 
207                        fname, strerror(errno));
208 #endif
209         }
210         if (sync_dirs)
211                 sync_parent(fname);
212 }
213
214 void nb_rmdir(char *fname)
215 {
216         strupper(fname);
217
218         if (rmdir(fname) != 0) {
219                 printf("rmdir %s failed (%s)\n", 
220                        fname, strerror(errno));
221         }
222         if (sync_dirs)
223                 sync_parent(fname);
224 }
225
226 void nb_rename(char *old, char *new)
227 {
228         strupper(old);
229         strupper(new);
230
231         if (rename(old, new) != 0) {
232                 printf("rename %s %s failed (%s)\n", 
233                        old, new, strerror(errno));
234         }
235         if (sync_dirs)
236                 sync_parent(new);
237 }
238
239
240 void nb_stat(char *fname, int size)
241 {
242         struct stat st;
243
244         strupper(fname);
245
246         if (stat(fname, &st) != 0) {
247                 printf("(%d) nb_stat: %s size=%d %s\n", 
248                        line_count, fname, size, strerror(errno));
249                 return;
250         }
251         if (S_ISDIR(st.st_mode)) return;
252
253         if (st.st_size != size) {
254                 printf("(%d) nb_stat: %s wrong size %d %d\n", 
255                        line_count, fname, (int)st.st_size, size);
256         }
257 }
258
259 void nb_create(char *fname, int size)
260 {
261         nb_open(fname, 5000, size);
262         nb_close(5000);
263 }