[ci] Fix netbsd job to upgrade existing packages
[xapian.git] / xapian-maintainer-tools / profiling / profiler.c
blobcb91949ad139345848cc266766bf95cbaebb6073
1 /** @file
2 * @brief C file implementing IO logging
3 */
4 /* Compile the profiler by running `make`.
6 * Run using the xapian-io-profile script, which expects profiler.so to be in the same directory as the script:
8 * ./xapian-io-profile --log=log_file_name ./executable
10 * The resulting log can be analysed with strace-analyse:
12 * ./strace-analyse log_file_name
15 #include <config.h>
17 #define _GNU_SOURCE
19 #include <dlfcn.h>
20 #include <errno.h>
21 #include <stdarg.h>
22 #include <stdio.h>
23 #include <stdlib.h>
25 /* Work out the appropriate printf specifier for off_t. */
26 #if SIZEOF_OFF_T == SIZEOF_INT
27 # define FORMAT_OFF_T "d"
28 #elif SIZEOF_OFF_T == SIZEOF_LONG
29 # define FORMAT_OFF_T "ld"
30 #elif SIZEOF_OFF_T == SIZEOF_LONG_LONG
31 # define FORMAT_OFF_T "lld"
32 #endif
34 /* Pick a suitable `off64_t` type to use for pread64(), etc. */
35 #if SIZEOF_OFF_T == 8
36 # define OFF64_T off_t
37 # define FORMAT_OFF64_T FORMAT_OFF_T
38 #elif SIZEOF_LONG == 8
39 # define OFF64_T long
40 # define FORMAT_OFF64_T "ld"
41 #elif SIZEOF_LONG_LONG == 8
42 # define OFF64_T long long
43 # define FORMAT_OFF64_T "lld"
44 #endif
46 // function for logging calls
48 void logcall(const char *format, ...)
50 static FILE *file_ptr = NULL;
51 int saved_errno = errno;
52 if (file_ptr == NULL) {
53 char *fd_str = getenv("XAPIAN_IO_PROFILE_LOG_FD");
54 if (fd_str) {
55 int fd = atoi(fd_str);
56 file_ptr = fdopen(fd, "w");
57 } else {
58 file_ptr = stderr;
61 va_list args_ptr;
62 va_start(args_ptr, format);
63 vfprintf(file_ptr, format, args_ptr);
64 va_end(args_ptr);
65 errno = saved_errno;
68 // wrapper for open()
70 typedef int (*real_open_t)(const char *, int, mode_t);
72 int open(const char *pathname, int flags, mode_t mode)
74 static real_open_t real_open = NULL;
75 if (!real_open) {
76 real_open = (real_open_t)dlsym(RTLD_NEXT, "open");
78 int fd = real_open(pathname, flags, mode);
79 // realpath can set errno
80 int saved_errno = errno;
81 char *abspath = realpath(pathname, NULL);
82 if (abspath) {
83 logcall("open(\"%s\",,) = %d\n", abspath, fd);
84 free(abspath);
85 } else {
86 // display pathname in case realpath fails
87 logcall("open(\"%s\",,) = %d\n", pathname, fd);
89 errno = saved_errno;
90 return fd;
93 #ifdef HAVE_OPEN64
94 // wrapper for open64()
96 typedef int (*real_open64_t)(const char *, int, mode_t);
98 int open64(const char *pathname, int flags, mode_t mode)
100 static real_open64_t real_open64 = NULL;
101 if (!real_open64) {
102 real_open64 = (real_open64_t)dlsym(RTLD_NEXT, "open64");
104 int fd = real_open64(pathname, flags, mode);
105 // realpath can set errno
106 int saved_errno = errno;
107 char *abspath = realpath(pathname, NULL);
108 if (abspath) {
109 logcall("open(\"%s\",,) = %d\n", abspath, fd);
110 free(abspath);
111 } else {
112 // display pathname in case realpath fails
113 logcall("open(\"%s\",,) = %d\n", pathname, fd);
115 errno = saved_errno;
116 return fd;
118 #endif
120 // wrapper for close()
122 typedef int (*real_close_t)(int);
124 int close(int fd)
126 static real_close_t real_close = NULL;
127 if (!real_close) {
128 real_close = (real_close_t)dlsym(RTLD_NEXT, "close");
130 int return_val = real_close(fd);
131 logcall("close(%d) = %d\n", fd, return_val);
132 return return_val;
135 #ifdef HAVE_FDATASYNC
136 // wrapper for fdatasync()
138 typedef ssize_t (*real_fdatasync_t)(int);
140 ssize_t fdatasync(int fd)
142 static real_fdatasync_t real_fdatasync = NULL;
143 if (!real_fdatasync) {
144 real_fdatasync = (real_fdatasync_t)dlsym(RTLD_NEXT, "fdatasync");
146 ssize_t return_val = real_fdatasync(fd);
147 logcall("fdatasync(%d) = %ld\n", fd, return_val);
148 return return_val;
150 #endif
152 #ifdef HAVE_FSYNC
153 // wrapper for fsync()
155 typedef ssize_t (*real_fsync_t)(int);
157 ssize_t fsync(int fd)
159 static real_fsync_t real_fsync = NULL;
160 if (!real_fsync) {
161 real_fsync = (real_fsync_t)dlsym(RTLD_NEXT, "fsync");
163 ssize_t return_val = real_fsync(fd);
164 logcall("fsync(%d) = %ld\n", fd, return_val);
165 return return_val;
167 #endif
169 // wrapper for pread()
171 typedef ssize_t (*real_pread_t)(int, void *, size_t, off_t);
173 ssize_t pread(int fd, void *buf, size_t count, off_t offset)
175 static real_pread_t real_pread = NULL;
176 if (!real_pread) {
177 real_pread = (real_pread_t)dlsym(RTLD_NEXT, "pread");
179 ssize_t return_val = real_pread(fd, buf, count, offset);
180 logcall("pread(%d, \"\", %zu, %" FORMAT_OFF_T ") = %zd\n",
181 fd, count, offset, return_val);
182 return return_val;
185 #ifdef HAVE_PREAD64
186 // wrapper for pread64()
188 typedef ssize_t (*real_pread64_t)(int, void *, size_t, OFF64_T);
190 ssize_t pread64(int fd, void *buf, size_t count, OFF64_T offset)
192 static real_pread64_t real_pread64 = NULL;
193 if (!real_pread64) {
194 real_pread64 = (real_pread64_t)dlsym(RTLD_NEXT, "pread64");
196 ssize_t return_val = real_pread64(fd, buf, count, offset);
197 logcall("pread(%d, \"\", %zu, %" FORMAT_OFF64_T ") = %zd\n",
198 fd, count, offset, return_val);
199 return return_val;
201 #endif
203 // wrapper for pwrite()
205 typedef ssize_t (*real_pwrite_t)(int, const void *, size_t, off_t);
207 ssize_t pwrite(int fd, const void *buf, size_t count, off_t offset)
209 static real_pwrite_t real_pwrite = NULL;
210 if (!real_pwrite) {
211 real_pwrite = (real_pwrite_t)dlsym(RTLD_NEXT, "pwrite");
213 ssize_t return_val = real_pwrite(fd, buf, count, offset);
214 logcall("pwrite(%d, \"\", %zu, %" FORMAT_OFF_T ") = %zd\n",
215 fd, count, offset, return_val);
216 return return_val;
219 #ifdef HAVE_PWRITE64
220 // wrapper for pwrite64()
222 typedef ssize_t (*real_pwrite64_t)(int, const void *, size_t, OFF64_T);
224 ssize_t pwrite64(int fd, const void *buf, size_t count, OFF64_T offset)
226 static real_pwrite64_t real_pwrite64 = NULL;
227 if (!real_pwrite64) {
228 real_pwrite64 = (real_pwrite64_t)dlsym(RTLD_NEXT, "pwrite64");
230 ssize_t return_val = real_pwrite64(fd, buf, count, offset);
231 logcall("pwrite(%d, \"\", %zu, %" FORMAT_OFF64_T ") = %zd\n",
232 fd, count, offset, return_val);
233 return return_val;
235 #endif