Folks, Please review the attached delta of apr 1.3 to 1.4 changes and chime in if you believe we are ready to tag 1.4. I suspect we are.
Thanks! Bill
Index: apr_poll.h =================================================================== --- apr_poll.h (.../1.3.x/include) (revision 885682) +++ apr_poll.h (.../1.4.x/include) (revision 885682) @@ -49,14 +49,37 @@ #define APR_POLLOUT 0x004 /**< Can write without blocking */ #define APR_POLLERR 0x010 /**< Pending error */ #define APR_POLLHUP 0x020 /**< Hangup occurred */ -#define APR_POLLNVAL 0x040 /**< Descriptior invalid */ +#define APR_POLLNVAL 0x040 /**< Descriptor invalid */ /** * Pollset Flags */ -#define APR_POLLSET_THREADSAFE 0x001 /**< Adding or Removing a Descriptor is thread safe */ -#define APR_POLLSET_NOCOPY 0x002 /**< Descriptors passed to apr_pollset_create() are not copied */ +#define APR_POLLSET_THREADSAFE 0x001 /**< Adding or removing a descriptor is + * thread-safe + */ +#define APR_POLLSET_NOCOPY 0x002 /**< Descriptors passed to apr_pollset_add() + * are not copied + */ +#define APR_POLLSET_WAKEABLE 0x004 /**< Poll operations are interruptable by + * apr_pollset_wakeup() + */ +#define APR_POLLSET_NODEFAULT 0x010 /**< Do not try to use the default method if + * the specified non-default method cannot be + * used + */ +/** + * Pollset Methods + */ +typedef enum { + APR_POLLSET_DEFAULT, /**< Platform default poll method */ + APR_POLLSET_SELECT, /**< Poll uses select method */ + APR_POLLSET_KQUEUE, + APR_POLLSET_PORT, + APR_POLLSET_EPOLL, + APR_POLLSET_POLL +} apr_pollset_method_e; + /** Used in apr_pollfd_t to determine what the apr_descriptor is */ typedef enum { APR_NO_DESC, /**< nothing here */ @@ -93,18 +116,27 @@ typedef struct apr_pollset_t apr_pollset_t; /** - * Setup a pollset object + * Set up a pollset object * @param pollset The pointer in which to return the newly created object * @param size The maximum number of descriptors that this pollset can hold * @param p The pool from which to allocate the pollset * @param flags Optional flags to modify the operation of the pollset. * - * @remark If flags equals APR_POLLSET_THREADSAFE, then a pollset is - * created on which it is safe to make concurrent calls to - * apr_pollset_add(), apr_pollset_remove() and apr_pollset_poll() from - * separate threads. This feature is only supported on some - * platforms; the apr_pollset_create() call will fail with - * APR_ENOTIMPL on platforms where it is not supported. + * @remark If flags contains APR_POLLSET_THREADSAFE, then a pollset is + * created on which it is safe to make concurrent calls to + * apr_pollset_add(), apr_pollset_remove() and apr_pollset_poll() + * from separate threads. This feature is only supported on some + * platforms; the apr_pollset_create() call will fail with + * APR_ENOTIMPL on platforms where it is not supported. + * @remark If flags contains APR_POLLSET_WAKEABLE, then a pollset is + * created with an additional internal pipe object used for the + * apr_pollset_wakeup() call. The actual size of pollset is + * in that case size + 1. This feature is only supported on some + * platforms; the apr_pollset_create() call will fail with + * APR_ENOTIMPL on platforms where it is not supported. + * @remark If flags contains APR_POLLSET_NOCOPY, then the apr_pollfd_t + * structures passed to apr_pollset_add() are not copied and + * must have a lifetime at least as long as the pollset. */ APR_DECLARE(apr_status_t) apr_pollset_create(apr_pollset_t **pollset, apr_uint32_t size, @@ -112,6 +144,38 @@ apr_uint32_t flags); /** + * Set up a pollset object + * @param pollset The pointer in which to return the newly created object + * @param size The maximum number of descriptors that this pollset can hold + * @param p The pool from which to allocate the pollset + * @param flags Optional flags to modify the operation of the pollset. + * @param method Poll method to use. See @apr_pollset_method_e. If this + * method cannot be used, the default method will be used unless the + * APR_POLLSET_NODEFAULT flag has been specified. + * + * @remark If flags contains APR_POLLSET_THREADSAFE, then a pollset is + * created on which it is safe to make concurrent calls to + * apr_pollset_add(), apr_pollset_remove() and apr_pollset_poll() + * from separate threads. This feature is only supported on some + * platforms; the apr_pollset_create_ex() call will fail with + * APR_ENOTIMPL on platforms where it is not supported. + * @remark If flags contains APR_POLLSET_WAKEABLE, then a pollset is + * created with additional internal pipe object used for the + * apr_pollset_wakeup() call. The actual size of pollset is + * in that case size + 1. This feature is only supported on some + * platforms; the apr_pollset_create_ex() call will fail with + * APR_ENOTIMPL on platforms where it is not supported. + * @remark If flags contains APR_POLLSET_NOCOPY, then the apr_pollfd_t + * structures passed to apr_pollset_add() are not copied and + * must have a lifetime at least as long as the pollset. + */ +APR_DECLARE(apr_status_t) apr_pollset_create_ex(apr_pollset_t **pollset, + apr_uint32_t size, + apr_pool_t *p, + apr_uint32_t flags, + apr_pollset_method_e method); + +/** * Destroy a pollset object * @param pollset The pollset to destroy */ @@ -133,6 +197,15 @@ * with APR_EINTR. Option (1) is recommended, but option (2) is * allowed for implementations where option (1) is impossible * or impractical. + * @remark If the pollset has been created with APR_POLLSET_NOCOPY, the + * apr_pollfd_t structure referenced by descriptor will not be copied + * and must have a lifetime at least as long as the pollset. + * @remark Do not add the same socket or file descriptor to the same pollset + * multiple times, even if the requested events differ for the + * different calls to apr_pollset_add(). If the events of interest + * for a descriptor change, you must first remove the descriptor + * from the pollset with apr_pollset_remove(), then add it again + * specifying all requested events. */ APR_DECLARE(apr_status_t) apr_pollset_add(apr_pollset_t *pollset, const apr_pollfd_t *descriptor); @@ -150,6 +223,9 @@ * with APR_EINTR. Option (1) is recommended, but option (2) is * allowed for implementations where option (1) is impossible * or impractical. + * @remark apr_pollset_remove() cannot be used to remove a subset of requested + * events for a descriptor. The reqevents field in the apr_pollfd_t + * parameter must contain the same value when removing as when adding. */ APR_DECLARE(apr_status_t) apr_pollset_remove(apr_pollset_t *pollset, const apr_pollfd_t *descriptor); @@ -157,31 +233,47 @@ /** * Block for activity on the descriptor(s) in a pollset * @param pollset The pollset to use - * @param timeout The amount of time in microseconds to wait. This is - * a maximum, not a minimum. If a descriptor is signalled, we - * will wake up before this time. A negative number means - * wait until a descriptor is signalled. + * @param timeout The amount of time in microseconds to wait. This is a + * maximum, not a minimum. If a descriptor is signalled, the + * function will return before this time. If timeout is + * negative, the function will block until a descriptor is + * signalled or until apr_pollset_wakeup() has been called. * @param num Number of signalled descriptors (output parameter) * @param descriptors Array of signalled descriptors (output parameter) + * @remark APR_EINTR will be returned if the pollset has been created with + * APR_POLLSET_WAKEABLE, apr_pollset_wakeup() has been called while + * waiting for activity, and there were no signalled descriptors at the + * time of the wakeup call. + * @remark Multiple signalled conditions for the same descriptor may be reported + * in one or more returned apr_pollfd_t structures, depending on the + * implementation. */ APR_DECLARE(apr_status_t) apr_pollset_poll(apr_pollset_t *pollset, apr_interval_time_t timeout, apr_int32_t *num, const apr_pollfd_t **descriptors); +/** + * Interrupt the blocked apr_pollset_poll() call. + * @param pollset The pollset to use + * @remark If the pollset was not created with APR_POLLSET_WAKEABLE the + * return value is APR_EINIT. + */ +APR_DECLARE(apr_status_t) apr_pollset_wakeup(apr_pollset_t *pollset); /** * Poll the descriptors in the poll structure * @param aprset The poll structure we will be using. * @param numsock The number of descriptors we are polling * @param nsds The number of descriptors signalled (output parameter) - * @param timeout The amount of time in microseconds to wait. This is - * a maximum, not a minimum. If a descriptor is signalled, we - * will wake up before this time. A negative number means - * wait until a descriptor is signalled. + * @param timeout The amount of time in microseconds to wait. This is a + * maximum, not a minimum. If a descriptor is signalled, the + * function will return before this time. If timeout is + * negative, the function will block until a descriptor is + * signalled or until apr_pollset_wakeup() has been called. * @remark The number of descriptors signalled is returned in the third argument. * This is a blocking call, and it will not return until either a - * descriptor has been signalled, or the timeout has expired. + * descriptor has been signalled or the timeout has expired. * @remark The rtnevents field in the apr_pollfd_t array will only be filled- * in if the return value is APR_SUCCESS. */ @@ -189,11 +281,23 @@ apr_int32_t *nsds, apr_interval_time_t timeout); +/** + * Return a printable representation of the pollset method. + * @param pollset The pollset to use + */ +APR_DECLARE(const char *) apr_pollset_method_name(apr_pollset_t *pollset); + +/** + * Return a printable representation of the default pollset method + * (APR_POLLSET_DEFAULT). + */ +APR_DECLARE(const char *) apr_poll_method_defname(void); + /** Opaque structure used for pollset API */ typedef struct apr_pollcb_t apr_pollcb_t; /** - * Setup a pollcb object + * Set up a pollcb object * @param pollcb The pointer in which to return the newly created object * @param size The maximum number of descriptors that a single _poll can return. * @param p The pool from which to allocate the pollcb @@ -208,15 +312,40 @@ apr_uint32_t flags); /** + * Set up a pollcb object + * @param pollcb The pointer in which to return the newly created object + * @param size The maximum number of descriptors that a single _poll can return. + * @param p The pool from which to allocate the pollcb + * @param flags Optional flags to modify the operation of the pollcb. + * @param method Poll method to use. See @apr_pollset_method_e. If this + * method cannot be used, the default method will be used unless the + * APR_POLLSET_NODEFAULT flag has been specified. + * + * @remark Pollcb is only supported on some platforms; the apr_pollcb_create_ex() + * call will fail with APR_ENOTIMPL on platforms where it is not supported. + */ +APR_DECLARE(apr_status_t) apr_pollcb_create_ex(apr_pollcb_t **pollcb, + apr_uint32_t size, + apr_pool_t *pool, + apr_uint32_t flags, + apr_pollset_method_e method); + +/** * Add a socket or file descriptor to a pollcb * @param pollcb The pollcb to which to add the descriptor * @param descriptor The descriptor to add - * @remark If you set client_data in the descriptor, that value - * will be returned in the client_data field whenever this - * descriptor is signalled in apr_pollcb_poll(). + * @remark If you set client_data in the descriptor, that value will be + * returned in the client_data field whenever this descriptor is + * signalled in apr_pollcb_poll(). * @remark Unlike the apr_pollset API, the descriptor is not copied, and users - * must retain the memory used by descriptor, as the same pointer will be - * returned to them from apr_pollcb_poll. + * must retain the memory used by descriptor, as the same pointer will + * be returned to them from apr_pollcb_poll. + * @remark Do not add the same socket or file descriptor to the same pollcb + * multiple times, even if the requested events differ for the + * different calls to apr_pollcb_add(). If the events of interest + * for a descriptor change, you must first remove the descriptor + * from the pollcb with apr_pollcb_remove(), then add it again + * specifying all requested events. */ APR_DECLARE(apr_status_t) apr_pollcb_add(apr_pollcb_t *pollcb, apr_pollfd_t *descriptor); @@ -224,6 +353,9 @@ * Remove a descriptor from a pollcb * @param pollcb The pollcb from which to remove the descriptor * @param descriptor The descriptor to remove + * @remark apr_pollcb_remove() cannot be used to remove a subset of requested + * events for a descriptor. The reqevents field in the apr_pollfd_t + * parameter must contain the same value when removing as when adding. */ APR_DECLARE(apr_status_t) apr_pollcb_remove(apr_pollcb_t *pollcb, apr_pollfd_t *descriptor); @@ -239,12 +371,16 @@ /** * Block for activity on the descriptor(s) in a pollcb * @param pollcb The pollcb to use - * @param timeout The amount of time in microseconds to wait. This is - * a maximum, not a minimum. If a descriptor is signalled, we - * will wake up before this time. A negative number means - * wait until a descriptor is signalled. - * @param func Callback function to call for each active socket + * @param timeout The amount of time in microseconds to wait. This is a + * maximum, not a minimum. If a descriptor is signalled, the + * function will return before this time. If timeout is + * negative, the function will block until a descriptor is + * signalled. + * @param func Callback function to call for each active descriptor. * @param baton Opaque baton passed to the callback function. + * @remark Multiple signalled conditions for the same descriptor may be reported + * in one or more calls to the callback function, depending on the + * implementation. */ APR_DECLARE(apr_status_t) apr_pollcb_poll(apr_pollcb_t *pollcb, apr_interval_time_t timeout, Index: apr_file_io.h =================================================================== --- apr_file_io.h (.../1.3.x/include) (revision 885682) +++ apr_file_io.h (.../1.4.x/include) (revision 885682) @@ -265,6 +265,15 @@ apr_pool_t *pool); /** + * Create a hard link to the specified file. + * @param from_path The full path to the original file (using / on all systems) + * @param to_path The full path to the new file (using / on all systems) + * @remark Both files must reside on the same device. + */ +APR_DECLARE(apr_status_t) apr_file_link(const char *from_path, + const char *to_path); + +/** * Copy the specified file to another file. * @param from_path The full path to the original file (using / on all systems) * @param to_path The full path to the new file (using / on all systems) @@ -556,6 +565,18 @@ APR_DECLARE(apr_status_t) apr_file_flush(apr_file_t *thefile); /** + * Transfer all file modified data and metadata to disk. + * @param thefile The file descriptor to sync + */ +APR_DECLARE(apr_status_t) apr_file_sync(apr_file_t *thefile); + +/** + * Transfer all file modified data to disk. + * @param thefile The file descriptor to sync + */ +APR_DECLARE(apr_status_t) apr_file_datasync(apr_file_t *thefile); + +/** * Duplicate the specified file descriptor. * @param new_file The structure to duplicate into. * @param old_file The file to duplicate. Index: apr_global_mutex.h =================================================================== --- apr_global_mutex.h (.../1.3.x/include) (revision 885682) +++ apr_global_mutex.h (.../1.4.x/include) (revision 885682) @@ -121,6 +121,20 @@ APR_DECLARE(apr_status_t) apr_global_mutex_destroy(apr_global_mutex_t *mutex); /** + * Return the name of the lockfile for the mutex, or NULL + * if the mutex doesn't use a lock file + */ +APR_DECLARE(const char *) apr_global_mutex_lockfile(apr_global_mutex_t *mutex); + +/** + * Display the name of the mutex, as it relates to the actual method used + * for the underlying apr_proc_mutex_t, if any. NULL is returned if + * there is no underlying apr_proc_mutex_t. + * @param mutex the name of the mutex + */ +APR_DECLARE(const char *) apr_global_mutex_name(apr_global_mutex_t *mutex); + +/** * Get the pool used by this global_mutex. * @return apr_pool_t the pool */ @@ -140,6 +154,8 @@ #define apr_global_mutex_trylock apr_proc_mutex_trylock #define apr_global_mutex_unlock apr_proc_mutex_unlock #define apr_global_mutex_destroy apr_proc_mutex_destroy +#define apr_global_mutex_lockfile apr_proc_mutex_lockfile +#define apr_global_mutex_name apr_proc_mutex_name #define apr_global_mutex_pool_get apr_proc_mutex_pool_get #endif Index: apr_hash.h =================================================================== --- apr_hash.h (.../1.3.x/include) (revision 885682) +++ apr_hash.h (.../1.4.x/include) (revision 885682) @@ -220,6 +220,36 @@ const void *data); /** + * Declaration prototype for the iterator callback function of apr_hash_do(). + * + * @param rec The data passed as the first argument to apr_hash_[v]do() + * @param key The key from this iteration of the hash table + * @param klen The key length from this iteration of the hash table + * @param value The value from this iteration of the hash table + * @remark Iteration continues while this callback function returns non-zero. + * To export the callback function for apr_hash_do() it must be declared + * in the _NONSTD convention. + */ +typedef int (apr_hash_do_callback_fn_t)(void *rec, const void *key, + apr_ssize_t klen, + const void *value); + +/** + * Iterate over a hash table running the provided function once for every + * element in the hash table. The @param comp function will be invoked for + * every element in the hash table. + * + * @param comp The function to run + * @param rec The data to pass as the first argument to the function + * @param ht The hash table to iterate over + * @return FALSE if one of the comp() iterations returned zero; TRUE if all + * iterations returned non-zero + * @see apr_hash_do_callback_fn_t + */ +APR_DECLARE(int) apr_hash_do(apr_hash_do_callback_fn_t *comp, + void *rec, const apr_hash_t *ht); + +/** * Get a pointer to the pool which the hash table was created in */ APR_POOL_DECLARE_ACCESSOR(hash); Index: apr_strings.h =================================================================== --- apr_strings.h (.../1.3.x/include) (revision 885682) +++ apr_strings.h (.../1.4.x/include) (revision 885682) @@ -136,7 +136,11 @@ * @param ... The strings to concatenate. The final string must be NULL * @return The new string */ -APR_DECLARE_NONSTD(char *) apr_pstrcat(apr_pool_t *p, ...); +APR_DECLARE_NONSTD(char *) apr_pstrcat(apr_pool_t *p, ...) +#if defined(__GNUC__) && __GNUC__ >= 4 + __attribute__((sentinel)) +#endif + ; /** * Concatenate multiple strings specified in a writev-style vector @@ -330,7 +334,7 @@ * digits are prefixed with '0x', in which case it will be treated as * base 16. * @return The numeric value of the string. On overflow, errno is set - * to ERANGE. + * to ERANGE. On success, errno is set to 0. */ APR_DECLARE(apr_int64_t) apr_strtoi64(const char *buf, char **end, int base); @@ -338,7 +342,8 @@ * parse a base-10 numeric string into a 64-bit numeric value. * Equivalent to apr_strtoi64(buf, (char**)NULL, 10). * @param buf The string to parse - * @return The numeric value of the string + * @return The numeric value of the string. On overflow, errno is set + * to ERANGE. On success, errno is set to 0. */ APR_DECLARE(apr_int64_t) apr_atoi64(const char *buf); Index: apr_time.h =================================================================== --- apr_time.h (.../1.3.x/include) (revision 885682) +++ apr_time.h (.../1.4.x/include) (revision 885682) @@ -72,7 +72,10 @@ /** @return apr_time_t as a msec */ #define apr_time_as_msec(time) ((time) / 1000) -/** @return a second as an apr_time_t */ +/** @return milliseconds as an apr_time_t */ +#define apr_time_from_msec(msec) ((apr_time_t)(msec) * 1000) + +/** @return seconds as an apr_time_t */ #define apr_time_from_sec(sec) ((apr_time_t)(sec) * APR_USEC_PER_SEC) /** @return a second and usec combination as an apr_time_t */ Index: apr_lib.h =================================================================== --- apr_lib.h (.../1.3.x/include) (revision 885682) +++ apr_lib.h (.../1.4.x/include) (revision 885682) @@ -125,9 +125,10 @@ * %%pF same as above, but takes a apr_off_t * * %%pS same as above, but takes a apr_size_t * * + * %%pA, %%pI, %%pT, %%pp are available from APR 1.0.0 onwards (and in 0.9.x). * %%pt is only available from APR 1.2.0 onwards. * %%pm, %%pB, %%pF and %%pS are only available from APR 1.3.0 onwards. - * + * * The %%p hacks are to force gcc's printf warning code to skip * over a pointer argument without complaining. This does * mean that the ANSI-style %%p (output a void * in hex format) won't Index: apr_want.h =================================================================== --- apr_want.h (.../1.3.x/include) (revision 885682) +++ apr_want.h (.../1.4.x/include) (revision 885682) @@ -91,7 +91,7 @@ struct iovec { - char *iov_base; + void *iov_base; size_t iov_len; }; Index: apr_tables.h =================================================================== --- apr_tables.h (.../1.3.x/include) (revision 885682) +++ apr_tables.h (.../1.4.x/include) (revision 885682) @@ -380,7 +380,11 @@ * @see apr_table_do_callback_fn_t */ APR_DECLARE_NONSTD(int) apr_table_do(apr_table_do_callback_fn_t *comp, - void *rec, const apr_table_t *t, ...); + void *rec, const apr_table_t *t, ...) +#if defined(__GNUC__) && __GNUC__ >= 4 + __attribute__((sentinel)) +#endif + ; /** * Iterate over a table running the provided function once for every Index: apr_network_io.h =================================================================== --- apr_network_io.h (.../1.3.x/include) (revision 885682) +++ apr_network_io.h (.../1.4.x/include) (revision 885682) @@ -348,6 +348,21 @@ apr_sockaddr_t *sa); /** + * Determine whether the receive part of the socket has been closed by + * the peer (such that a subsequent call to apr_socket_read would + * return APR_EOF), if the socket's receive buffer is empty. This + * function does not block waiting for I/O. + * + * @param socket The socket to check + * @param atreadeof If APR_SUCCESS is returned, *atreadeof is set to + * non-zero if a subsequent read would return APR_EOF + * @return an error is returned if it was not possible to determine the + * status, in which case *atreadeof is not changed. + */ +APR_DECLARE(apr_status_t) apr_socket_atreadeof(apr_socket_t *sock, + int *atreadeof); + +/** * Create apr_sockaddr_t from hostname, address family, and port. * @param sa The new apr_sockaddr_t. * @param hostname The hostname or numeric address string to resolve/parse, or Index: apr_version.h =================================================================== --- apr_version.h (.../1.3.x/include) (revision 885682) +++ apr_version.h (.../1.4.x/include) (revision 885682) @@ -53,13 +53,13 @@ * Minor API changes that do not cause binary compatibility problems. * Reset to 0 when upgrading APR_MAJOR_VERSION */ -#define APR_MINOR_VERSION 3 +#define APR_MINOR_VERSION 4 /** patch level * The Patch Level never includes API changes, simply bug fixes. * Reset to 0 when upgrading APR_MINOR_VERSION */ -#define APR_PATCH_VERSION 10 +#define APR_PATCH_VERSION 0 /** * The symbol APR_IS_DEV_VERSION is only defined for internal,