summaryrefslogtreecommitdiff
path: root/examples/Reactor/Proactor/test_aiocb_ace.cpp
blob: 2ae450968ea4dc2aaeb9b4c22235cbc75bf534ea (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
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
// $Id$

// ============================================================================
//
// = LIBRARY
//    proactor
//
// = FILENAME
//    test_aiocb_ace.cpp
//
// = DESCRIPTION
//    This program helps you to test the <aio_*> calls on a
//    platform.
//
//    Before running this test, make sure the platform can 
//    support POSIX <aio_> calls, using
//    ACE_ROOT/tests/Aio_Platform_Test.
// 
//    This program tests the AIOCB (AIO Control Blocks) based
//    completion approach which uses <aio_suspend> for completion
//    querying. 
// 
//    If this test is successful, ACE_POSIX_AIOCB_PROACTOR
//    can be used on this platform.
// 
// = COMPILE and RUN
//    % make
//    % ./test_aiocb_ace
// 
// = AUTHOR
//    Alexander Babu Arulanthu <alex@cs.wustl.edu>
//
// ============================================================================

#include "ace/ACE.h"
#include "ace/Log_Msg.h"
#include "ace/os_include/os_aio.h"
#include "ace/OS_NS_string.h"

class Test_Aio
{
public:
  Test_Aio (void);
  // Default constructor.

  int init (void);
  // Initting the output file and the buffer.

  int do_aio (void);
  // Doing the testing stuff.

  ~Test_Aio (void);
  // Destructor.
private:
  int out_fd_;
  // Output file descriptor.

  struct aiocb *aiocb_write_;
  // For writing to the file.

  struct aiocb *aiocb_read_;
  // Reading stuff from the file.

  char *buffer_write_;
  // The buffer to be written to the out_fd.

  char *buffer_read_;
  // The buffer to be read back from the file.
};

Test_Aio::Test_Aio (void)
  : aiocb_write_ (0),
    aiocb_read_ (0),
    buffer_write_ (0),
    buffer_read_ (0)
{
  ACE_NEW (this->aiocb_write_,
           struct aiocb);
  ACE_NEW (this->aiocb_read_,
           struct aiocb);
}

Test_Aio::~Test_Aio (void)
{
  delete aiocb_write_;
  delete aiocb_read_;
  delete buffer_write_;
  delete buffer_read_;
}

// Init the output file and init the buffer.
int
Test_Aio::init (void)
{
  // Open the output file.
  this->out_fd_ = ACE_OS::open ("test_aio.log",
                                O_RDWR | O_CREAT | O_TRUNC,
                                0666); 
  if (this->out_fd_ == 0)
    ACE_ERROR_RETURN ((LM_ERROR,
                       "Error: Opening file\n"),
                      -1);

  // Init the buffers.
  this->buffer_write_ = ACE::strnew ("Welcome to the world of AIO... AIO Rules !!!");
  ACE_DEBUG ((LM_DEBUG,
              "The buffer : %s\n",
              this->buffer_write_));
  
  // Allocate memory for the read buffer.
  ACE_NEW_RETURN (this->buffer_read_,
                  char [ACE_OS::strlen (this->buffer_write_)],
                  -1);

  return 0;
}

// Set the necessary things for the AIO stuff.
// Write the buffer asynchly.hmm Disable signals.
// Go on aio_suspend. Wait for completion.
// Print out the result.
int
Test_Aio::do_aio (void)
{
  // = Write to the file.

  // Setup AIOCB.
  this->aiocb_write_->aio_fildes = this->out_fd_;
  this->aiocb_write_->aio_offset = 0;
  this->aiocb_write_->aio_buf = this->buffer_write_;
  this->aiocb_write_->aio_nbytes = ACE_OS::strlen (this->buffer_write_);
  this->aiocb_write_->aio_reqprio = 0;
  this->aiocb_write_->aio_sigevent.sigev_notify = SIGEV_NONE;
  //this->this->aiocb_.aio_sigevent.sigev_signo = SIGRTMAX;
  this->aiocb_write_->aio_sigevent.sigev_value.sival_ptr =
    (void *) this->aiocb_write_;
  
  // Fire off the aio write.
  if (aio_write (this->aiocb_write_) != 0)
    ACE_ERROR_RETURN ((LM_ERROR,
                       "%p\n",
                       "aio_write"),
                      -1);
  
  // = Read from that file.

  // Setup AIOCB.
  this->aiocb_read_->aio_fildes = this->out_fd_;
  this->aiocb_read_->aio_offset = 0;
  this->aiocb_read_->aio_buf = this->buffer_read_;
  this->aiocb_read_->aio_nbytes = ACE_OS::strlen (this->buffer_write_);
  this->aiocb_read_->aio_reqprio = 0;
  this->aiocb_read_->aio_sigevent.sigev_notify = SIGEV_NONE;
  //this->this->aiocb_.aio_sigevent.sigev_signo = SIGRTMAX;
  this->aiocb_read_->aio_sigevent.sigev_value.sival_ptr =
    (void *) this->aiocb_read_;

  // Fire off the aio write. If it doesnt get queued, carry on to get
  // the completion for the first one.
  if (aio_read (this->aiocb_read_) < 0)
    ACE_ERROR_RETURN ((LM_ERROR,
                       "%p\n",
                       "aio_read"),
                      -1);
  
  // Wait for the completion on aio_suspend.
  struct aiocb *list_aiocb[2];
  list_aiocb [0] = this->aiocb_write_;
  list_aiocb [1] = this->aiocb_read_;

  // Do suspend till all the aiocbs in the list are done.
  int to_finish = 2;
  int return_val = 0;
  while (to_finish > 0)
    {
      return_val = aio_suspend (list_aiocb,
                                to_finish,
                                0);
      ACE_DEBUG ((LM_DEBUG,
                  "Result of <aio_suspend> : %d\n",
                  return_val));

      // Analyze return and error values.     
      if (to_finish > 1)
        {
          if (aio_error (list_aiocb [1]) != EINPROGRESS)
            {
              if (aio_return (list_aiocb [1]) == -1)
                ACE_ERROR_RETURN ((LM_ERROR,
                                   "%p\n",
                                   "aio_return, item 1"),
                                  -1);
              else
                {
                  // Successful. Remember we have one less thing to finish.
                  --to_finish;
                  list_aiocb [1] = 0;
                }
            }
          else
            ACE_DEBUG ((LM_DEBUG, 
                        "aio_error says aio 1 is in progress\n"));
        }

      if (aio_error (list_aiocb [0]) != EINPROGRESS)
        {
          if (aio_return (list_aiocb [0]) == -1)
            ACE_ERROR_RETURN ((LM_ERROR,
                               "%p\n",
                               "aio_return, item 0"),
                              -1);
          else
            {
              // Successful. Store the pointer somewhere and bump the
              // read entry up to the front, if it is still not done.
              --to_finish;
              list_aiocb [0] = this->aiocb_read_;
            }
        }
      else
        ACE_DEBUG ((LM_DEBUG, 
                    "aio_error says aio 0 is in progress\n"));
    }

  ACE_DEBUG ((LM_DEBUG, 
              "Both the AIO operations done.\n"
              "The buffer is : %s\n",
              this->buffer_read_));
  
  return 0;
}

int
ACE_TMAIN (int argc, ACE_TCHAR **argv)
{

  ACE_UNUSED_ARG (argc);
  ACE_UNUSED_ARG (argv);

  Test_Aio test_aio;

  if (test_aio.init () != 0)
    ACE_ERROR_RETURN ((LM_ERROR,
                       "AIOCB test failed:\n"
                       "ACE_POSIX_AIOCB_PROACTOR may not work in this platform\n"),
                      -1);
  
  if (test_aio.do_aio () != 0)
    ACE_ERROR_RETURN ((LM_ERROR,
                       "AIOCB test failed:\n"
                       "ACE_POSIX_AIOCB_PROACTOR may not work in this platform\n"),
                      -1);
  
  ACE_DEBUG ((LM_DEBUG,
              "AIOCB test successful:\n"
              "ACE_POSIX_AIOCB_PROACTOR should work in this platform\n"));
  
  return 0;
}