Coverage Report

Created: 2025-07-01 06:08

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