This is an automated email from the ASF dual-hosted git repository.

swebb2066 pushed a commit to branch next_abi_socket_appender
in repository https://gitbox.apache.org/repos/asf/logging-log4cxx.git

commit cbf6ca0347d7c44c9352f40cb62d53e3f903e29e
Author: Stephen Webb <[email protected]>
AuthorDate: Fri May 8 11:46:15 2026 +1000

    Simplify socket appender sub-classing by enhancing SocketAppenderSkeleton
---
 src/main/cpp/nteventlogappender.cpp                |   2 +-
 src/main/cpp/socketappenderskeleton.cpp            | 155 ++++++++++++---------
 src/main/cpp/xmlsocketappender.cpp                 |  51 +++----
 .../include/log4cxx/net/socketappenderskeleton.h   |  90 +++++++++---
 src/main/include/log4cxx/net/xmlsocketappender.h   |  74 ++++------
 src/main/include/log4cxx/nt/nteventlogappender.h   |   4 +-
 .../log4cxx/private/socketappenderskeleton_priv.h  |  25 +++-
 7 files changed, 224 insertions(+), 177 deletions(-)

diff --git a/src/main/cpp/nteventlogappender.cpp 
b/src/main/cpp/nteventlogappender.cpp
index 553d107c..fec9447a 100644
--- a/src/main/cpp/nteventlogappender.cpp
+++ b/src/main/cpp/nteventlogappender.cpp
@@ -223,7 +223,7 @@ void NTEventLogAppender::append( 
LOG4CXX_APPEND_FORMAL_PARAMETERS )
 
        LogString oss;
        Pool tempPool;
-       this->m_priv->layout->format(oss, event, tempPool);
+       this->m_priv->layout->format(oss, event);
        wchar_t* msgs = Transcoder::wencode(oss, tempPool);
        BOOL bSuccess = ::ReportEventW(
                        priv->hEventLog,
diff --git a/src/main/cpp/socketappenderskeleton.cpp 
b/src/main/cpp/socketappenderskeleton.cpp
index 930a74f4..00ca2aae 100644
--- a/src/main/cpp/socketappenderskeleton.cpp
+++ b/src/main/cpp/socketappenderskeleton.cpp
@@ -18,14 +18,16 @@
 #define __STDC_CONSTANT_MACROS
 #include <log4cxx/net/socketappenderskeleton.h>
 #include <log4cxx/helpers/loglog.h>
+#include <log4cxx/helpers/charsetencoder.h>
 #include <log4cxx/helpers/optionconverter.h>
 #include <log4cxx/helpers/stringhelper.h>
 #include <log4cxx/spi/loggingevent.h>
 #include <log4cxx/helpers/threadutility.h>
 #include <log4cxx/helpers/transcoder.h>
 #include <log4cxx/helpers/bytearrayoutputstream.h>
+#include <log4cxx/helpers/outputstreamwriter.h>
+#include <log4cxx/helpers/socketoutputstream.h>
 #include <log4cxx/helpers/threadutility.h>
-#include <log4cxx/private/appenderskeleton_priv.h>
 #include <log4cxx/private/socketappenderskeleton_priv.h>
 #include <functional>
 #include <chrono>
@@ -41,7 +43,11 @@ SocketAppenderSkeleton::SocketAppenderSkeleton(int 
defaultPort, int reconnection
 {
 }
 
+#if LOG4CXX_ABI_VERSION <= 15
 SocketAppenderSkeleton::SocketAppenderSkeleton(helpers::InetAddressPtr 
address, int port, int reconnectionDelay)
+#else
+SocketAppenderSkeleton::SocketAppenderSkeleton(const helpers::InetAddressPtr& 
address, int port, int reconnectionDelay)
+#endif
        : 
AppenderSkeleton(std::make_unique<SocketAppenderSkeletonPriv>(address, port, 
reconnectionDelay))
 {
 }
@@ -62,8 +68,7 @@ SocketAppenderSkeleton::~SocketAppenderSkeleton()
 
 void SocketAppenderSkeleton::activateOptions( 
LOG4CXX_ACTIVATE_OPTIONS_FORMAL_PARAMETERS )
 {
-       Pool my_pool;
-       connect(my_pool);
+       _priv->connect();
 }
 
 void SocketAppenderSkeleton::close()
@@ -72,38 +77,37 @@ void SocketAppenderSkeleton::close()
                _priv->close();
 }
 
-void SocketAppenderSkeleton::connect(Pool& p)
+void SocketAppenderSkeleton::SocketAppenderSkeletonPriv::connect()
 {
-       if (_priv->address == 0)
+       if (this->address == 0)
        {
                LogLog::error(LogString(LOG4CXX_STR("No remote host is set for 
Appender named \"")) +
-                       _priv->name + LOG4CXX_STR("\"."));
+                       this->name + LOG4CXX_STR("\"."));
        }
        else
        {
-               _priv->close();
+               this->close();
 
                try
                {
                        if (LogLog::isDebugEnabled())
                        {
                                LogString msg(LOG4CXX_STR("Connecting to [")
-                                       + _priv->address->toString() + 
LOG4CXX_STR(":"));
-                               StringHelper::toString(_priv->port, msg);
+                                       + this->address->toString() + 
LOG4CXX_STR(":"));
+                               StringHelper::toString(this->port, msg);
                                msg += LOG4CXX_STR("].");
                                LogLog::debug(msg);
                        }
-                       SocketPtr socket = Socket::create(_priv->address, 
_priv->port);
-                       setSocket(socket, p);
+                       this->setOutputSink(Socket::create(this->address, 
this->port));
                }
                catch (SocketException& e)
                {
                        LogString msg = LOG4CXX_STR("Could not connect to [")
-                               + _priv->address->toString() + LOG4CXX_STR(":");
-                       StringHelper::toString(_priv->port, msg);
+                               + this->address->toString() + LOG4CXX_STR(":");
+                       StringHelper::toString(this->port, msg);
                        msg += LOG4CXX_STR("].");
 
-                       fireConnector(); // fire the connector thread
+                       this->fireConnector(); // fire the connector thread
                        LogLog::warn(msg, e);
                }
        }
@@ -133,95 +137,99 @@ void SocketAppenderSkeleton::setOption(const LogString& 
option, const LogString&
        }
 }
 
+void SocketAppenderSkeleton::SocketAppenderSkeletonPriv::fireConnector()
+{
+       std::lock_guard<std::recursive_mutex> lock(this->mutex);
+       if (this->taskName.empty())
+       {
+               this->taskName = this->name + LOG4CXX_STR(":")
+                       + this->address->toString() + LOG4CXX_STR(":");
+               StringHelper::toString(this->port, this->taskName);
+       }
+       auto taskManager = ThreadUtility::instancePtr();
+       if (!taskManager->value().hasPeriodicTask(this->taskName))
+       {
+               if (LogLog::isDebugEnabled())
+               {
+                       LogString msg(LOG4CXX_STR("Waiting "));
+                       StringHelper::toString(this->reconnectionDelay, msg);
+                       msg += LOG4CXX_STR(" ms before retrying [")
+                               + this->address->toString() + LOG4CXX_STR(":");
+                       StringHelper::toString(this->port, msg);
+                       msg += LOG4CXX_STR("].");
+                       LogLog::debug(msg);
+               }
+               taskManager->value().addPeriodicTask(this->taskName
+                       , 
std::bind(&SocketAppenderSkeleton::SocketAppenderSkeletonPriv::retryConnect, 
this)
+                       , std::chrono::milliseconds(this->reconnectionDelay)
+                       );
+       }
+       this->taskManager = taskManager;
+}
+
+#if LOG4CXX_ABI_VERSION <= 15
 void SocketAppenderSkeleton::fireConnector()
 {
-       std::lock_guard<std::recursive_mutex> lock(_priv->mutex);
-    if (_priv->taskName.empty())
-    {
-        _priv->taskName = _priv->name + LOG4CXX_STR(":")
-            + _priv->address->toString() + LOG4CXX_STR(":");
-        StringHelper::toString(_priv->port, _priv->taskName);
-    }
-    auto taskManager = ThreadUtility::instancePtr();
-    if (!taskManager->value().hasPeriodicTask(_priv->taskName))
-    {
-        if (LogLog::isDebugEnabled())
-        {
-            LogString msg(LOG4CXX_STR("Waiting "));
-            StringHelper::toString(_priv->reconnectionDelay, msg);
-            msg += LOG4CXX_STR(" ms before retrying [")
-                + _priv->address->toString() + LOG4CXX_STR(":");
-            StringHelper::toString(_priv->port, msg);
-            msg += LOG4CXX_STR("].");
-            LogLog::debug(msg);
-        }
-        taskManager->value().addPeriodicTask(_priv->taskName
-            , std::bind(&SocketAppenderSkeleton::retryConnect, this)
-            , std::chrono::milliseconds(_priv->reconnectionDelay)
-            );
-    }
-    _priv->taskManager = taskManager;
+       _priv->fireConnector();
 }
+#endif
 
-void SocketAppenderSkeleton::retryConnect()
+void SocketAppenderSkeleton::SocketAppenderSkeletonPriv::retryConnect()
 {
-       if (is_closed())
+       if (this->closed)
        {
-               if (auto pManager = _priv->taskManager.lock())
-                       pManager->value().removePeriodicTask(_priv->taskName);
+               if (auto pManager = this->taskManager.lock())
+                       pManager->value().removePeriodicTask(this->taskName);
        }
        else
        {
-        Pool p;
-               SocketPtr socket;
                try
                {
                        if (LogLog::isDebugEnabled())
                        {
                                LogString msg(LOG4CXX_STR("Attempting 
connection to [")
-                                       + _priv->address->toString() + 
LOG4CXX_STR(":"));
-                               StringHelper::toString(_priv->port, msg);
+                                       + this->address->toString() + 
LOG4CXX_STR(":"));
+                               StringHelper::toString(this->port, msg);
                                msg += LOG4CXX_STR("].");
                                LogLog::debug(msg);
                        }
-                       socket = Socket::create(_priv->address, _priv->port);
-                       setSocket(socket, p);
+                       this->setOutputSink(Socket::create(this->address, 
this->port));
                        if (LogLog::isDebugEnabled())
                        {
                                LogString msg(LOG4CXX_STR("Connection 
established to [")
-                                       + _priv->address->toString() + 
LOG4CXX_STR(":"));
-                               StringHelper::toString(_priv->port, msg);
+                                       + this->address->toString() + 
LOG4CXX_STR(":"));
+                               StringHelper::toString(this->port, msg);
                                msg += LOG4CXX_STR("].");
                                LogLog::debug(msg);
                        }
-                       if (auto pManager = _priv->taskManager.lock())
-                               
pManager->value().removePeriodicTask(_priv->taskName);
+                       if (auto pManager = this->taskManager.lock())
+                               
pManager->value().removePeriodicTask(this->taskName);
                        return;
                }
                catch (ConnectException& e)
                {
                        LogLog::warn(LOG4CXX_STR("Remote host ")
-                               + _priv->address->toString()
+                               + this->address->toString()
                                + LOG4CXX_STR(" refused connection."), e);
                }
                catch (IOException& e)
                {
                        LogString msg(LOG4CXX_STR("Could not connect to [")
-                               + _priv->address->toString() + 
LOG4CXX_STR(":"));
-                       StringHelper::toString(_priv->port, msg);
+                               + this->address->toString() + LOG4CXX_STR(":"));
+                       StringHelper::toString(this->port, msg);
                        msg += LOG4CXX_STR("].");
                        LogLog::warn(msg, e);
                }
 
-               if (_priv->reconnectionDelay > 0)
+               if (this->reconnectionDelay > 0)
                {
                        if (LogLog::isDebugEnabled())
                        {
                                LogString msg(LOG4CXX_STR("Waiting "));
-                               
StringHelper::toString(_priv->reconnectionDelay, msg);
+                               StringHelper::toString(this->reconnectionDelay, 
msg);
                                msg += LOG4CXX_STR(" ms before retrying [")
-                                       + _priv->address->toString() + 
LOG4CXX_STR(":");
-                               StringHelper::toString(_priv->port, msg);
+                                       + this->address->toString() + 
LOG4CXX_STR(":");
+                               StringHelper::toString(this->port, msg);
                                msg += LOG4CXX_STR("].");
                                LogLog::debug(msg);
                        }
@@ -229,17 +237,30 @@ void SocketAppenderSkeleton::retryConnect()
        }
 }
 
+void SocketAppenderSkeleton::SocketAppenderSkeletonPriv::setOutputSink(const 
SocketPtr& socket)
+{
+       OutputStreamPtr os = std::make_shared<SocketOutputStream>(socket);
+       auto charset = CharsetEncoder::getUTF8Encoder();
+       this->outputSink = std::make_shared<OutputStreamWriter>(os, charset);
+}
+
 void SocketAppenderSkeleton::SocketAppenderSkeletonPriv::close()
 {
        if (this->taskName.empty())
                ;
        else if (auto pManager = this->taskManager.lock())
                pManager->value().removePeriodicTask(this->taskName);
-}
-
-bool SocketAppenderSkeleton::is_closed()
-{
-       return _priv->closed;
+       if (this->outputSink)
+       {
+               try
+               {
+                       this->outputSink->close();
+                       this->outputSink.reset();
+               }
+               catch (std::exception&)
+               {
+               }
+       }
 }
 
 void SocketAppenderSkeleton::setRemoteHost(const LogString& host)
@@ -283,7 +304,7 @@ void SocketAppenderSkeleton::setReconnectionDelay(int 
reconnectionDelay1)
        {
                pManager->value().removePeriodicTask(_priv->taskName);
                pManager->value().addPeriodicTask(_priv->taskName
-                       , std::bind(&SocketAppenderSkeleton::retryConnect, this)
+                       , 
std::bind(&SocketAppenderSkeleton::SocketAppenderSkeletonPriv::retryConnect, 
_priv)
                        , std::chrono::milliseconds(_priv->reconnectionDelay)
                        );
        }
diff --git a/src/main/cpp/xmlsocketappender.cpp 
b/src/main/cpp/xmlsocketappender.cpp
index 7793626b..60484633 100644
--- a/src/main/cpp/xmlsocketappender.cpp
+++ b/src/main/cpp/xmlsocketappender.cpp
@@ -17,15 +17,12 @@
 
 #include <log4cxx/net/xmlsocketappender.h>
 #include <log4cxx/helpers/loglog.h>
-#include <log4cxx/helpers/outputstreamwriter.h>
-#include <log4cxx/helpers/charsetencoder.h>
 #include <log4cxx/helpers/optionconverter.h>
 #include <log4cxx/helpers/stringhelper.h>
 #include <log4cxx/xml/xmllayout.h>
 #include <log4cxx/level.h>
 #include <log4cxx/helpers/transform.h>
 #include <log4cxx/helpers/transcoder.h>
-#include <log4cxx/helpers/socketoutputstream.h>
 #include <log4cxx/private/appenderskeleton_priv.h>
 #include <log4cxx/private/socketappenderskeleton_priv.h>
 
@@ -45,9 +42,9 @@ struct XMLSocketAppender::XMLSocketAppenderPriv : public 
SocketAppenderSkeletonP
        XMLSocketAppenderPriv(const LogString& host, int port, int delay) :
                SocketAppenderSkeletonPriv( host, port, delay ) {}
 
-       LOG4CXX_NS::helpers::WriterPtr writer;
-
-       void close() override;
+#if LOG4CXX_ABI_VERSION <= 15
+       LOG4CXX_NS::helpers::WriterPtr unused_writer;
+#endif
 };
 
 IMPLEMENT_LOG4CXX_OBJECT(XMLSocketAppender)
@@ -60,7 +57,9 @@ int XMLSocketAppender::DEFAULT_PORT                 = 4560;
 // The default reconnection delay (30000 milliseconds or 30 seconds).
 int XMLSocketAppender::DEFAULT_RECONNECTION_DELAY   = 30000;
 
+#if LOG4CXX_ABI_VERSION <= 15
 const int XMLSocketAppender::MAX_EVENT_LEN          = 1024;
+#endif
 
 XMLSocketAppender::XMLSocketAppender()
        : 
SocketAppenderSkeleton(std::make_unique<XMLSocketAppenderPriv>(DEFAULT_PORT, 
DEFAULT_RECONNECTION_DELAY))
@@ -68,7 +67,11 @@ XMLSocketAppender::XMLSocketAppender()
        _priv->layout = std::make_shared<XMLLayout>();
 }
 
+#if LOG4CXX_ABI_VERSION <= 15
 XMLSocketAppender::XMLSocketAppender(InetAddressPtr address1, int port1)
+#else
+XMLSocketAppender::XMLSocketAppender(const InetAddressPtr& address1, int port1)
+#endif
        : 
SocketAppenderSkeleton(std::make_unique<XMLSocketAppenderPriv>(address1, port1, 
DEFAULT_RECONNECTION_DELAY))
 {
        _priv->layout = std::make_shared<XMLLayout>();
@@ -84,8 +87,6 @@ XMLSocketAppender::XMLSocketAppender(const LogString& host, 
int port1)
 
 XMLSocketAppender::~XMLSocketAppender()
 {
-       if (_priv->setClosed())
-               _priv->close();
 }
 
 
@@ -99,57 +100,39 @@ int XMLSocketAppender::getDefaultPort() const
        return DEFAULT_PORT;
 }
 
+#if LOG4CXX_ABI_VERSION <= 15
 void XMLSocketAppender::setSocket(LOG4CXX_NS::helpers::SocketPtr& socket, 
Pool& p)
 {
-       OutputStreamPtr os = std::make_shared<SocketOutputStream>(socket);
-       CharsetEncoderPtr charset(CharsetEncoder::getUTF8Encoder());
-       std::lock_guard<std::recursive_mutex> lock(_priv->mutex);
-       _priv->writer = std::make_shared<OutputStreamWriter>(os, charset);
+       _priv->setOutputSink(socket);
 }
 
-#if LOG4CXX_ABI_VERSION <= 15
+
 void XMLSocketAppender::cleanUp(Pool& p)
 {
        _priv->close();
 }
 #endif
 
-void XMLSocketAppender::XMLSocketAppenderPriv::close()
-{
-       SocketAppenderSkeletonPriv::close();
-       if (this->writer)
-       {
-               try
-               {
-                       this->writer->close();
-                       this->writer = nullptr;
-               }
-               catch (std::exception&)
-               {
-               }
-       }
-}
-
 void XMLSocketAppender::append( LOG4CXX_APPEND_FORMAL_PARAMETERS )
 {
-       if (_priv->writer)
+       if (_priv->outputSink)
        {
                LogString output;
                _priv->layout->format(output, event);
 
                try
                {
-                       _priv->writer->write(output);
-                       _priv->writer->flush();
+                       _priv->outputSink->write(output);
+                       _priv->outputSink->flush();
                }
                catch (std::exception& e)
                {
-                       _priv->writer = nullptr;
+                       _priv->outputSink.reset();
                        LogLog::warn(LOG4CXX_STR("Detected problem with 
connection: "), e);
 
                        if (getReconnectionDelay() > 0)
                        {
-                               fireConnector();
+                               _priv->fireConnector();
                        }
                }
        }
diff --git a/src/main/include/log4cxx/net/socketappenderskeleton.h 
b/src/main/include/log4cxx/net/socketappenderskeleton.h
index afb0c530..c96f50ec 100644
--- a/src/main/include/log4cxx/net/socketappenderskeleton.h
+++ b/src/main/include/log4cxx/net/socketappenderskeleton.h
@@ -19,9 +19,11 @@
 #define _LOG4CXX_NET_SOCKET_APPENDER_SKELETON_H
 
 #include <log4cxx/appenderskeleton.h>
+#include <log4cxx/helpers/inetaddress.h>
+#if LOG4CXX_ABI_VERSION <= 15
 #include <log4cxx/helpers/socket.h>
-#include <thread>
-#include <condition_variable>
+#endif
+
 
 namespace LOG4CXX_NS
 {
@@ -30,7 +32,53 @@ namespace net
 {
 
 /**
- *  Abstract base class for SocketAppender and XMLSocketAppender
+Abstract base class that sends spi::LoggingEvent elements to a remote server.
+
+\anchor socket_appender_properties
+This appender has the following properties:
+
+- The event will be logged with the same time stamp,
+NDC, location info as if it were logged locally by
+the client.
+
+- Remote logging uses the TCP protocol,
+so if the server is reachable,
+log events will eventually arrive at the server.
+
+- If the remote server is down, the logging requests are simply dropped.
+However, if and when the server comes back up,
+then event transmission is resumed transparently.
+This transparent reconneciton is performed by a <em>connector</em>
+task which periodically attempts to connect to the server.
+
+- Logging events are automatically <em>buffered</em> by the
+native TCP implementation. This means that if the link to server
+is slow but still faster than the rate of (log) event production
+by the client, the client will not be affected by the slow
+network connection. However, if the network connection is slower
+then the rate of event production, then the client can only
+progress at the network rate. In particular, if the network link
+to the the server is down, the client will be blocked.
+On the other hand, if the network link is up, but the server
+is down, the client will not be blocked when making log requests
+but the log events will be lost due to server unavailability.
+
+- If the application hosting this appender exits before it is closed,
+either explicitly or subsequent to destruction,
+then there might be untransmitted data in the pipe which might be lost.
+
+To avoid lost data, it is usually sufficient to
+#close the appender either explicitly or by
+calling the LogManager#shutdown method
+before exiting the application.
+
+A periodic task will connect when the server becomes available.
+It does this by attempting to open a new connection every
+<code>reconnectionDelay</code> milliseconds.
+
+The periodic task stops trying whenever a connection is established.
+It will restart attempting to open a new connection to the server
+when a previously open connection is droppped.
  */
 class LOG4CXX_EXPORT SocketAppenderSkeleton : public AppenderSkeleton
 {
@@ -44,8 +92,11 @@ class LOG4CXX_EXPORT SocketAppenderSkeleton : public 
AppenderSkeleton
                /**
                Connects to remote server at <code>address</code> and 
<code>port</code>.
                */
+#if LOG4CXX_ABI_VERSION <= 15
                SocketAppenderSkeleton(helpers::InetAddressPtr address, int 
port, int reconnectionDelay);
-
+#else
+               SocketAppenderSkeleton(const helpers::InetAddressPtr& address, 
int port, int reconnectionDelay);
+#endif
                /**
                Connects to remote server at <code>host</code> and 
<code>port</code>.
                */
@@ -61,7 +112,7 @@ class LOG4CXX_EXPORT SocketAppenderSkeleton : public 
AppenderSkeleton
 
                void close() override;
 
-
+#if LOG4CXX_ABI_VERSION <= 15
                /**
                * This appender does not use a layout. Hence, this method
                * returns <code>false</code>.
@@ -71,7 +122,7 @@ class LOG4CXX_EXPORT SocketAppenderSkeleton : public 
AppenderSkeleton
                {
                        return false;
                }
-
+#endif
                /**
                * The <b>RemoteHost</b> option takes a string value which 
should be
                * the host name of the server where a
@@ -123,7 +174,12 @@ class LOG4CXX_EXPORT SocketAppenderSkeleton : public 
AppenderSkeleton
                */
                int getReconnectionDelay() const;
 
+#if LOG4CXX_ABI_VERSION <= 15
+               /**
+               @deprecated This method will be removed in a future version.
+               */
                void fireConnector();
+#endif
 
                /**
                \copybrief AppenderSkeleton::setOption()
@@ -145,9 +201,15 @@ class LOG4CXX_EXPORT SocketAppenderSkeleton : public 
AppenderSkeleton
        protected:
                
SocketAppenderSkeleton(std::unique_ptr<SocketAppenderSkeletonPriv> priv);
 
-               virtual void setSocket(LOG4CXX_NS::helpers::SocketPtr& socket, 
LOG4CXX_NS::helpers::Pool& p) = 0;
-
 #if LOG4CXX_ABI_VERSION <= 15
+               /**
+               @deprecated This method will be removed in a future version.
+               */
+               virtual void setSocket(helpers::SocketPtr& socket, 
helpers::Pool& p) = 0;
+
+               /**
+               @deprecated This method will be removed in a future version.
+               */
                virtual void cleanUp(LOG4CXX_NS::helpers::Pool& p) = 0;
 #endif
                virtual int getDefaultDelay() const = 0;
@@ -155,19 +217,7 @@ class LOG4CXX_EXPORT SocketAppenderSkeleton : public 
AppenderSkeleton
                virtual int getDefaultPort() const = 0;
 
        private:
-               void connect(LOG4CXX_NS::helpers::Pool& p);
-               /**
-                    The Connector will reconnect when the server becomes 
available
-                    again.  It does this by attempting to open a new 
connection every
-                    <code>reconnectionDelay</code> milliseconds.
-
-                    <p>It stops trying whenever a connection is established. 
It will
-                    restart to try reconnect to the server when previously open
-                    connection is droppped.
-                    */
 
-               void retryConnect();
-               bool is_closed();
                SocketAppenderSkeleton(const SocketAppenderSkeleton&);
                SocketAppenderSkeleton& operator=(const 
SocketAppenderSkeleton&);
 
diff --git a/src/main/include/log4cxx/net/xmlsocketappender.h 
b/src/main/include/log4cxx/net/xmlsocketappender.h
index f22f036f..562bf00f 100644
--- a/src/main/include/log4cxx/net/xmlsocketappender.h
+++ b/src/main/include/log4cxx/net/xmlsocketappender.h
@@ -19,7 +19,6 @@
 #define _LOG4CXX_NET_XML_SOCKET_APPENDER_H
 
 #include <log4cxx/net/socketappenderskeleton.h>
-#include <log4cxx/helpers/writer.h>
 
 namespace LOG4CXX_NS
 {
@@ -47,53 +46,7 @@ running on the same system as the application:
 </log4j:configuration>
 ~~~
 
-<p>XMLSocketAppender has the following properties:
-
-- The event will be logged with the same time stamp,
-NDC, location info as if it were logged locally by
-the client.
-
-- Remote logging uses the TCP protocol. Consequently, if
-the server is reachable, then log events will eventually arrive
-at the server.
-
-- If the remote server is down, the logging requests are
-simply dropped. However, if and when the server comes back up,
-then event transmission is resumed transparently. This
-transparent reconneciton is performed by a <em>connector</em>
-thread which periodically attempts to connect to the server.
-
-- Logging events are automatically <em>buffered</em> by the
-native TCP implementation. This means that if the link to server
-is slow but still faster than the rate of (log) event production
-by the client, the client will not be affected by the slow
-network connection. However, if the network connection is slower
-then the rate of event production, then the client can only
-progress at the network rate. In particular, if the network link
-to the the server is down, the client will be blocked.
-@n @n On the other hand, if the network link is up, but the server
-is down, the client will not be blocked when making log requests
-but the log events will be lost due to server unavailability.
-
-- Even if an <code>XMLSocketAppender</code> is no longer
-attached to any logger, it will not be destroyed in
-the presence of a connector thread. A connector thread exists
-only if the connection to the server is down. To avoid this
-destruction problem, you should #close the the
-<code>XMLSocketAppender</code> explicitly. See also next item.
-@n @n Long lived applications which create/destroy many
-<code>XMLSocketAppender</code> instances should be aware of this
-destruction problem. Most other applications can safely
-ignore it.
-
-- If the application hosting the <code>XMLSocketAppender</code>
-exits before the <code>XMLSocketAppender</code> is closed either
-explicitly or subsequent to destruction, then there might
-be untransmitted data in the pipe which might be lost.
-@n @n To avoid lost data, it is usually sufficient to
-#close the <code>XMLSocketAppender</code> either explicitly or by
-calling the LogManager#shutdown method
-before exiting the application.
+See \ref socket_appender_properties "SocketAppenderSkeleton" for more 
information on the behaviour this appender.
 */
 
 class LOG4CXX_EXPORT XMLSocketAppender : public SocketAppenderSkeleton
@@ -109,10 +62,12 @@ class LOG4CXX_EXPORT XMLSocketAppender : public 
SocketAppenderSkeleton
                */
                static int DEFAULT_RECONNECTION_DELAY;
 
+#if LOG4CXX_ABI_VERSION <= 15
                /**
                Unused
                */
                static const int MAX_EVENT_LEN;
+#endif
 
                DECLARE_LOG4CXX_OBJECT(XMLSocketAppender)
                BEGIN_LOG4CXX_CAST_MAP()
@@ -126,7 +81,11 @@ class LOG4CXX_EXPORT XMLSocketAppender : public 
SocketAppenderSkeleton
                /**
                Connects to remote server at <code>address</code> and 
<code>port</code>.
                */
+#if LOG4CXX_ABI_VERSION <= 15
                XMLSocketAppender(helpers::InetAddressPtr address, int port);
+#else
+               XMLSocketAppender(const helpers::InetAddressPtr& address, int 
port);
+#endif
 
                /**
                Connects to remote server at <code>host</code> and 
<code>port</code>.
@@ -135,10 +94,27 @@ class LOG4CXX_EXPORT XMLSocketAppender : public 
SocketAppenderSkeleton
 
                using SocketAppenderSkeleton::activateOptions;
 
+#if 15 < LOG4CXX_ABI_VERSION
+               /**
+               * This appender has a default layout.
+               * @returns false
+               */
+               bool requiresLayout() const override
+               {
+                       return false;
+               }
+#endif
+
        protected:
+#if LOG4CXX_ABI_VERSION <= 15
+               /**
+               @deprecated This method will be removed in a future version.
+               */
                void setSocket(LOG4CXX_NS::helpers::SocketPtr& socket, 
helpers::Pool& p) override;
 
-#if LOG4CXX_ABI_VERSION <= 15
+               /**
+               @deprecated This method will be removed in a future version.
+               */
                void cleanUp(helpers::Pool& p) override;
 #endif
                int getDefaultDelay() const override;
diff --git a/src/main/include/log4cxx/nt/nteventlogappender.h 
b/src/main/include/log4cxx/nt/nteventlogappender.h
index 2ebbf969..d88154a7 100644
--- a/src/main/include/log4cxx/nt/nteventlogappender.h
+++ b/src/main/include/log4cxx/nt/nteventlogappender.h
@@ -69,8 +69,8 @@ class LOG4CXX_EXPORT NTEventLogAppender : public 
AppenderSkeleton
                void setOption(const LogString& option, const LogString& value) 
override;
 
                /**
-                * The SocketAppender does not use a layout. Hence, this method
-                * returns <code>false</code>.
+                * This appender does need a layout.
+                * returns <code>true</code>.
                 *
                 */
                bool requiresLayout() const override
diff --git a/src/main/include/log4cxx/private/socketappenderskeleton_priv.h 
b/src/main/include/log4cxx/private/socketappenderskeleton_priv.h
index 4e31bb29..e92f0f4e 100644
--- a/src/main/include/log4cxx/private/socketappenderskeleton_priv.h
+++ b/src/main/include/log4cxx/private/socketappenderskeleton_priv.h
@@ -19,8 +19,9 @@
 
 #include <log4cxx/net/socketappenderskeleton.h>
 #include <log4cxx/private/appenderskeleton_priv.h>
-#include <log4cxx/helpers/inetaddress.h>
+#include <log4cxx/helpers/socket.h>
 #include <log4cxx/helpers/threadutility.h>
+#include <log4cxx/helpers/writer.h>
 
 namespace LOG4CXX_NS
 {
@@ -38,7 +39,7 @@ struct SocketAppenderSkeleton::SocketAppenderSkeletonPriv : 
public AppenderSkele
                locationInfo(false)
         { }
 
-       SocketAppenderSkeletonPriv(helpers::InetAddressPtr address, int 
defaultPort, int reconnectionDelay) :
+       SocketAppenderSkeletonPriv(const helpers::InetAddressPtr& address, int 
defaultPort, int reconnectionDelay) :
                AppenderSkeletonPrivate(),
                remoteHost(),
                address(address),
@@ -56,8 +57,10 @@ struct SocketAppenderSkeleton::SocketAppenderSkeletonPriv : 
public AppenderSkele
                locationInfo(false)
        { }
 
-       virtual ~SocketAppenderSkeletonPriv()
+       ~SocketAppenderSkeletonPriv()
        {
+               if (this->setClosed())
+                       this->close();
        }
 
        /**
@@ -73,7 +76,7 @@ struct SocketAppenderSkeleton::SocketAppenderSkeletonPriv : 
public AppenderSkele
        int port;
        int reconnectionDelay;
        bool locationInfo;
-       virtual void close();
+       void close();
 
        /**
        Manages asynchronous reconnection attempts.
@@ -84,6 +87,20 @@ struct SocketAppenderSkeleton::SocketAppenderSkeletonPriv : 
public AppenderSkele
        The reconnection task name.
        */
        LogString taskName;
+
+       /**
+       The sink for formatted logging events.
+       */
+       helpers::WriterPtr outputSink;
+
+       void connect();
+
+       void fireConnector();
+
+       void setOutputSink(const helpers::SocketPtr& socket);
+
+       void retryConnect();
+
 };
 
 } // namespace net

Reply via email to