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

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

#ifdef LOG4CXX_MULTI_PROCESS
	#include <apr_portable.h>
	#include <libgen.h>
	#include <apr_file_io.h>
	#include <apr_atomic.h>
	#include <apr_mmap.h>
	#ifndef MAX_FILE_LEN
		#define MAX_FILE_LEN 2048
	#endif
	#include <log4cxx/pattern/filedatepatternconverter.h>
	#include <log4cxx/helpers/date.h>
#endif

#include <log4cxx/rolling/rollingfileappender.h>
#include <log4cxx/helpers/loglog.h>
#include <log4cxx/helpers/synchronized.h>
#include <log4cxx/rolling/rolloverdescription.h>
#include <log4cxx/helpers/fileoutputstream.h>
#include <log4cxx/helpers/bytebuffer.h>
#include <log4cxx/rolling/fixedwindowrollingpolicy.h>
#include <log4cxx/rolling/manualtriggeringpolicy.h>

using namespace log4cxx;
using namespace log4cxx::rolling;
using namespace log4cxx::helpers;
using namespace log4cxx::spi;


IMPLEMENT_LOG4CXX_OBJECT(RollingFileAppenderSkeleton)
IMPLEMENT_LOG4CXX_OBJECT(RollingFileAppender)


/**
 * Construct a new instance.
 */
RollingFileAppenderSkeleton::RollingFileAppenderSkeleton() : _event(NULL)
{
}

RollingFileAppender::RollingFileAppender()
{
}

/**
 * Prepare instance of use.
 */
void RollingFileAppenderSkeleton::activateOptions(Pool& p)
{
	if (rollingPolicy == NULL)
	{
		FixedWindowRollingPolicy* fwrp = new FixedWindowRollingPolicy();
		fwrp->setFileNamePattern(getFile() + LOG4CXX_STR(".%i"));
		rollingPolicy = fwrp;
	}

	//
	//  if no explicit triggering policy and rolling policy is both.
	//
	if (triggeringPolicy == NULL)
	{
		TriggeringPolicyPtr trig(rollingPolicy);

		if (trig != NULL)
		{
			triggeringPolicy = trig;
		}
	}

	if (triggeringPolicy == NULL)
	{
		triggeringPolicy = new ManualTriggeringPolicy();
	}

	{
		LOCK_W sync(mutex);
		triggeringPolicy->activateOptions(p);
		rollingPolicy->activateOptions(p);

		try
		{
			RolloverDescriptionPtr rollover1 =
				rollingPolicy->initialize(getFile(), getAppend(), p);

			if (rollover1 != NULL)
			{
				ActionPtr syncAction(rollover1->getSynchronous());

				if (syncAction != NULL)
				{
					syncAction->execute(p);
				}

				setFile(rollover1->getActiveFileName());
				setAppend(rollover1->getAppend());

				//
				//  async action not yet implemented
				//
				ActionPtr asyncAction(rollover1->getAsynchronous());

				if (asyncAction != NULL)
				{
					asyncAction->execute(p);
				}
			}

			File activeFile;
			activeFile.setPath(getFile());

			if (getAppend())
			{
				fileLength = activeFile.length(p);
			}
			else
			{
				fileLength = 0;
			}

			FileAppender::activateOptions(p);
		}
		catch (std::exception&)
		{
			LogLog::warn(
				LogString(LOG4CXX_STR("Exception will initializing RollingFileAppender named "))
				+ getName());
		}
	}
}

#ifdef LOG4CXX_MULTI_PROCESS
void RollingFileAppenderSkeleton::releaseFileLock(apr_file_t* lock_file)
{
	if (lock_file)
	{
		apr_status_t stat = apr_file_unlock(lock_file);

		if (stat != APR_SUCCESS)
		{
			LogLog::warn(LOG4CXX_STR("flock: unlock failed"));
		}

		apr_file_close(lock_file);
		lock_file = NULL;
	}
}
#endif
/**
   Implements the usual roll over behaviour.

   <p>If <code>MaxBackupIndex</code> is positive, then files
   {<code>File.1</code>, ..., <code>File.MaxBackupIndex -1</code>}
   are renamed to {<code>File.2</code>, ...,
   <code>File.MaxBackupIndex</code>}. Moreover, <code>File</code> is
   renamed <code>File.1</code> and closed. A new <code>File</code> is
   created to receive further log output.

   <p>If <code>MaxBackupIndex</code> is equal to zero, then the
   <code>File</code> is truncated with no backup files created.

 * @return true if rollover performed.
 */
bool RollingFileAppenderSkeleton::rollover(Pool& p)
{
	//
	//   can't roll without a policy
	//
	if (rollingPolicy != NULL)
	{

		{
			LOCK_W sync(mutex);

#ifdef LOG4CXX_MULTI_PROCESS
			std::string fileName(getFile());
			RollingPolicyBase* basePolicy = dynamic_cast<RollingPolicyBase* >(&(*rollingPolicy));
			apr_time_t n = apr_time_now();
			ObjectPtr obj(new Date(n));
			LogString fileNamePattern;

			if (basePolicy)
			{
				if (basePolicy->getPatternConverterList().size())
				{
					(*(basePolicy->getPatternConverterList().begin()))->format(obj, fileNamePattern, p);
					fileName = std::string(fileNamePattern);
				}
			}

			bool bAlreadyRolled = true;
			char szDirName[MAX_FILE_LEN] = {'\0'};
			char szBaseName[MAX_FILE_LEN] = {'\0'};
			char szUid[MAX_FILE_LEN] = {'\0'};
			memcpy(szDirName, fileName.c_str(), fileName.size() > MAX_FILE_LEN ? MAX_FILE_LEN : fileName.size());
			memcpy(szBaseName, fileName.c_str(), fileName.size() > MAX_FILE_LEN ? MAX_FILE_LEN : fileName.size());
			apr_uid_t uid;
			apr_gid_t groupid;
			apr_status_t stat = apr_uid_current(&uid, &groupid, pool.getAPRPool());

			if (stat == APR_SUCCESS)
			{
				snprintf(szUid, MAX_FILE_LEN, "%u", uid);
			}

			const std::string lockname = std::string(::dirname(szDirName)) + "/." + ::basename(szBaseName) + szUid + ".lock";
			apr_file_t* lock_file;
			stat = apr_file_open(&lock_file, lockname.c_str(), APR_CREATE | APR_READ | APR_WRITE, APR_OS_DEFAULT, p.getAPRPool());

			if (stat != APR_SUCCESS)
			{
				std::string err = "lockfile return error: open lockfile failed. ";
				err += (strerror(errno));
				LogLog::warn(LOG4CXX_STR(err.c_str()));
				bAlreadyRolled = false;
				lock_file = NULL;
			}
			else
			{
				stat = apr_file_lock(lock_file, APR_FLOCK_EXCLUSIVE);

				if (stat != APR_SUCCESS)
				{
					std::string err = "apr_file_lock: lock failed. ";
					err += (strerror(errno));
					LogLog::warn(LOG4CXX_STR(err.c_str()));
					bAlreadyRolled = false;
				}
				else
				{
					if (_event)
					{
						triggeringPolicy->isTriggeringEvent(this, *_event, getFile(), getFileLength());
					}
				}
			}

			if (bAlreadyRolled)
			{
				apr_finfo_t finfo1, finfo2;
				apr_status_t st1, st2;
				apr_file_t* _fd = getWriter()->getOutPutStreamPtr()->getFileOutPutStreamPtr().getFilePtr();
				st1 = apr_file_info_get(&finfo1, APR_FINFO_IDENT, _fd);

				if (st1 != APR_SUCCESS)
				{
					LogLog::warn(LOG4CXX_STR("apr_file_info_get failed"));
				}

				st2 = apr_stat(&finfo2, std::string(getFile()).c_str(), APR_FINFO_IDENT, p.getAPRPool());

				if (st2 != APR_SUCCESS)
				{
					LogLog::warn(LOG4CXX_STR("apr_stat failed."));
				}

				bAlreadyRolled = ((st1 == APR_SUCCESS) && (st2 == APR_SUCCESS)
						&& ((finfo1.device != finfo2.device) || (finfo1.inode != finfo2.inode)));
			}

			if (!bAlreadyRolled)
			{
#endif

				try
				{
					RolloverDescriptionPtr rollover1(rollingPolicy->rollover(this->getFile(), this->getAppend(), p));

					if (rollover1 != NULL)
					{
						if (rollover1->getActiveFileName() == getFile())
						{
							closeWriter();

							bool success = true;

							if (rollover1->getSynchronous() != NULL)
							{
								success = false;

								try
								{
									success = rollover1->getSynchronous()->execute(p);
								}
								catch (std::exception&)
								{
									LogLog::warn(LOG4CXX_STR("Exception on rollover"));
								}
							}

							if (success)
							{
								if (rollover1->getAppend())
								{
									fileLength = File().setPath(rollover1->getActiveFileName()).length(p);
								}
								else
								{
									fileLength = 0;
								}

								//
								//  async action not yet implemented
								//
								ActionPtr asyncAction(rollover1->getAsynchronous());

								if (asyncAction != NULL)
								{
									asyncAction->execute(p);
								}

								setFile(
									rollover1->getActiveFileName(), rollover1->getAppend(),
									bufferedIO, bufferSize, p);
							}
							else
							{
								setFile(
									rollover1->getActiveFileName(), true, bufferedIO, bufferSize, p);
							}
						}
						else
						{
							closeWriter();
							setFile(rollover1->getActiveFileName());
							// Call activateOptions to create any intermediate directories(if required)
							FileAppender::activateOptions(p);
							OutputStreamPtr os(new FileOutputStream(
									rollover1->getActiveFileName(), rollover1->getAppend()));
							WriterPtr newWriter(createWriter(os));
							setWriter(newWriter);

							bool success = true;

							if (rollover1->getSynchronous() != NULL)
							{
								success = false;

								try
								{
									success = rollover1->getSynchronous()->execute(p);
								}
								catch (std::exception&)
								{
									LogLog::warn(LOG4CXX_STR("Exception during rollover"));
								}
							}

							if (success)
							{
								if (rollover1->getAppend())
								{
									fileLength = File().setPath(rollover1->getActiveFileName()).length(p);
								}
								else
								{
									fileLength = 0;
								}

								//
								//   async action not yet implemented
								//
								ActionPtr asyncAction(rollover1->getAsynchronous());

								if (asyncAction != NULL)
								{
									asyncAction->execute(p);
								}
							}

							writeHeader(p);
						}

#ifdef LOG4CXX_MULTI_PROCESS
						releaseFileLock(lock_file);
#endif
						return true;
					}
				}
				catch (std::exception&)
				{
					LogLog::warn(LOG4CXX_STR("Exception during rollover"));
				}

#ifdef LOG4CXX_MULTI_PROCESS
			}
			else
			{
				reopenLatestFile(p);
			}

			releaseFileLock(lock_file);
#endif
		}
	}

	return false;
}

#ifdef LOG4CXX_MULTI_PROCESS
/**
 * re-open current file when its own handler has been renamed
 */
void RollingFileAppenderSkeleton::reopenLatestFile(Pool& p)
{
	closeWriter();
	OutputStreamPtr os(new FileOutputStream(getFile(), true));
	WriterPtr newWriter(createWriter(os));
	setFile(getFile());
	setWriter(newWriter);
	fileLength = File().setPath(getFile()).length(p);
	writeHeader(p);
}

#endif

/**
 * {@inheritDoc}
*/
void RollingFileAppenderSkeleton::subAppend(const LoggingEventPtr& event, Pool& p)
{
	// The rollover check must precede actual writing. This is the
	// only correct behavior for time driven triggers.
	if (
		triggeringPolicy->isTriggeringEvent(
			this, event, getFile(), getFileLength()))
	{
		//
		//   wrap rollover request in try block since
		//    rollover may fail in case read access to directory
		//    is not provided.  However appender should still be in good
		//     condition and the append should still happen.
		try
		{
			_event = &(const_cast<LoggingEventPtr&>(event));
			rollover(p);
		}
		catch (std::exception&)
		{
			LogLog::warn(LOG4CXX_STR("Exception during rollover attempt."));
		}
	}

#ifdef LOG4CXX_MULTI_PROCESS
	//do re-check before every write
	//
	apr_finfo_t finfo1, finfo2;
	apr_status_t st1, st2;
	apr_file_t* _fd = getWriter()->getOutPutStreamPtr()->getFileOutPutStreamPtr().getFilePtr();
	st1 = apr_file_info_get(&finfo1, APR_FINFO_IDENT, _fd);

	if (st1 != APR_SUCCESS)
	{
		LogLog::warn(LOG4CXX_STR("apr_file_info_get failed"));
	}

	st2 = apr_stat(&finfo2, std::string(getFile()).c_str(), APR_FINFO_IDENT, p.getAPRPool());

	if (st2 != APR_SUCCESS)
	{
		std::string err = "apr_stat failed. file:" + std::string(getFile());
		LogLog::warn(LOG4CXX_STR(err.c_str()));
	}

	bool bAlreadyRolled = ((st1 == APR_SUCCESS) && (st2 == APR_SUCCESS)
			&& ((finfo1.device != finfo2.device) || (finfo1.inode != finfo2.inode)));

	if (bAlreadyRolled)
	{
		reopenLatestFile(p);
	}

#endif

	FileAppender::subAppend(event, p);
}

/**
 * Get rolling policy.
 * @return rolling policy.
 */
RollingPolicyPtr RollingFileAppenderSkeleton::getRollingPolicy() const
{
	return rollingPolicy;
}

/**
 * Get triggering policy.
 * @return triggering policy.
 */
TriggeringPolicyPtr RollingFileAppenderSkeleton::getTriggeringPolicy() const
{
	return triggeringPolicy;
}

/**
 * Sets the rolling policy.
 * @param policy rolling policy.
 */
void RollingFileAppenderSkeleton::setRollingPolicy(const RollingPolicyPtr& policy)
{
	rollingPolicy = policy;
}

/**
 * Set triggering policy.
 * @param policy triggering policy.
 */
void RollingFileAppenderSkeleton::setTriggeringPolicy(const TriggeringPolicyPtr& policy)
{
	triggeringPolicy = policy;
}

/**
 * Close appender.  Waits for any asynchronous file compression actions to be completed.
 */
void RollingFileAppenderSkeleton::close()
{
	FileAppender::close();
}

namespace log4cxx
{
namespace rolling
{
/**
 * Wrapper for OutputStream that will report all write
 * operations back to this class for file length calculations.
 */
class CountingOutputStream : public OutputStream
{
		/**
		 * Wrapped output stream.
		 */
	private:
		OutputStreamPtr os;

		/**
		 * Rolling file appender to inform of stream writes.
		 */
		RollingFileAppenderSkeleton* rfa;

	public:
		/**
		 * Constructor.
		 * @param os output stream to wrap.
		 * @param rfa rolling file appender to inform.
		 */
		CountingOutputStream(
			OutputStreamPtr& os1, RollingFileAppenderSkeleton* rfa1) :
			os(os1), rfa(rfa1)
		{
		}

		/**
		 * {@inheritDoc}
		 */
		void close(Pool& p)
		{
			os->close(p);
			rfa = 0;
		}

		/**
		 * {@inheritDoc}
		 */
		void flush(Pool& p)
		{
			os->flush(p);
		}

		/**
		 * {@inheritDoc}
		 */
		void write(ByteBuffer& buf, Pool& p)
		{
			os->write(buf, p);

			if (rfa != 0)
			{
#ifndef LOG4CXX_MULTI_PROCESS
				rfa->incrementFileLength(buf.limit());
#else
				rfa->setFileLength(File().setPath(rfa->getFile()).length(p));
#endif
			}
		}

#ifdef LOG4CXX_MULTI_PROCESS
		OutputStream& getFileOutPutStreamPtr()
		{
			return *os;
		}
#endif
};
}
}

/**
   Returns an OutputStreamWriter when passed an OutputStream.  The
   encoding used will depend on the value of the
   <code>encoding</code> property.  If the encoding value is
   specified incorrectly the writer will be opened using the default
   system encoding (an error message will be printed to the loglog.
 @param os output stream, may not be null.
 @return new writer.
 */
WriterPtr RollingFileAppenderSkeleton::createWriter(OutputStreamPtr& os)
{
	OutputStreamPtr cos(new CountingOutputStream(os, this));
	return FileAppender::createWriter(cos);
}

/**
 * Get byte length of current active log file.
 * @return byte length of current active log file.
 */
size_t RollingFileAppenderSkeleton::getFileLength() const
{
	return fileLength;
}

#ifdef LOG4CXX_MULTI_PROCESS
void RollingFileAppenderSkeleton::setFileLength(size_t length)
{
	fileLength = length;
}
#endif

/**
 * Increments estimated byte length of current active log file.
 * @param increment additional bytes written to log file.
 */
void RollingFileAppenderSkeleton::incrementFileLength(size_t increment)
{
	fileLength += increment;
}
