/*
 * 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.
 */

#ifndef _LOG4CXX_NET_XML_SOCKET_APPENDER_H
#define _LOG4CXX_NET_XML_SOCKET_APPENDER_H

#include <log4cxx/net/socketappenderskeleton.h>
#include <log4cxx/helpers/writer.h>

namespace log4cxx
{
namespace net
{

/**
Sends {@link log4cxx::spi::LoggingEvent LoggingEvent} objects in XML format
        to a remote a log server, usually a XMLSocketNode.

<p>The XMLSocketAppender has the following properties:

- If sent to a XMLSocketNode, remote logging
        is non-intrusive as far as the log event is concerned. In other
words, the event will be logged with the same time stamp, {@link
NDC NDC}, location info as if it were logged locally by
the client.

- XMLSocketAppenders use exclusively an XMLLayout. They ship an
XML stream representing a {@link spi::LoggingEvent LoggingEvent} object
        to the server side.

- 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.
*/

class LOG4CXX_EXPORT XMLSocketAppender : public SocketAppenderSkeleton
{
	public:
		/**
		The default port number of remote logging server (4560).
		*/
		static int DEFAULT_PORT;

		/**
		The default reconnection delay (30000 milliseconds or 30 seconds).
		*/
		static int DEFAULT_RECONNECTION_DELAY;

		/**
		An event XML stream cannot exceed 1024 bytes.
		*/
		static const int MAX_EVENT_LEN;

		DECLARE_LOG4CXX_OBJECT(XMLSocketAppender)
		BEGIN_LOG4CXX_CAST_MAP()
		LOG4CXX_CAST_ENTRY(XMLSocketAppender)
		LOG4CXX_CAST_ENTRY_CHAIN(AppenderSkeleton)
		END_LOG4CXX_CAST_MAP()

		XMLSocketAppender();
		~XMLSocketAppender();

		/**
		Connects to remote server at <code>address</code> and <code>port</code>.
		*/
		XMLSocketAppender(helpers::InetAddressPtr address, int port);

		/**
		Connects to remote server at <code>host</code> and <code>port</code>.
		*/
		XMLSocketAppender(const LogString& host, int port);


	protected:
		virtual void setSocket(log4cxx::helpers::SocketPtr& socket, log4cxx::helpers::Pool& p);

		virtual void cleanUp(log4cxx::helpers::Pool& p);

		virtual int getDefaultDelay() const;

		virtual int getDefaultPort() const;

		void append(const spi::LoggingEventPtr& event, log4cxx::helpers::Pool& pool);

	private:
		log4cxx::helpers::WriterPtr writer;
		//  prevent copy and assignment statements
		XMLSocketAppender(const XMLSocketAppender&);
		XMLSocketAppender& operator=(const XMLSocketAppender&);
}; // class XMLSocketAppender

LOG4CXX_PTR_DEF(XMLSocketAppender);

} // namespace net
} // namespace log4cxx

#endif // _LOG4CXX_NET_XML_SOCKET_APPENDER_H

