/src/dcmtk/oflog/libsrc/socketap.cc
Line | Count | Source |
1 | | // Module: Log4CPLUS |
2 | | // File: socketappender.cxx |
3 | | // Created: 5/2003 |
4 | | // Author: Tad E. Smith |
5 | | // |
6 | | // |
7 | | // Copyright 2003-2010 Tad E. Smith |
8 | | // |
9 | | // Licensed under the Apache License, Version 2.0 (the "License"); |
10 | | // you may not use this file except in compliance with the License. |
11 | | // You may obtain a copy of the License at |
12 | | // |
13 | | // http://www.apache.org/licenses/LICENSE-2.0 |
14 | | // |
15 | | // Unless required by applicable law or agreed to in writing, software |
16 | | // distributed under the License is distributed on an "AS IS" BASIS, |
17 | | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
18 | | // See the License for the specific language governing permissions and |
19 | | // limitations under the License. |
20 | | |
21 | | #include <cstdlib> |
22 | | #include "dcmtk/oflog/socketap.h" |
23 | | #include "dcmtk/oflog/layout.h" |
24 | | #include "dcmtk/oflog/spi/logevent.h" |
25 | | #include "dcmtk/oflog/helpers/loglog.h" |
26 | | #include "dcmtk/oflog/helpers/sleep.h" |
27 | | #include "dcmtk/oflog/helpers/property.h" |
28 | | #include "dcmtk/oflog/thread/syncpub.h" |
29 | | |
30 | | |
31 | | namespace dcmtk { |
32 | | namespace log4cplus { |
33 | | |
34 | | int const DCMTK_LOG4CPLUS_MESSAGE_VERSION = 3; |
35 | | |
36 | | |
37 | | #if ! defined (DCMTK_LOG4CPLUS_SINGLE_THREADED) |
38 | | SocketAppender::ConnectorThread::ConnectorThread ( |
39 | | SocketAppender & socket_appender) |
40 | 0 | : sa (socket_appender) |
41 | 0 | , trigger_ev () |
42 | 0 | , exit_flag (false) |
43 | 0 | { }Unexecuted instantiation: dcmtk::log4cplus::SocketAppender::ConnectorThread::ConnectorThread(dcmtk::log4cplus::SocketAppender&) Unexecuted instantiation: dcmtk::log4cplus::SocketAppender::ConnectorThread::ConnectorThread(dcmtk::log4cplus::SocketAppender&) |
44 | | |
45 | | |
46 | | SocketAppender::ConnectorThread::~ConnectorThread () |
47 | 0 | { } |
48 | | |
49 | | |
50 | | void |
51 | | SocketAppender::ConnectorThread::run () |
52 | 0 | { |
53 | 0 | while (true) |
54 | 0 | { |
55 | 0 | trigger_ev.timed_wait (30 * 1000); |
56 | |
|
57 | 0 | helpers::getLogLog().debug ( |
58 | 0 | DCMTK_LOG4CPLUS_TEXT("SocketAppender::ConnectorThread::run()") |
59 | 0 | DCMTK_LOG4CPLUS_TEXT("- running...")); |
60 | | |
61 | | // Check exit condition as the very first thing. |
62 | |
|
63 | 0 | { |
64 | 0 | thread::MutexGuard guard (access_mutex); |
65 | 0 | if (exit_flag) |
66 | 0 | return; |
67 | 0 | trigger_ev.reset (); |
68 | 0 | } |
69 | | |
70 | | // Do not try to re-open already open socket. |
71 | | |
72 | 0 | { |
73 | 0 | thread::MutexGuard guard (sa.access_mutex); |
74 | 0 | if (sa.socket.isOpen ()) |
75 | 0 | continue; |
76 | 0 | } |
77 | | |
78 | | // The socket is not open, try to reconnect. |
79 | | |
80 | 0 | helpers::Socket new_socket (sa.host, |
81 | 0 | OFstatic_cast(unsigned short, sa.port)); |
82 | 0 | if (! new_socket.isOpen ()) |
83 | 0 | { |
84 | 0 | helpers::getLogLog().error( |
85 | 0 | DCMTK_LOG4CPLUS_TEXT("SocketAppender::ConnectorThread::run()") |
86 | 0 | DCMTK_LOG4CPLUS_TEXT("- Cannot connect to server")); |
87 | | |
88 | | // Sleep for a short while after unsuccessful connection attempt |
89 | | // so that we do not try to reconnect after each logging attempt |
90 | | // which could be many times per second. |
91 | 0 | helpers::sleep (5); |
92 | |
|
93 | 0 | continue; |
94 | 0 | } |
95 | | |
96 | | // Connection was successful, move the socket into SocketAppender. |
97 | | |
98 | 0 | { |
99 | 0 | thread::MutexGuard guard (sa.access_mutex); |
100 | 0 | sa.socket = new_socket; |
101 | 0 | sa.connected = true; |
102 | 0 | } |
103 | 0 | } |
104 | 0 | } |
105 | | |
106 | | |
107 | | void |
108 | | SocketAppender::ConnectorThread::terminate () |
109 | 0 | { |
110 | 0 | { |
111 | 0 | thread::MutexGuard guard (access_mutex); |
112 | 0 | exit_flag = true; |
113 | 0 | trigger_ev.signal (); |
114 | 0 | } |
115 | 0 | join (); |
116 | 0 | } |
117 | | |
118 | | |
119 | | void |
120 | | SocketAppender::ConnectorThread::trigger () |
121 | 0 | { |
122 | 0 | trigger_ev.signal (); |
123 | 0 | } |
124 | | |
125 | | #endif |
126 | | |
127 | | |
128 | | ////////////////////////////////////////////////////////////////////////////// |
129 | | // SocketAppender ctors and dtor |
130 | | ////////////////////////////////////////////////////////////////////////////// |
131 | | |
132 | | SocketAppender::SocketAppender(const tstring& host_, |
133 | | unsigned short port_, const tstring& serverName_) |
134 | 0 | : socket(), |
135 | 0 | host(host_), |
136 | 0 | port(port_), |
137 | 0 | serverName(serverName_) |
138 | | #if ! defined (DCMTK_LOG4CPLUS_SINGLE_THREADED) |
139 | 0 | ,connected(false), |
140 | 0 | connector() |
141 | | #endif |
142 | 0 | { |
143 | 0 | openSocket(); |
144 | 0 | initConnector (); |
145 | 0 | } Unexecuted instantiation: dcmtk::log4cplus::SocketAppender::SocketAppender(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, unsigned short, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&) Unexecuted instantiation: dcmtk::log4cplus::SocketAppender::SocketAppender(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, unsigned short, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&) |
146 | | |
147 | | |
148 | | |
149 | | SocketAppender::SocketAppender(const helpers::Properties & properties) |
150 | 0 | : Appender(properties), |
151 | 0 | socket(), |
152 | 0 | host(), |
153 | 0 | port(9998), |
154 | 0 | serverName() |
155 | | #if ! defined (DCMTK_LOG4CPLUS_SINGLE_THREADED) |
156 | 0 | ,connected(false), |
157 | 0 | connector() |
158 | | #endif |
159 | 0 | { |
160 | 0 | host = properties.getProperty( DCMTK_LOG4CPLUS_TEXT("host") ); |
161 | 0 | properties.getUInt (port, DCMTK_LOG4CPLUS_TEXT("port")); |
162 | 0 | serverName = properties.getProperty( DCMTK_LOG4CPLUS_TEXT("ServerName") ); |
163 | |
|
164 | 0 | openSocket(); |
165 | 0 | initConnector (); |
166 | 0 | } Unexecuted instantiation: dcmtk::log4cplus::SocketAppender::SocketAppender(dcmtk::log4cplus::helpers::Properties const&) Unexecuted instantiation: dcmtk::log4cplus::SocketAppender::SocketAppender(dcmtk::log4cplus::helpers::Properties const&) |
167 | | |
168 | | |
169 | | |
170 | | SocketAppender::~SocketAppender() |
171 | 0 | { |
172 | 0 | #if ! defined (DCMTK_LOG4CPLUS_SINGLE_THREADED) |
173 | 0 | connector->terminate (); |
174 | 0 | #endif |
175 | |
|
176 | 0 | destructorImpl(); |
177 | 0 | } |
178 | | |
179 | | |
180 | | |
181 | | ////////////////////////////////////////////////////////////////////////////// |
182 | | // SocketAppender public methods |
183 | | ////////////////////////////////////////////////////////////////////////////// |
184 | | |
185 | | void |
186 | | SocketAppender::close() |
187 | 0 | { |
188 | 0 | helpers::getLogLog().debug( |
189 | 0 | DCMTK_LOG4CPLUS_TEXT("Entering SocketAppender::close()...")); |
190 | |
|
191 | 0 | #if ! defined (DCMTK_LOG4CPLUS_SINGLE_THREADED) |
192 | 0 | connector->terminate (); |
193 | 0 | #endif |
194 | |
|
195 | 0 | socket.close(); |
196 | 0 | closed = true; |
197 | 0 | } |
198 | | |
199 | | |
200 | | |
201 | | ////////////////////////////////////////////////////////////////////////////// |
202 | | // SocketAppender protected methods |
203 | | ////////////////////////////////////////////////////////////////////////////// |
204 | | |
205 | | void |
206 | | SocketAppender::openSocket() |
207 | 0 | { |
208 | 0 | if(!socket.isOpen()) { |
209 | 0 | socket = helpers::Socket(host, OFstatic_cast(unsigned short, port)); |
210 | 0 | } |
211 | 0 | } |
212 | | |
213 | | |
214 | | void |
215 | | SocketAppender::initConnector () |
216 | 0 | { |
217 | 0 | #if ! defined (DCMTK_LOG4CPLUS_SINGLE_THREADED) |
218 | 0 | connected = true; |
219 | 0 | connector = new ConnectorThread (*this); |
220 | 0 | connector->start (); |
221 | 0 | #endif |
222 | 0 | } |
223 | | |
224 | | |
225 | | void |
226 | | SocketAppender::append(const spi::InternalLoggingEvent& event) |
227 | 0 | { |
228 | 0 | #if ! defined (DCMTK_LOG4CPLUS_SINGLE_THREADED) |
229 | 0 | if (! connected) |
230 | 0 | { |
231 | 0 | connector->trigger (); |
232 | 0 | return; |
233 | 0 | } |
234 | | |
235 | | #else |
236 | | if(!socket.isOpen()) { |
237 | | openSocket(); |
238 | | if(!socket.isOpen()) { |
239 | | helpers::getLogLog().error( |
240 | | DCMTK_LOG4CPLUS_TEXT( |
241 | | "SocketAppender::append()- Cannot connect to server")); |
242 | | return; |
243 | | } |
244 | | } |
245 | | #endif |
246 | | |
247 | 0 | helpers::SocketBuffer buffer(DCMTK_LOG4CPLUS_MAX_MESSAGE_SIZE - sizeof(unsigned int)); |
248 | 0 | helpers::convertToBuffer (buffer, event, serverName); |
249 | 0 | helpers::SocketBuffer msgBuffer(DCMTK_LOG4CPLUS_MAX_MESSAGE_SIZE); |
250 | |
|
251 | 0 | msgBuffer.appendInt(OFstatic_cast(unsigned, buffer.getSize())); |
252 | 0 | msgBuffer.appendBuffer(buffer); |
253 | |
|
254 | 0 | bool ret = socket.write(msgBuffer); |
255 | 0 | if (! ret) |
256 | 0 | { |
257 | 0 | #if ! defined (DCMTK_LOG4CPLUS_SINGLE_THREADED) |
258 | 0 | connected = false; |
259 | 0 | connector->trigger (); |
260 | 0 | #endif |
261 | 0 | } |
262 | 0 | } |
263 | | |
264 | | |
265 | | ///////////////////////////////////////////////////////////////////////////// |
266 | | // namespace helpers methods |
267 | | ///////////////////////////////////////////////////////////////////////////// |
268 | | |
269 | | namespace helpers |
270 | | { |
271 | | |
272 | | |
273 | | void |
274 | | convertToBuffer(SocketBuffer & buffer, |
275 | | const spi::InternalLoggingEvent& event, |
276 | | const tstring& serverName) |
277 | 0 | { |
278 | 0 | buffer.appendByte(DCMTK_LOG4CPLUS_MESSAGE_VERSION); |
279 | 0 | #ifndef DCMTK_OFLOG_UNICODE |
280 | 0 | buffer.appendByte(1); |
281 | | #else |
282 | | buffer.appendByte(2); |
283 | | #endif |
284 | |
|
285 | 0 | buffer.appendString(serverName); |
286 | 0 | buffer.appendString(event.getLoggerName()); |
287 | 0 | buffer.appendInt(event.getLogLevel()); |
288 | 0 | buffer.appendString(event.getNDC()); |
289 | 0 | buffer.appendString(event.getMessage()); |
290 | 0 | buffer.appendString(event.getThread()); |
291 | 0 | buffer.appendInt( OFstatic_cast(unsigned int, event.getTimestamp().sec()) ); |
292 | 0 | buffer.appendInt( OFstatic_cast(unsigned int, event.getTimestamp().usec()) ); |
293 | 0 | buffer.appendString(event.getFile()); |
294 | 0 | buffer.appendInt(event.getLine()); |
295 | 0 | buffer.appendString(event.getFunction()); |
296 | 0 | } |
297 | | |
298 | | |
299 | | spi::InternalLoggingEvent |
300 | | readFromBuffer(SocketBuffer& buffer) |
301 | 0 | { |
302 | 0 | unsigned char msgVersion = buffer.readByte(); |
303 | 0 | if(msgVersion != DCMTK_LOG4CPLUS_MESSAGE_VERSION) { |
304 | 0 | LogLog * loglog = LogLog::getLogLog(); |
305 | 0 | loglog->warn(DCMTK_LOG4CPLUS_TEXT("readFromBuffer() received socket message with an invalid version")); |
306 | 0 | } |
307 | |
|
308 | 0 | unsigned char sizeOfChar = buffer.readByte(); |
309 | |
|
310 | 0 | tstring serverName = buffer.readString(sizeOfChar); |
311 | 0 | tstring loggerName = buffer.readString(sizeOfChar); |
312 | 0 | LogLevel ll = buffer.readInt(); |
313 | 0 | tstring ndc = buffer.readString(sizeOfChar); |
314 | 0 | if(! serverName.empty ()) { |
315 | 0 | if(ndc.empty ()) { |
316 | 0 | ndc = serverName; |
317 | 0 | } |
318 | 0 | else { |
319 | 0 | ndc = serverName + DCMTK_LOG4CPLUS_TEXT(" - ") + ndc; |
320 | 0 | } |
321 | 0 | } |
322 | 0 | tstring message = buffer.readString(sizeOfChar); |
323 | 0 | tstring thread = buffer.readString(sizeOfChar); |
324 | 0 | long sec = buffer.readInt(); |
325 | 0 | long usec = buffer.readInt(); |
326 | 0 | tstring file = buffer.readString(sizeOfChar); |
327 | 0 | int line = buffer.readInt(); |
328 | 0 | tstring function = buffer.readString(sizeOfChar); |
329 | | |
330 | | // TODO: Pass MDC through. |
331 | 0 | spi::InternalLoggingEvent ev (loggerName, ll, ndc, |
332 | 0 | MappedDiagnosticContextMap (), message, thread, Time(sec, usec), file, |
333 | 0 | line); |
334 | 0 | ev.setFunction (function); |
335 | 0 | return ev; |
336 | 0 | } |
337 | | |
338 | | |
339 | | } // namespace helpers |
340 | | |
341 | | |
342 | | } // namespace log4cplus |
343 | | } // end namespace dcmtk |