136 lines
3.5 KiB
C++
136 lines
3.5 KiB
C++
/*
|
|
* Licensed to the Apache Software Foundation (ASF) under one
|
|
* or more contributor license agreements. See the NOTICE file
|
|
* distributed with this work for additional information
|
|
* regarding copyright ownership. The ASF licenses this file
|
|
* to you under the Apache License, Version 2.0 (the
|
|
* "License"); you may not use this file except in compliance
|
|
* with the License. You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing,
|
|
* software distributed under the License is distributed on an
|
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
|
* KIND, either express or implied. See the License for the
|
|
* specific language governing permissions and limitations
|
|
* under the License.
|
|
*/
|
|
#include "EventLog.h"
|
|
|
|
#include <stdarg.h>
|
|
#include <stdlib.h>
|
|
|
|
using namespace apache::thrift::concurrency;
|
|
|
|
namespace {
|
|
|
|
// Define environment variable DEBUG_EVENTLOG to enable debug logging
|
|
// ex: $ DEBUG_EVENTLOG=1 processor_test
|
|
static const char * DEBUG_EVENTLOG = getenv("DEBUG_EVENTLOG");
|
|
|
|
void debug(const char* fmt, ...) {
|
|
if (DEBUG_EVENTLOG) {
|
|
va_list ap;
|
|
va_start(ap, fmt);
|
|
vfprintf(stderr, fmt, ap);
|
|
va_end(ap);
|
|
|
|
fprintf(stderr, "\n");
|
|
}
|
|
}
|
|
}
|
|
|
|
namespace apache {
|
|
namespace thrift {
|
|
namespace test {
|
|
|
|
uint32_t EventLog::nextId_ = 0;
|
|
|
|
#define EVENT_TYPE(value) EventType EventLog::value = #value
|
|
EVENT_TYPE(ET_LOG_END);
|
|
EVENT_TYPE(ET_CONN_CREATED);
|
|
EVENT_TYPE(ET_CONN_DESTROYED);
|
|
EVENT_TYPE(ET_CALL_STARTED);
|
|
EVENT_TYPE(ET_CALL_FINISHED);
|
|
EVENT_TYPE(ET_PROCESS);
|
|
EVENT_TYPE(ET_PRE_READ);
|
|
EVENT_TYPE(ET_POST_READ);
|
|
EVENT_TYPE(ET_PRE_WRITE);
|
|
EVENT_TYPE(ET_POST_WRITE);
|
|
EVENT_TYPE(ET_ASYNC_COMPLETE);
|
|
EVENT_TYPE(ET_HANDLER_ERROR);
|
|
|
|
EVENT_TYPE(ET_CALL_INCREMENT_GENERATION);
|
|
EVENT_TYPE(ET_CALL_GET_GENERATION);
|
|
EVENT_TYPE(ET_CALL_ADD_STRING);
|
|
EVENT_TYPE(ET_CALL_GET_STRINGS);
|
|
EVENT_TYPE(ET_CALL_GET_DATA_WAIT);
|
|
EVENT_TYPE(ET_CALL_ONEWAY_WAIT);
|
|
EVENT_TYPE(ET_CALL_EXCEPTION_WAIT);
|
|
EVENT_TYPE(ET_CALL_UNEXPECTED_EXCEPTION_WAIT);
|
|
EVENT_TYPE(ET_CALL_SET_VALUE);
|
|
EVENT_TYPE(ET_CALL_GET_VALUE);
|
|
EVENT_TYPE(ET_WAIT_RETURN);
|
|
|
|
EventLog::EventLog() {
|
|
id_ = nextId_++;
|
|
debug("New log: %d", id_);
|
|
}
|
|
|
|
void EventLog::append(EventType type,
|
|
uint32_t connectionId,
|
|
uint32_t callId,
|
|
const std::string& message) {
|
|
Synchronized s(monitor_);
|
|
debug("%d <-- %u, %u, %s \"%s\"", id_, connectionId, callId, type, message.c_str());
|
|
|
|
Event e(type, connectionId, callId, message);
|
|
events_.push_back(e);
|
|
|
|
monitor_.notify();
|
|
}
|
|
|
|
Event EventLog::waitForEvent(int64_t timeout) {
|
|
Synchronized s(monitor_);
|
|
|
|
try {
|
|
while (events_.empty()) {
|
|
monitor_.wait(timeout);
|
|
}
|
|
} catch (const TimedOutException &) {
|
|
return Event(ET_LOG_END, 0, 0, "");
|
|
}
|
|
|
|
Event event = events_.front();
|
|
events_.pop_front();
|
|
return event;
|
|
}
|
|
|
|
Event EventLog::waitForConnEvent(uint32_t connId, int64_t timeout) {
|
|
Synchronized s(monitor_);
|
|
|
|
auto it = events_.begin();
|
|
while (true) {
|
|
try {
|
|
// TODO: it would be nicer to honor timeout for the duration of this
|
|
// call, rather than restarting it for each call to wait(). It shouldn't
|
|
// be a big problem in practice, though.
|
|
while (it == events_.end()) {
|
|
monitor_.wait(timeout);
|
|
}
|
|
} catch (const TimedOutException &) {
|
|
return Event(ET_LOG_END, 0, 0, "");
|
|
}
|
|
|
|
if (it->connectionId == connId) {
|
|
Event event = *it;
|
|
events_.erase(it);
|
|
return event;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
} // apache::thrift::test
|