/* * 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 #include 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