Revert "Use a variable on the stack to not have a temporary in the call"
[ACE_TAO.git] / ACE / netsvcs / lib / Server_Logging_Handler_T.cpp
blobb52d99b4ddc4e73680eeeafd265a74861a50d978
1 #ifndef ACE_SERVER_LOGGING_HANDLERT_C
2 #define ACE_SERVER_LOGGING_HANDLERT_C
4 #include "ace/config-all.h"
5 #include <memory>
6 #include "ace/Get_Opt.h"
7 #include "ace/Log_Record.h"
8 #include "ace/CDR_Stream.h"
9 #include "Server_Logging_Handler_T.h"
10 #include "ace/Signal.h"
12 // Track number of requests.
13 template <ACE_PEER_STREAM_1, class COUNTER, ACE_SYNCH_DECL, class LMR>
14 COUNTER ACE_Server_Logging_Handler_T<ACE_PEER_STREAM_2, COUNTER, ACE_SYNCH_USE, LMR>::request_count_ = (COUNTER) 0;
16 template <ACE_PEER_STREAM_1, class COUNTER, ACE_SYNCH_DECL, class LMR>
17 ACE_Server_Logging_Handler_T<ACE_PEER_STREAM_2, COUNTER, ACE_SYNCH_USE, LMR>::ACE_Server_Logging_Handler_T
18 (ACE_Thread_Manager *,
19 LMR const &receiver)
20 // Initialize the CString to something that is not the empty string
21 // to avoid problems when calling fast_rep()
22 #if !defined (__GNUG__)
23 : receiver_ (receiver, ACE_TString (ACE_TEXT(" "), 1))
24 #else
25 : receiver_ (receiver),
26 host_name_ (ACE_TString (ACE_TEXT (" "), 1))
27 #endif /* ! __GNUG__ */
31 // Callback routine for handling the reception of remote logging
32 // transmissions.
34 template <ACE_PEER_STREAM_1, class COUNTER, ACE_SYNCH_DECL, class LMR> int
35 ACE_Server_Logging_Handler_T<ACE_PEER_STREAM_2, COUNTER, ACE_SYNCH_USE, LMR>::handle_input (ACE_HANDLE)
37 int result = this->handle_logging_record ();
38 return result >= 0 ? 0 : -1;
41 template <ACE_PEER_STREAM_1, class COUNTER, ACE_SYNCH_DECL, class LMR> const ACE_TCHAR *
42 ACE_Server_Logging_Handler_T<ACE_PEER_STREAM_2, COUNTER, ACE_SYNCH_USE, LMR>::host_name ()
44 #if !defined (__GNUG__)
45 return this->receiver_.m_.fast_rep ();
46 #else
47 return this->host_name_.fast_rep ();
48 #endif /* ! __GNUG__ */
51 template <ACE_PEER_STREAM_1, class COUNTER, ACE_SYNCH_DECL, class LMR> int
52 ACE_Server_Logging_Handler_T<ACE_PEER_STREAM_2, COUNTER, ACE_SYNCH_USE, LMR>::handle_logging_record ()
54 ACE_Log_Record log_record;
56 // We need to use the old two-read trick here since TCP sockets
57 // don't support framing natively. Allocate a message block for the
58 // payload; initially at least large enough to hold the header, but
59 // needs some room for alignment.
60 ACE_Message_Block *payload_p = 0;
61 ACE_Message_Block *header_p = 0;
62 ACE_NEW_RETURN (header_p,
63 ACE_Message_Block (ACE_DEFAULT_CDR_BUFSIZE),
64 -1);
66 std::unique_ptr <ACE_Message_Block> header (header_p);
68 // Align the Message Block for a CDR stream
69 ACE_CDR::mb_align (header.get ());
71 ACE_CDR::Boolean byte_order;
72 ACE_CDR::ULong length;
74 ssize_t count = ACE::recv_n (this->peer ().get_handle (),
75 header->wr_ptr (),
76 8);
77 switch (count)
79 // Handle shutdown and error cases.
80 default:
81 case -1:
82 case 0:
83 ACE_DEBUG ((LM_DEBUG,
84 ACE_TEXT ("server logging daemon closing down at host %s\n"),
85 this->host_name ()));
87 return -1;
88 /* NOTREACHED */
90 case 8:
91 // Just fall through in this case..
92 break;
95 header->wr_ptr (8); // Reflect addition of 8 bytes.
97 // Create a CDR stream to parse the 8-byte header.
98 ACE_InputCDR header_cdr (header.get ());
100 // Extract the byte-order and use helper methods to disambiguate
101 // octet, booleans, and chars.
102 if (!(header_cdr >> ACE_InputCDR::to_boolean (byte_order)))
104 ACE_ERROR ((LM_ERROR,
105 ACE_TEXT ("Can't extract byte_order\n")));
106 return 0;
109 // Set the byte-order on the stream...
110 header_cdr.reset_byte_order (byte_order);
112 // Extract the length
113 if (!(header_cdr >> length))
115 ACE_ERROR ((LM_ERROR,
116 ACE_TEXT ("Can't extract length\n")));
117 return 0;
120 ACE_NEW_RETURN (payload_p,
121 ACE_Message_Block (length),
122 -1);
123 std::unique_ptr <ACE_Message_Block> payload (payload_p);
125 // Ensure there's sufficient room for log record payload.
126 ACE_CDR::grow (payload.get (), 8 + ACE_CDR::MAX_ALIGNMENT + length);
128 // Use <recv_n> to obtain the contents.
129 if (ACE::recv_n (this->peer ().get_handle (),
130 payload->wr_ptr (),
131 length) <= 0)
133 ACE_ERROR ((LM_ERROR,
134 ACE_TEXT ("%p\n"),
135 ACE_TEXT ("recv_n()")));
136 return -1;
139 payload->wr_ptr (length); // Reflect additional bytes
141 ACE_InputCDR payload_cdr (payload.get ());
142 payload_cdr.reset_byte_order (byte_order);
143 if (!(payload_cdr >> log_record)) // Finally extract the <ACE_log_record>.
145 ACE_ERROR ((LM_ERROR,
146 ACE_TEXT ("Can't extract log_record\n")));
147 return 0;
150 log_record.length (length);
152 // Send the log record to the log message receiver for processing.
153 if (ACE_BIT_ENABLED (ACE_Log_Msg::instance ()->flags (), ACE_Log_Msg::STDERR))
154 receiver ().log_record (this->host_name (), log_record);
156 ostream *orig_ostream = ACE_Log_Msg::instance ()->msg_ostream ();
157 receiver ().log_output (this->host_name (),
158 log_record,
159 orig_ostream);
160 return 0;
162 #if 0
163 ACE_INT32 length;
165 // We need to use the ol' two-read trick here since TCP sockets
166 // don't support framing natively. Note that the first call is just
167 // a "peek" -- we don't actually remove the data until the second
168 // call. Note that this code is portable as long as ACE_UNIT32 is
169 // always 32 bits on both the sender and receiver side.
171 switch (this->peer ().recv ((void *) &length,
172 sizeof length,
173 MSG_PEEK))
175 default:
176 case -1:
177 ACE_ERROR_RETURN ((LM_ERROR,
178 ACE_TEXT ("%p at host %s\n"),
179 ACE_TEXT ("server logger"),
180 this->host_name ()),
181 -1);
182 /* NOTREACHED */
183 case 0:
184 ACE_ERROR_RETURN ((LM_ERROR,
185 ACE_TEXT ("closing log daemon at host %C\n"),
186 this->host_name ()),
187 -1);
188 /* NOTREACHED */
189 case sizeof length:
191 ACE_Log_Record lp;
193 // Use ACE_NTOHL to get around bug in egcs 2.91.6x.
194 length = ACE_NTOHL (length);
196 ++this->request_count_;
198 u_long count = this->request_count_;
199 ACE_DEBUG ((LM_DEBUG,
200 ACE_TEXT ("request count = %d, length = %d\n"),
201 count,
202 length));
204 // Perform the actual <recv> this time.
205 ssize_t n = this->peer ().recv_n ((void *) &lp,
206 length);
207 if (n != length)
208 ACE_ERROR_RETURN ((LM_ERROR,
209 ACE_TEXT ("%d != %d, %p at host %C\n"),
211 length,
212 ACE_TEXT ("server logger"),
213 this->host_name ()),
214 -1);
216 lp.decode ();
218 if (lp.length () == n)
220 // Send the log record to the log message receiver for
221 // processing.
222 if (ACE_BIT_ENABLED (ACE_Log_Msg::instance ()->flags (),
223 ACE_Log_Msg::STDERR))
224 receiver ().log_record (this->host_name (),
225 lp);
226 ostream *orig_ostream = ACE_Log_Msg::instance ()->msg_ostream ();
227 receiver ().log_output (this->host_name (),
229 orig_ostream);
231 else
232 ACERROR ((LM_ERROR,
233 ACE_TEXT ("error, lp.length = %d, n = %d\n"),
234 lp.length (),
235 n));
236 return n;
239 #endif
241 ACE_NOTREACHED (return -1;)
244 // Hook called by Server_Logging_Acceptor when connection is
245 // established.
247 template <ACE_PEER_STREAM_1, class COUNTER, ACE_SYNCH_DECL, class LMR> int
248 ACE_Server_Logging_Handler_T<ACE_PEER_STREAM_2, COUNTER, ACE_SYNCH_USE, LMR>::open_common ()
250 // Shut off non-blocking IO if it was enabled...
251 if (this->peer ().disable (ACE_NONBLOCK) == -1)
252 ACE_ERROR_RETURN ((LM_ERROR,
253 ACE_TEXT ("%p\n"),
254 ACE_TEXT ("disable")),
255 -1);
256 ACE_PEER_STREAM_ADDR client_addr;
258 // Determine the address of the client and display it.
259 if (this->peer ().get_remote_addr (client_addr) == -1)
260 ACE_ERROR_RETURN ((LM_ERROR,
261 ACE_TEXT ("%p\n"),
262 ACE_TEXT ("get_remote_addr")),
263 -1);
265 #if !defined (__GNUG__)
266 this->receiver_.m_ =
267 ACE_TString (ACE_TEXT_CHAR_TO_TCHAR (client_addr.get_host_name ()));
268 #else
269 this->host_name_ =
270 ACE_TString (ACE_TEXT_CHAR_TO_TCHAR (client_addr.get_host_name ()));
271 #endif /* ! __GNUG__ */
273 ACE_DEBUG ((LM_DEBUG,
274 ACE_TEXT ("(%t) accepted connection from host %C on fd %d\n"),
275 client_addr.get_host_name (),
276 this->peer ().get_handle ()));
278 return 0;
281 template<class SLH, class LMR, class SST>
282 ACE_Server_Logging_Acceptor_T<SLH, LMR, SST>::ACE_Server_Logging_Acceptor_T ()
286 template<class SLH, class LMR, class SST> LMR &
287 ACE_Server_Logging_Acceptor_T<SLH, LMR, SST>::receiver ()
289 return receiver_;
292 template<class SLH, class LMR, class SST> SST &
293 ACE_Server_Logging_Acceptor_T<SLH, LMR, SST>::scheduling_strategy ()
295 #if !defined (__GNUG__)
296 return receiver_.m_;
297 #else
298 return schedule_strategy_;
299 #endif /* ! __GNUG__ */
302 template<class SLH, class LMR, class SST> int
303 ACE_Server_Logging_Acceptor_T<SLH, LMR, SST>::init (int argc, ACE_TCHAR *argv[])
305 ACE_TRACE ("ACE_Server_Logging_Acceptor_T<SLH, LMR, SST>::init");
307 // Use the options hook to parse the command line arguments and set
308 // options.
309 this->parse_args (argc, argv);
311 // Set the acceptor endpoint into listen mode (use the Singleton
312 // global Reactor...).
313 if (this->open (this->service_addr_,
314 ACE_Reactor::instance (),
315 0, 0, 0,
316 &this->scheduling_strategy(),
317 ACE_TEXT ("Logging Server"),
318 ACE_TEXT ("ACE logging service")) == -1)
319 ACE_ERROR_RETURN ((LM_ERROR,
320 ACE_TEXT ("%n: %p on port %d\n"),
321 ACE_TEXT ("acceptor::open failed"),
322 this->service_addr_.get_port_number ()),
323 -1);
324 // Ignore SIGPIPE so that each <SVC_HANDLER> can handle this on its
325 // own.
326 ACE_Sig_Action sig ((ACE_SignalHandler) SIG_IGN, SIGPIPE);
327 ACE_UNUSED_ARG (sig);
329 ACE_INET_Addr server_addr;
331 // Figure out what port we're really bound to.
332 if (this->acceptor ().get_local_addr (server_addr) == -1)
333 ACE_ERROR_RETURN ((LM_ERROR,
334 ACE_TEXT ("%p\n"),
335 ACE_TEXT ("get_local_addr")),
336 -1);
337 ACE_DEBUG ((LM_DEBUG,
338 ACE_TEXT ("starting up Logging Server at port %d on handle %d\n"),
339 server_addr.get_port_number (),
340 this->acceptor ().get_handle ()));
341 return 0;
344 template<class SLH, class LMR, class SST> int
345 ACE_Server_Logging_Acceptor_T<SLH, LMR, SST>::parse_args (int argc, ACE_TCHAR *argv[])
347 ACE_TRACE ("ACE_Server_Logging_Acceptor_T<SLH, LMR, SST>::parse_args");
349 int service_port = ACE_DEFAULT_SERVER_PORT;
351 ACE_LOG_MSG->open (ACE_TEXT ("Logging Service"), ACE_LOG_MSG->flags ());
353 ACE_Get_Opt get_opt (argc, argv, ACE_TEXT ("p:"), 0);
355 for (int c; (c = get_opt ()) != -1; )
357 switch (c)
359 case 'p':
360 service_port = ACE_OS::atoi (get_opt.opt_arg ());
361 break;
362 default:
363 ACE_ERROR_RETURN ((LM_ERROR,
364 ACE_TEXT ("%n:\n[-p server-port]\n")),
365 -1);
369 this->service_addr_.set (service_port);
370 return 0;
373 template<class SERVER_LOGGING_HANDLER, class LOG_MESSAGE_RECEIVER, class SCHEDULE_STRATEGY> int
374 ACE_Server_Logging_Acceptor_T<SERVER_LOGGING_HANDLER,
375 LOG_MESSAGE_RECEIVER,
376 SCHEDULE_STRATEGY>
377 ::make_svc_handler (SERVER_LOGGING_HANDLER *&handler)
379 ACE_NEW_RETURN (handler,
380 SERVER_LOGGING_HANDLER (ACE_Thread_Manager::instance (),
381 this->receiver()),
382 -1);
383 return 0;
386 template<class LOG_MESSAGE_RECEIVER>
387 ACE_Server_Logging_Handler<LOG_MESSAGE_RECEIVER>::ACE_Server_Logging_Handler (ACE_Thread_Manager * tm,
388 LOG_MESSAGE_RECEIVER const& receiver)
389 : ACE_Server_Logging_Handler_T<LOGGING_PEER_STREAM, u_long, ACE_NULL_SYNCH, LOG_MESSAGE_RECEIVER>(tm,
390 receiver)
394 template<class LOG_MESSAGE_RECEIVER>
395 ACE_Server_Logging_Handler<LOG_MESSAGE_RECEIVER>::ACE_Server_Logging_Handler(ACE_Thread_Manager * tm)
396 : ACE_Server_Logging_Handler_T<LOGGING_PEER_STREAM, u_long, ACE_NULL_SYNCH, LOG_MESSAGE_RECEIVER>(tm, LOG_MESSAGE_RECEIVER())
400 template<class LOG_MESSAGE_RECEIVER> int
401 ACE_Server_Logging_Handler<LOG_MESSAGE_RECEIVER>::open (void *)
403 // call base class open_common
404 if (this->open_common () != 0)
405 return -1;
407 // Register ourselves with the Reactor to enable subsequent
408 // dispatching.
409 if (ACE_Reactor::instance ()->register_handler
410 (this, ACE_Event_Handler::READ_MASK) == -1)
411 return -1;
412 return 0;
415 template<class LOG_MESSAGE_RECEIVER>
416 ACE_Thr_Server_Logging_Handler<LOG_MESSAGE_RECEIVER>::ACE_Thr_Server_Logging_Handler (ACE_Thread_Manager *tm, LOG_MESSAGE_RECEIVER const &receiver)
417 : ACE_Server_Logging_Handler_T<LOGGING_PEER_STREAM, ACE_LOGGER_COUNTER, ACE_LOGGER_SYNCH, LOG_MESSAGE_RECEIVER>(tm, receiver)
421 template<class LOG_MESSAGE_RECEIVER>
422 ACE_Thr_Server_Logging_Handler<LOG_MESSAGE_RECEIVER>::ACE_Thr_Server_Logging_Handler (ACE_Thread_Manager *tm)
423 : ACE_Server_Logging_Handler_T<LOGGING_PEER_STREAM, ACE_LOGGER_COUNTER, ACE_LOGGER_SYNCH, LOG_MESSAGE_RECEIVER>(tm, LOG_MESSAGE_RECEIVER ())
427 template<class LOG_MESSAGE_RECEIVER> int
428 ACE_Thr_Server_Logging_Handler<LOG_MESSAGE_RECEIVER>::open (void *)
430 // call base class open_common
431 if (this->open_common () != 0)
432 return -1;
434 // Spawn a new thread of control to handle logging records with the
435 // client using a thread-per-connection concurrency model. Note
436 // that this implicitly uses the <ACE_Thread_Manager::instance> to
437 // control all the threads.
438 if (this->activate (THR_BOUND | THR_DETACHED) == -1)
439 ACE_ERROR_RETURN ((LM_ERROR,
440 ACE_TEXT ("%p\n"),
441 ACE_TEXT ("spawn")),
442 -1);
443 return 0;
446 // Process remote logging records.
448 template<class LOG_MESSAGE_RECEIVER> int
449 ACE_Thr_Server_Logging_Handler<LOG_MESSAGE_RECEIVER>::svc ()
451 int result = 0;
453 // Loop until the client terminates the connection or an error occurs.
455 while ((result = this->handle_input ()) == 0)
456 continue;
458 return result;
460 #endif /* ACE_SERVER_LOGGING_HANDLER_TT_C */