7 /* measure directory operation overhead
10 /* \fBfsstone\fR [\fB-cr\fR] [\fB-s \fIsize\fR]
11 /* \fImsg_count files_per_dir\fR
13 /* The \fBfsstone\fR command measures the cost of creating, renaming
14 /* and deleting queue files versus appending messages to existing
15 /* files and truncating them after use.
17 /* The program simulates the arrival of \fImsg_count\fR short messages,
18 /* and arranges for at most \fIfiles_per_dir\fR simultaneous files
19 /* in the same directory.
23 /* Create and delete files.
25 /* Rename files twice (requires \fB-c\fR).
26 /* .IP \fB-s \fIsize\fR
27 /* Specify the file size in kbytes.
29 /* Problems are reported to the standard error stream.
31 /* The \fB-r\fR option renames files within the same directory.
32 /* For a more realistic simulation, the program should rename files
33 /* <i>between</i> directories, and should also have an option to use
34 /* <i>hashed</i> directories as implemented with, for example, the
35 /* \fBdir_forest\fR(3) module.
39 /* The Secure Mailer license must be distributed with this software.
42 /* IBM T.J. Watson Research
44 /* Yorktown Heights, NY 10598, USA
56 /* Utility library. */
59 #include <msg_vstream.h>
61 /* Global directory. */
63 #include <mail_version.h>
65 /* rename_file - rename a file */
67 static void rename_file(int old
, int new)
69 char new_path
[BUFSIZ
];
70 char old_path
[BUFSIZ
];
72 sprintf(new_path
, "%06d", new);
73 sprintf(old_path
, "%06d", old
);
74 if (rename(old_path
, new_path
))
75 msg_fatal("rename %s to %s: %m", old_path
, new_path
);
78 /* make_file - create a little file and use it */
80 static void make_file(int seqno
, int size
)
87 sprintf(path
, "%06d", seqno
);
88 if ((fp
= fopen(path
, "w")) == 0)
89 msg_fatal("open %s: %m", path
);
90 memset(buf
, 'x', sizeof(buf
));
91 for (i
= 0; i
< size
; i
++)
92 if (fwrite(buf
, 1, sizeof(buf
), fp
) != sizeof(buf
))
93 msg_fatal("fwrite: %m");
94 if (fsync(fileno(fp
)))
95 msg_fatal("fsync: %m");
97 msg_fatal("fclose: %m");
98 if ((fp
= fopen(path
, "r")) == 0)
99 msg_fatal("open %s: %m", path
);
100 while (fgets(path
, sizeof(path
), fp
))
103 msg_fatal("fclose: %m");
106 /* use_file - use existing file */
108 static void use_file(int seqno
)
114 sprintf(path
, "%06d", seqno
);
115 if ((fp
= fopen(path
, "w")) == 0)
116 msg_fatal("open %s: %m", path
);
117 for (i
= 0; i
< 400; i
++)
118 fprintf(fp
, "hello");
119 if (fsync(fileno(fp
)))
120 msg_fatal("fsync: %m");
122 msg_fatal("fclose: %m");
123 if ((fp
= fopen(path
, "r+")) == 0)
124 msg_fatal("open %s: %m", path
);
125 while (fgets(path
, sizeof(path
), fp
))
127 if (ftruncate(fileno(fp
), (off_t
) 0))
128 msg_fatal("ftruncate: %m");;
130 msg_fatal("fclose: %m");
133 /* remove_file - delete specified file */
135 static void remove_file(int seq
)
139 sprintf(path
, "%06d", seq
);
141 msg_fatal("remove %s: %m", path
);
144 /* remove_silent - delete specified file, silently */
146 static void remove_silent(int seq
)
150 sprintf(path
, "%06d", seq
);
154 /* usage - explain */
156 static void usage(char *myname
)
158 msg_fatal("usage: %s [-cr] [-s size] messages directory_entries", myname
);
161 MAIL_VERSION_STAMP_DECLARE
;
163 int main(int argc
, char **argv
)
167 struct timeval start
, end
;
175 * Fingerprint executables and core dumps.
177 MAIL_VERSION_STAMP_ALLOCATE
;
179 msg_vstream_init(argv
[0], VSTREAM_ERR
);
180 while ((ch
= GETOPT(argc
, argv
, "crs:")) != EOF
) {
189 if ((size
= atoi(optarg
)) <= 0)
197 if (argc
- optind
!= 2 || (do_rename
&& !do_create
))
199 if ((op_count
= atoi(argv
[optind
])) <= 0)
201 if ((max_file
= atoi(argv
[optind
+ 1])) <= 0)
205 * Populate the directory with little files.
207 for (seq
= 0; seq
< max_file
; seq
++)
208 make_file(seq
, size
);
211 * Simulate arrival and delivery of mail messages.
213 GETTIMEOFDAY(&start
);
214 while (op_count
> 0) {
218 make_file(seq
, size
);
220 rename_file(seq
, seq
+ max_file
);
221 rename_file(seq
+ max_file
, seq
);
230 if (end
.tv_usec
< start
.tv_usec
) {
232 end
.tv_usec
+= 1000000;
234 printf("elapsed time: %ld.%06ld\n",
235 (long) (end
.tv_sec
- start
.tv_sec
),
236 (long) (end
.tv_usec
- start
.tv_usec
));
239 * Clean up directory fillers.
241 for (seq
= 0; seq
< max_file
; seq
++)