Show Contents Previous Page Next Page
Chapter 10 - C API Reference Guide, Part I / Server Core Routines The Piped Log API Apache Version 1.3.0 introduced reliable piped log support, which allows your
module to send log data to a running program.6
If the program happens to die, it will be automatically restarted. Internally,
this API is used when processing log file directives that begin with the |
(pipe character). Everything following the pipe character is treated as a program
to be run. After the program is launched, log entries are sent to the program
on its standard input. You will probably not need to use the piped log routines because
this functionality is already handled in a generic way by Apache's
mod_log_config module. However, if you wish to support
this feature in a custom logging module of your own, these calls
are available for your use. The main data structure used by the piped log API is the piped_log
record, defined in http_log.h. This data structure
should be treated as an opaque data structure. Use ap_open_piped_log()
to open a pipe to a new process, ap_piped_log_read_fd()
and ap_piped_log_write_fd() to obtain file descriptors
that you can use to read and write from the process, and ap_close_piped_log()
to close the pipe when you're through. piped_log *ap_open_piped_log (pool *p, const char *program)
Given a resource pool p and the path to an
executable program, ap_open_piped_log()
will launch the program, open a bidirectional pipe to it,
and return a piped_log pointer if successful
or NULL if not. You should make this call during the module or child initialization
phases. This will avoid the overhead of opening and closing
the pipe for each request. If you open the pipe at module initialization
time, the subprocess will be run as root, but there will be
only one copy running. If you open the pipe during child initialization,
it will run as the httpd user, but there will be
one copy of the subprocess running for each child. It's your
call which to use. Here's an example of opening a log file specified by the module-specific
configuration record cfg . If the initial character
of the filename is the pipe symbol, the code opens it as a piped
command. Otherwise, it opens it as a normal file. For simplicity,
we've omitted error checking from this example.
if(*cfg->log_file == '|') {
/* open as a command pipe */
piped_log *pl = ap_open_piped_log(p, cfg->log_file + 1);
cfg->log_fd = ap_piped_log_write_fd(pl);
}
else {
/* open as normal file */
cls->log_fd = ap_popenf(p, cfg->log_file, flags, mode);
}
if (!cls->log_fd) {
... raise some sort of error...
Some of the routines in this example are described in the next
chapter.
void ap_close_piped_log (piped_log *pl)
This function closes a previously opened piped log. Conveniently,
this function will be called at pool destruction time if you don't
call it yourself.
int ap_piped_log_write_fd (piped_log *pl)
ap_piped_log_write_fd() returns a file descriptor
that you can use to write to the logging process using the standard
write() library call. Typically, you will write some
form of accounting or status information, but the contents of
the information you send are entirely up to you. Because all writing
is done through a file descriptor, the same code routines that
write to plain text files can be used to write to the pipe.
int ap_piped_log_read_fd (piped_log *pl)
ap_piped_log_read() returns a file descriptor that
you can use to read from the logging process with the standard
read() library call. It is far more usual to write to
a logging process than to read from one, but you can do this if
the process provides status information, for instance. If you
both read and write from the process, beware of deadlock situations
in which both your module and the logging process are waiting
for the other. Show Contents Previous Page Next Page Copyright © 1999 by O'Reilly & Associates, Inc. |