bool MultiprocessRollingFileAppender::rolloverInternal()

in src/main/cpp/multiprocessrollingfileappender.cpp [209:456]


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

		{
			LogString fileName(getFile());
			RollingPolicyBasePtr basePolicy = log4cxx::cast<RollingPolicyBase>(_priv->rollingPolicy);
			apr_time_t n = apr_time_now();
			ObjectPtr obj = std::make_shared<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, p.getAPRPool());

			if (stat == APR_SUCCESS)
			{
#ifdef WIN32
				snprintf(szUid, MAX_FILE_LEN, "%p", uid);
#else
				snprintf(szUid, MAX_FILE_LEN, "%u", (unsigned int)uid);
#endif
			}

			log4cxx::filesystem::path path = szDirName;
			const auto lockname = path.parent_path() / (path.filename().string() + szUid + ".lock");
			apr_file_t* lock_file;
			stat = apr_file_open(&lock_file, lockname.string().c_str(), APR_CREATE | APR_READ | APR_WRITE, APR_OS_DEFAULT, p.getAPRPool());

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

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

			if (bAlreadyRolled)
			{
				apr_finfo_t finfo1, finfo2;
				apr_status_t st1, st2;
				const WriterPtr writer = getWriter();
				const FileOutputStreamPtr fos = log4cxx::cast<FileOutputStream>( writer );
				if( !fos ){
					LogLog::error( LOG4CXX_STR("Can't cast writer to FileOutputStream") );
					return false;
				}
				apr_file_t* _fd = fos->getFilePtr();
				st1 = apr_file_info_get(&finfo1, APR_FINFO_IDENT, _fd);

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

				LogString fname = getFile();
				st2 = apr_stat(&finfo2, fname.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)
			{

				try
				{
					RolloverDescriptionPtr rollover1(_priv->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& ex)
								{
									LogLog::warn(LOG4CXX_STR("Exception on rollover"));
									LogString exmsg;
									log4cxx::helpers::Transcoder::decode(ex.what(), exmsg);
									_priv->errorHandler->error(exmsg, ex, 0);
								}
							}

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

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

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

								setFileInternal(
									rollover1->getActiveFileName(), rollover1->getAppend(),
									_priv->bufferedIO, _priv->bufferSize, p);
							}
							else
							{
								setFileInternal(
									rollover1->getActiveFileName(), true, _priv->bufferedIO, _priv->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& ex)
								{
									LogLog::warn(LOG4CXX_STR("Exception during rollover"));
									LogString exmsg;
									log4cxx::helpers::Transcoder::decode(ex.what(), exmsg);
									_priv->errorHandler->error(exmsg, ex, 0);
								}
							}

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

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

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

							writeHeader(p);
						}

						releaseFileLock(lock_file);
						return true;
					}
				}
				catch (std::exception& ex)
				{
					LogLog::warn(LOG4CXX_STR("Exception during rollover"));
					LogString exmsg;
					log4cxx::helpers::Transcoder::decode(ex.what(), exmsg);
					_priv->errorHandler->error(exmsg, ex, 0);
				}

			}
			else
			{
				reopenLatestFile(p);
			}

			releaseFileLock(lock_file);
		}
	}

	return false;
}