1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
|
/*
** $Id$
**
** Copyright 2001 Addison Wesley. All Rights Reserved.
*/
#include "ace/OS.h"
#include "ace/CDR_Stream.h"
#include "ace/INET_Addr.h"
#include "ace/SOCK_Connector.h"
#include "ace/SOCK_Stream.h"
#include "ace/Log_Record.h"
#include "ace/streams.h"
#include <string>
int operator<< (ACE_OutputCDR &cdr, const ACE_Log_Record &log_record)
{
size_t msglen = log_record.msg_data_len ();
// The ACE_Log_Record::msg_data () function is non-const, since it
// returns a non-const pointer to internal class members. Since we
// know that no members are modified here, we can safely const_cast
// the log_record parameter without violating the interface
// contract.
ACE_Log_Record &nonconst_record = (ACE_const_cast (ACE_Log_Record&,
log_record));
// Insert each field from <log_record> into the output CDR stream.
cdr << ACE_CDR::Long (log_record.type ());
cdr << ACE_CDR::Long (log_record.pid ());
cdr << ACE_CDR::Long (log_record.time_stamp ().sec ());
cdr << ACE_CDR::Long (log_record.time_stamp ().usec ());
cdr << ACE_CDR::ULong (msglen);
cdr.write_char_array (nonconst_record.msg_data (), msglen);
return cdr.good_bit ();
}
class Logging_Client {
private:
ACE_SOCK_Stream logging_peer_;
public:
ACE_SOCK_Stream &peer () { return logging_peer_; }
int send (const ACE_Log_Record &log_record) {
// Serialize the log record using a CDR stream, allocate
// enough space for the complete <ACE_Log_Record>.
const size_t max_payload_size =
4 // type()
+ 8 // timestamp
+ 4 // process id
+ 4 // data length
+ ACE_Log_Record::MAXLOGMSGLEN // data
+ ACE_CDR::MAX_ALIGNMENT; // padding;
// Insert contents of <log_record> into payload stream.
ACE_OutputCDR payload (max_payload_size);
payload << log_record;
// Get the number of bytes used by the CDR stream.
ACE_CDR::ULong length = payload.total_length ();
// Send a header so the receiver can determine the byte
// order and size of the incoming CDR stream.
ACE_OutputCDR header (ACE_CDR::MAX_ALIGNMENT + 8);
header << ACE_OutputCDR::from_boolean (ACE_CDR_BYTE_ORDER);
// Store the size of the payload that follows
header << ACE_CDR::ULong (length);
// Use an iovec to send both buffer and payload simultaneously.
iovec iov[2];
iov[0].iov_base = header.begin ()->rd_ptr ();
iov[0].iov_len = 8;
iov[1].iov_base = payload.begin ()->rd_ptr ();
iov[1].iov_len = length;
// Send header and payload efficiently using "gather-write".
return logging_peer_.sendv_n (iov, 2);
}
~Logging_Client () { logging_peer_.close (); }
};
int main (int argc, char *argv[])
{
u_short logger_port = argc > 1 ? atoi (argv[1]) : 0;
const char *logger_host =
argc > 2 ? argv[2] : ACE_DEFAULT_SERVER_HOST;
int result;
ACE_INET_Addr server_addr;
if (logger_port != 0)
result = server_addr.set (logger_port, logger_host);
else
result = server_addr.set ("ace_logger", logger_host);
if (result == -1)
ACE_ERROR_RETURN ((LM_ERROR, "lookup %s, %p\n",
logger_port == 0 ? "ace_logger" : argv[1],
logger_host), 1);
ACE_SOCK_Connector connector;
Logging_Client logging_client;
if (connector.connect (logging_client.peer (), server_addr) < 0)
ACE_ERROR_RETURN ((LM_ERROR, "%p\n", "connect()"), 1);
// Limit the number of characters read on each record
cin.width (ACE_Log_Record::MAXLOGMSGLEN);
for (;;) {
std::string user_input;
std::getline (cin, user_input, '\n');
if (!cin || cin.eof ()) break;
ACE_Time_Value now (ACE_OS::gettimeofday ());
ACE_Log_Record log_record (LM_INFO, now, ACE_OS::getpid ());
log_record.msg_data (user_input.c_str ());
if (logging_client.send (log_record) == -1)
ACE_ERROR_RETURN ((LM_ERROR,
"%p\n", "logging_client.send()"), 1);
}
return 0; // Logging_Client destructor closes TCP connection.
}
|