/*
 * 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_ASYNC_APPENDER_H
#define _LOG4CXX_ASYNC_APPENDER_H

#if defined(_MSC_VER)
	#pragma warning ( push )
	#pragma warning ( disable: 4231 4251 4275 4786 )
#endif


#include <log4cxx/appenderskeleton.h>
#include <log4cxx/helpers/appenderattachableimpl.h>
#include <deque>
#include <log4cxx/spi/loggingevent.h>

#if defined(NON_BLOCKING)
	#include <boost/lockfree/queue.hpp>
#endif

namespace log4cxx
{
LOG4CXX_LIST_DEF(LoggingEventList, log4cxx::spi::LoggingEventPtr);

/**
The AsyncAppender lets users log events asynchronously. It uses a
bounded buffer to store logging events.

<p>The AsyncAppender will collect the events sent to it and then
dispatch them to all the appenders that are attached to it. You can
attach multiple appenders to an AsyncAppender.

<p>The AsyncAppender uses a separate thread to serve the events in
its bounded buffer.

<p><b>Important note:</b> The <code>AsyncAppender</code> can only
be script configured using the {@link xml::DOMConfigurator DOMConfigurator}.
*/
class LOG4CXX_EXPORT AsyncAppender :
	public virtual spi::AppenderAttachable,
	public virtual AppenderSkeleton
{
	public:
		DECLARE_LOG4CXX_OBJECT(AsyncAppender)
		BEGIN_LOG4CXX_CAST_MAP()
		LOG4CXX_CAST_ENTRY(AsyncAppender)
		LOG4CXX_CAST_ENTRY_CHAIN(AppenderSkeleton)
		LOG4CXX_CAST_ENTRY(spi::AppenderAttachable)
		END_LOG4CXX_CAST_MAP()

		/**
		 * Create new instance.
		*/
		AsyncAppender();

		/**
		 *  Destructor.
		 */
		virtual ~AsyncAppender();

		/**
		 * Add appender.
		 *
		 * @param newAppender appender to add, may not be null.
		*/
        void addAppender(const AppenderPtr newAppender);

		virtual void doAppend(const spi::LoggingEventPtr& event,
			log4cxx::helpers::Pool& pool1);

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

		/**
		Close this <code>AsyncAppender</code> by interrupting the
		dispatcher thread which will process all pending events before
		exiting.
		*/
		void close();

		/**
		 * Get iterator over attached appenders.
		 * @return list of all attached appenders.
		*/
		AppenderList getAllAppenders() const;

		/**
		 * Get appender by name.
		 *
		 * @param name name, may not be null.
		 * @return matching appender or null.
		*/
		AppenderPtr getAppender(const LogString& name) const;

		/**
		 * Gets whether the location of the logging request call
		 * should be captured.
		 *
		 * @return the current value of the <b>LocationInfo</b> option.
		*/
		bool getLocationInfo() const;
		/**
		* Determines if specified appender is attached.
		* @param appender appender.
		* @return true if attached.
		*/
        bool isAttached(const AppenderPtr appender) const;

		virtual bool requiresLayout() const;

		/**
		 * Removes and closes all attached appenders.
		*/
		void removeAllAppenders();

		/**
		 * Removes an appender.
		 * @param appender appender to remove.
		*/
        void removeAppender(const AppenderPtr appender);
		/**
		* Remove appender by name.
		* @param name name.
		*/
		void removeAppender(const LogString& name);

		/**
		* The <b>LocationInfo</b> attribute is provided for compatibility
		* with log4j and has no effect on the log output.
		* @param flag new value.
		*/
		void setLocationInfo(bool flag);

		/**
		* The <b>BufferSize</b> option takes a non-negative integer value.
		* This integer value determines the maximum size of the bounded
		* buffer.
		* */
		void setBufferSize(int size);

		/**
		 * Gets the current buffer size.
		 * @return the current value of the <b>BufferSize</b> option.
		*/
		int getBufferSize() const;

		/**
		 * Sets whether appender should wait if there is no
		 * space available in the event buffer or immediately return.
		 *
		 * @param value true if appender should wait until available space in buffer.
		 */
		void setBlocking(bool value);

		/**
		 * Gets whether appender should block calling thread when buffer is full.
		 * If false, messages will be counted by logger and a summary
		 * message appended after the contents of the buffer have been appended.
		 *
		 * @return true if calling thread will be blocked when buffer is full.
		 */
		bool getBlocking() const;


		/**
		 * Set appender properties by name.
		 * @param option property name.
		 * @param value property value.
		 */
		void setOption(const LogString& option, const LogString& value);


	private:
		AsyncAppender(const AsyncAppender&);
		AsyncAppender& operator=(const AsyncAppender&);
		/**
		 * The default buffer size is set to 128 events.
		*/
		enum { DEFAULT_BUFFER_SIZE = 128 };

		/**
		 * Event buffer.
		*/
#if defined(NON_BLOCKING)
		boost::lockfree::queue<log4cxx::spi::LoggingEvent* > buffer;
		std::atomic<size_t> discardedCount;
#else
		LoggingEventList buffer;
#endif

		/**
		 *  Mutex used to guard access to buffer and discardMap.
		 */
		log4cxx::mutex bufferMutex;

#if defined(NON_BLOCKING)
		::log4cxx::helpers::Semaphore bufferNotFull;
		::log4cxx::helpers::Semaphore bufferNotEmpty;
#else
		log4cxx::condition_variable bufferNotFull;
		log4cxx::condition_variable bufferNotEmpty;
#endif
		class DiscardSummary
		{
			private:
				/**
				 * First event of the highest severity.
				*/
				::log4cxx::spi::LoggingEventPtr maxEvent;

				/**
				* Total count of messages discarded.
				*/
				int count;

			public:
				/**
				 * Create new instance.
				 *
				 * @param event event, may not be null.
				*/
				DiscardSummary(const ::log4cxx::spi::LoggingEventPtr& event);
				/** Copy constructor.  */
				DiscardSummary(const DiscardSummary& src);
				/** Assignment operator. */
				DiscardSummary& operator=(const DiscardSummary& src);

				/**
				 * Add discarded event to summary.
				 *
				 * @param event event, may not be null.
				*/
				void add(const ::log4cxx::spi::LoggingEventPtr& event);

				/**
				 * Create event with summary information.
				 *
				 * @return new event.
				 */
				::log4cxx::spi::LoggingEventPtr createEvent(::log4cxx::helpers::Pool& p);

				static
				::log4cxx::spi::LoggingEventPtr createEvent(::log4cxx::helpers::Pool& p,
					size_t discardedCount);
		};

		/**
		  * Map of DiscardSummary objects keyed by logger name.
		*/
		typedef std::map<LogString, DiscardSummary> DiscardMap;
		DiscardMap* discardMap;

		/**
		 * Buffer size.
		*/
		int bufferSize;

		/**
		 * Nested appenders.
		*/
		helpers::AppenderAttachableImplPtr appenders;

		/**
		 *  Dispatcher.
		 */
		log4cxx::thread dispatcher;

		/**
		 * Should location info be included in dispatched messages.
		*/
		bool locationInfo;

		/**
		 * Does appender block when buffer is full.
		*/
		bool blocking;

		/**
		 *  Dispatch routine.
		 */
		void dispatch();

}; // class AsyncAppender
LOG4CXX_PTR_DEF(AsyncAppender);
}  //  namespace log4cxx

#if defined(_MSC_VER)
	#pragma warning ( pop )
#endif


#endif//  _LOG4CXX_ASYNC_APPENDER_H

