/*
 * 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/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)
	{
        FixedWindowRollingPolicyPtr fwrp = FixedWindowRollingPolicyPtr(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 = log4cxx::cast<TriggeringPolicy>(rollingPolicy);

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

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

	{
		log4cxx::unique_lock<log4cxx::shared_mutex> lock(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);
				}

				fileName = rollover1->getActiveFileName();
				fileAppend = 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::activateOptionsInternal(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)
{
	log4cxx::unique_lock<log4cxx::shared_mutex> lock(mutex);
	return rolloverInternal(p);
}

bool RollingFileAppenderSkeleton::rolloverInternal(Pool& p)
{
	//
	//   can't roll without a policy
	//
	if (rollingPolicy != NULL)
	{

		{

#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);
								}

								setFileInternal(
									rollover1->getActiveFileName(), rollover1->getAppend(),
									bufferedIO, bufferSize, p);
							}
							else
							{
								setFileInternal(
									rollover1->getActiveFileName(), true, bufferedIO, bufferSize, p);
							}
						}
						else
						{
							closeWriter();
							setFileInternal(rollover1->getActiveFileName());
							// Call activateOptions to create any intermediate directories(if required)
							FileAppender::activateOptionsInternal(p);
							OutputStreamPtr os(new FileOutputStream(
									rollover1->getActiveFileName(), rollover1->getAppend()));
							WriterPtr newWriter(createWriter(os));
							setWriterInternal(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));
			rolloverInternal(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;
}
