/*
 * 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.
 */
#include <log4cxx/logstring.h>
#if !defined(LOG4CXX)
	#define LOG4CXX 1
#endif
#include <log4cxx/helpers/aprinitializer.h>
#include <apr_pools.h>
#include <apr_atomic.h>
#include <assert.h>
#include <log4cxx/helpers/threadspecificdata.h>
#include <apr_thread_mutex.h>
#include <apr_thread_proc.h>
#include <log4cxx/helpers/filewatchdog.h>

using namespace log4cxx::helpers;
using namespace log4cxx;

bool APRInitializer::isDestructed = false;


namespace
{
extern "C" void tlsDestruct(void* ptr)
{
	delete ((ThreadSpecificData*) ptr);
}
}

APRInitializer::APRInitializer() : p(0), startTime(0), tlsKey(0)
{
	apr_initialize();
	apr_pool_create(&p, NULL);
	apr_atomic_init(p);
	startTime = apr_time_now();
#if APR_HAS_THREADS
	apr_status_t stat = apr_threadkey_private_create(&tlsKey, tlsDestruct, p);
    assert(stat == APR_SUCCESS);
	assert(stat == APR_SUCCESS);
#endif
}

APRInitializer::~APRInitializer()
{
	{
#if APR_HAS_THREADS
		log4cxx::unique_lock<log4cxx::mutex> lock(mutex);
		apr_threadkey_private_delete(tlsKey);
#endif

		for (std::list<FileWatchdog*>::iterator iter = watchdogs.begin();
			iter != watchdogs.end();
			iter++)
		{
			delete *iter;
		}
	}

	// TODO LOGCXX-322
#ifndef APR_HAS_THREADS
	apr_terminate();
#endif
	isDestructed = true;
}

APRInitializer& APRInitializer::getInstance()
{
	static APRInitializer init;
	return init;
}


log4cxx_time_t APRInitializer::initialize()
{
	return getInstance().startTime;
}

apr_pool_t* APRInitializer::getRootPool()
{
	return getInstance().p;
}

apr_threadkey_t* APRInitializer::getTlsKey()
{
	return getInstance().tlsKey;
}

void APRInitializer::registerCleanup(FileWatchdog* watchdog)
{
	APRInitializer& instance(getInstance());
#if APR_HAS_THREADS
	log4cxx::unique_lock<log4cxx::mutex> lock(instance.mutex);
#endif
	instance.watchdogs.push_back(watchdog);
}

void APRInitializer::unregisterCleanup(FileWatchdog* watchdog)
{
	APRInitializer& instance(getInstance());
#if APR_HAS_THREADS
	log4cxx::unique_lock<log4cxx::mutex> lock(instance.mutex);
#endif

	for (std::list<FileWatchdog*>::iterator iter = instance.watchdogs.begin();
		iter != instance.watchdogs.end();
		iter++)
	{
		if (*iter == watchdog)
		{
			instance.watchdogs.erase(iter);
			return;
		}
	}
}

