1 // server_loggerd.cpp,v 4.29 2003/12/30 23:18:59 shuston Exp
3 // This server daemon collects, formats, and displays logging
4 // information forwarded from client daemons running on other hosts in
5 // the network. In addition, this example illustrates how to use the
6 // ACE_Reactor, ACE_Acceptor, ACE_Singleton, and the ACE_Test_and_Set
9 #include "ace/OS_NS_string.h"
10 #include "ace/Get_Opt.h"
11 #include "ace/Acceptor.h"
12 #include "ace/Null_Mutex.h"
13 #include "ace/SOCK_Acceptor.h"
14 #include "ace/Singleton.h"
15 #include "ace/CDR_Stream.h"
16 #include "ace/Test_and_Set.h"
18 // FUZZ: disable check_for_streams_include
19 #include "ace/streams.h"
21 #include "ace/Log_Record.h"
22 #include "ace/Test_and_Set.h"
24 #include "server_loggerd.h"
27 // ----------------------------------------
29 // Return the port number.
37 // Parse the command-line options.
40 Options::parse_args (int argc
, ACE_TCHAR
*argv
[])
42 this->port_
= ACE_DEFAULT_SERVER_PORT
;
44 ACE_Get_Opt
get_opt (argc
, argv
, ACE_TEXT ("p:"));
46 for (int c
; (c
= get_opt ()) != -1; )
50 this->port_
= ACE_OS::atoi (get_opt
.opt_arg ());
57 // ----------------------------------------
59 // Our Reactor Singleton.
60 typedef ACE_Singleton
<ACE_Reactor
, ACE_Null_Mutex
>
63 // Our Options Singleton.
64 typedef ACE_Singleton
<Options
, ACE_Null_Mutex
>
67 // Our ACE_Test_and_Set Singleton.
68 typedef ACE_Singleton
<ACE_Test_and_Set
<ACE_Null_Mutex
, sig_atomic_t>, ACE_Null_Mutex
>
71 // ----------------------------------------
73 // Specialize a Logging Acceptor.
74 typedef ACE_Acceptor
<Logging_Handler
, ACE_SOCK_ACCEPTOR
>
77 // Default constructor.
79 Logging_Handler::Logging_Handler ()
84 Logging_Handler::handle_timeout (const ACE_Time_Value
&,
87 #if defined (ACE_NDEBUG)
89 #endif /* ACE_NDEBUG */
91 ACE_ASSERT (arg
== this);
93 ACE_TEXT ("(%P|%t) handling timeout from this = %@\n"), this));
97 // Perform the logging record receive.
100 Logging_Handler::handle_input (ACE_HANDLE
)
102 ACE_Log_Record log_record
;
104 // We need to use the old two-read trick here since TCP sockets
105 // don't support framing natively. Allocate a message block for the
106 // payload; initially at least large enough to hold the header, but
107 // needs some room for alignment.
108 ACE_Message_Block
*payload_p
= 0;
109 ACE_Message_Block
*header_p
= 0;
110 ACE_NEW_RETURN (header_p
,
111 ACE_Message_Block (ACE_DEFAULT_CDR_BUFSIZE
),
114 std::unique_ptr
<ACE_Message_Block
> header (header_p
);
116 // Align the Message Block for a CDR stream
117 ACE_CDR::mb_align (header
.get ());
119 ACE_CDR::Boolean byte_order
;
120 ACE_CDR::ULong length
;
122 ssize_t count
= ACE::recv_n (this->peer ().get_handle (),
127 // Handle shutdown and error cases.
132 ACE_DEBUG ((LM_DEBUG
,
133 ACE_TEXT ("server logging daemon closing down\n")));
139 // Just fall through in this case..
143 header
->wr_ptr (8); // Reflect addition of 8 bytes.
145 // Create a CDR stream to parse the 8-byte header.
146 ACE_InputCDR
header_cdr (header
.get ());
148 // Extract the byte-order and use helper methods to disambiguate
149 // octet, booleans, and chars.
150 header_cdr
>> ACE_InputCDR::to_boolean (byte_order
);
152 // Set the byte-order on the stream...
153 header_cdr
.reset_byte_order (byte_order
);
155 // Extract the length
156 header_cdr
>> length
;
158 ACE_NEW_RETURN (payload_p
,
159 ACE_Message_Block (length
),
161 std::unique_ptr
<ACE_Message_Block
> payload (payload_p
);
163 // Ensure there's sufficient room for log record payload.
164 ACE_CDR::grow (payload
.get (), 8 + ACE_CDR::MAX_ALIGNMENT
+ length
);
166 // Use <recv_n> to obtain the contents.
167 if (ACE::recv_n (this->peer ().get_handle (),
171 ACE_ERROR ((LM_ERROR
,
173 ACE_TEXT ("recv_n()")));
177 payload
->wr_ptr (length
); // Reflect additional bytes
179 ACE_InputCDR
payload_cdr (payload
.get ());
180 payload_cdr
.reset_byte_order (byte_order
);
181 payload_cdr
>> log_record
; // Finally extract the <ACE_log_record>.
183 log_record
.length (length
);
185 log_record
.print (ACE_TEXT_CHAR_TO_TCHAR (this->peer_name_
), 1, stderr
);
191 Logging_Handler::open (void *)
195 if (this->peer ().get_remote_addr (addr
) == -1)
199 ACE_OS::strncpy (this->peer_name_
,
200 addr
.get_host_name (),
203 if (REACTOR::instance ()->register_handler (this, READ_MASK
) == -1)
204 ACE_ERROR_RETURN ((LM_ERROR
,
205 ACE_TEXT ("(%P|%t) can't register with reactor\n")),
207 else if (REACTOR::instance ()->schedule_timer
211 ACE_Time_Value (2)) == -1)
212 ACE_ERROR_RETURN ((LM_ERROR
,
213 ACE_TEXT ("(%P|%t) can't register with reactor\n")),
216 ACE_DEBUG ((LM_DEBUG
,
217 ACE_TEXT ("(%P|%t) connected with %C\n"),
224 ACE_TMAIN (int argc
, ACE_TCHAR
*argv
[])
227 Logging_Acceptor peer_acceptor
;
229 OPTIONS::instance ()->parse_args (argc
, argv
);
231 // We need to pass in REACTOR::instance () here so that we don't use
232 // the default ACE_Reactor::instance ().
234 if (peer_acceptor
.open
235 (ACE_INET_Addr (OPTIONS::instance ()->port ()),
236 REACTOR::instance ()) == -1)
237 ACE_ERROR_RETURN ((LM_ERROR
, ACE_TEXT ("%p\n"), ACE_TEXT ("open")), -1);
239 // Register QUIT_HANDLER to receive SIGINT commands. When received,
240 // QUIT_HANDLER becomes "set" and thus, the event loop below will
242 else if (REACTOR::instance ()->register_handler
243 (SIGINT
, QUIT_HANDLER::instance ()) == -1)
244 ACE_ERROR_RETURN ((LM_ERROR
,
245 ACE_TEXT ("registering service with ACE_Reactor\n")),
248 // Run forever, performing logging service.
250 ACE_DEBUG ((LM_DEBUG
,
251 ACE_TEXT ("(%P|%t) starting up server logging daemon\n")));
253 // Perform logging service until QUIT_HANDLER receives SIGINT.
254 while (QUIT_HANDLER::instance ()->is_set () == 0)
255 REACTOR::instance ()->handle_events ();
257 ACE_DEBUG ((LM_DEBUG
,
258 ACE_TEXT ("(%P|%t) shutting down server logging daemon\n")));
263 ACE_SINGLETON_TEMPLATE_INSTANTIATE(ACE_Singleton
, ACE_Reactor
, ACE_Null_Mutex
);
264 ACE_SINGLETON_TEMPLATE_INSTANTIATE(ACE_Singleton
, Options
, ACE_Null_Mutex
);
265 #define ACE_Test_and_Set_type \
266 ACE_Test_and_Set<ACE_Null_Mutex, sig_atomic_t>
267 ACE_SINGLETON_TEMPLATE_INSTANTIATE(ACE_Singleton
, ACE_Test_and_Set_type
, ACE_Null_Mutex
);