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

using namespace log4cxx;
using namespace log4cxx::helpers;


ThreadSpecificData::ThreadSpecificData()
    : ndcStack(), mdcMap()
{
}

ThreadSpecificData::~ThreadSpecificData()
{
}


log4cxx::NDC::Stack& ThreadSpecificData::getStack()
{
    return ndcStack;
}

log4cxx::MDC::Map& ThreadSpecificData::getMap()
{
    return mdcMap;
}

ThreadSpecificData& ThreadSpecificData::getDataNoThreads()
{
    static ThreadSpecificData noThreadData;
    return noThreadData;
}

ThreadSpecificData* ThreadSpecificData::getCurrentData()
{
#if APR_HAS_THREADS
    void* pData = NULL;
    apr_threadkey_private_get(&pData, APRInitializer::getTlsKey());
    return (ThreadSpecificData*) pData;
#else
    return &getDataNoThreads();
#endif
}

void ThreadSpecificData::recycle()
{
#if APR_HAS_THREADS

    if (ndcStack.empty() && mdcMap.empty())
    {
        void* pData = NULL;
        apr_status_t stat = apr_threadkey_private_get(&pData, APRInitializer::getTlsKey());

        if (stat == APR_SUCCESS && pData == this)
        {
            stat = apr_threadkey_private_set(0, APRInitializer::getTlsKey());

            if (stat == APR_SUCCESS)
            {
                delete this;
            }
        }
    }

#endif
}

void ThreadSpecificData::put(const LogString& key, const LogString& val)
{
    ThreadSpecificData* data = getCurrentData();

    if (data == 0)
    {
        data = createCurrentData();
    }

    if (data != 0)
    {
        data->getMap()[key] = val;
    }
}




void ThreadSpecificData::push(const LogString& val)
{
    ThreadSpecificData* data = getCurrentData();

    if (data == 0)
    {
        data = createCurrentData();
    }

    if (data != 0)
    {
        NDC::Stack& stack = data->getStack();

        if (stack.empty())
        {
            stack.push(NDC::DiagnosticContext(val, val));
        }
        else
        {
            LogString fullMessage(stack.top().second);
            fullMessage.append(1, (logchar) 0x20);
            fullMessage.append(val);
            stack.push(NDC::DiagnosticContext(val, fullMessage));
        }
    }
}

void ThreadSpecificData::inherit(const NDC::Stack& src)
{
    ThreadSpecificData* data = getCurrentData();

    if (data == 0)
    {
        data = createCurrentData();
    }

    if (data != 0)
    {
        data->getStack() = src;
    }
}



ThreadSpecificData* ThreadSpecificData::createCurrentData()
{
#if APR_HAS_THREADS
    ThreadSpecificData* newData = new ThreadSpecificData();
    apr_status_t stat = apr_threadkey_private_set(newData, APRInitializer::getTlsKey());

    if (stat != APR_SUCCESS)
    {
        delete newData;
        newData = NULL;
    }

    return newData;
#else
    return 0;
#endif
}
