blob: 04b4c4126b0a2b9a84914c16505f7d2716a4c550 [file] [log] [blame]
/*
* 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
}