Postfix3.3.1
fsstone.c
[詳解]
1 /*++
2 /* NAME
3 /* fsstone 1
4 /* SUMMARY
5 /* measure directory operation overhead
6 /* SYNOPSIS
7 /* .fi
8 /* \fBfsstone\fR [\fB-cr\fR] [\fB-s \fIsize\fR]
9 /* \fImsg_count files_per_dir\fR
10 /* DESCRIPTION
11 /* The \fBfsstone\fR command measures the cost of creating, renaming
12 /* and deleting queue files versus appending messages to existing
13 /* files and truncating them after use.
14 /*
15 /* The program simulates the arrival of \fImsg_count\fR short messages,
16 /* and arranges for at most \fIfiles_per_dir\fR simultaneous files
17 /* in the same directory.
18 /*
19 /* Options:
20 /* .IP \fB-c\fR
21 /* Create and delete files.
22 /* .IP \fB-r\fR
23 /* Rename files twice (requires \fB-c\fR).
24 /* .IP \fB-s \fIsize\fR
25 /* Specify the file size in kbytes.
26 /* DIAGNOSTICS
27 /* Problems are reported to the standard error stream.
28 /* BUGS
29 /* The \fB-r\fR option renames files within the same directory.
30 /* For a more realistic simulation, the program should rename files
31 /* <i>between</i> directories, and should also have an option to use
32 /* <i>hashed</i> directories as implemented with, for example, the
33 /* \fBdir_forest\fR(3) module.
34 /* LICENSE
35 /* .ad
36 /* .fi
37 /* The Secure Mailer license must be distributed with this software.
38 /* AUTHOR(S)
39 /* Wietse Venema
40 /* IBM T.J. Watson Research
41 /* P.O. Box 704
42 /* Yorktown Heights, NY 10598, USA
43 /*--*/
44 
45 /* System library. */
46 
47 #include <sys_defs.h>
48 #include <stdio.h>
49 #include <stdlib.h>
50 #include <unistd.h>
51 #include <string.h>
52 #include <sys/time.h>
53 
54 /* Utility library. */
55 
56 #include <msg.h>
57 #include <msg_vstream.h>
58 
59 /* Global directory. */
60 
61 #include <mail_version.h>
62 
63 /* rename_file - rename a file */
64 
65 static void rename_file(int old, int new)
66 {
67  char new_path[BUFSIZ];
68  char old_path[BUFSIZ];
69 
70  sprintf(new_path, "%06d", new);
71  sprintf(old_path, "%06d", old);
72  if (rename(old_path, new_path))
73  msg_fatal("rename %s to %s: %m", old_path, new_path);
74 }
75 
76 /* make_file - create a little file and use it */
77 
78 static void make_file(int seqno, int size)
79 {
80  char path[BUFSIZ];
81  char buf[1024];
82  FILE *fp;
83  int i;
84 
85  sprintf(path, "%06d", seqno);
86  if ((fp = fopen(path, "w")) == 0)
87  msg_fatal("open %s: %m", path);
88  memset(buf, 'x', sizeof(buf));
89  for (i = 0; i < size; i++)
90  if (fwrite(buf, 1, sizeof(buf), fp) != sizeof(buf))
91  msg_fatal("fwrite: %m");
92  if (fsync(fileno(fp)))
93  msg_fatal("fsync: %m");
94  if (fclose(fp))
95  msg_fatal("fclose: %m");
96  if ((fp = fopen(path, "r")) == 0)
97  msg_fatal("open %s: %m", path);
98  while (fgets(path, sizeof(path), fp))
99  /* void */ ;
100  if (fclose(fp))
101  msg_fatal("fclose: %m");
102 }
103 
104 /* use_file - use existing file */
105 
106 static void use_file(int seqno)
107 {
108  char path[BUFSIZ];
109  FILE *fp;
110  int i;
111 
112  sprintf(path, "%06d", seqno);
113  if ((fp = fopen(path, "w")) == 0)
114  msg_fatal("open %s: %m", path);
115  for (i = 0; i < 400; i++)
116  fprintf(fp, "hello");
117  if (fsync(fileno(fp)))
118  msg_fatal("fsync: %m");
119  if (fclose(fp))
120  msg_fatal("fclose: %m");
121  if ((fp = fopen(path, "r+")) == 0)
122  msg_fatal("open %s: %m", path);
123  while (fgets(path, sizeof(path), fp))
124  /* void */ ;
125  if (ftruncate(fileno(fp), (off_t) 0))
126  msg_fatal("ftruncate: %m");;
127  if (fclose(fp))
128  msg_fatal("fclose: %m");
129 }
130 
131 /* remove_file - delete specified file */
132 
133 static void remove_file(int seq)
134 {
135  char path[BUFSIZ];
136 
137  sprintf(path, "%06d", seq);
138  if (remove(path))
139  msg_fatal("remove %s: %m", path);
140 }
141 
142 /* remove_silent - delete specified file, silently */
143 
144 static void remove_silent(int seq)
145 {
146  char path[BUFSIZ];
147 
148  sprintf(path, "%06d", seq);
149  (void) remove(path);
150 }
151 
152 /* usage - explain */
153 
154 static void usage(char *myname)
155 {
156  msg_fatal("usage: %s [-cr] [-s size] messages directory_entries", myname);
157 }
158 
160 
161 int main(int argc, char **argv)
162 {
163  int op_count;
164  int max_file;
165  struct timeval start, end;
166  int do_rename = 0;
167  int do_create = 0;
168  int seq;
169  int ch;
170  int size = 2;
171 
172  /*
173  * Fingerprint executables and core dumps.
174  */
176 
177  msg_vstream_init(argv[0], VSTREAM_ERR);
178  while ((ch = GETOPT(argc, argv, "crs:")) != EOF) {
179  switch (ch) {
180  case 'c':
181  do_create++;
182  break;
183  case 'r':
184  do_rename++;
185  break;
186  case 's':
187  if ((size = atoi(optarg)) <= 0)
188  usage(argv[0]);
189  break;
190  default:
191  usage(argv[0]);
192  }
193  }
194 
195  if (argc - optind != 2 || (do_rename && !do_create))
196  usage(argv[0]);
197  if ((op_count = atoi(argv[optind])) <= 0)
198  usage(argv[0]);
199  if ((max_file = atoi(argv[optind + 1])) <= 0)
200  usage(argv[0]);
201 
202  /*
203  * Populate the directory with little files.
204  */
205  for (seq = 0; seq < max_file; seq++)
206  make_file(seq, size);
207 
208  /*
209  * Simulate arrival and delivery of mail messages.
210  */
211  GETTIMEOFDAY(&start);
212  while (op_count > 0) {
213  seq %= max_file;
214  if (do_create) {
215  remove_file(seq);
216  make_file(seq, size);
217  if (do_rename) {
218  rename_file(seq, seq + max_file);
219  rename_file(seq + max_file, seq);
220  }
221  } else {
222  use_file(seq);
223  }
224  seq++;
225  op_count--;
226  }
227  GETTIMEOFDAY(&end);
228  if (end.tv_usec < start.tv_usec) {
229  end.tv_sec--;
230  end.tv_usec += 1000000;
231  }
232  printf("elapsed time: %ld.%06ld\n",
233  (long) (end.tv_sec - start.tv_sec),
234  (long) (end.tv_usec - start.tv_usec));
235 
236  /*
237  * Clean up directory fillers.
238  */
239  for (seq = 0; seq < max_file; seq++)
240  remove_silent(seq);
241  return (0);
242 }
#define MAIL_VERSION_STAMP_ALLOCATE
Definition: mail_version.h:67
NORETURN msg_fatal(const char *fmt,...)
Definition: msg.c:249
#define GETOPT(argc, argv, str)
Definition: sys_defs.h:1313
int main(int argc, char **argv)
Definition: fsstone.c:161
void msg_vstream_init(const char *name, VSTREAM *vp)
Definition: msg_vstream.c:77
MAIL_VERSION_STAMP_DECLARE
Definition: fsstone.c:159
#define VSTREAM_ERR
Definition: vstream.h:68