@@ -18,6 +18,7 @@ limitations under the License.
18
18
19
19
#include < cassert>
20
20
#include < functional>
21
+ #include < iostream>
21
22
#include < thread>
22
23
23
24
#include " ev.h"
@@ -108,11 +109,15 @@ void ConnectionState::writeRequest() {
108
109
void ConnectionState::ConnectAndSend () {
109
110
startTime_ = GetTime ();
110
111
if (needsOpen_) {
111
- int err = Connect ();
112
- mandatoryAssert (err == 0 );
113
- // Should only fail if we can't create a new socket --
114
- // errors actually connecting will be handled during write.
115
- RecordConnectionOpen ();
112
+ const int err = Connect ();
113
+ if (err == 0 ) {
114
+ RecordConnectionOpen ();
115
+ } else {
116
+ std::cerr << " Error opening TCP connection: " << err << std::endl;
117
+ RecordSocketError ();
118
+ sendAfterDelay (kConnectFailureDelay );
119
+ return ;
120
+ }
116
121
}
117
122
writeRequest ();
118
123
SendWrite ();
@@ -127,22 +132,26 @@ void ConnectionState::thinkingDone(struct ev_loop* loop, ev_timer* t,
127
132
128
133
void ConnectionState::addThinkTime () {
129
134
const double thinkTime = (double )(t_->thinkTime ) / 1000.0 ;
130
- io_Verbose (this , " Thinking for %.4lf seconds\n " , thinkTime);
131
- ev_timer_init (&thinkTimer_, thinkingDone, thinkTime, 0 );
135
+ sendAfterDelay (thinkTime);
136
+ }
137
+
138
+ void ConnectionState::sendAfterDelay (double seconds) {
139
+ io_Verbose (this , " Thinking for %.4lf seconds\n " , seconds);
140
+ ev_timer_init (&thinkTimer_, thinkingDone, seconds, 0 );
132
141
thinkTimer_.data = this ;
133
142
ev_timer_start (t_->loop (), &thinkTimer_);
134
143
}
135
144
136
- void ConnectionState::recycle (int closeConn) {
145
+ void ConnectionState::recycle (bool closeConn) {
137
146
if (closeConn || t_->noKeepAlive || !t_->shouldKeepRunning ()) {
138
- needsOpen_ = 1 ;
147
+ needsOpen_ = true ;
139
148
// Close is async, especially for TLS. So we will
140
149
// reconnect later...
141
150
Close ();
142
151
return ;
143
152
}
144
153
145
- needsOpen_ = 0 ;
154
+ needsOpen_ = false ;
146
155
if (t_->thinkTime > 0 ) {
147
156
addThinkTime ();
148
157
} else {
@@ -152,7 +161,7 @@ void ConnectionState::recycle(int closeConn) {
152
161
153
162
int ConnectionState::StartConnect () {
154
163
url_ = URLInfo::GetNext (t_->rand ());
155
- needsOpen_ = 1 ;
164
+ needsOpen_ = true ;
156
165
ConnectAndSend ();
157
166
return 0 ;
158
167
}
@@ -174,7 +183,7 @@ void ConnectionState::WriteDone(int err) {
174
183
if (err != 0 ) {
175
184
RecordSocketError ();
176
185
io_Verbose (this , " Error on write: %i\n " , err);
177
- recycle (1 );
186
+ recycle (true );
178
187
} else {
179
188
io_Verbose (this , " Write complete. Starting to read\n " );
180
189
// Prepare to read.
@@ -191,32 +200,45 @@ void ConnectionState::ReadDone(int err) {
191
200
if (err != 0 ) {
192
201
io_Verbose (this , " Error on read: %i\n " , err);
193
202
RecordSocketError ();
194
- recycle (1 );
203
+ recycle (true );
195
204
return ;
196
205
}
197
206
198
- RecordResult (parser_.status_code );
199
- t_->recordLatency (GetTime () - startTime_);
207
+ t_->recordResult (parser_.status_code , GetTime () - startTime_);
200
208
if (!http_should_keep_alive (&(parser_))) {
201
209
io_Verbose (this , " Server does not want keep-alive\n " );
202
- recycle (1 );
210
+ recycle (true );
203
211
} else {
204
212
const URLInfo* oldUrl = url_;
205
213
url_ = URLInfo::GetNext (t_->rand ());
206
214
if (!URLInfo::IsSameServer (*oldUrl, *url_, t_->index )) {
207
215
io_Verbose (this , " Switching to a different server\n " );
208
216
writeDirty_ = true ;
209
- recycle (1 );
217
+ recycle (true );
210
218
} else {
211
219
// URLs are static throughout the run, so we can just compare pointer here
212
220
if (url_ != oldUrl) {
213
221
writeDirty_ = true ;
214
222
}
215
- recycle (0 );
223
+ recycle (false );
216
224
}
217
225
}
218
226
}
219
227
228
+ void IOThread::recordResult (int statusCode, int_fast64_t latency) {
229
+ Counters* c = getCounters ();
230
+ if ((statusCode >= 200 ) && (statusCode < 300 )) {
231
+ c->successfulRequests ++;
232
+ } else {
233
+ c->failedRequests ++;
234
+ }
235
+ c->latencies .push_back (latency);
236
+ }
237
+
238
+ void IOThread::recordRead (size_t c) { getCounters ()->bytesRead += c; }
239
+
240
+ void IOThread::recordWrite (size_t c) { getCounters ()->bytesWritten += c; }
241
+
220
242
void IOThread::setNumConnections (size_t newVal) {
221
243
iothread_Verbose (this , " Current connections = %zu. New connections = %zu\n " ,
222
244
connections_.size (), newVal);
@@ -277,10 +299,6 @@ void IOThread::processCommands(struct ev_loop* loop, ev_async* a, int revents) {
277
299
278
300
void IOThread::threadLoop () {
279
301
int ret = 0 ;
280
- readCount_ = 0 ;
281
- writeCount_ = 0 ;
282
- readBytes_ = 0 ;
283
- writeBytes_ = 0 ;
284
302
285
303
iothread_Verbose (this , " Starting new event loop %i for %i connection\n " ,
286
304
index , numConnections);
@@ -311,8 +329,6 @@ void IOThread::threadLoop() {
311
329
}
312
330
ret = ev_run (loop_, 0 );
313
331
iothread_Verbose (this , " ev_run finished: %i\n " , ret);
314
- RecordByteCounts (writeBytes_, readBytes_);
315
- RecordLatencies (latencies_);
316
332
317
333
finish:
318
334
iothread_Verbose (this , " Cleaning up event loop %i\n " , index );
@@ -322,13 +338,26 @@ void IOThread::threadLoop() {
322
338
ev_loop_destroy (loop_);
323
339
}
324
340
341
+ IOThread::IOThread () {
342
+ Counters* c = new Counters ();
343
+ counterPtr_.store (reinterpret_cast <uintptr_t >(c));
344
+ }
345
+
325
346
IOThread::~IOThread () {
326
347
if (sslCtx != nullptr ) {
327
348
SSL_CTX_free (sslCtx);
328
349
}
329
350
if (thread_ != nullptr ) {
330
351
delete thread_;
331
352
}
353
+ Counters* c = reinterpret_cast <Counters*>(counterPtr_.load ());
354
+ delete c;
355
+ }
356
+
357
+ Counters* IOThread::exchangeCounters () {
358
+ Counters* newCounters = new Counters ();
359
+ return reinterpret_cast <Counters*>(
360
+ counterPtr_.exchange (reinterpret_cast <uintptr_t >(newCounters)));
332
361
}
333
362
334
363
void IOThread::initializeParser () {
@@ -383,14 +412,4 @@ void IOThread::SetNumConnections(int newConnections) {
383
412
ev_async_send (loop_, &async_);
384
413
}
385
414
386
- void IOThread::recordRead (size_t c) {
387
- readCount_++;
388
- readBytes_ += c;
389
- }
390
-
391
- void IOThread::recordWrite (size_t c) {
392
- writeCount_++;
393
- writeBytes_ += c;
394
- }
395
-
396
415
} // namespace apib
0 commit comments