ostream.h revision d6193a892452ae87548f5745dada01f82816765d
c25356d5978632df6203437e1953bcb29e0c736fTimo Sirainen#ifndef OSTREAM_H
c25356d5978632df6203437e1953bcb29e0c736fTimo Sirainen#define OSTREAM_H
57f4445a46726a17bfe78b0964dd301a6ccb40ecTimo Sirainen
c8296ac1ed68ed5c5168de545b76f9b27fc76d35Timo Sirainen#include "ioloop.h"
c8296ac1ed68ed5c5168de545b76f9b27fc76d35Timo Sirainen
57f4445a46726a17bfe78b0964dd301a6ccb40ecTimo Sirainenenum ostream_send_istream_result {
57f4445a46726a17bfe78b0964dd301a6ccb40ecTimo Sirainen /* All of the istream was successfully sent to ostream. */
c8296ac1ed68ed5c5168de545b76f9b27fc76d35Timo Sirainen OSTREAM_SEND_ISTREAM_RESULT_FINISHED,
c8296ac1ed68ed5c5168de545b76f9b27fc76d35Timo Sirainen /* Caller needs to wait for more input from non-blocking istream. */
c8296ac1ed68ed5c5168de545b76f9b27fc76d35Timo Sirainen OSTREAM_SEND_ISTREAM_RESULT_WAIT_INPUT,
c8296ac1ed68ed5c5168de545b76f9b27fc76d35Timo Sirainen /* Caller needs to wait for output to non-blocking ostream.
c37098f8ce6d512ba41f09564d04ed25720f0a77Timo Sirainen o_stream_set_flush_pending() is automatically called. */
c8296ac1ed68ed5c5168de545b76f9b27fc76d35Timo Sirainen OSTREAM_SEND_ISTREAM_RESULT_WAIT_OUTPUT,
c8296ac1ed68ed5c5168de545b76f9b27fc76d35Timo Sirainen /* Read from istream failed. See istream->stream_errno. */
c8296ac1ed68ed5c5168de545b76f9b27fc76d35Timo Sirainen OSTREAM_SEND_ISTREAM_RESULT_ERROR_INPUT,
c8296ac1ed68ed5c5168de545b76f9b27fc76d35Timo Sirainen /* Write to ostream failed. See ostream->stream_errno. */
c8296ac1ed68ed5c5168de545b76f9b27fc76d35Timo Sirainen OSTREAM_SEND_ISTREAM_RESULT_ERROR_OUTPUT
c8296ac1ed68ed5c5168de545b76f9b27fc76d35Timo Sirainen};
c8296ac1ed68ed5c5168de545b76f9b27fc76d35Timo Sirainen
c8296ac1ed68ed5c5168de545b76f9b27fc76d35Timo Sirainenstruct ostream {
57f4445a46726a17bfe78b0964dd301a6ccb40ecTimo Sirainen /* Number of bytes sent via o_stream_send*() and similar functions.
c8296ac1ed68ed5c5168de545b76f9b27fc76d35Timo Sirainen This is counting the input data. For example with a compressed
57f4445a46726a17bfe78b0964dd301a6ccb40ecTimo Sirainen ostream this is counting the uncompressed bytes. The compressed
5666a3d6a7ea89362b8d9e8b39b15424cd9d6388Timo Sirainen bytes could be counted from the parent ostream's offset.
57f4445a46726a17bfe78b0964dd301a6ccb40ecTimo Sirainen
57f4445a46726a17bfe78b0964dd301a6ccb40ecTimo Sirainen Seeking to a specified offset only makes sense if there is no
57f4445a46726a17bfe78b0964dd301a6ccb40ecTimo Sirainen difference between input and output data sizes (e.g. there are no
wrapper ostreams changing the data). */
uoff_t offset;
/* errno for the last operation send/seek operation. cleared before
each call. */
int stream_errno;
/* overflow is set when some of the data given to send()
functions was neither sent nor buffered. It's never unset inside
ostream code. */
bool overflow:1;
/* o_stream_send() writes all the data or returns failure */
bool blocking:1;
bool closed:1;
struct ostream_private *real_stream;
};
/* Returns 1 if all data is sent (not necessarily flushed), 0 if not.
Pretty much the only real reason to return 0 is if you wish to send more
data to client which isn't buffered, eg. o_stream_send_istream(). */
typedef int stream_flush_callback_t(void *context);
typedef void ostream_callback_t(void *context);
/* Create new output stream from given file descriptor.
If max_buffer_size is 0, an "optimal" buffer size is used (max 128kB). */
struct ostream *o_stream_create_fd(int fd, size_t max_buffer_size);
/* The fd is set to -1 immediately to avoid accidentally closing it twice. */
struct ostream *o_stream_create_fd_autoclose(int *fd, size_t max_buffer_size);
/* Create an output stream from a regular file which begins at given offset.
If offset==(uoff_t)-1, the current offset isn't known. */
struct ostream *
o_stream_create_fd_file(int fd, uoff_t offset, bool autoclose_fd);
struct ostream *o_stream_create_fd_file_autoclose(int *fd, uoff_t offset);
/* Create an output stream to a buffer. */
struct ostream *o_stream_create_buffer(buffer_t *buf);
/* Create an output streams that always fails the writes. */
struct ostream *o_stream_create_error(int stream_errno);
struct ostream *
o_stream_create_error_str(int stream_errno, const char *fmt, ...)
ATTR_FORMAT(2, 3);
/* Create an output stream that simply passes through data. This is mainly
useful as a wrapper when combined with destroy callbacks. */
struct ostream *o_stream_create_passthrough(struct ostream *output);
/* Set name (e.g. path) for output stream. */
void o_stream_set_name(struct ostream *stream, const char *name);
/* Get output stream's name. Returns "" if stream has no name. */
const char *o_stream_get_name(struct ostream *stream);
/* Return file descriptor for stream, or -1 if none is available. */
int o_stream_get_fd(struct ostream *stream);
/* Returns error string for the previous error. */
const char *o_stream_get_error(struct ostream *stream);
/* Close this stream (but not its parents) and unreference it. */
void o_stream_destroy(struct ostream **stream);
/* Reference counting. References start from 1, so calling o_stream_unref()
destroys the stream if o_stream_ref() is never used. */
void o_stream_ref(struct ostream *stream);
/* Unreferences the stream and sets stream pointer to NULL. */
void o_stream_unref(struct ostream **stream);
/* Call the given callback function when stream is destroyed. */
void o_stream_add_destroy_callback(struct ostream *stream,
ostream_callback_t *callback, void *context)
ATTR_NULL(3);
#define o_stream_add_destroy_callback(stream, callback, context) \
o_stream_add_destroy_callback(stream + \
CALLBACK_TYPECHECK(callback, void (*)(typeof(context))), \
(ostream_callback_t *)callback, context)
/* Remove the destroy callback. */
void o_stream_remove_destroy_callback(struct ostream *stream,
void (*callback)());
/* Mark the stream and all of its parent streams closed. Nothing will be
sent after this call. When using ostreams that require writing a trailer,
o_stream_finish() must be used before the stream is closed. When ostream
is destroyed, it's also closed but its parents aren't.
Closing the ostream (also via destroy) will first flush the ostream, and
afterwards requires one of: a) stream has failed, b) there is no more
buffered data, c) o_stream_set_no_error_handling() has been called. */
void o_stream_close(struct ostream *stream);
/* Set IO_WRITE callback. Default will just try to flush the output and
finishes when the buffer is empty. */
void o_stream_set_flush_callback(struct ostream *stream,
stream_flush_callback_t *callback,
void *context) ATTR_NULL(3);
#define o_stream_set_flush_callback(stream, callback, context) \
o_stream_set_flush_callback(stream + \
CALLBACK_TYPECHECK(callback, int (*)(typeof(context))), \
(stream_flush_callback_t *)callback, context)
void o_stream_unset_flush_callback(struct ostream *stream);
/* Change the maximum size for stream's output buffer to grow. */
void o_stream_set_max_buffer_size(struct ostream *stream, size_t max_size);
/* Returns the current max. buffer size. */
size_t o_stream_get_max_buffer_size(struct ostream *stream);
/* Delays sending as far as possible, writing only full buffers. Also sets
TCP_CORK on if supported. */
void o_stream_cork(struct ostream *stream);
/* Try to flush the buffer by calling o_stream_flush() and remove TCP_CORK.
Note that after this o_stream_flush() must be called, unless the stream
ignores errors. */
void o_stream_uncork(struct ostream *stream);
bool o_stream_is_corked(struct ostream *stream);
/* Try to flush the output stream. If o_stream_nsend*() had been used and
the stream had overflown, return error. Returns 1 if all data is sent,
0 there's still buffered data, -1 if error. */
int o_stream_flush(struct ostream *stream);
/* Set "flush pending" state of stream. If set, the flush callback is called
when more data is allowed to be sent, even if the buffer itself is empty. */
void o_stream_set_flush_pending(struct ostream *stream, bool set);
/* Returns number of bytes currently in buffer. */
size_t o_stream_get_buffer_used_size(const struct ostream *stream) ATTR_PURE;
/* Returns number of bytes we can still write without failing. */
size_t o_stream_get_buffer_avail_size(const struct ostream *stream) ATTR_PURE;
/* Seek to specified position from beginning of file. This works only for
files. Returns 1 if successful, -1 if error. */
int o_stream_seek(struct ostream *stream, uoff_t offset);
/* Returns number of bytes sent, -1 = error */
ssize_t o_stream_send(struct ostream *stream, const void *data, size_t size);
ssize_t o_stream_sendv(struct ostream *stream, const struct const_iovec *iov,
unsigned int iov_count);
ssize_t o_stream_send_str(struct ostream *stream, const char *str);
/* Send with delayed error handling. o_stream_flush() or
o_stream_ignore_last_errors() must be called after these functions before
the stream is destroyed. If any of the data can't be sent due to stream's
buffer getting full, all further nsends are ignores and o_stream_flush()
will fail. */
void o_stream_nsend(struct ostream *stream, const void *data, size_t size);
void o_stream_nsendv(struct ostream *stream, const struct const_iovec *iov,
unsigned int iov_count);
void o_stream_nsend_str(struct ostream *stream, const char *str);
/* Mark the ostream as finished and flush it. If the ostream has a footer,
it's written here. Any further write attempts to the ostream will
assert-crash. Returns the same as o_stream_flush(). Afterwards any calls to
this function are identical to o_stream_flush(). */
int o_stream_finish(struct ostream *stream);
/* Specify whether calling o_stream_finish() will cause the parent stream to
be finished as well. The default is yes. */
void o_stream_set_finish_also_parent(struct ostream *stream, bool set);
/* Specify whether calling o_stream_finish() on a child stream will cause
this stream to be finished as well. The default is yes. */
void o_stream_set_finish_via_child(struct ostream *stream, bool set);
/* Marks the stream's error handling as completed to avoid i_panic() on
destroy. */
void o_stream_ignore_last_errors(struct ostream *stream);
/* If error handling is disabled, the i_panic() on destroy is never called.
This function can be called immediately after the stream is created.
When creating wrapper streams, they copy this behavior from the parent
stream. */
void o_stream_set_no_error_handling(struct ostream *stream, bool set);
/* Send all of the instream to outstream.
On non-failure instream is skips over all data written to outstream.
This means that the number of bytes written to outstream is always equal to
the number of bytes skipped in instream.
It's also possible to use this function to copy data within same file
descriptor, even if the source and destination overlaps. If the file must
be grown, you have to do it manually before calling this function. */
enum ostream_send_istream_result
o_stream_send_istream(struct ostream *outstream, struct istream *instream);
/* Same as o_stream_send_istream(), but assume that reads and writes will
succeed. If not, o_stream_flush() will fail with the correct error
message (even istream's). */
void o_stream_nsend_istream(struct ostream *outstream, struct istream *instream);
/* Write data to specified offset. Returns 0 if successful, -1 if error. */
int o_stream_pwrite(struct ostream *stream, const void *data, size_t size,
uoff_t offset);
/* If there are any I/O loop items associated with the stream, move all of
them to current_ioloop. */
void o_stream_switch_ioloop(struct ostream *stream);
#endif