Coverage Report

Created: 2025-07-18 06:17

/src/logging-log4cxx/src/main/cpp/aprinitializer.cpp
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Licensed to the Apache Software Foundation (ASF) under one or more
3
 * contributor license agreements.  See the NOTICE file distributed with
4
 * this work for additional information regarding copyright ownership.
5
 * The ASF licenses this file to You under the Apache License, Version 2.0
6
 * (the "License"); you may not use this file except in compliance with
7
 * the License.  You may obtain a copy of the License at
8
 *
9
 *      http://www.apache.org/licenses/LICENSE-2.0
10
 *
11
 * Unless required by applicable law or agreed to in writing, software
12
 * distributed under the License is distributed on an "AS IS" BASIS,
13
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
 * See the License for the specific language governing permissions and
15
 * limitations under the License.
16
 */
17
#include <log4cxx/logstring.h>
18
#if !defined(LOG4CXX)
19
  #define LOG4CXX 1
20
#endif
21
#include <log4cxx/helpers/aprinitializer.h>
22
#include <apr_pools.h>
23
#include <assert.h>
24
#include <log4cxx/helpers/threadspecificdata.h>
25
#include <apr_thread_proc.h>
26
#include <log4cxx/helpers/date.h>
27
#include <log4cxx/helpers/loglog.h>
28
#include <vector>
29
#include <algorithm>
30
#include <mutex>
31
32
using namespace LOG4CXX_NS::helpers;
33
using namespace LOG4CXX_NS;
34
35
#if LOG4CXX_ABI_VERSION <= 15
36
bool APRInitializer::isDestructed = false;
37
#endif
38
39
using IdentifiedObject = std::pair<size_t, ObjectPtr>;
40
41
struct APRInitializer::APRInitializerPrivate{
42
  APRInitializerPrivate() :
43
1
    p(0),
44
1
    startTime(0),
45
1
    tlsKey(0){
46
47
1
  }
48
  ~APRInitializerPrivate()
49
1
  {
50
    // Delete in reverse order
51
2
    while (!objects.empty())
52
1
      objects.pop_back();
53
1
  }
54
55
  apr_pool_t* p;
56
  std::mutex mutex;
57
  log4cxx_time_t startTime;
58
  apr_threadkey_t* tlsKey;
59
  std::vector<IdentifiedObject> objects;
60
};
61
62
namespace
63
{
64
void tlsDestructImpl(void* ptr)
65
0
{
66
0
  delete ((ThreadSpecificData*) ptr);
67
0
}
68
}
69
70
#if LOG4CXX_ABI_VERSION <= 15
71
extern "C" void tlsDestruct(void* ptr)
72
0
{
73
0
  tlsDestructImpl(ptr);
74
0
}
75
#endif
76
77
namespace
78
{
79
// The first object created and the last object destroyed
80
struct apr_environment
81
{
82
    apr_environment()
83
1
    {
84
1
        apr_initialize();
85
1
    }
86
    ~apr_environment()
87
1
    {
88
1
        apr_terminate();
89
1
    }
90
};
91
92
}
93
94
95
APRInitializer::APRInitializer() :
96
1
  m_priv(std::make_unique<APRInitializerPrivate>())
97
1
{
98
1
  apr_pool_create(&m_priv->p, NULL);
99
1
  m_priv->startTime = Date::currentTime();
100
1
#if APR_HAS_THREADS
101
1
  apr_status_t stat = apr_threadkey_private_create(&m_priv->tlsKey, tlsDestructImpl, m_priv->p);
102
1
  assert(stat == APR_SUCCESS);
103
1
#endif
104
1
}
105
106
APRInitializer::~APRInitializer()
107
1
{
108
1
#if LOG4CXX_ABI_VERSION <= 15
109
1
  isDestructed = true;
110
1
#endif
111
1
#if APR_HAS_THREADS
112
1
  std::lock_guard<std::mutex> lock(m_priv->mutex);
113
1
  apr_threadkey_private_delete(m_priv->tlsKey);
114
1
#endif
115
1
}
116
117
#if LOG4CXX_ABI_VERSION <= 15
118
void APRInitializer::unregisterAll()
119
0
{
120
0
}
121
#endif
122
123
APRInitializer& APRInitializer::getInstance()
124
285
{
125
285
  static WideLife<apr_environment> env;
126
285
  static WideLife<APRInitializer> init;
127
285
  return init;
128
285
}
129
130
131
#if LOG4CXX_ABI_VERSION <= 15
132
log4cxx_time_t APRInitializer::initialize()
133
0
{
134
0
  return getInstance().m_priv->startTime;
135
0
}
136
#endif
137
138
log4cxx_time_t APRInitializer::getStartTime()
139
0
{
140
0
  return getInstance().m_priv->startTime;
141
0
}
142
143
apr_pool_t* APRInitializer::getRootPool()
144
3
{
145
3
  return getInstance().m_priv->p;
146
3
}
147
148
apr_threadkey_t* APRInitializer::getTlsKey()
149
0
{
150
0
  return getInstance().m_priv->tlsKey;
151
0
}
152
153
#if LOG4CXX_ABI_VERSION <= 15
154
void APRInitializer::registerCleanup(FileWatchdog* watchdog)
155
0
{
156
0
}
157
158
void APRInitializer::unregisterCleanup(FileWatchdog* watchdog)
159
0
{
160
0
}
161
#endif
162
163
void APRInitializer::addObject(size_t key, const ObjectPtr& pObject)
164
0
{
165
0
  std::lock_guard<std::mutex> lock(m_priv->mutex);
166
0
  auto pItem = std::find_if(m_priv->objects.begin(), m_priv->objects.end()
167
0
    , [key](const IdentifiedObject& item) { return item.first == key; }
168
0
    );
169
0
  if (m_priv->objects.end() != pItem)
170
0
    pItem->second = pObject;
171
0
  else
172
0
    m_priv->objects.emplace_back(key, pObject);
173
0
}
174
175
const ObjectPtr& APRInitializer::findOrAddObject(size_t key, std::function<ObjectPtr()> creator)
176
282
{
177
282
  std::lock_guard<std::mutex> lock(m_priv->mutex);
178
282
  if (m_priv->objects.empty())
179
1
  {
180
    // Ensure the internal logger has a longer life than other Log4cxx static data
181
1
    LogLog::debug(LOG4CXX_STR("Started"));
182
1
  }
183
282
  auto pItem = std::find_if(m_priv->objects.begin(), m_priv->objects.end()
184
282
    , [key](const IdentifiedObject& item) { return item.first == key; }
185
282
    );
186
282
  if (m_priv->objects.end() != pItem)
187
281
    return pItem->second;
188
1
  m_priv->objects.emplace_back(key, creator());
189
1
  return m_priv->objects.back().second;
190
282
}