~ps10gel/ubuntu/xenial/trafficserver/6.2.0

« back to all changes in this revision

Viewing changes to iocore/aio/NTAIO.cc

  • Committer: Package Import Robot
  • Author(s): Aron Xu
  • Date: 2013-05-09 01:00:04 UTC
  • mto: (1.1.11) (5.3.3 experimental)
  • mto: This revision was merged to the branch mainline in revision 15.
  • Revision ID: package-import@ubuntu.com-20130509010004-9fqq9n0adseg3f8w
Tags: upstream-3.3.2
ImportĀ upstreamĀ versionĀ 3.3.2

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/** @file
2
 
 
3
 
  A brief file description
4
 
 
5
 
  @section license License
6
 
 
7
 
  Licensed to the Apache Software Foundation (ASF) under one
8
 
  or more contributor license agreements.  See the NOTICE file
9
 
  distributed with this work for additional information
10
 
  regarding copyright ownership.  The ASF licenses this file
11
 
  to you under the Apache License, Version 2.0 (the
12
 
  "License"); you may not use this file except in compliance
13
 
  with the License.  You may obtain a copy of the License at
14
 
 
15
 
      http://www.apache.org/licenses/LICENSE-2.0
16
 
 
17
 
  Unless required by applicable law or agreed to in writing, software
18
 
  distributed under the License is distributed on an "AS IS" BASIS,
19
 
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
20
 
  See the License for the specific language governing permissions and
21
 
  limitations under the License.
22
 
 */
23
 
 
24
 
/****************************************************************************
25
 
 
26
 
  NTAIO.cc
27
 
 
28
 
 
29
 
 ****************************************************************************/
30
 
 
31
 
#include "P_AIO.h"
32
 
 
33
 
extern Continuation *aio_err_callbck;
34
 
 
35
 
// AIO Stats
36
 
extern uint64_t aio_num_read;
37
 
extern uint64_t aio_bytes_read;
38
 
extern uint64_t aio_num_write;
39
 
extern uint64_t aio_bytes_written;
40
 
 
41
 
NTIOCompletionPort aio_completion_port(1);
42
 
 
43
 
 
44
 
static inline void
45
 
init_op_sequence(AIOCallback * op, int opcode)
46
 
{
47
 
 
48
 
  // zero aio_result's and init opcodes
49
 
  AIOCallback *cur_op;
50
 
  for (cur_op = op; cur_op; cur_op = cur_op->then) {
51
 
    cur_op->aio_result = 0;
52
 
    cur_op->aiocb.aio_lio_opcode = opcode;
53
 
    // set the last op to point to the first op
54
 
    if (cur_op->then == NULL)
55
 
      ((AIOCallbackInternal *) cur_op)->first = op;
56
 
  }
57
 
}
58
 
 
59
 
static inline void
60
 
cache_op(AIOCallback * op)
61
 
{
62
 
 
63
 
  DWORD bytes_trans;
64
 
 
65
 
  // make op continuation share op->action's mutex
66
 
  op->mutex = op->action.mutex;
67
 
 
68
 
  // construct a continuation to handle the io completion
69
 
  NTCompletionEvent *ce = NTCompletionEvent_alloc(op);
70
 
  OVERLAPPED *overlapped = ce->get_overlapped();
71
 
  overlapped->Offset = (unsigned long) (op->aiocb.aio_offset & 0xFFFFFFFF);
72
 
  overlapped->OffsetHigh = (unsigned long)
73
 
    (op->aiocb.aio_offset >> 32) & 0xFFFFFFFF;
74
 
  // do the io
75
 
  BOOL ret;
76
 
  switch (op->aiocb.aio_lio_opcode) {
77
 
  case LIO_READ:
78
 
    ret = ReadFile((HANDLE) op->aiocb.aio_fildes,
79
 
                   op->aiocb.aio_buf, (unsigned long) op->aiocb.aio_nbytes, &bytes_trans, overlapped);
80
 
    break;
81
 
  case LIO_WRITE:
82
 
    ret = WriteFile((HANDLE) op->aiocb.aio_fildes,
83
 
                    op->aiocb.aio_buf, (unsigned long) op->aiocb.aio_nbytes, &bytes_trans, overlapped);
84
 
    break;
85
 
  default:
86
 
    ink_debug_assert(!"unknown aio_lio_opcode");
87
 
  }
88
 
  DWORD lerror = GetLastError();
89
 
  if (ret == FALSE && lerror != ERROR_IO_PENDING) {
90
 
 
91
 
    op->aio_result = -((int) lerror);
92
 
    eventProcessor.schedule_imm(op);
93
 
  }
94
 
 
95
 
}
96
 
 
97
 
int
98
 
ink_aio_read(AIOCallback * op)
99
 
{
100
 
  init_op_sequence(op, LIO_READ);
101
 
  cache_op(op);
102
 
  return 1;
103
 
}
104
 
 
105
 
int
106
 
ink_aio_write(AIOCallback * op)
107
 
{
108
 
  init_op_sequence(op, LIO_WRITE);
109
 
  cache_op(op);
110
 
  return 1;
111
 
}
112
 
 
113
 
 
114
 
struct AIOMissEvent:Continuation
115
 
{
116
 
  AIOCallback *cb;
117
 
 
118
 
  int mainEvent(int event, Event * e)
119
 
  {
120
 
    if (!cb->action.cancelled)
121
 
      cb->action.continuation->handleEvent(AIO_EVENT_DONE, cb);
122
 
    delete this;
123
 
      return EVENT_DONE;
124
 
  }
125
 
 
126
 
  AIOMissEvent(ProxyMutex * amutex, AIOCallback * acb)
127
 
  : Continuation(amutex), cb(acb)
128
 
  {
129
 
    SET_HANDLER(&AIOMissEvent::mainEvent);
130
 
  }
131
 
};
132
 
 
133
 
int
134
 
AIOCallbackInternal::io_complete(int event, void *data)
135
 
{
136
 
 
137
 
  int lerror;
138
 
  NTCompletionEvent *ce = (NTCompletionEvent *) data;
139
 
 
140
 
  // if aio_result is set, the original Read/Write call failed
141
 
  if (!aio_result) {
142
 
    lerror = ce->lerror;
143
 
    aio_result = lerror ? -lerror : ce->_bytes_transferred;
144
 
  }
145
 
  // handle io errors
146
 
  if ((lerror != 0) && aio_err_callbck) {
147
 
    // schedule aio_err_callbck to be called-back
148
 
    // FIXME: optimization, please... ^_^
149
 
    AIOCallback *op = NEW(new AIOCallbackInternal());
150
 
    op->aiocb.aio_fildes = aiocb.aio_fildes;
151
 
    op->action = aio_err_callbck;
152
 
    eventProcessor.schedule_imm(NEW(new AIOMissEvent(op->action.mutex, op)));
153
 
  } else {
154
 
    ink_debug_assert(ce->_bytes_transferred == aiocb.aio_nbytes);
155
 
  }
156
 
 
157
 
  if (then) {
158
 
    // more op's in this sequence
159
 
    cache_op(then);
160
 
  } else {
161
 
    // we're done! callback action
162
 
    if (!first->action.cancelled) {
163
 
      first->action.continuation->handleEvent(AIO_EVENT_DONE, first);
164
 
    }
165
 
  }
166
 
 
167
 
  return 0;
168
 
}