[dbench @ cvs-1:tridge-20020204031729-va6wl2depao9crhf]
[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 200
24
25 static char buf[70000];
26
27 char *server = NULL;
28 extern int sync_open, sync_dirs;
29
30 static struct {
31         int fd;
32         int handle;
33 } ftable[MAX_FILES];
34
35 static int find_handle(struct child_struct *child, int handle)
36 {
37         int i;
38         for (i=0;i<MAX_FILES;i++) {
39                 if (ftable[i].handle == handle) return i;
40         }
41         printf("(%d) ERROR: handle %d was not found\n", 
42                child->line, handle);
43         exit(1);
44 }
45
46
47 /* Find the directory holding a file, and flush it to disk.  We do
48    this in -S mode after a directory-modifying mode, to simulate the
49    way knfsd tries to flush directories.  MKDIR and similar operations
50    are meant to be synchronous on NFSv2. */
51 void sync_parent(char *fname)
52 {
53         char *copy_name;
54         int dir_fd;
55         char *slash;
56
57         if (strchr(fname, '/')) {
58                 copy_name = strdup(fname);
59                 slash = strrchr(copy_name, '/');
60                 *slash = '\0';
61         } else {
62                 copy_name = strdup(".");
63         } 
64         
65         dir_fd = open(copy_name, O_RDONLY);
66         if (dir_fd == -1) {
67                 printf("open directory \"%s\" for sync failed: %s\n",
68                        copy_name,
69                        strerror(errno));
70         } else {
71                 if (fdatasync(dir_fd) == -1) {
72                         printf("datasync directory \"%s\" failed: %s\n",
73                                copy_name,
74                                strerror(errno));
75                 }
76                 if (close(dir_fd) == -1) {
77                         printf("close directory failed: %s\n",
78                                strerror(errno));
79                 }
80         }
81         free(copy_name);
82 }
83
84
85 void nb_setup(struct child_struct *child)
86 {
87         char path[100];
88         sprintf(path, "/bin/rm -rf clients/client%d", child->id);
89         system(path);
90 }
91
92 void nb_unlink(struct child_struct *child, char *fname)
93 {
94         if (unlink(fname) != 0) {
95                 printf("(%d) unlink %s failed (%s)\n", 
96                        child->line, fname, strerror(errno));
97         }
98         if (sync_dirs) sync_parent(fname);
99 }
100
101 void nb_rmdir(struct child_struct *child, char *fname)
102 {
103         if (rmdir(fname) != 0) {
104                 printf("(%d) rmdir %s failed (%s)\n", 
105                        child->line, fname, strerror(errno));
106         }
107         if (sync_dirs) sync_parent(fname);
108 }
109
110 void nb_createx(struct child_struct *child, char *fname, 
111                 unsigned create_options, unsigned create_disposition, int fnum)
112 {
113         int fd, i;
114         int flags = O_RDWR;
115
116         if (sync_open) flags |= O_SYNC;
117
118         if (create_disposition == FILE_CREATE) {
119                 flags |= O_CREAT;
120         }
121
122         if (create_disposition == FILE_OVERWRITE ||
123             create_disposition == FILE_OVERWRITE_IF) {
124                 flags |= O_CREAT | O_TRUNC;
125         }
126
127         if (create_options & FILE_DIRECTORY_FILE) {
128                 /* not strictly correct, but close enough */
129                 mkdir(fname, 0700);
130         }
131
132         if (create_options & FILE_DIRECTORY_FILE) flags = O_RDONLY|O_DIRECTORY;
133         
134         fd = open(fname, flags, 0600);
135         if (fd == -1) {
136                 if (fnum != -1) {
137                         printf("(%d) open %s failed for handle %d (%s)\n", 
138                                child->line, fname, fnum, strerror(errno));
139                 }
140                 return;
141         }
142         if (fnum == -1) {
143                 printf("(%d) open %s succeeded for handle %d\n", 
144                        child->line, fname, fnum);
145                 close(fd);
146                 return;
147         }
148
149         for (i=0;i<MAX_FILES;i++) {
150                 if (ftable[i].handle == 0) break;
151         }
152         if (i == MAX_FILES) {
153                 printf("file table full for %s\n", fname);
154                 exit(1);
155         }
156         ftable[i].handle = fnum;
157         ftable[i].fd = fd;
158 }
159
160 void nb_writex(struct child_struct *child, int handle, int offset, 
161                int size, int ret_size)
162 {
163         int i = find_handle(child, handle);
164
165         if (buf[0] == 0) memset(buf, 1, sizeof(buf));
166
167         if (pwrite(ftable[i].fd, buf, size, offset) != ret_size) {
168                 printf("write failed on handle %d\n", handle);
169                 exit(1);
170         }
171
172         child->bytes_out += size;
173 }
174
175 void nb_readx(struct child_struct *child, int handle, int offset, 
176               int size, int ret_size)
177 {
178         int i = find_handle(child, handle);
179
180         if (pread(ftable[i].fd, buf, size, offset) != ret_size) {
181                 printf("read failed on handle %d\n", handle);
182         }
183
184         child->bytes_in += size;
185 }
186
187 void nb_close(struct child_struct *child, int handle)
188 {
189         int i = find_handle(child, handle);
190         close(ftable[i].fd);
191         ftable[i].handle = 0;
192 }
193
194 void nb_rename(struct child_struct *child, char *old, char *new)
195 {
196         if (rename(old, new) != 0) {
197                 printf("rename %s %s failed (%s)\n", 
198                        old, new, strerror(errno));
199                 exit(1);
200         }
201         if (sync_dirs) sync_parent(new);
202 }
203
204 void nb_flush(struct child_struct *child, int handle)
205 {
206         find_handle(child, handle);
207         /* noop */
208 }
209
210 void nb_qpathinfo(struct child_struct *child, const char *fname)
211 {
212         struct stat st;
213         stat(fname, &st);
214 }
215
216 void nb_qfileinfo(struct child_struct *child, int handle)
217 {
218         struct stat st;
219         int i = find_handle(child, handle);
220         fstat(ftable[i].fd, &st);
221 }
222
223 void nb_qfsinfo(struct child_struct *child, int level)
224 {
225         /* hmm, should do this one */
226 }
227
228 void nb_findfirst(struct child_struct *child, char *fname)
229 {
230         DIR *dir;
231         struct dirent *d;
232         char *p;
233         p = strrchr(fname, '/');
234         if (!p) return;
235         *p = 0;
236         dir = opendir(fname);
237         if (!dir) return;
238         while ((d = readdir(dir))) ;
239         closedir(dir);
240 }
241
242 void nb_cleanup(struct child_struct *child)
243 {
244 }