summaryrefslogtreecommitdiff
path: root/examples/C++NPv1/Logging_Client.cpp
blob: fc14388e0e6b90d1912fb45a913b42273b3b71d2 (plain)
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.
}