peter 6c648dd642 Introduce svnlite so that we can check out our source code again.
This is actually a fully functional build except:
* All internal shared libraries are static linked to make sure there
  is no interference with ports (and to reduce build time).
* It does not have the python/perl/etc plugin or API support.
* By default, it installs as "svnlite" rather than "svn".
* If WITH_SVN added in make.conf, you get "svn".
* If WITHOUT_SVNLITE is in make.conf, this is completely disabled.

To be absolutely clear, this is not intended for any use other than
checking out freebsd source and committing, like we once did with cvs.

It should be usable for small scale local repositories that don't
need the python/perl plugin architecture.
2013-06-18 02:53:45 +00:00

345 lines
10 KiB
C

/* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifdef WIN32
/* POSIX defines 1024 for the FD_SETSIZE */
#define FD_SETSIZE 1024
#endif
#include "apr.h"
#include "apr_poll.h"
#include "apr_time.h"
#include "apr_portable.h"
#include "apr_arch_file_io.h"
#include "apr_arch_networkio.h"
#include "apr_arch_poll_private.h"
#include "apr_arch_inherit.h"
static apr_pollset_method_e pollset_default_method = POLLSET_DEFAULT_METHOD;
#if !APR_FILES_AS_SOCKETS
#if defined (WIN32)
/* Create a dummy wakeup socket pipe for interrupting the poller
*/
static apr_status_t create_wakeup_pipe(apr_pollset_t *pollset)
{
apr_status_t rv;
if ((rv = apr_file_socket_pipe_create(&pollset->wakeup_pipe[0],
&pollset->wakeup_pipe[1],
pollset->pool)) != APR_SUCCESS)
return rv;
pollset->wakeup_pfd.p = pollset->pool;
pollset->wakeup_pfd.reqevents = APR_POLLIN;
pollset->wakeup_pfd.desc_type = APR_POLL_FILE;
pollset->wakeup_pfd.desc.f = pollset->wakeup_pipe[0];
return apr_pollset_add(pollset, &pollset->wakeup_pfd);
}
#else /* !WIN32 */
static apr_status_t create_wakeup_pipe(apr_pollset_t *pollset)
{
return APR_ENOTIMPL;
}
static apr_status_t apr_file_socket_pipe_close(apr_file_t *file)
{
return APR_ENOTIMPL;
}
#endif /* WIN32 */
#else /* APR_FILES_AS_SOCKETS */
/* Create a dummy wakeup pipe for interrupting the poller
*/
static apr_status_t create_wakeup_pipe(apr_pollset_t *pollset)
{
apr_status_t rv;
if ((rv = apr_file_pipe_create(&pollset->wakeup_pipe[0],
&pollset->wakeup_pipe[1],
pollset->pool)) != APR_SUCCESS)
return rv;
pollset->wakeup_pfd.p = pollset->pool;
pollset->wakeup_pfd.reqevents = APR_POLLIN;
pollset->wakeup_pfd.desc_type = APR_POLL_FILE;
pollset->wakeup_pfd.desc.f = pollset->wakeup_pipe[0];
{
int flags;
if ((flags = fcntl(pollset->wakeup_pipe[0]->filedes, F_GETFD)) == -1)
return errno;
flags |= FD_CLOEXEC;
if (fcntl(pollset->wakeup_pipe[0]->filedes, F_SETFD, flags) == -1)
return errno;
}
{
int flags;
if ((flags = fcntl(pollset->wakeup_pipe[1]->filedes, F_GETFD)) == -1)
return errno;
flags |= FD_CLOEXEC;
if (fcntl(pollset->wakeup_pipe[1]->filedes, F_SETFD, flags) == -1)
return errno;
}
return apr_pollset_add(pollset, &pollset->wakeup_pfd);
}
#endif /* !APR_FILES_AS_SOCKETS */
/* Read and discard what's ever in the wakeup pipe.
*/
void apr_pollset_drain_wakeup_pipe(apr_pollset_t *pollset)
{
char rb[512];
apr_size_t nr = sizeof(rb);
while (apr_file_read(pollset->wakeup_pipe[0], rb, &nr) == APR_SUCCESS) {
/* Although we write just one byte to the other end of the pipe
* during wakeup, multiple threads could call the wakeup.
* So simply drain out from the input side of the pipe all
* the data.
*/
if (nr != sizeof(rb))
break;
}
}
static apr_status_t pollset_cleanup(void *p)
{
apr_pollset_t *pollset = (apr_pollset_t *) p;
if (pollset->provider->cleanup) {
(*pollset->provider->cleanup)(pollset);
}
if (pollset->flags & APR_POLLSET_WAKEABLE) {
/* Close both sides of the wakeup pipe */
if (pollset->wakeup_pipe[0]) {
#if APR_FILES_AS_SOCKETS
apr_file_close(pollset->wakeup_pipe[0]);
#else
apr_file_socket_pipe_close(pollset->wakeup_pipe[0]);
#endif
pollset->wakeup_pipe[0] = NULL;
}
if (pollset->wakeup_pipe[1]) {
#if APR_FILES_AS_SOCKETS
apr_file_close(pollset->wakeup_pipe[1]);
#else
apr_file_socket_pipe_close(pollset->wakeup_pipe[1]);
#endif
pollset->wakeup_pipe[1] = NULL;
}
}
return APR_SUCCESS;
}
#if defined(HAVE_KQUEUE)
extern apr_pollset_provider_t *apr_pollset_provider_kqueue;
#endif
#if defined(HAVE_PORT_CREATE)
extern apr_pollset_provider_t *apr_pollset_provider_port;
#endif
#if defined(HAVE_EPOLL)
extern apr_pollset_provider_t *apr_pollset_provider_epoll;
#endif
#if defined(HAVE_POLL)
extern apr_pollset_provider_t *apr_pollset_provider_poll;
#endif
extern apr_pollset_provider_t *apr_pollset_provider_select;
static apr_pollset_provider_t *pollset_provider(apr_pollset_method_e method)
{
apr_pollset_provider_t *provider = NULL;
switch (method) {
case APR_POLLSET_KQUEUE:
#if defined(HAVE_KQUEUE)
provider = apr_pollset_provider_kqueue;
#endif
break;
case APR_POLLSET_PORT:
#if defined(HAVE_PORT_CREATE)
provider = apr_pollset_provider_port;
#endif
break;
case APR_POLLSET_EPOLL:
#if defined(HAVE_EPOLL)
provider = apr_pollset_provider_epoll;
#endif
break;
case APR_POLLSET_POLL:
#if defined(HAVE_POLL)
provider = apr_pollset_provider_poll;
#endif
break;
case APR_POLLSET_SELECT:
provider = apr_pollset_provider_select;
break;
case APR_POLLSET_DEFAULT:
break;
}
return provider;
}
APR_DECLARE(apr_status_t) apr_pollset_create_ex(apr_pollset_t **ret_pollset,
apr_uint32_t size,
apr_pool_t *p,
apr_uint32_t flags,
apr_pollset_method_e method)
{
apr_status_t rv;
apr_pollset_t *pollset;
apr_pollset_provider_t *provider = NULL;
*ret_pollset = NULL;
#ifdef WIN32
/* Favor WSAPoll if supported.
* This will work only if ws2_32.dll has WSAPoll funtion.
* In other cases it will fall back to select() method unless
* the APR_POLLSET_NODEFAULT is added to the flags.
*/
if (method == APR_POLLSET_DEFAULT) {
method = APR_POLLSET_POLL;
}
#endif
if (method == APR_POLLSET_DEFAULT)
method = pollset_default_method;
while (provider == NULL) {
provider = pollset_provider(method);
if (!provider) {
if ((flags & APR_POLLSET_NODEFAULT) == APR_POLLSET_NODEFAULT)
return APR_ENOTIMPL;
if (method == pollset_default_method)
return APR_ENOTIMPL;
method = pollset_default_method;
}
}
if (flags & APR_POLLSET_WAKEABLE) {
/* Add room for wakeup descriptor */
size++;
}
pollset = apr_palloc(p, sizeof(*pollset));
pollset->nelts = 0;
pollset->nalloc = size;
pollset->pool = p;
pollset->flags = flags;
pollset->provider = provider;
rv = (*provider->create)(pollset, size, p, flags);
if (rv == APR_ENOTIMPL) {
if (method == pollset_default_method) {
return rv;
}
provider = pollset_provider(pollset_default_method);
if (!provider) {
return APR_ENOTIMPL;
}
rv = (*provider->create)(pollset, size, p, flags);
if (rv != APR_SUCCESS) {
return rv;
}
pollset->provider = provider;
}
else if (rv != APR_SUCCESS) {
return rv;
}
if (flags & APR_POLLSET_WAKEABLE) {
/* Create wakeup pipe */
if ((rv = create_wakeup_pipe(pollset)) != APR_SUCCESS) {
return rv;
}
}
if ((flags & APR_POLLSET_WAKEABLE) || provider->cleanup)
apr_pool_cleanup_register(p, pollset, pollset_cleanup,
apr_pool_cleanup_null);
*ret_pollset = pollset;
return APR_SUCCESS;
}
APR_DECLARE(const char *) apr_pollset_method_name(apr_pollset_t *pollset)
{
return pollset->provider->name;
}
APR_DECLARE(const char *) apr_poll_method_defname()
{
apr_pollset_provider_t *provider = NULL;
provider = pollset_provider(pollset_default_method);
if (provider)
return provider->name;
else
return "unknown";
}
APR_DECLARE(apr_status_t) apr_pollset_create(apr_pollset_t **pollset,
apr_uint32_t size,
apr_pool_t *p,
apr_uint32_t flags)
{
apr_pollset_method_e method = APR_POLLSET_DEFAULT;
return apr_pollset_create_ex(pollset, size, p, flags, method);
}
APR_DECLARE(apr_status_t) apr_pollset_destroy(apr_pollset_t * pollset)
{
if (pollset->flags & APR_POLLSET_WAKEABLE ||
pollset->provider->cleanup)
return apr_pool_cleanup_run(pollset->pool, pollset,
pollset_cleanup);
else
return APR_SUCCESS;
}
APR_DECLARE(apr_status_t) apr_pollset_wakeup(apr_pollset_t *pollset)
{
if (pollset->flags & APR_POLLSET_WAKEABLE)
return apr_file_putc(1, pollset->wakeup_pipe[1]);
else
return APR_EINIT;
}
APR_DECLARE(apr_status_t) apr_pollset_add(apr_pollset_t *pollset,
const apr_pollfd_t *descriptor)
{
return (*pollset->provider->add)(pollset, descriptor);
}
APR_DECLARE(apr_status_t) apr_pollset_remove(apr_pollset_t *pollset,
const apr_pollfd_t *descriptor)
{
return (*pollset->provider->remove)(pollset, descriptor);
}
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)
{
return (*pollset->provider->poll)(pollset, timeout, num, descriptors);
}