| /* |
| * 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. |
| */ |
| #if defined(_MSC_VER) |
| #pragma warning ( disable: 4231 4251 4275 4786 ) |
| #endif |
| |
| #define __STDC_CONSTANT_MACROS |
| #include <log4cxx/net/socketappenderskeleton.h> |
| #include <log4cxx/helpers/loglog.h> |
| #include <log4cxx/helpers/optionconverter.h> |
| #include <log4cxx/helpers/stringhelper.h> |
| #include <log4cxx/spi/loggingevent.h> |
| #include <log4cxx/helpers/synchronized.h> |
| #include <log4cxx/helpers/transcoder.h> |
| #include <log4cxx/helpers/bytearrayoutputstream.h> |
| |
| using namespace log4cxx; |
| using namespace log4cxx::helpers; |
| using namespace log4cxx::net; |
| |
| SocketAppenderSkeleton::SocketAppenderSkeleton(int defaultPort, int reconnectionDelay1) |
| : remoteHost(), |
| address(), |
| port(defaultPort), |
| reconnectionDelay(reconnectionDelay1), |
| locationInfo(false), |
| thread() |
| { |
| } |
| |
| SocketAppenderSkeleton::SocketAppenderSkeleton(InetAddressPtr address1, int port1, int delay) |
| : |
| remoteHost(), |
| address(address1), |
| port(port1), |
| reconnectionDelay(delay), |
| locationInfo(false), |
| thread() |
| { |
| remoteHost = this->address->getHostName(); |
| } |
| |
| SocketAppenderSkeleton::SocketAppenderSkeleton(const LogString& host, int port1, int delay) |
| : remoteHost(host), |
| address(InetAddress::getByName(host)), |
| port(port1), |
| reconnectionDelay(delay), |
| locationInfo(false), |
| thread() |
| { |
| } |
| |
| SocketAppenderSkeleton::~SocketAppenderSkeleton() |
| { |
| finalize(); |
| |
| try |
| { |
| thread.join(); |
| } |
| catch (ThreadException& ex) |
| { |
| LogLog::error(LOG4CXX_STR("Error closing socket appender connection thread"), ex); |
| } |
| } |
| |
| void SocketAppenderSkeleton::activateOptions(Pool& p) |
| { |
| AppenderSkeleton::activateOptions(p); |
| connect(p); |
| } |
| |
| void SocketAppenderSkeleton::close() |
| { |
| LOCK_W sync(mutex); |
| |
| if (closed) |
| { |
| return; |
| } |
| |
| closed = true; |
| cleanUp(pool); |
| thread.interrupt(); |
| } |
| |
| void SocketAppenderSkeleton::connect(Pool& p) |
| { |
| if (address == 0) |
| { |
| LogLog::error(LogString(LOG4CXX_STR("No remote host is set for Appender named \"")) + |
| name + LOG4CXX_STR("\".")); |
| } |
| else |
| { |
| cleanUp(p); |
| |
| try |
| { |
| SocketPtr socket(new Socket(address, port)); |
| setSocket(socket, p); |
| } |
| catch (SocketException& e) |
| { |
| LogString msg = LOG4CXX_STR("Could not connect to remote log4cxx server at [") |
| + address->getHostName() + LOG4CXX_STR("]."); |
| |
| if (reconnectionDelay > 0) |
| { |
| msg += LOG4CXX_STR(" We will try again later. "); |
| } |
| |
| fireConnector(); // fire the connector thread |
| LogLog::error(msg, e); |
| } |
| } |
| } |
| |
| void SocketAppenderSkeleton::setOption(const LogString& option, const LogString& value) |
| { |
| if (StringHelper::equalsIgnoreCase(option, LOG4CXX_STR("REMOTEHOST"), LOG4CXX_STR("remotehost"))) |
| { |
| setRemoteHost(value); |
| } |
| else if (StringHelper::equalsIgnoreCase(option, LOG4CXX_STR("PORT"), LOG4CXX_STR("port"))) |
| { |
| setPort(OptionConverter::toInt(value, getDefaultPort())); |
| } |
| else if (StringHelper::equalsIgnoreCase(option, LOG4CXX_STR("LOCATIONINFO"), LOG4CXX_STR("locationinfo"))) |
| { |
| setLocationInfo(OptionConverter::toBoolean(value, false)); |
| } |
| else if (StringHelper::equalsIgnoreCase(option, LOG4CXX_STR("RECONNECTIONDELAY"), LOG4CXX_STR("reconnectiondelay"))) |
| { |
| setReconnectionDelay(OptionConverter::toInt(value, getDefaultDelay())); |
| } |
| else |
| { |
| AppenderSkeleton::setOption(option, value); |
| } |
| } |
| |
| void SocketAppenderSkeleton::fireConnector() |
| { |
| LOCK_W sync(mutex); |
| |
| if ( !thread.isAlive() ) |
| { |
| LogLog::debug(LOG4CXX_STR("Connector thread not alive: starting monitor.")); |
| |
| try |
| { |
| thread.run(monitor, this); |
| } |
| catch ( ThreadException& te ) |
| { |
| LogLog::error(LOG4CXX_STR("Monitor not started: "), te); |
| } |
| } |
| } |
| |
| void* LOG4CXX_THREAD_FUNC SocketAppenderSkeleton::monitor(apr_thread_t* /* thread */, void* data) |
| { |
| SocketAppenderSkeleton* socketAppender = (SocketAppenderSkeleton*) data; |
| SocketPtr socket; |
| bool isClosed = socketAppender->closed; |
| |
| while (!isClosed) |
| { |
| try |
| { |
| Thread::sleep(socketAppender->reconnectionDelay); |
| |
| if (!socketAppender->closed) |
| { |
| LogLog::debug(LogString(LOG4CXX_STR("Attempting connection to ")) |
| + socketAppender->address->getHostName()); |
| socket = new Socket(socketAppender->address, socketAppender->port); |
| Pool p; |
| socketAppender->setSocket(socket, p); |
| LogLog::debug(LOG4CXX_STR("Connection established. Exiting connector thread.")); |
| } |
| |
| return NULL; |
| } |
| catch (InterruptedException&) |
| { |
| LogLog::debug(LOG4CXX_STR("Connector interrupted. Leaving loop.")); |
| return NULL; |
| } |
| catch (ConnectException&) |
| { |
| LogLog::debug(LOG4CXX_STR("Remote host ") |
| + socketAppender->address->getHostName() |
| + LOG4CXX_STR(" refused connection.")); |
| } |
| catch (IOException& e) |
| { |
| LogString exmsg; |
| log4cxx::helpers::Transcoder::decode(e.what(), exmsg); |
| |
| LogLog::debug(((LogString) LOG4CXX_STR("Could not connect to ")) |
| + socketAppender->address->getHostName() |
| + LOG4CXX_STR(". Exception is ") |
| + exmsg); |
| } |
| |
| isClosed = socketAppender->closed; |
| } |
| |
| LogLog::debug(LOG4CXX_STR("Exiting Connector.run() method.")); |
| return NULL; |
| } |