Coverage Report

Created: 2026-03-12 07:00

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/logging-log4cxx/src/main/cpp/socketappenderskeleton.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
#define __STDC_CONSTANT_MACROS
19
#include <log4cxx/net/socketappenderskeleton.h>
20
#include <log4cxx/helpers/loglog.h>
21
#include <log4cxx/helpers/optionconverter.h>
22
#include <log4cxx/helpers/stringhelper.h>
23
#include <log4cxx/spi/loggingevent.h>
24
#include <log4cxx/helpers/threadutility.h>
25
#include <log4cxx/helpers/transcoder.h>
26
#include <log4cxx/helpers/bytearrayoutputstream.h>
27
#include <log4cxx/helpers/threadutility.h>
28
#include <log4cxx/private/appenderskeleton_priv.h>
29
#include <log4cxx/private/socketappenderskeleton_priv.h>
30
#include <functional>
31
#include <chrono>
32
33
using namespace LOG4CXX_NS;
34
using namespace LOG4CXX_NS::helpers;
35
using namespace LOG4CXX_NS::net;
36
37
0
#define _priv static_cast<SocketAppenderSkeletonPriv*>(m_priv.get())
38
39
SocketAppenderSkeleton::SocketAppenderSkeleton(int defaultPort, int reconnectionDelay)
40
0
  : AppenderSkeleton(std::make_unique<SocketAppenderSkeletonPriv>(defaultPort, reconnectionDelay))
41
0
{
42
0
}
43
44
SocketAppenderSkeleton::SocketAppenderSkeleton(helpers::InetAddressPtr address, int port, int reconnectionDelay)
45
0
  : AppenderSkeleton(std::make_unique<SocketAppenderSkeletonPriv>(address, port, reconnectionDelay))
46
0
{
47
0
}
48
49
SocketAppenderSkeleton::SocketAppenderSkeleton(const LogString& host, int port, int reconnectionDelay)
50
0
  : AppenderSkeleton(std::make_unique<SocketAppenderSkeletonPriv>(host, port, reconnectionDelay))
51
0
{
52
0
}
53
54
SocketAppenderSkeleton::SocketAppenderSkeleton(std::unique_ptr<SocketAppenderSkeletonPriv> priv)
55
0
  :  AppenderSkeleton (std::move(priv))
56
0
{
57
0
}
58
59
SocketAppenderSkeleton::~SocketAppenderSkeleton()
60
0
{
61
0
}
62
63
void SocketAppenderSkeleton::activateOptions(Pool& p)
64
0
{
65
0
  AppenderSkeleton::activateOptions(p);
66
0
  connect(p);
67
0
}
68
69
void SocketAppenderSkeleton::close()
70
0
{
71
0
  if (_priv->setClosed())
72
0
    _priv->close();
73
0
}
74
75
void SocketAppenderSkeleton::connect(Pool& p)
76
0
{
77
0
  if (_priv->address == 0)
78
0
  {
79
0
    LogLog::error(LogString(LOG4CXX_STR("No remote host is set for Appender named \"")) +
80
0
      _priv->name + LOG4CXX_STR("\"."));
81
0
  }
82
0
  else
83
0
  {
84
0
    _priv->close();
85
86
0
    try
87
0
    {
88
0
      if (LogLog::isDebugEnabled())
89
0
      {
90
0
        LogString msg(LOG4CXX_STR("Connecting to [")
91
0
          + _priv->address->toString() + LOG4CXX_STR(":"));
92
0
        StringHelper::toString(_priv->port, p, msg);
93
0
        msg += LOG4CXX_STR("].");
94
0
        LogLog::debug(msg);
95
0
      }
96
0
      SocketPtr socket = Socket::create(_priv->address, _priv->port);
97
0
      setSocket(socket, p);
98
0
    }
99
0
    catch (SocketException& e)
100
0
    {
101
0
      LogString msg = LOG4CXX_STR("Could not connect to [")
102
0
        + _priv->address->toString() + LOG4CXX_STR(":");
103
0
      StringHelper::toString(_priv->port, p, msg);
104
0
      msg += LOG4CXX_STR("].");
105
106
0
      fireConnector(); // fire the connector thread
107
0
      LogLog::warn(msg, e);
108
0
    }
109
0
  }
110
0
}
111
112
void SocketAppenderSkeleton::setOption(const LogString& option, const LogString& value)
113
0
{
114
0
  if (StringHelper::equalsIgnoreCase(option, LOG4CXX_STR("REMOTEHOST"), LOG4CXX_STR("remotehost")))
115
0
  {
116
0
    setRemoteHost(value);
117
0
  }
118
0
  else if (StringHelper::equalsIgnoreCase(option, LOG4CXX_STR("PORT"), LOG4CXX_STR("port")))
119
0
  {
120
0
    setPort(OptionConverter::toInt(value, getDefaultPort()));
121
0
  }
122
0
  else if (StringHelper::equalsIgnoreCase(option, LOG4CXX_STR("LOCATIONINFO"), LOG4CXX_STR("locationinfo")))
123
0
  {
124
0
    setLocationInfo(OptionConverter::toBoolean(value, false));
125
0
  }
126
0
  else if (StringHelper::equalsIgnoreCase(option, LOG4CXX_STR("RECONNECTIONDELAY"), LOG4CXX_STR("reconnectiondelay")))
127
0
  {
128
0
    setReconnectionDelay(OptionConverter::toInt(value, getDefaultDelay()));
129
0
  }
130
0
  else
131
0
  {
132
0
    AppenderSkeleton::setOption(option, value);
133
0
  }
134
0
}
135
136
void SocketAppenderSkeleton::fireConnector()
137
0
{
138
0
  std::lock_guard<std::recursive_mutex> lock(_priv->mutex);
139
0
    if (_priv->taskName.empty())
140
0
    {
141
0
        Pool p;
142
0
        _priv->taskName = _priv->name + LOG4CXX_STR(":")
143
0
            + _priv->address->toString() + LOG4CXX_STR(":");
144
0
        StringHelper::toString(_priv->port, p, _priv->taskName);
145
0
    }
146
0
    auto taskManager = ThreadUtility::instancePtr();
147
0
    if (!taskManager->value().hasPeriodicTask(_priv->taskName))
148
0
    {
149
0
        Pool p;
150
0
        if (LogLog::isDebugEnabled())
151
0
        {
152
0
            Pool p;
153
0
            LogString msg(LOG4CXX_STR("Waiting "));
154
0
            StringHelper::toString(_priv->reconnectionDelay, p, msg);
155
0
            msg += LOG4CXX_STR(" ms before retrying [")
156
0
                + _priv->address->toString() + LOG4CXX_STR(":");
157
0
            StringHelper::toString(_priv->port, p, msg);
158
0
            msg += LOG4CXX_STR("].");
159
0
            LogLog::debug(msg);
160
0
        }
161
0
        taskManager->value().addPeriodicTask(_priv->taskName
162
0
            , std::bind(&SocketAppenderSkeleton::retryConnect, this)
163
0
            , std::chrono::milliseconds(_priv->reconnectionDelay)
164
0
            );
165
0
    }
166
0
    _priv->taskManager = taskManager;
167
0
}
168
169
void SocketAppenderSkeleton::retryConnect()
170
0
{
171
0
  if (is_closed())
172
0
  {
173
0
    if (auto pManager = _priv->taskManager.lock())
174
0
      pManager->value().removePeriodicTask(_priv->taskName);
175
0
  }
176
0
  else
177
0
  {
178
0
    Pool p;
179
0
    SocketPtr socket;
180
0
    try
181
0
    {
182
0
      if (LogLog::isDebugEnabled())
183
0
      {
184
0
        LogString msg(LOG4CXX_STR("Attempting connection to [")
185
0
          + _priv->address->toString() + LOG4CXX_STR(":"));
186
0
        StringHelper::toString(_priv->port, p, msg);
187
0
        msg += LOG4CXX_STR("].");
188
0
        LogLog::debug(msg);
189
0
      }
190
0
      socket = Socket::create(_priv->address, _priv->port);
191
0
      setSocket(socket, p);
192
0
      if (LogLog::isDebugEnabled())
193
0
      {
194
0
        LogString msg(LOG4CXX_STR("Connection established to [")
195
0
          + _priv->address->toString() + LOG4CXX_STR(":"));
196
0
        StringHelper::toString(_priv->port, p, msg);
197
0
        msg += LOG4CXX_STR("].");
198
0
        LogLog::debug(msg);
199
0
      }
200
0
      if (auto pManager = _priv->taskManager.lock())
201
0
        pManager->value().removePeriodicTask(_priv->taskName);
202
0
      return;
203
0
    }
204
0
    catch (ConnectException& e)
205
0
    {
206
0
      LogLog::warn(LOG4CXX_STR("Remote host ")
207
0
        + _priv->address->toString()
208
0
        + LOG4CXX_STR(" refused connection."), e);
209
0
    }
210
0
    catch (IOException& e)
211
0
    {
212
0
      LogString msg(LOG4CXX_STR("Could not connect to [")
213
0
        + _priv->address->toString() + LOG4CXX_STR(":"));
214
0
      StringHelper::toString(_priv->port, p, msg);
215
0
      msg += LOG4CXX_STR("].");
216
0
      LogLog::warn(msg, e);
217
0
    }
218
219
0
    if (_priv->reconnectionDelay > 0)
220
0
    {
221
0
      if (LogLog::isDebugEnabled())
222
0
      {
223
0
        LogString msg(LOG4CXX_STR("Waiting "));
224
0
        StringHelper::toString(_priv->reconnectionDelay, p, msg);
225
0
        msg += LOG4CXX_STR(" ms before retrying [")
226
0
          + _priv->address->toString() + LOG4CXX_STR(":");
227
0
        StringHelper::toString(_priv->port, p, msg);
228
0
        msg += LOG4CXX_STR("].");
229
0
        LogLog::debug(msg);
230
0
      }
231
0
    }
232
0
  }
233
0
}
234
235
void SocketAppenderSkeleton::SocketAppenderSkeletonPriv::close()
236
0
{
237
0
  if (this->taskName.empty())
238
0
    ;
239
0
  else if (auto pManager = this->taskManager.lock())
240
0
    pManager->value().removePeriodicTask(this->taskName);
241
0
}
242
243
bool SocketAppenderSkeleton::is_closed()
244
0
{
245
0
  return _priv->closed;
246
0
}
247
248
void SocketAppenderSkeleton::setRemoteHost(const LogString& host)
249
0
{
250
0
  _priv->address = helpers::InetAddress::getByName(host);
251
0
  _priv->remoteHost.assign(host);
252
0
}
253
254
const LogString& SocketAppenderSkeleton::getRemoteHost() const
255
0
{
256
0
  return _priv->remoteHost;
257
0
}
258
259
void SocketAppenderSkeleton::setPort(int port1)
260
0
{
261
0
  _priv->port = port1;
262
0
}
263
264
int SocketAppenderSkeleton::getPort() const
265
0
{
266
0
  return _priv->port;
267
0
}
268
269
void SocketAppenderSkeleton::setLocationInfo(bool locationInfo1)
270
0
{
271
0
  _priv->locationInfo = locationInfo1;
272
0
}
273
274
bool SocketAppenderSkeleton::getLocationInfo() const
275
0
{
276
0
  return _priv->locationInfo;
277
0
}
278
279
void SocketAppenderSkeleton::setReconnectionDelay(int reconnectionDelay1)
280
0
{
281
0
  _priv->reconnectionDelay = reconnectionDelay1;
282
0
  if (_priv->taskName.empty())
283
0
    return;
284
0
  auto pManager = _priv->taskManager.lock();
285
0
  if (pManager && pManager->value().hasPeriodicTask(_priv->taskName))
286
0
  {
287
0
    pManager->value().removePeriodicTask(_priv->taskName);
288
0
    pManager->value().addPeriodicTask(_priv->taskName
289
0
      , std::bind(&SocketAppenderSkeleton::retryConnect, this)
290
0
      , std::chrono::milliseconds(_priv->reconnectionDelay)
291
0
      );
292
0
  }
293
0
}
294
295
int SocketAppenderSkeleton::getReconnectionDelay() const
296
0
{
297
0
  return _priv->reconnectionDelay;
298
0
}