/*
 * 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_SOCKET_APPENDER_H
#define _LOG4CXX_NET_SOCKET_APPENDER_H

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

namespace log4cxx
{
	namespace net
	{
		/**
		Sends {@link log4cxx::spi::LoggingEvent LoggingEvent} objects to a remote a log server,
		usually Apache Chainsaw.

		<p>The SocketAppender has the following properties:

		- If sent to Apache Chainsaw, 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.

		- SocketAppenders do not use a layout. They ship a
		serialized {@link log4cxx::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 a <code>SocketAppender</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>SocketAppender</code> explicitly. See also next item.
		@n @n Long lived applications which create/destroy many
		<code>SocketAppender</code> instances should be aware of this
		destruction problem. Most other applications can safely
		ignore it.

		- If the application hosting the <code>SocketAppender</code>
				exits before the <code>SocketAppender</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>SocketAppender</code> either explicitly or by
		calling the LogManager#shutdown method
		before exiting the application.
		*/
		class LOG4CXX_EXPORT SocketAppender : 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;

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

				SocketAppender();
				~SocketAppender();

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

				/**
				Connects to remote server at <code>host</code> and <code>port</code>.
				*/
				SocketAppender(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::ObjectOutputStreamPtr oos;

		}; // class SocketAppender

		LOG4CXX_PTR_DEF(SocketAppender);
	} // namespace net
} // namespace log4cxx

#endif // _LOG4CXX_NET_SOCKET_APPENDER_H

