Index: subversion/include/svn_log.h
===================================================================
--- subversion/include/svn_log.h	(revision 0)
+++ subversion/include/svn_log.h	(revision 0)
@@ -0,0 +1,126 @@
+/**
+ * @copyright
+ * ====================================================================
+ * Copyright (c) 2000-2004 CollabNet.  All rights reserved.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution.  The terms
+ * are also available at http://subversion.tigris.org/license-1.html.
+ * If newer versions of this license are posted there, you may use a
+ * newer version instead, at your option.
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals.  For exact contribution history, see the revision
+ * history and logs, available at http://subversion.tigris.org/.
+ * ====================================================================
+ * @endcopyright
+ *
+ * @file svn_log.h
+ * @brief Tracing and log writing code.
+ */
+
+#ifndef SVN_LOG_H
+#define SVN_LOG_H
+
+#include <apr_pools.h>
+
+#include "svn_error.h"
+#include "svn_pools.h"
+#include "svn_io.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+
+/* typedefs for logging routings... */
+
+enum svn_log_method_e
+{
+    svn_log_method_unknown = 0,
+    svn_log_method_none = 1,
+    svn_log_method_file = 2,
+    svn_log_method_socket = 3,
+    svn_log_method_win32eventlog = 4,
+    svn_log_method_syslog = 5,
+};
+typedef enum svn_log_method_e svn_log_method_t;
+
+
+struct svn_log_s
+{
+  /* useless really */
+  svn_log_method_t log_method;  
+
+  /* abstracted svn_stream_t handles all our output */
+  svn_stream_t* stream;
+
+  /* the current log level, log messages must be at this level or higher to 
+   * be written 
+   */
+  int level;
+};
+typedef struct svn_log_s svn_log_t;
+
+
+
+
+/*** Logging routine prototypes. ***/
+
+#ifdef SVN_ENABLE_LOG_DUP
+svn_log_t* svn_log_dup (const svn_log_t *log, apr_pool_t *pool);
+#endif
+
+/** Open a logging session that has no output. */
+svn_error_t* svn_log_open_empty(svn_log_t** log, apr_pool_t* pool);
+
+
+/** Open a logging session that opens a file and writes to it. */
+svn_error_t* svn_log_open_file(svn_log_t** log, const char* path, 
+                               apr_pool_t* pool);
+
+/** Open a logging session that writes to a give APR file handle. */
+svn_error_t* svn_log_from_aprfile(svn_log_t** log, apr_file_t* file, 
+                                  apr_pool_t* pool);
+
+/** Open a logging session that writes to STDOUT. */
+svn_error_t* svn_log_open_stdout(svn_log_t** log, apr_pool_t* pool);
+
+/** Open a logging session that connects to remote host sepecified by
+ * @a hostname on @a port. 
+ */
+svn_error_t* svn_log_open_socket(svn_log_t** log, const char* hostname, 
+                                 unsigned short port, apr_pool_t* pool);
+
+/** Gets the active log level for a logging session. */
+int svn_log_getlevel(svn_log_t* log);
+
+/** Sets the given logging session's active log level to @a newlevel logging 
+ * session and returns the previous log level. 
+ */
+int svn_log_setlevel(svn_log_t* log, int newlevel);
+
+/** Writes a cstring to the log. */
+svn_error_t* svn_log_write(svn_log_t* log, apr_pool_t* pool, int loglevel, 
+                           const char* msg);
+
+/** Writes a svn_string_t to the log. */
+svn_error_t* svn_log_writes(svn_log_t* log, apr_pool_t* pool, int loglevel, 
+                           svn_string_t* msg);
+
+/** Accepts a variable argument list and Writes a formated string. */
+svn_error_t* svn_log_writev(svn_log_t* log, apr_pool_t* pool, int loglevel, 
+                           const char* fmt, va_list ap);
+
+/** Accepts a variable number of paramters and writes a formated string to 
+ * the log. 
+ */
+svn_error_t* svn_log_writef(svn_log_t* log, apr_pool_t* pool, int loglevel, 
+                           const char* fmt, ...);
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* SVN_LOG_H */
Index: subversion/include/svn_repos.h
===================================================================
--- subversion/include/svn_repos.h	(revision 15457)
+++ subversion/include/svn_repos.h	(working copy)
@@ -30,8 +30,8 @@
 #include "svn_types.h"
 #include "svn_error.h"
 #include "svn_version.h"
+#include "svn_log.h"
 
-
 #ifdef __cplusplus
 extern "C" {
 #endif /* __cplusplus */
@@ -1729,6 +1729,69 @@
                               svn_boolean_t *access_granted,
                               apr_pool_t *pool);
 
+
+/* ---------------------------------------------------------------*/
+
+
+/**
+ * @defgroup svn_repos_logging Repository access logging
+ * @{
+ *
+ * @since New in 1.3.
+ */
+
+
+/** Identify the user of @a repos as @a processname. */
+void
+svn_repos_set_processname (svn_repos_t *repos,
+                           const char *processname);
+
+/** Set @a *processname to the name of the process using @a repos, or
+    NULL if none is defined.  */
+void
+svn_repos_get_processname (const char **processname,
+                           svn_repos_t *repos);
+
+/** Have @a repos write all accesslog messages to @a logfile. */
+void
+svn_repos_set_accesslog (svn_repos_t *repos,
+                         svn_log_t *logfile);
+
+/** Set @a *logfile to the current accesslog of @a repos, or NULL if
+    none is defined. */
+void
+svn_repos_get_accesslog (svn_log_t **logfile,
+                         svn_repos_t *repos);
+
+
+/** Write a message into the accesslog of @a repos, using a
+ * printf-style error message produced by passing @a fmt to @c
+ * apr_psprintf.
+ *
+ * If the name of the process using @a repos is not @c NULL, then log
+ * it as well.  (See @c svn_repos_set_processname.)
+ *
+ * If not @c NULL, then log @a sockaddr as the incoming IP address of
+ * the request.
+ *
+ * If not @c NULL, then log @a username as the user performing the
+ * request.
+ *
+ * Use @a pool for any temporary memory allocation, including possibly
+ * calling apr_psprintf() to format the message.
+ */
+svn_error_t*
+svn_repos_write_accesslogf (svn_repos_t *repos,
+                           apr_pool_t *pool,
+                           int level,
+                           const char *username,
+                           const char *fmt,
+                           ...);
+
+
+/** @} */
+
+
 #ifdef __cplusplus
 }
 #endif /* __cplusplus */
Index: subversion/include/svn_io.h
===================================================================
--- subversion/include/svn_io.h	(revision 15457)
+++ subversion/include/svn_io.h	(working copy)
@@ -28,6 +28,7 @@
 #include <apr.h>
 #include <apr_pools.h>
 #include <apr_file_io.h>
+#include <apr_network_io.h>
 #include <apr_thread_proc.h>
 
 #include "svn_types.h"
@@ -520,6 +521,14 @@
  */
 svn_stream_t *svn_stream_from_aprfile (apr_file_t *file, apr_pool_t *pool);
 
+/** Convenience function for creating streams which operate on APR
+ * sockets.  For convenience, if @a socket is NULL then svn_stream_empty(pool) 
+ * is returned.  Note that the stream returned by these operations is not 
+ * considered to "own" the underlying spcket, meaning that svn_stream_close() 
+ * on the stream will not close the socket.
+ */
+svn_stream_t *svn_stream_from_aprsocket (apr_socket_t *socket, apr_pool_t *pool);
+
 /** Set @a *out to a generic stream connected to stdout, allocated in 
  * @a pool.  The stream and its underlying APR handle will be closed
  * when @a pool is cleared or destroyed.
Index: subversion/libsvn_subr/stream.c
===================================================================
--- subversion/libsvn_subr/stream.c	(revision 15457)
+++ subversion/libsvn_subr/stream.c	(working copy)
@@ -310,6 +310,74 @@
 }
 
 
+/*** Generic stream for APR sockets ***/
+struct baton_aprsocket {
+  apr_socket_t *socket;
+  apr_pool_t *pool;
+  void* block_handler;  /* not-implemented yet */
+};
+
+
+static svn_error_t *
+read_handler_aprsocket (void *baton, char *buffer, apr_size_t *len)
+{
+  struct baton_aprsocket *btn = baton;
+  svn_error_t *err;
+
+  apr_status_t status;
+
+  /* Always block for reading. */
+  if (btn->block_handler)
+    apr_socket_timeout_set(btn->socket, -1);
+  status = apr_socket_recv(btn->socket, buffer, len);
+  if (btn->block_handler)
+    apr_socket_timeout_set(btn->socket, 0);
+  /*
+  if (status && !APR_STATUS_IS_EOF(status))
+    return svn_error_wrap_apr(status, _("Can't read from connection"));
+  if (*len == 0)
+    return svn_error_create(SVN_ERR_RA_SVN_CONNECTION_CLOSED, NULL,
+                            _("Connection closed unexpectedly"));
+  */
+  if (status != APR_SUCCESS)
+    return svn_error_wrap_apr(status, _("Can't read from socket"));
+
+  return SVN_NO_ERROR;
+}
+
+
+static svn_error_t *
+write_handler_aprsocket (void *baton, const char *data, apr_size_t *len)
+{
+  struct baton_aprsocket *btn = baton;
+  apr_status_t status;
+
+  status = apr_socket_send(btn->socket, data, len);
+  if (status != APR_SUCCESS)
+    return svn_error_wrap_apr(status, _("Can't write to socket"));
+
+  return SVN_NO_ERROR;
+}
+
+
+svn_stream_t *
+svn_stream_from_aprsocket (apr_socket_t *socket, apr_pool_t *pool)
+{
+  struct baton_aprsocket *baton;
+  svn_stream_t *stream;
+
+  if (socket == NULL)
+    return svn_stream_empty(pool);
+  baton = apr_palloc (pool, sizeof (*baton));
+  baton->socket = socket;
+  baton->pool = pool;
+  stream = svn_stream_create (baton, pool);
+  svn_stream_set_read (stream, read_handler_aprsocket);
+  svn_stream_set_write (stream, write_handler_aprsocket);
+  return stream;
+}
+
+
 /* Compressed stream support */
 
 #ifdef SVN_HAVE_ZLIB
Index: subversion/libsvn_subr/log.c
===================================================================
--- subversion/libsvn_subr/log.c	(revision 0)
+++ subversion/libsvn_subr/log.c	(revision 0)
@@ -0,0 +1,425 @@
+/*
+ * log.c:  routines for svn_log_t objects.
+ *
+ * ====================================================================
+ * Copyright (c) 2000-2005 CollabNet.  All rights reserved.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution.  The terms
+ * are also available at http://subversion.tigris.org/license-1.html.
+ * If newer versions of this license are posted there, you may use a
+ * newer version instead, at your option.
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals.  For exact contribution history, see the revision
+ * history and logs, available at http://subversion.tigris.org/.
+ * ====================================================================
+ */
+
+/* ==================================================================== */
+
+
+
+/*** Includes. ***/
+#include <apr_pools.h>
+#include <apr_strings.h>
+#include <apr_file_io.h>
+#include <apr_network_io.h>
+
+#ifdef WIN32
+#include <windows.h>
+//#define USE_WIN32EVENTLOG
+#endif
+
+#ifdef USE_SYSLOGD
+#include <syslog.h>
+#endif
+
+#include "svn_types.h"
+#include "svn_log.h"
+#include "svn_error.h"
+
+#include "svn_private_config.h"
+
+
+
+/*** Generic stream for Win32 Event Log writing ***/
+struct baton_win32eventlog_t
+{
+  svn_string_t * logname;
+  apr_pool_t * pool;
+  svn_log_t * log;
+  int errorlevel;
+  int warninglevel;
+};
+
+
+static svn_error_t *
+read_handler_empty (void *baton, char *buffer, apr_size_t *len)
+{
+  return SVN_NO_ERROR;
+}
+
+
+static svn_error_t *
+write_handler_win32eventlog (void *baton, const char *data, apr_size_t *len)
+{
+  struct baton_win32eventlog_t *btn = baton;
+
+#ifdef USE_WIN32EVENTLOG
+  // Logs an "Error"-type event to the "Application" log.
+  HANDLE h;
+  int eventtype;
+  int loglevel = btn->log->level;
+  const char* logname = NULL;
+
+  if (btn->logname == NULL)
+    logname = "Application";
+  else
+    logname = btn->logname->data;
+
+  // Get a handle to the event log.
+  h = RegisterEventSource(NULL, logname);
+  if (h == NULL)
+  {
+     return svn_error_createf (SVN_ERR_IO_WRITE_ERROR, NULL,
+                      "Can't write to Windows Event Log '%s'", 
+                      logname);
+   }
+
+   /* 
+    * We have to find a way to map log level to one of these 
+    * platform-specific types.  We could just define a threshold
+    * for each one.
+    */
+  if (loglevel > btn->errorlevel)
+    eventtype = EVENTLOG_ERROR_TYPE;
+  else if (loglevel > btn->warninglevel)
+    eventtype = EVENTLOG_WARNING_TYPE;
+  else
+    eventtype = EVENTLOG_INFORMATION_TYPE;
+  /* These other types are also avilable
+  eventtype = EVENTLOG_WARNING_TYPE;
+  eventtype = EVENTLOG_SUCCESS;
+  eventtype = EVENTLOG_AUDIT_SUCCESS;
+  eventtype = EVENTLOG_AUDIT_FAILURE;
+  */
+
+  // Report the event.
+  ReportEvent(h,          /* event log handle */
+    EVENTLOG_ERROR_TYPE,  /* event type (error) */
+    0,                    /* event category */
+    0,                    /* event identifier */
+    NULL,                 /* no user security identifier */
+    1,                    /* number of substitution strings */
+    0,                    /* no data */
+    &data,                /* pointer to strings */
+    NULL);                /* no data */
+
+   // Close the handle.
+   DeregisterEventSource(h);
+#endif
+
+  return SVN_NO_ERROR;
+}
+
+
+svn_stream_t *
+svn_stream_for_win32eventlog(char* logname, apr_pool_t *pool)
+{
+  struct baton_win32eventlog_t *baton;
+  svn_stream_t *stream;
+
+  baton = apr_palloc (pool, sizeof (*baton));
+  baton->logname = svn_string_create(logname, pool);
+  baton->warninglevel = 10;         /* dummy value */
+  baton->errorlevel = 20;           /* dummy value */
+  baton->pool = pool;
+  stream = svn_stream_create (baton, pool);
+  svn_stream_set_read (stream, read_handler_empty);
+  svn_stream_set_write (stream, write_handler_win32eventlog);
+  return stream;
+}
+
+
+/*** Generic stream for syslogd interfacing ***/
+struct baton_syslog_t
+{
+  apr_pool_t* pool;
+  svn_log_t* log;
+  svn_string_t* logname;
+};
+
+static svn_error_t *
+write_handler_syslog (void *baton, const char *data, apr_size_t *len)
+{
+  struct baton_syslog_t *btn = baton;
+
+#ifdef USING_SYSLOGD
+  /* This is just filler code.  */
+  /*
+  setlogmask (LOG_UPTO (LOG_NOTICE));
+     
+  openlog ("exampleprog", LOG_CONS | LOG_PID | LOG_NDELAY, LOG_LOCAL1);
+     
+  syslog (LOG_NOTICE, "Program started by User %d", getuid ());
+  syslog (LOG_INFO, "A tree falls in a forest");
+     
+  closelog ();
+  */
+#endif
+
+  return SVN_NO_ERROR;
+}
+
+
+svn_stream_t *
+svn_stream_for_syslog(const char* logname, apr_pool_t *pool)
+{
+  struct baton_syslog_t *baton;
+  svn_stream_t *stream;
+
+  baton = apr_palloc (pool, sizeof (*baton));
+  baton->logname = svn_string_create(logname, pool);
+  baton->pool = pool;
+  stream = svn_stream_create (baton, pool);
+  svn_stream_set_read (stream, read_handler_empty);
+  svn_stream_set_write (stream, write_handler_win32eventlog);
+  return stream;
+}
+
+
+/*** Logging routines. ***/
+
+static svn_log_t* svn_log_create (apr_pool_t *pool)
+{
+  return apr_pcalloc (pool, sizeof (svn_log_t));
+}
+
+#ifdef SVN_ENABLE_LOG_DUP
+svn_log_t* svn_log_dup (const svn_log_t *log, apr_pool_t *pool)
+{
+  svn_log_t *new_l = apr_palloc (pool, sizeof (*new_l));
+
+  *new_l = *log;
+
+  /*
+    NOT IMPLEMENTED
+  */
+
+  return new_l;
+}
+#endif
+
+
+svn_error_t* svn_log_open_empty(svn_log_t** log, apr_pool_t* pool)
+{
+  svn_log_t* log_tmp;
+
+  log_tmp = svn_log_create(pool);
+
+  log_tmp->log_method = svn_log_method_none;
+  log_tmp->stream = svn_stream_empty(pool);
+
+  *log = log_tmp;
+
+  return SVN_NO_ERROR;
+}
+
+svn_error_t* svn_log_open_file(svn_log_t** log, const char* path, 
+                               apr_pool_t* pool)
+{
+  apr_file_t* file = NULL;
+  svn_log_t* log_tmp;
+
+  SVN_ERR (svn_io_file_open (&file, path, APR_WRITE | APR_APPEND
+                             | APR_BUFFERED, APR_OS_DEFAULT, pool));
+
+  log_tmp = svn_log_create(pool);
+
+  log_tmp->log_method = svn_log_method_file;
+  log_tmp->stream = svn_stream_from_aprfile(file, pool);
+
+  *log = log_tmp;
+
+  return SVN_NO_ERROR;
+}
+
+svn_error_t* svn_log_from_aprfile(svn_log_t** log, apr_file_t* file, 
+                                  apr_pool_t* pool)
+{
+    apr_status_t status;
+    apr_file_t* file2 = NULL;
+    svn_log_t* log_tmp;
+
+    status = apr_file_dup(&file2, file, pool);
+    if (status != APR_SUCCESS)
+        return svn_error_wrap_apr(status, "Unable to duplicate file handle.");
+
+    log_tmp = svn_log_create(pool);
+
+    log_tmp->log_method = svn_log_method_file;
+    log_tmp->stream = svn_stream_from_aprfile(file2, pool);
+
+    *log = log_tmp;
+
+    return SVN_NO_ERROR;
+}
+
+svn_error_t* svn_log_open_stdout(svn_log_t** log, apr_pool_t* pool)
+{
+  svn_log_t* log_tmp;
+  svn_stream_t* stream;
+
+  SVN_ERR(svn_stream_for_stdout(&stream, pool));
+
+  log_tmp = svn_log_create(pool);
+
+  log_tmp->log_method = svn_log_method_file;
+  log_tmp->stream = stream;
+
+  *log = log_tmp;
+
+  return SVN_NO_ERROR;
+}
+
+/*
+ * This function was lifted from svn_ra_svn
+ */
+static svn_error_t *make_connection(const char *hostname, unsigned short port,
+                                    apr_socket_t **sock, apr_pool_t *pool)
+{
+  apr_sockaddr_t *sa;
+  apr_status_t status;
+  int family = APR_INET;
+  
+  /* Make sure we have IPV6 support first before giving apr_sockaddr_info_get
+     APR_UNSPEC, because it may give us back an IPV6 address even if we can't
+     create IPV6 sockets.  */  
+
+#if APR_HAVE_IPV6
+#ifdef MAX_SECS_TO_LINGER
+  status = apr_socket_create(sock, APR_INET6, SOCK_STREAM, pool);
+#else
+  status = apr_socket_create(sock, APR_INET6, SOCK_STREAM,
+                             APR_PROTO_TCP, pool);
+#endif
+  if (status == 0)
+    {
+      apr_socket_close(*sock);
+      family = APR_UNSPEC;
+    }
+#endif
+
+  /* Resolve the hostname. */
+  status = apr_sockaddr_info_get(&sa, hostname, family, port, 0, pool);
+  if (status)
+    return svn_error_createf(status, NULL, _("Unknown hostname '%s'"),
+                             hostname);
+
+  /* Create the socket. */
+#ifdef MAX_SECS_TO_LINGER
+  /* ### old APR interface */
+  status = apr_socket_create(sock, sa->family, SOCK_STREAM, pool);
+#else
+  status = apr_socket_create(sock, sa->family, SOCK_STREAM, APR_PROTO_TCP, 
+                             pool);
+#endif
+  if (status)
+    return svn_error_wrap_apr(status, _("Can't create socket"));
+
+  status = apr_socket_connect(*sock, sa);
+  if (status)
+    return svn_error_wrap_apr(status, _("Can't connect to host '%s'"),
+                              hostname);
+
+  return SVN_NO_ERROR;
+}
+
+svn_error_t* svn_log_open_socket(svn_log_t** log, const char* hostname, 
+                                 unsigned short port, apr_pool_t* pool)
+{
+  apr_socket_t* socket = NULL;
+  svn_log_t* log_tmp;
+
+  SVN_ERR(make_connection(hostname, port, &socket, pool));
+
+  log_tmp = svn_log_create(pool);
+
+  log_tmp->log_method = svn_log_method_socket;
+  log_tmp->stream = svn_stream_from_aprsocket(socket, pool);
+
+  *log = log_tmp;
+
+  return SVN_NO_ERROR;
+}
+
+
+int svn_log_getlevel(svn_log_t* log)
+{
+    return log->level;
+}
+
+int svn_log_setlevel(svn_log_t* log, int newlevel)
+{
+    int oldlevel = log->level;
+    log->level = newlevel;
+    return oldlevel;
+}
+
+svn_error_t* svn_log_write(svn_log_t* log, apr_pool_t* pool, int loglevel, 
+                           const char* msg)
+{
+  if (loglevel > log->level)
+  {
+    int len = strlen(msg);
+    return svn_stream_write(log->stream, msg, &len);
+  }
+  return SVN_NO_ERROR;
+}
+
+svn_error_t* svn_log_writes(svn_log_t* log, apr_pool_t* pool, int loglevel, 
+                           svn_string_t* msg)
+{
+  if (loglevel > log->level)
+  {
+    int len = msg->len;
+    return svn_stream_write(log->stream, msg->data, &len);
+  }
+  return SVN_NO_ERROR;
+}
+
+svn_error_t* svn_log_writev(svn_log_t* log, apr_pool_t* pool, int loglevel, 
+                           const char* fmt, va_list ap)
+{
+  if (loglevel > log->level)
+  {
+    char* data = apr_pvsprintf(pool, fmt, ap);
+    int len = strlen(data);
+    return svn_stream_write(log->stream, data, &len);
+  }
+
+  return SVN_NO_ERROR;
+}
+
+svn_error_t* svn_log_writef(svn_log_t* log, apr_pool_t* pool, int loglevel, 
+                           const char* fmt, ...)
+{
+  if (loglevel > log->level)
+  {
+    svn_error_t* svnerr;
+    char* data;
+    int len;
+
+    va_list ap;
+    va_start (ap, fmt);
+    data = apr_pvsprintf(pool, fmt, ap);
+    len = strlen(data);
+    svnerr = svn_stream_write(log->stream, data, &len);
+    va_end (ap);
+
+    return svnerr;
+  }
+
+  return SVN_NO_ERROR;
+}
\ No newline at end of file
Index: subversion/libsvn_repos/repos.c
===================================================================
--- subversion/libsvn_repos/repos.c	(revision 15457)
+++ subversion/libsvn_repos/repos.c	(working copy)
@@ -2011,3 +2011,92 @@
   *dirent = ent;
   return SVN_NO_ERROR;
 }
+
+
+
+/* Specialized logging functions. */
+
+
+/** Identify the user of @a repos as @a processname. */
+void
+svn_repos_set_processname (svn_repos_t *repos,
+                           const char *processname)
+{
+    /* should we duplicate this string so we have a permanent copy? */
+    repos->process = processname;
+}
+
+/** Set @a *processname to the name of the process using @a repos, or
+    NULL if none is defined.  */
+void
+svn_repos_get_processname (const char **processname,
+                           svn_repos_t *repos)
+{
+    *processname = repos->process;
+}
+
+/** Have @a repos write all accesslog messages to @a logfile. */
+void
+svn_repos_set_accesslog (svn_repos_t *repos,
+                         svn_log_t *log)
+{
+    repos->log = log;
+}
+
+/** Set @a *logfile to the current accesslog of @a repos, or NULL if
+    none is defined. */
+void
+svn_repos_get_accesslog (svn_log_t **log,
+                         svn_repos_t *repos)
+{
+    *log = repos->log;
+}
+
+
+/** Write a message into the accesslog of @a repos, using a
+ * printf-style error message produced by passing @a fmt to @c
+ * apr_psprintf.
+ *
+ * If the name of the process using @a repos is not @c NULL, then log
+ * it as well.  (See @c svn_repos_set_processname.)
+ *
+ * If not @c NULL, then log @a sockaddr as the incoming IP address of
+ * the request.
+ *
+ * If not @c NULL, then log @a username as the user performing the
+ * request.
+ *
+ * Use @a pool for any temporary memory allocation, including possibly
+ * calling apr_psprintf() to format the message.
+ */
+svn_error_t*
+svn_repos_write_accesslogf (svn_repos_t *repos,
+                           apr_pool_t *pool,
+                           int level,
+                           const char *username,
+                           const char *fmt,
+                           ...)
+{
+  if (repos->log != NULL)
+  {
+    if (level > repos->log->level)
+    {
+      svn_error_t* svnerr;
+      char* newstr;
+      va_list ap;
+
+      newstr = apr_psprintf(pool, "[%s] %s : %s", 
+          repos->process != NULL ? repos->process : "(process)", 
+          username != NULL ? username : "(user)", 
+          fmt);
+
+      va_start (ap, fmt);
+      svnerr = svn_log_writev(repos->log, pool, level, newstr, ap);
+      va_end (ap);
+
+      return svnerr;
+    }
+  }
+
+  return SVN_NO_ERROR;
+}
\ No newline at end of file
Index: subversion/libsvn_repos/repos.h
===================================================================
--- subversion/libsvn_repos/repos.h	(revision 15457)
+++ subversion/libsvn_repos/repos.h	(working copy)
@@ -22,6 +22,7 @@
 #include <apr_hash.h>
 
 #include "svn_fs.h"
+#include "svn_log.h"
 
 #ifdef __cplusplus
 extern "C" {
@@ -98,6 +99,12 @@
 
   /* The format number of this repository. */
   int format;
+
+  /* Names the owning process. Used for logging. */
+  char *process;
+
+  /* Logging sessions */
+  svn_log_t* log;
 };
 
 
Index: subversion/svnserve/main.c
===================================================================
--- subversion/svnserve/main.c	(revision 15457)
+++ subversion/svnserve/main.c	(working copy)
@@ -478,11 +478,14 @@
 
   while (1)
     {
+        svn_log_t* log;
       /* Non-standard pool handling.  The main thread never blocks to join
          the connection threads so it cannot clean up after each one.  So
          separate pools, that can be cleared at thread exit, are used */
       connection_pool = svn_pool_create(NULL);
 
+      svn_error_clear(svn_log_open_stdout(&log, connection_pool));
+
       status = apr_socket_accept(&usock, sock, connection_pool);
       if (handling_mode == connection_mode_fork)
         {
@@ -507,6 +510,8 @@
 
       conn = svn_ra_svn_create_conn(usock, NULL, NULL, connection_pool);
 
+      svn_log_writef(log, connection_pool, 10, "Connection received!");
+
       if (run_mode == run_mode_listen_once)
         {
           err = serve(conn, &params, connection_pool);
