Coverage Report

Created: 2026-04-27 06:50

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/logging-log4cxx/src/main/cpp/hierarchy.cpp
Line
Count
Source
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
18
#include <log4cxx/hierarchy.h>
19
#if LOG4CXX_ABI_VERSION <= 15
20
#include <log4cxx/defaultloggerfactory.h>
21
#endif
22
#include <log4cxx/helpers/loglog.h>
23
#include <log4cxx/appender.h>
24
#include <log4cxx/helpers/stringhelper.h>
25
#include <log4cxx/spi/rootlogger.h>
26
#include <algorithm>
27
#include <map>
28
#include <mutex>
29
#include <vector>
30
31
32
using namespace LOG4CXX_NS;
33
using namespace LOG4CXX_NS::spi;
34
using namespace LOG4CXX_NS::helpers;
35
36
37
typedef std::map<LogString, LoggerPtr> LoggerMap;
38
typedef std::map<LogString, ProvisionNode> ProvisionNodeMap;
39
40
struct Hierarchy::HierarchyPrivate
41
{
42
  HierarchyPrivate()
43
5
    : configured(false)
44
5
    , emittedNoAppenderWarning(false)
45
5
    , emittedNoResourceBundleWarning(false)
46
5
    , thresholdInt(Level::ALL_INT)
47
5
  {
48
5
  }
49
50
  helpers::Pool pool;
51
  mutable std::recursive_mutex mutex;
52
  mutable std::recursive_mutex configuredMutex;
53
  bool configured;
54
  bool emittedNoAppenderWarning;
55
  bool emittedNoResourceBundleWarning;
56
  int thresholdInt;
57
58
  spi::HierarchyEventListenerList listeners;
59
  LoggerPtr root;
60
  LevelPtr threshold;
61
  LoggerMap loggers;
62
  ProvisionNodeMap provisionNodes;
63
64
#if LOG4CXX_ABI_VERSION <= 15
65
  std::vector<AppenderPtr> allAppenders;
66
#endif
67
  mutable std::mutex listenerMutex;
68
69
  const char* alreadyTriedMethod{ NULL };
70
};
71
72
IMPLEMENT_LOG4CXX_OBJECT(Hierarchy)
73
74
Hierarchy::Hierarchy() :
75
5
  m_priv(std::make_unique<HierarchyPrivate>())
76
5
{
77
5
}
Unexecuted instantiation: log4cxx::Hierarchy::Hierarchy()
log4cxx::Hierarchy::Hierarchy()
Line
Count
Source
75
5
  m_priv(std::make_unique<HierarchyPrivate>())
76
5
{
77
5
}
78
79
Hierarchy::~Hierarchy()
80
5
{
81
5
  std::lock_guard<std::recursive_mutex> lock(m_priv->mutex);
82
5
  for (auto& item : m_priv->loggers)
83
2.10k
  {
84
2.10k
    if (auto& pLogger = item.second)
85
2.10k
    {
86
2.10k
      pLogger->removeHierarchy();
87
2.10k
      pLogger->removeAllAppenders();
88
2.10k
    }
89
2.10k
  }
90
5
  if (m_priv->root)
91
5
  {
92
5
    m_priv->root->removeHierarchy();
93
5
    m_priv->root->removeAllAppenders();
94
5
  }
95
5
}
96
97
void Hierarchy::addHierarchyEventListener(const spi::HierarchyEventListenerPtr& listener)
98
0
{
99
0
  std::lock_guard<std::mutex> lock(m_priv->listenerMutex);
100
101
0
  if (std::find(m_priv->listeners.begin(), m_priv->listeners.end(), listener) != m_priv->listeners.end())
102
0
  {
103
0
    LogLog::warn(LOG4CXX_STR("Ignoring attempt to add an existent listener."));
104
0
  }
105
0
  else
106
0
  {
107
0
    m_priv->listeners.push_back(listener);
108
0
  }
109
0
}
110
111
void Hierarchy::removeHierarchyEventListener(const spi::HierarchyEventListenerPtr& listener)
112
0
{
113
0
  std::lock_guard<std::mutex> lock(m_priv->listenerMutex);
114
115
0
    auto found = std::find(m_priv->listeners.begin(), m_priv->listeners.end(), listener);
116
0
    if(found != m_priv->listeners.end()){
117
0
        m_priv->listeners.erase(found);
118
0
    }
119
0
}
120
121
void Hierarchy::clear()
122
0
{
123
0
  std::lock_guard<std::recursive_mutex> lock(m_priv->mutex);
124
0
  m_priv->loggers.clear();
125
0
}
126
127
void Hierarchy::emitNoAppenderWarning(const Logger* logger)
128
0
{
129
0
  bool emitWarning = false;
130
0
  {
131
0
    std::lock_guard<std::recursive_mutex> lock(m_priv->mutex);
132
0
    emitWarning = !m_priv->emittedNoAppenderWarning;
133
0
    m_priv->emittedNoAppenderWarning = true;
134
0
  }
135
136
  // No appender in hierarchy, warn user only once.
137
0
  if (emitWarning)
138
0
  {
139
0
    LogLog::warn(((LogString) LOG4CXX_STR("No appender could be found for logger ("))
140
0
      + logger->getName() + LOG4CXX_STR(")."));
141
0
    LogLog::warn(LOG4CXX_STR("Please initialize the log4cxx system properly."));
142
0
  }
143
0
}
144
145
146
LoggerPtr Hierarchy::exists(const LogString& name)
147
0
{
148
0
  std::lock_guard<std::recursive_mutex> lock(m_priv->mutex);
149
150
0
  LoggerPtr logger;
151
0
  LoggerMap::iterator it = m_priv->loggers.find(name);
152
153
0
  if (it != m_priv->loggers.end())
154
0
  {
155
0
    logger = it->second;
156
0
  }
157
158
159
0
  return logger;
160
0
}
Unexecuted instantiation: log4cxx::Hierarchy::exists(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)
Unexecuted instantiation: log4cxx::Hierarchy::exists(std::__1::basic_string<wchar_t, std::__1::char_traits<wchar_t>, std::__1::allocator<wchar_t> > const&)
161
162
void Hierarchy::setThreshold(const LevelPtr& l)
163
658
{
164
658
  if (l != 0)
165
658
  {
166
658
    std::lock_guard<std::recursive_mutex> lock(m_priv->mutex);
167
658
    setThresholdInternal(l);
168
658
  }
169
658
}
170
171
void Hierarchy::setThreshold(const LogString& levelStr)
172
0
{
173
0
  LevelPtr l(Level::toLevelLS(levelStr, 0));
174
175
0
  if (l != 0)
176
0
  {
177
0
    setThreshold(l);
178
0
  }
179
0
  else
180
0
  {
181
0
    LogLog::warn(((LogString) LOG4CXX_STR("No level could be found named \""))
182
0
      + levelStr + LOG4CXX_STR("\"."));
183
0
  }
184
0
}
Unexecuted instantiation: log4cxx::Hierarchy::setThreshold(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)
Unexecuted instantiation: log4cxx::Hierarchy::setThreshold(std::__1::basic_string<wchar_t, std::__1::char_traits<wchar_t>, std::__1::allocator<wchar_t> > const&)
185
186
void Hierarchy::setThresholdInternal(const LevelPtr& l)
187
658
{
188
658
  m_priv->thresholdInt = l->toInt();
189
658
  m_priv->threshold = l;
190
191
658
  if (m_priv->thresholdInt != Level::ALL_INT)
192
13
  {
193
13
    m_priv->configured = true;
194
13
  }
195
658
}
196
197
void Hierarchy::fireAddAppenderEvent(const Logger* logger, const Appender* appender)
198
451
{
199
451
  setConfigured(true);
200
451
  HierarchyEventListenerList clonedList;
201
451
  {
202
451
    std::lock_guard<std::mutex> lock(m_priv->listenerMutex);
203
451
    clonedList = m_priv->listeners;
204
451
  }
205
206
451
  for (auto& item : clonedList)
207
0
    item->addAppenderEvent(logger, appender);
208
451
}
209
210
void Hierarchy::fireRemoveAppenderEvent(const Logger* logger, const Appender* appender)
211
212
449
{
213
449
  HierarchyEventListenerList clonedList;
214
449
  {
215
449
    std::lock_guard<std::mutex> lock(m_priv->listenerMutex);
216
449
    clonedList = m_priv->listeners;
217
449
  }
218
449
  for (auto& item : clonedList)
219
0
    item->removeAppenderEvent(logger, appender);
220
449
}
221
222
LevelPtr Hierarchy::getThreshold() const
223
656
{
224
656
  return m_priv->threshold ? m_priv->threshold : Level::getAll();
225
656
}
226
227
LoggerPtr Hierarchy::getLogger(const LogString& name)
228
449
{
229
449
#if LOG4CXX_ABI_VERSION <= 15
230
449
  static WideLife<spi::LoggerFactoryPtr> defaultFactory = std::make_shared<DefaultLoggerFactory>();
231
#else
232
  static WideLife<spi::LoggerFactoryPtr> defaultFactory = std::make_shared<LoggerFactory>();
233
#endif
234
449
  return getLogger(name, defaultFactory);
235
449
}
log4cxx::Hierarchy::getLogger(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)
Line
Count
Source
228
449
{
229
449
#if LOG4CXX_ABI_VERSION <= 15
230
449
  static WideLife<spi::LoggerFactoryPtr> defaultFactory = std::make_shared<DefaultLoggerFactory>();
231
#else
232
  static WideLife<spi::LoggerFactoryPtr> defaultFactory = std::make_shared<LoggerFactory>();
233
#endif
234
449
  return getLogger(name, defaultFactory);
235
449
}
Unexecuted instantiation: log4cxx::Hierarchy::getLogger(std::__1::basic_string<wchar_t, std::__1::char_traits<wchar_t>, std::__1::allocator<wchar_t> > const&)
236
237
LoggerPtr Hierarchy::getLogger(const LogString& name,
238
  const spi::LoggerFactoryPtr& factory)
239
14.9k
{
240
14.9k
  auto root = getRootLogger();
241
14.9k
  std::lock_guard<std::recursive_mutex> lock(m_priv->mutex);
242
243
14.9k
  LoggerMap::iterator it = m_priv->loggers.find(name);
244
14.9k
  LoggerPtr result;
245
246
14.9k
  if (it != m_priv->loggers.end())
247
12.8k
  {
248
12.8k
    result = it->second;
249
12.8k
  }
250
14.9k
  if (!result && factory)
251
2.10k
  {
252
2.10k
#if LOG4CXX_ABI_VERSION <= 15
253
2.10k
    LoggerPtr logger(factory->makeNewLoggerInstance(m_priv->pool, name));
254
#else
255
    LoggerPtr logger(factory->makeNewLoggerInstance(name));
256
#endif
257
2.10k
    logger->setHierarchy(this);
258
2.10k
    m_priv->loggers.insert(LoggerMap::value_type(name, logger));
259
260
2.10k
    ProvisionNodeMap::iterator it2 = m_priv->provisionNodes.find(name);
261
262
2.10k
    if (it2 != m_priv->provisionNodes.end())
263
201
    {
264
201
      updateChildren(it2->second, logger);
265
201
      m_priv->provisionNodes.erase(it2);
266
201
    }
267
268
2.10k
    updateParents(logger, root);
269
2.10k
    result = logger;
270
2.10k
  }
271
14.9k
  return result;
272
273
14.9k
}
log4cxx::Hierarchy::getLogger(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::shared_ptr<log4cxx::spi::LoggerFactory> const&)
Line
Count
Source
239
14.9k
{
240
14.9k
  auto root = getRootLogger();
241
14.9k
  std::lock_guard<std::recursive_mutex> lock(m_priv->mutex);
242
243
14.9k
  LoggerMap::iterator it = m_priv->loggers.find(name);
244
14.9k
  LoggerPtr result;
245
246
14.9k
  if (it != m_priv->loggers.end())
247
12.8k
  {
248
12.8k
    result = it->second;
249
12.8k
  }
250
14.9k
  if (!result && factory)
251
2.04k
  {
252
2.04k
#if LOG4CXX_ABI_VERSION <= 15
253
2.04k
    LoggerPtr logger(factory->makeNewLoggerInstance(m_priv->pool, name));
254
#else
255
    LoggerPtr logger(factory->makeNewLoggerInstance(name));
256
#endif
257
2.04k
    logger->setHierarchy(this);
258
2.04k
    m_priv->loggers.insert(LoggerMap::value_type(name, logger));
259
260
2.04k
    ProvisionNodeMap::iterator it2 = m_priv->provisionNodes.find(name);
261
262
2.04k
    if (it2 != m_priv->provisionNodes.end())
263
200
    {
264
200
      updateChildren(it2->second, logger);
265
200
      m_priv->provisionNodes.erase(it2);
266
200
    }
267
268
2.04k
    updateParents(logger, root);
269
2.04k
    result = logger;
270
2.04k
  }
271
14.9k
  return result;
272
273
14.9k
}
log4cxx::Hierarchy::getLogger(std::__1::basic_string<wchar_t, std::__1::char_traits<wchar_t>, std::__1::allocator<wchar_t> > const&, std::__1::shared_ptr<log4cxx::spi::LoggerFactory> const&)
Line
Count
Source
239
60
{
240
60
  auto root = getRootLogger();
241
60
  std::lock_guard<std::recursive_mutex> lock(m_priv->mutex);
242
243
60
  LoggerMap::iterator it = m_priv->loggers.find(name);
244
60
  LoggerPtr result;
245
246
60
  if (it != m_priv->loggers.end())
247
1
  {
248
1
    result = it->second;
249
1
  }
250
60
  if (!result && factory)
251
59
  {
252
59
#if LOG4CXX_ABI_VERSION <= 15
253
59
    LoggerPtr logger(factory->makeNewLoggerInstance(m_priv->pool, name));
254
#else
255
    LoggerPtr logger(factory->makeNewLoggerInstance(name));
256
#endif
257
59
    logger->setHierarchy(this);
258
59
    m_priv->loggers.insert(LoggerMap::value_type(name, logger));
259
260
59
    ProvisionNodeMap::iterator it2 = m_priv->provisionNodes.find(name);
261
262
59
    if (it2 != m_priv->provisionNodes.end())
263
1
    {
264
1
      updateChildren(it2->second, logger);
265
1
      m_priv->provisionNodes.erase(it2);
266
1
    }
267
268
59
    updateParents(logger, root);
269
59
    result = logger;
270
59
  }
271
60
  return result;
272
273
60
}
274
275
LoggerList Hierarchy::getCurrentLoggers() const
276
0
{
277
0
  std::lock_guard<std::recursive_mutex> lock(m_priv->mutex);
278
279
0
  LoggerList v;
280
0
  for (auto& item : m_priv->loggers)
281
0
  {
282
0
    if (auto pLogger = item.second)
283
0
      v.push_back(pLogger);
284
0
  }
285
0
  return v;
286
0
}
287
288
LoggerPtr Hierarchy::getRootLogger() const
289
33.8k
{
290
33.8k
  std::lock_guard<std::recursive_mutex> lock(m_priv->mutex);
291
33.8k
  if (!m_priv->root)
292
5
  {
293
5
    m_priv->root = std::make_shared<RootLogger>(Level::getDebug());
294
5
    m_priv->root->setHierarchy(const_cast<Hierarchy*>(this));
295
5
  }
296
297
33.8k
  return m_priv->root;
298
33.8k
}
299
300
bool Hierarchy::isDisabled(int level) const
301
99.2k
{
302
99.2k
  return m_priv->thresholdInt > level;
303
99.2k
}
304
305
void Hierarchy::ensureIsConfigured(std::function<void()> configurator)
306
1.32k
{
307
1.32k
  std::lock_guard<std::recursive_mutex> lock(m_priv->configuredMutex);
308
1.32k
  if (!m_priv->configured && m_priv->alreadyTriedMethod != configurator.target_type().name())
309
449
  {
310
449
    configurator();
311
449
    m_priv->alreadyTriedMethod = configurator.target_type().name();
312
449
  }
313
1.32k
}
314
315
void Hierarchy::resetConfiguration()
316
0
{
317
0
  std::lock_guard<std::recursive_mutex> lock(m_priv->mutex);
318
319
0
  if (m_priv->root)
320
0
  {
321
0
    m_priv->root->setLevel(Level::getDebug());
322
0
    m_priv->root->setResourceBundle(0);
323
0
  }
324
0
  setThresholdInternal(Level::getAll());
325
326
0
  shutdownInternal();
327
328
0
  for (auto& item : m_priv->loggers)
329
0
  {
330
0
    if (auto pLogger = item.second)
331
0
    {
332
0
      pLogger->setLevel(0);
333
0
      pLogger->setAdditivity(true);
334
0
      pLogger->setResourceBundle(0);
335
0
    }
336
0
  }
337
0
}
338
339
void Hierarchy::shutdown()
340
449
{
341
449
  std::lock_guard<std::recursive_mutex> lock(m_priv->mutex);
342
343
449
  shutdownInternal();
344
449
}
345
346
void Hierarchy::shutdownInternal()
347
449
{
348
449
  m_priv->configured = false;
349
449
  m_priv->alreadyTriedMethod = NULL;
350
351
  // begin by closing nested appenders
352
449
  if (m_priv->root)
353
449
    m_priv->root->closeNestedAppenders();
354
355
449
  for (auto& item : m_priv->loggers)
356
449
  {
357
449
    if (auto pLogger = item.second)
358
449
      pLogger->closeNestedAppenders();
359
449
  }
360
361
  // then, remove all appenders
362
449
  if (m_priv->root)
363
449
    m_priv->root->removeAllAppenders();
364
365
449
  for (auto& item : m_priv->loggers)
366
449
  {
367
449
    if (auto pLogger = item.second)
368
449
      pLogger->removeAllAppenders();
369
449
  }
370
449
}
371
372
void Hierarchy::updateParents(const LoggerPtr& logger, const LoggerPtr& root)
373
2.10k
{
374
2.10k
  const LogString name(logger->getName());
375
2.10k
  size_t length = name.size();
376
2.10k
  bool parentFound = false;
377
378
379
  // if name = "w.x.y.z", loop through "w.x.y", "w.x" and "w", but not "w.x.y.z"
380
2.10k
  for (size_t i = name.find_last_of(0x2E /* '.' */, length - 1);
381
109k
    (i != LogString::npos) && (i != 0);
382
107k
    i = name.find_last_of(0x2E /* '.' */, i - 1))
383
108k
  {
384
108k
    LogString substr = name.substr(0, i);
385
386
108k
    LoggerMap::iterator it = m_priv->loggers.find(substr);
387
388
108k
    if (it != m_priv->loggers.end())
389
822
    {
390
822
      parentFound = true;
391
822
      logger->setParent( it->second );
392
822
      break; // no need to update the ancestors of the closest ancestor
393
822
    }
394
107k
    else
395
107k
    {
396
107k
      ProvisionNodeMap::iterator it2 = m_priv->provisionNodes.find(substr);
397
398
107k
      if (it2 != m_priv->provisionNodes.end())
399
19.6k
      {
400
19.6k
        it2->second.push_back(logger);
401
19.6k
      }
402
88.2k
      else
403
88.2k
      {
404
88.2k
        ProvisionNode node(1, logger);
405
88.2k
        m_priv->provisionNodes.insert(
406
88.2k
          ProvisionNodeMap::value_type(substr, node));
407
88.2k
      }
408
107k
    }
409
108k
  }
410
411
  // If we could not find any existing parents, then link with root.
412
2.10k
  if (!parentFound)
413
1.28k
  {
414
1.28k
    logger->setParent( root );
415
1.28k
  }
416
2.10k
}
417
418
void Hierarchy::updateChildren(ProvisionNode& pn, const LoggerPtr& logger)
419
201
{
420
201
  for (auto& l : pn)
421
737
  {
422
    // Unless this child already points to a correct (lower) parent,
423
    // make logger.parent point to l.parent and l.parent to logger.
424
737
    if (!StringHelper::startsWith(l->getParent()->getName(), logger->getName()))
425
487
    {
426
487
      logger->setParent( l->getParent() );
427
487
      l->setParent( logger );
428
487
    }
429
737
  }
430
    
431
201
}
432
433
void Hierarchy::updateChildren(const Logger* parent)
434
3.08k
{
435
3.08k
  for (auto& item : m_priv->loggers)
436
2.97M
  {
437
16.7M
    for (auto l = item.second; l; l = l->getParent())
438
13.7M
    {
439
13.7M
      if (l->getParent().get() == parent)
440
9.34k
      {
441
9.34k
        item.second->updateThreshold();
442
9.34k
        break;
443
9.34k
      }
444
13.7M
    }
445
2.97M
  }
446
3.08k
}
447
448
void Hierarchy::setConfigured(bool newValue)
449
453
{
450
453
  std::unique_lock<std::recursive_mutex> lock(m_priv->configuredMutex, std::try_to_lock);
451
453
  if (lock.owns_lock()) // Not being auto-configured?
452
453
    m_priv->configured = newValue;
453
453
}
454
455
bool Hierarchy::isConfigured()
456
0
{
457
0
  std::lock_guard<std::recursive_mutex> lock(m_priv->configuredMutex); // Blocks while auto-configuration is active
458
0
  return m_priv->configured;
459
0
}
460
461
HierarchyPtr Hierarchy::create()
462
5
{
463
5
  HierarchyPtr ret(new Hierarchy);
464
5
  return ret;
465
5
}
466
467
#if LOG4CXX_ABI_VERSION <= 15
468
void Hierarchy::clearAppenders()
469
0
{
470
0
  m_priv->allAppenders.clear();
471
0
}
472
473
void Hierarchy::addAppender(AppenderPtr appender)
474
0
{
475
0
  m_priv->allAppenders.push_back(appender);
476
0
}
477
#endif
478
479
bool Hierarchy::removeLogger(const LogString& name, bool ifNotUsed)
480
0
{
481
0
  auto parentRefCount = [this](const LoggerPtr& child) -> int
482
0
  {
483
0
    int result = 0;
484
0
    for (auto& node : m_priv->provisionNodes)
485
0
    {
486
0
      if (node.second.end() != std::find(node.second.begin(), node.second.end(), child))
487
0
        ++result;
488
0
    }
489
0
    return result;
490
0
  };
Unexecuted instantiation: hierarchy.cpp:log4cxx::Hierarchy::removeLogger(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, bool)::$_0::operator()(std::__1::shared_ptr<log4cxx::Logger> const&) const
Unexecuted instantiation: hierarchy.cpp:log4cxx::Hierarchy::removeLogger(std::__1::basic_string<wchar_t, std::__1::char_traits<wchar_t>, std::__1::allocator<wchar_t> > const&, bool)::$_0::operator()(std::__1::shared_ptr<log4cxx::Logger> const&) const
491
0
  bool result = false;
492
0
  std::lock_guard<std::recursive_mutex> lock(m_priv->mutex);
493
0
  auto it = m_priv->loggers.find(name);
494
0
  if (it == m_priv->loggers.end())
495
0
    ;
496
0
  else if (ifNotUsed && 1 + parentRefCount(it->second) < it->second.use_count())
497
0
    ;
498
0
  else
499
0
  {
500
0
    for (auto& node : m_priv->provisionNodes)
501
0
    {
502
0
      for (size_t i = node.second.size(); 0 < i; )
503
0
      {
504
0
        if (node.second[--i] == it->second)
505
0
          node.second.erase(node.second.begin() + i);
506
0
      }
507
0
    }
508
0
    m_priv->loggers.erase(it);
509
0
    result = true;
510
0
  }
511
0
  return result;
512
0
}
Unexecuted instantiation: log4cxx::Hierarchy::removeLogger(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, bool)
Unexecuted instantiation: log4cxx::Hierarchy::removeLogger(std::__1::basic_string<wchar_t, std::__1::char_traits<wchar_t>, std::__1::allocator<wchar_t> > const&, bool)