bool StandardSerialPortBackend::writeRawFrame(const QByteArray &data) { // qDebug() << "!d" << tr("DBG -- Serial Port writeRawFrame..."); DWORD result; OVERLAPPED ov; memset(&ov, 0, sizeof(ov)); ov.hEvent = CreateEvent(0, true, false, 0); if (!PurgeComm(mHandle, PURGE_TXCLEAR)) { qCritical() << "!e" << tr("Cannot clear serial port write buffer: %1").arg(lastErrorMessage()); return false; } if (!WriteFile(mHandle, data.constData(), data.size(), &result, &ov)) { if (GetLastError() == ERROR_IO_PENDING) { if (!GetOverlappedResult(mHandle, &ov, &result, true)) { qCritical() << "!e" << tr("Cannot write to serial port: %1").arg(lastErrorMessage()); CloseHandle(ov.hEvent); return false; } } else { qCritical() << "!e" << tr("Cannot write to serial port: %1").arg(lastErrorMessage()); return false; } } CloseHandle(ov.hEvent); if (result != (DWORD)data.size()) { qCritical() << "!e" << tr("Serial port write timeout."); return false; } return true; }
void DatabaseSync::changeVersion(const String& oldVersion, const String& newVersion, PassOwnPtr<SQLTransactionSyncCallback> changeVersionCallback, ExceptionState& exceptionState) { ASSERT(m_executionContext->isContextThread()); if (sqliteDatabase().transactionInProgress()) { reportChangeVersionResult(1, SQLError::DATABASE_ERR, 0); setLastErrorMessage("unable to changeVersion from within a transaction"); exceptionState.throwUninformativeAndGenericDOMException(SQLDatabaseError); return; } RefPtr<SQLTransactionSync> transaction = SQLTransactionSync::create(this, changeVersionCallback, false); transaction->begin(exceptionState); if (exceptionState.hadException()) { ASSERT(!lastErrorMessage().isEmpty()); return; } String actualVersion; if (!getVersionFromDatabase(actualVersion)) { reportChangeVersionResult(2, SQLError::UNKNOWN_ERR, sqliteDatabase().lastError()); setLastErrorMessage("unable to read the current version", sqliteDatabase().lastError(), sqliteDatabase().lastErrorMsg()); exceptionState.throwDOMException(UnknownError, SQLError::unknownErrorMessage); return; } if (actualVersion != oldVersion) { reportChangeVersionResult(3, SQLError::VERSION_ERR, 0); setLastErrorMessage("current version of the database and `oldVersion` argument do not match"); exceptionState.throwDOMException(VersionError, SQLError::versionErrorMessage); return; } transaction->execute(exceptionState); if (exceptionState.hadException()) { ASSERT(!lastErrorMessage().isEmpty()); return; } if (!setVersionInDatabase(newVersion)) { reportChangeVersionResult(4, SQLError::UNKNOWN_ERR, sqliteDatabase().lastError()); setLastErrorMessage("unable to set the new version", sqliteDatabase().lastError(), sqliteDatabase().lastErrorMsg()); exceptionState.throwDOMException(UnknownError, SQLError::unknownErrorMessage); return; } transaction->commit(exceptionState); if (exceptionState.hadException()) { ASSERT(!lastErrorMessage().isEmpty()); setCachedVersion(oldVersion); return; } reportChangeVersionResult(0, -1, 0); // OK setExpectedVersion(newVersion); setLastErrorMessage(""); }
QByteArray StandardSerialPortBackend::readRawFrame(uint size, bool verbose) { // qDebug() << "!d" << tr("DBG -- Serial Port readRawFrame..."); QByteArray data; DWORD result; if(mMethod==HANDSHAKE_SOFTWARE) { data.resize(size); if (!ReadFile(mHandle, data.data(), size, &result, NULL) || (result != (DWORD)size)) { data.clear(); } } else { OVERLAPPED ov; memset(&ov, 0, sizeof(ov)); ov.hEvent = CreateEvent(0, true, false, 0); if (ov.hEvent == INVALID_HANDLE_VALUE) { qCritical() << "!e" << tr("Cannot create event: %1").arg(lastErrorMessage()); return data; } data.resize(size); if (!ReadFile(mHandle, data.data(), size, &result, &ov)) { if (GetLastError() == ERROR_IO_PENDING) { if (!GetOverlappedResult(mHandle, &ov, &result, true)) { qCritical() << "!e" << tr("Cannot read from serial port: %1").arg(lastErrorMessage()); data.clear(); CloseHandle(ov.hEvent); return data; } } else { qCritical() << "!e" << tr("Cannot read from serial port: %1").arg(lastErrorMessage()); data.clear(); CloseHandle(ov.hEvent); return data; } } CloseHandle(ov.hEvent); if (result != (DWORD)size) { if(verbose) { qCritical() << "!e" << tr("Serial port read timeout."); } data.clear(); return data; } } return data; }
void Dispatcher::dispatch() { NativeContext* context; for (;;) { if (firstResumingContext != nullptr) { context = firstResumingContext; firstResumingContext = context->next; break; } epoll_event event; int count = epoll_wait(epoll, &event, 1, -1); if (count == 1) { ContextPair *contextPair = static_cast<ContextPair*>(event.data.ptr); if(((event.events & (EPOLLIN | EPOLLOUT)) != 0) && contextPair->readContext == nullptr && contextPair->writeContext == nullptr) { uint64_t buf; auto transferred = read(remoteSpawnEvent, &buf, sizeof buf); if(transferred == -1) { throw std::runtime_error("Dispatcher::dispatch, read(remoteSpawnEvent) failed, " + lastErrorMessage()); } MutextGuard guard(*reinterpret_cast<pthread_mutex_t*>(this->mutex)); while (!remoteSpawningProcedures.empty()) { spawn(std::move(remoteSpawningProcedures.front())); remoteSpawningProcedures.pop(); } continue; } if ((event.events & EPOLLOUT) != 0) { context = contextPair->writeContext->context; contextPair->writeContext->events = event.events; } else if ((event.events & EPOLLIN) != 0) { context = contextPair->readContext->context; contextPair->readContext->events = event.events; } else { continue; } assert(context != nullptr); break; } if (errno != EINTR) { throw std::runtime_error("Dispatcher::dispatch, epoll_wait failed, " + lastErrorMessage()); } } if (context != currentContext) { ucontext_t* oldContext = static_cast<ucontext_t*>(currentContext->ucontext); currentContext = context; if (swapcontext(oldContext, static_cast<ucontext_t *>(context->ucontext)) == -1) { throw std::runtime_error("Dispatcher::dispatch, swapcontext failed, " + lastErrorMessage()); } } }
void DatabaseSync::changeVersion(const String& oldVersion, const String& newVersion, PassRefPtr<SQLTransactionSyncCallback> changeVersionCallback, ExceptionCode& ec) { ASSERT(m_scriptExecutionContext->isContextThread()); if (sqliteDatabase().transactionInProgress()) { reportChangeVersionResult(1, SQLException::DATABASE_ERR, 0); setLastErrorMessage("unable to changeVersion from within a transaction"); ec = SQLException::DATABASE_ERR; return; } RefPtr<SQLTransactionSync> transaction = SQLTransactionSync::create(this, changeVersionCallback, false); if ((ec = transaction->begin())) { ASSERT(!lastErrorMessage().isEmpty()); return; } String actualVersion; if (!getVersionFromDatabase(actualVersion)) { reportChangeVersionResult(2, SQLException::UNKNOWN_ERR, sqliteDatabase().lastError()); setLastErrorMessage("unable to read the current version", sqliteDatabase().lastError(), sqliteDatabase().lastErrorMsg()); ec = SQLException::UNKNOWN_ERR; return; } if (actualVersion != oldVersion) { reportChangeVersionResult(3, SQLException::VERSION_ERR, 0); setLastErrorMessage("current version of the database and `oldVersion` argument do not match"); ec = SQLException::VERSION_ERR; return; } if ((ec = transaction->execute())) { ASSERT(!lastErrorMessage().isEmpty()); return; } if (!setVersionInDatabase(newVersion)) { reportChangeVersionResult(4, SQLException::UNKNOWN_ERR, sqliteDatabase().lastError()); setLastErrorMessage("unable to set the new version", sqliteDatabase().lastError(), sqliteDatabase().lastErrorMsg()); ec = SQLException::UNKNOWN_ERR; return; } if ((ec = transaction->commit())) { ASSERT(!lastErrorMessage().isEmpty()); setCachedVersion(oldVersion); return; } reportChangeVersionResult(0, -1, 0); // OK setExpectedVersion(newVersion); setLastErrorMessage(""); }
Dispatcher::Dispatcher() { std::string message; epoll = ::epoll_create1(0); if (epoll == -1) { message = "epoll_create1 failed, " + lastErrorMessage(); } else { mainContext.ucontext = new ucontext_t; if (getcontext(reinterpret_cast<ucontext_t*>(mainContext.ucontext)) == -1) { message = "getcontext failed, " + lastErrorMessage(); } else { remoteSpawnEvent = eventfd(0, O_NONBLOCK); if(remoteSpawnEvent == -1) { message = "eventfd failed, " + lastErrorMessage(); } else { remoteSpawnEventContext.writeContext = nullptr; remoteSpawnEventContext.readContext = nullptr; epoll_event remoteSpawnEventEpollEvent; remoteSpawnEventEpollEvent.events = EPOLLIN; remoteSpawnEventEpollEvent.data.ptr = &remoteSpawnEventContext; if (epoll_ctl(epoll, EPOLL_CTL_ADD, remoteSpawnEvent, &remoteSpawnEventEpollEvent) == -1) { message = "epoll_ctl failed, " + lastErrorMessage(); } else { *reinterpret_cast<pthread_mutex_t*>(this->mutex) = pthread_mutex_t(PTHREAD_MUTEX_INITIALIZER); mainContext.interrupted = false; mainContext.group = &contextGroup; mainContext.groupPrev = nullptr; mainContext.groupNext = nullptr; contextGroup.firstContext = nullptr; contextGroup.lastContext = nullptr; contextGroup.firstWaiter = nullptr; contextGroup.lastWaiter = nullptr; currentContext = &mainContext; firstResumingContext = nullptr; firstReusableContext = nullptr; runningContextCount = 0; return; } auto result = close(remoteSpawnEvent); assert(result == 0); } } auto result = close(epoll); assert(result == 0); } throw std::runtime_error("Dispatcher::Dispatcher, "+message); }
Dispatcher::Dispatcher() { static_assert(sizeof(CRITICAL_SECTION) == sizeof(Dispatcher::criticalSection), "CRITICAL_SECTION size doesn't fit sizeof(Dispatcher::criticalSection)"); BOOL result = InitializeCriticalSectionAndSpinCount(reinterpret_cast<LPCRITICAL_SECTION>(criticalSection), 4000); assert(result != FALSE); std::string message; if (ConvertThreadToFiberEx(NULL, 0) == NULL) { message = "ConvertThreadToFiberEx failed, " + lastErrorMessage(); } else { completionPort = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 0); if (completionPort == NULL) { message = "CreateIoCompletionPort failed, " + lastErrorMessage(); } else { WSADATA wsaData; int wsaResult = WSAStartup(0x0202, &wsaData); if (wsaResult != 0) { message = "WSAStartup failed, " + errorMessage(wsaResult); } else { remoteNotificationSent = false; reinterpret_cast<LPOVERLAPPED>(remoteSpawnOverlapped)->hEvent = NULL; threadId = GetCurrentThreadId(); mainContext.fiber = GetCurrentFiber(); mainContext.interrupted = false; mainContext.group = &contextGroup; mainContext.groupPrev = nullptr; mainContext.groupNext = nullptr; mainContext.inExecutionQueue = false; contextGroup.firstContext = nullptr; contextGroup.lastContext = nullptr; contextGroup.firstWaiter = nullptr; contextGroup.lastWaiter = nullptr; currentContext = &mainContext; firstResumingContext = nullptr; firstReusableContext = nullptr; runningContextCount = 0; return; } BOOL result2 = CloseHandle(completionPort); assert(result2 == TRUE); } BOOL result2 = ConvertFiberToThread(); assert(result == TRUE); } DeleteCriticalSection(reinterpret_cast<LPCRITICAL_SECTION>(criticalSection)); throw std::runtime_error("Dispatcher::Dispatcher, " + message); }
void Timer::sleep(std::chrono::nanoseconds duration) { assert(dispatcher != nullptr); assert(context == nullptr); if (dispatcher->interrupted()) { throw InterruptedException(); } OperationContext timerContext; timerContext.context = dispatcher->getCurrentContext(); timerContext.interrupted = false; timer = dispatcher->getTimer(); struct kevent event; EV_SET(&event, timer, EVFILT_TIMER, EV_ADD | EV_ENABLE | EV_ONESHOT, NOTE_NSECONDS, duration.count(), &timerContext); if (kevent(dispatcher->getKqueue(), &event, 1, NULL, 0, NULL) == -1) { throw std::runtime_error("Timer::stop, kevent failed, " + lastErrorMessage()); } context = &timerContext; dispatcher->getCurrentContext()->interruptProcedure = [&] { assert(dispatcher != nullptr); assert(context != nullptr); OperationContext* timerContext = static_cast<OperationContext*>(context); if (!timerContext->interrupted) { struct kevent event; EV_SET(&event, timer, EVFILT_TIMER, EV_DELETE, 0, 0, NULL); if (kevent(dispatcher->getKqueue(), &event, 1, NULL, 0, NULL) == -1) { throw std::runtime_error("Timer::stop, kevent failed, " + lastErrorMessage()); } dispatcher->pushContext(timerContext->context); timerContext->interrupted = true; } }; dispatcher->dispatch(); dispatcher->getCurrentContext()->interruptProcedure = nullptr; assert(dispatcher != nullptr); assert(timerContext.context == dispatcher->getCurrentContext()); assert(context == &timerContext); context = nullptr; timerContext.context = nullptr; dispatcher->pushTimer(timer); if (timerContext.interrupted) { throw InterruptedException(); } }
void DatabaseSync::rollbackTransaction(PassRefPtr<SQLTransactionSync> transaction) { ASSERT(!lastErrorMessage().isEmpty()); transaction->rollback(); setLastErrorMessage(""); return; }
void Dispatcher::contextProcedure(void* ucontext) { assert(firstReusableContext == nullptr); NativeContext context; context.ucontext = ucontext; context.interrupted = false; context.next = nullptr; firstReusableContext = &context; ucontext_t* oldContext = static_cast<ucontext_t*>(context.ucontext); if (swapcontext(oldContext, static_cast<ucontext_t*>(currentContext->ucontext)) == -1) { throw std::runtime_error("Dispatcher::contextProcedure, swapcontext failed, " + lastErrorMessage()); } for (;;) { ++runningContextCount; try { context.procedure(); } catch(std::exception&) { } if (context.group != nullptr) { if (context.groupPrev != nullptr) { assert(context.groupPrev->groupNext == &context); context.groupPrev->groupNext = context.groupNext; if (context.groupNext != nullptr) { assert(context.groupNext->groupPrev == &context); context.groupNext->groupPrev = context.groupPrev; } else { assert(context.group->lastContext == &context); context.group->lastContext = context.groupPrev; } } else { assert(context.group->firstContext == &context); context.group->firstContext = context.groupNext; if (context.groupNext != nullptr) { assert(context.groupNext->groupPrev == &context); context.groupNext->groupPrev = nullptr; } else { assert(context.group->lastContext == &context); if (context.group->firstWaiter != nullptr) { if (firstResumingContext != nullptr) { assert(lastResumingContext->next == nullptr); lastResumingContext->next = context.group->firstWaiter; } else { firstResumingContext = context.group->firstWaiter; } lastResumingContext = context.group->lastWaiter; context.group->firstWaiter = nullptr; } } } pushReusableContext(context); } dispatch(); } };
std::pair<Ipv4Address, uint16_t> TcpConnection::getPeerAddressAndPort() const { sockaddr_in addr; socklen_t size = sizeof(addr); if (getpeername(connection, reinterpret_cast<sockaddr*>(&addr), &size) != 0) { throw std::runtime_error("TcpConnection::getPeerAddress, getpeername failed, " + lastErrorMessage()); } assert(size == sizeof(sockaddr_in)); return std::make_pair(Ipv4Address(htonl(addr.sin_addr.s_addr)), htons(addr.sin_port)); }
void Dispatcher::remoteSpawn(std::function<void()>&& procedure) { { MutextGuard guard(*reinterpret_cast<pthread_mutex_t*>(this->mutex)); remoteSpawningProcedures.push(std::move(procedure)); } uint64_t one = 1; auto transferred = write(remoteSpawnEvent, &one, sizeof one); if(transferred == - 1) { throw std::runtime_error("Dispatcher::remoteSpawn, write failed, " + lastErrorMessage()); } }
void StandardSerialPortBackend::close() { // qDebug() << "!d" << tr("DBG -- Serial Port Close..."); cancel(); if (!CloseHandle(mHandle)) { qCritical() << "!e" << tr("Cannot close serial port: %1").arg(lastErrorMessage()); } CloseHandle(mCancelHandle); mCancelHandle = mHandle = INVALID_HANDLE_VALUE; }
void Dispatcher::yield() { for(;;){ epoll_event events[16]; int count = epoll_wait(epoll, events, 16, 0); if (count == 0) { break; } if(count > 0) { for(int i = 0; i < count; ++i) { ContextPair *contextPair = static_cast<ContextPair*>(events[i].data.ptr); if(((events[i].events & (EPOLLIN | EPOLLOUT)) != 0) && contextPair->readContext == nullptr && contextPair->writeContext == nullptr) { uint64_t buf; auto transferred = read(remoteSpawnEvent, &buf, sizeof buf); if(transferred == -1) { throw std::runtime_error("Dispatcher::dispatch, read(remoteSpawnEvent) failed, " + lastErrorMessage()); } MutextGuard guard(*reinterpret_cast<pthread_mutex_t*>(this->mutex)); while (!remoteSpawningProcedures.empty()) { spawn(std::move(remoteSpawningProcedures.front())); remoteSpawningProcedures.pop(); } continue; } if ((events[i].events & EPOLLOUT) != 0) { contextPair->writeContext->context->interruptProcedure = nullptr; pushContext(contextPair->writeContext->context); contextPair->writeContext->events = events[i].events; } else if ((events[i].events & EPOLLIN) != 0) { contextPair->readContext->context->interruptProcedure = nullptr; pushContext(contextPair->readContext->context); contextPair->readContext->events = events[i].events; } else { continue; } } } else { if (errno != EINTR) { throw std::runtime_error("Dispatcher::dispatch, epoll_wait failed, " + lastErrorMessage()); } } } if (firstResumingContext != nullptr) { pushContext(currentContext); dispatch(); } }
/* * Set a multiphase mixture to a state of chemical equilibrium. * This is the top-level driver for multiphase equilibrium. It * doesn't do much more than call the equilibrate method of class * MultiPhase, except that it adds some messages to the logfile, * if loglevel is set > 0. * * @ingroup equil */ doublereal equilibrate(MultiPhase& s, const char* XY, doublereal tol, int maxsteps, int maxiter, int loglevel) { if (loglevel > 0) { beginLogGroup("equilibrate",loglevel); addLogEntry("multiphase equilibrate function"); beginLogGroup("arguments"); addLogEntry("XY",XY); addLogEntry("tol",tol); addLogEntry("maxsteps",maxsteps); addLogEntry("maxiter",maxiter); addLogEntry("loglevel",loglevel); endLogGroup("arguments"); } s.init(); int ixy = _equilflag(XY); if (ixy == TP || ixy == HP || ixy == SP || ixy == TV) { try { double err = s.equilibrate(ixy, tol, maxsteps, maxiter, loglevel); if (loglevel > 0) { addLogEntry("Success. Error",err); endLogGroup("equilibrate"); } return err; } catch (CanteraError &err) { if (loglevel > 0) { addLogEntry("Failure.",lastErrorMessage()); endLogGroup("equilibrate"); } throw err; } } else { if (loglevel > 0) { addLogEntry("multiphase equilibrium can be done only for TP, HP, SP, or TV"); endLogGroup("equilibrate"); } throw CanteraError("equilibrate","unsupported option"); return -1.0; } return 0.0; }
void DatabaseSync::runTransaction(PassRefPtr<SQLTransactionSyncCallback> callback, bool readOnly, ExceptionCode& ec) { ASSERT(m_scriptExecutionContext->isContextThread()); if (sqliteDatabase().transactionInProgress()) { setLastErrorMessage("unable to start a transaction from within a transaction"); ec = SQLException::DATABASE_ERR; return; } RefPtr<SQLTransactionSync> transaction = SQLTransactionSync::create(this, callback, readOnly); if ((ec = transaction->begin()) || (ec = transaction->execute()) || (ec = transaction->commit())) { ASSERT(!lastErrorMessage().isEmpty()); transaction->rollback(); } setLastErrorMessage(""); }
void Dispatcher::clear() { while (firstReusableContext != nullptr) { auto ucontext = static_cast<ucontext_t*>(firstReusableContext->ucontext); auto stackPtr = static_cast<uint8_t *>(firstReusableContext->stackPtr); firstReusableContext = firstReusableContext->next; delete[] stackPtr; delete ucontext; } while (!timers.empty()) { int result = ::close(timers.top()); if (result == -1) { throw std::runtime_error("Dispatcher::clear, close failed, " + lastErrorMessage()); } timers.pop(); } }
int Dispatcher::getTimer() { int timer; if (timers.empty()) { timer = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK); epoll_event timerEvent; timerEvent.events = 0; timerEvent.data.ptr = nullptr; if (epoll_ctl(getEpoll(), EPOLL_CTL_ADD, timer, &timerEvent) == -1) { throw std::runtime_error("Dispatcher::getTimer, epoll_ctl failed, " + lastErrorMessage()); } } else { timer = timers.top(); timers.pop(); } return timer; }
TcpListener& TcpListener::operator=(TcpListener&& other) { if (dispatcher != nullptr) { assert(context == nullptr); if (close(listener) == -1) { throw std::runtime_error("TcpListener::operator=, close failed, " + lastErrorMessage()); } } dispatcher = other.dispatcher; if (other.dispatcher != nullptr) { assert(other.context == nullptr); listener = other.listener; context = nullptr; other.dispatcher = nullptr; } return *this; }
/* * * @param s The MultiPhase object to be set to an equilibrium state * @param iphase Phase index within the multiphase object to be * tested for stability. * @param funcStab Function value that tests equilibrium. > 0 indicates stable * < 0 indicates unstable * * @param printLvl Determines the amount of printing that * gets sent to stdout from the vcs package * (Note, you may have to compile with debug * flags to get some printing). * * @param loglevel Controls amount of diagnostic output. loglevel * = 0 suppresses diagnostics, and increasingly-verbose * messages are written as loglevel increases. The * messages are written to a file in HTML format for viewing * in a web browser. @see HTML_logs */ int vcs_determine_PhaseStability(MultiPhase& s, int iphase, double& funcStab, int printLvl, int loglevel) { int iStab = 0; static int counter = 0; beginLogGroup("PhaseStability",loglevel); addLogEntry("multiphase phase stability function"); beginLogGroup("arguments"); addLogEntry("iphase",iphase); addLogEntry("loglevel",loglevel); endLogGroup("arguments"); int printLvlSub = std::max(0, printLvl-1); s.init(); try { VCSnonideal::vcs_MultiPhaseEquil* eqsolve = new VCSnonideal::vcs_MultiPhaseEquil(&s, printLvlSub); iStab = eqsolve->determine_PhaseStability(iphase, funcStab, printLvlSub, loglevel); if (iStab != 0) { addLogEntry("Phase is stable - ", iphase); } else { addLogEntry("Phase is not stable - ", iphase); } endLogGroup("PhaseStability"); // hard code a csv output file. if (printLvl > 0) { string reportFile = "vcs_phaseStability.csv"; if (counter > 0) { reportFile = "vcs_phaseStability_" + int2str(counter) + ".csv"; } eqsolve->reportCSV(reportFile); counter++; } delete eqsolve; } catch (CanteraError& e) { addLogEntry("Failure.", lastErrorMessage()); endLogGroup("equilibrate"); throw e; } return iStab; }
TcpListener::TcpListener(Dispatcher& dispatcher, const Ipv4Address& addr, uint16_t port) : dispatcher(&dispatcher) { std::string message; listener = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if (listener == -1) { message = "socket failed, " + lastErrorMessage(); } else { int flags = fcntl(listener, F_GETFL, 0); if (flags == -1 || (fcntl(listener, F_SETFL, flags | O_NONBLOCK) == -1)) { message = "fcntl failed, " + lastErrorMessage(); } else { int on = 1; if (setsockopt(listener, SOL_SOCKET, SO_REUSEADDR, &on, sizeof on) == -1) { message = "setsockopt failed, " + lastErrorMessage(); } else { sockaddr_in address; address.sin_family = AF_INET; address.sin_port = htons(port); address.sin_addr.s_addr = htonl(addr.getValue()); if (bind(listener, reinterpret_cast<sockaddr*>(&address), sizeof address) != 0) { message = "bind failed, " + lastErrorMessage(); } else if (listen(listener, SOMAXCONN) != 0) { message = "listen failed, " + lastErrorMessage(); } else { struct kevent event; EV_SET(&event, listener, EVFILT_READ, EV_ADD | EV_DISABLE | EV_CLEAR, 0, SOMAXCONN, NULL); if (kevent(dispatcher.getKqueue(), &event, 1, NULL, 0, NULL) == -1) { message = "kevent failed, " + lastErrorMessage(); } else { context = nullptr; return; } } } } if (close(listener) == -1) { message = "close failed, " + lastErrorMessage(); } } throw std::runtime_error("TcpListener::TcpListener, " + message); }
TcpConnection& TcpConnection::operator=(TcpConnection&& other) { if (dispatcher != nullptr) { assert(readContext == nullptr); assert(writeContext == nullptr); if (close(connection) == -1) { throw std::runtime_error("TcpConnection::operator=, close failed, " + lastErrorMessage()); } } dispatcher = other.dispatcher; if (other.dispatcher != nullptr) { assert(other.readContext == nullptr); assert(other.writeContext == nullptr); connection = other.connection; readContext = nullptr; writeContext = nullptr; other.dispatcher = nullptr; } return *this; }
TcpListener::TcpListener(Dispatcher& dispatcher, const Ipv4Address& address, uint16_t port) : dispatcher(&dispatcher) { std::string message; listener = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if (listener == INVALID_SOCKET) { message = "socket failed, " + errorMessage(WSAGetLastError()); } else { sockaddr_in addressData; addressData.sin_family = AF_INET; addressData.sin_port = htons(port); addressData.sin_addr.S_un.S_addr = htonl(address.getValue()); if (bind(listener, reinterpret_cast<sockaddr*>(&addressData), sizeof(addressData)) != 0) { message = "bind failed, " + errorMessage(WSAGetLastError()); } else if (listen(listener, SOMAXCONN) != 0) { message = "listen failed, " + errorMessage(WSAGetLastError()); } else { GUID guidAcceptEx = WSAID_ACCEPTEX; DWORD read = sizeof acceptEx; if (acceptEx == nullptr && WSAIoctl(listener, SIO_GET_EXTENSION_FUNCTION_POINTER, &guidAcceptEx, sizeof guidAcceptEx, &acceptEx, sizeof acceptEx, &read, NULL, NULL) != 0) { message = "WSAIoctl failed, " + errorMessage(WSAGetLastError()); } else { assert(read == sizeof acceptEx); if (CreateIoCompletionPort(reinterpret_cast<HANDLE>(listener), dispatcher.getCompletionPort(), 0, 0) != dispatcher.getCompletionPort()) { message = "CreateIoCompletionPort failed, " + lastErrorMessage(); } else { context = nullptr; return; } } } int result = closesocket(listener); assert(result == 0); } throw std::runtime_error("TcpListener::TcpListener, " + message); }
TcpListener::TcpListener(Dispatcher& dispatcher, const Ipv4Address& addr, uint16_t port) : dispatcher(&dispatcher) { std::string message; listener = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if (listener == -1) { message = "socket failed, " + lastErrorMessage(); } else { int flags = fcntl(listener, F_GETFL, 0); if (flags == -1 || fcntl(listener, F_SETFL, flags | O_NONBLOCK) == -1) { message = "fcntl failed, " + lastErrorMessage(); } else { int on = 1; if (setsockopt(listener, SOL_SOCKET, SO_REUSEADDR, &on, sizeof on) == -1) { message = "setsockopt failed, " + lastErrorMessage(); } else { sockaddr_in address; address.sin_family = AF_INET; address.sin_port = htons(port); address.sin_addr.s_addr = htonl( addr.getValue()); if (bind(listener, reinterpret_cast<sockaddr *>(&address), sizeof address) != 0) { message = "bind failed, " + lastErrorMessage(); } else if (listen(listener, SOMAXCONN) != 0) { message = "listen failed, " + lastErrorMessage(); } else { epoll_event listenEvent; listenEvent.events = 0; listenEvent.data.ptr = nullptr; if (epoll_ctl(dispatcher.getEpoll(), EPOLL_CTL_ADD, listener, &listenEvent) == -1) { message = "epoll_ctl failed, " + lastErrorMessage(); } else { context = nullptr; return; } } } } int result = close(listener); assert(result != -1); } throw std::runtime_error("TcpListener::TcpListener, " + message); }
TcpConnection TcpListener::accept() { assert(dispatcher != nullptr); assert(context == nullptr); if (dispatcher->interrupted()) { throw InterruptedException(); } std::string message; SOCKET connection = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if (connection == INVALID_SOCKET) { message = "socket failed, " + errorMessage(WSAGetLastError()); } else { uint8_t addresses[sizeof sockaddr_in * 2 + 32]; DWORD received; TcpListenerContext context2; context2.hEvent = NULL; if (acceptEx(listener, connection, addresses, 0, sizeof(sockaddr_in) + 16, sizeof(sockaddr_in) + 16, &received, &context2) == TRUE) { message = "AcceptEx returned immediately, which is not supported."; } else { int lastError = WSAGetLastError(); if (lastError != WSA_IO_PENDING) { message = "AcceptEx failed, " + errorMessage(lastError); } else { context2.context = dispatcher->getCurrentContext(); context2.interrupted = false; context = &context2; dispatcher->getCurrentContext()->interruptProcedure = [&]() { assert(dispatcher != nullptr); assert(context != nullptr); TcpListenerContext* context2 = static_cast<TcpListenerContext*>(context); if (!context2->interrupted) { if (CancelIoEx(reinterpret_cast<HANDLE>(listener), context2) != TRUE) { DWORD lastError = GetLastError(); if (lastError != ERROR_NOT_FOUND) { throw std::runtime_error("TcpListener::stop, CancelIoEx failed, " + lastErrorMessage()); } context2->context->interrupted = true; } context2->interrupted = true; } }; dispatcher->dispatch(); dispatcher->getCurrentContext()->interruptProcedure = nullptr; assert(context2.context == dispatcher->getCurrentContext()); assert(dispatcher != nullptr); assert(context == &context2); context = nullptr; DWORD transferred; DWORD flags; if (WSAGetOverlappedResult(listener, &context2, &transferred, FALSE, &flags) != TRUE) { lastError = WSAGetLastError(); if (lastError != ERROR_OPERATION_ABORTED) { message = "AcceptEx failed, " + errorMessage(lastError); } else { assert(context2.interrupted); if (closesocket(connection) != 0) { throw std::runtime_error("TcpListener::accept, closesocket failed, " + errorMessage(WSAGetLastError())); } else { throw InterruptedException(); } } } else { assert(transferred == 0); assert(flags == 0); if (setsockopt(connection, SOL_SOCKET, SO_UPDATE_ACCEPT_CONTEXT, reinterpret_cast<char*>(&listener), sizeof listener) != 0) { message = "setsockopt failed, " + errorMessage(WSAGetLastError()); } else { if (CreateIoCompletionPort(reinterpret_cast<HANDLE>(connection), dispatcher->getCompletionPort(), 0, 0) != dispatcher->getCompletionPort()) { message = "CreateIoCompletionPort failed, " + lastErrorMessage(); } else { return TcpConnection(*dispatcher, connection); } } } } } int result = closesocket(connection); assert(result == 0); } throw std::runtime_error("TcpListener::accept, " + message); }
void Timer::sleep(std::chrono::nanoseconds duration) { assert(dispatcher != nullptr); assert(context == nullptr); if (dispatcher->interrupted()) { throw InterruptedException(); } if(duration.count() == 0 ) { dispatcher->yield(); } else { timer = dispatcher->getTimer(); auto seconds = std::chrono::duration_cast<std::chrono::seconds>(duration); itimerspec expires; expires.it_interval.tv_nsec = expires.it_interval.tv_sec = 0; expires.it_value.tv_sec = seconds.count(); expires.it_value.tv_nsec = std::chrono::duration_cast<std::chrono::nanoseconds>(duration - seconds).count(); timerfd_settime(timer, 0, &expires, NULL); ContextPair contextPair; OperationContext timerContext; timerContext.interrupted = false; timerContext.context = dispatcher->getCurrentContext(); contextPair.writeContext = nullptr; contextPair.readContext = &timerContext; epoll_event timerEvent; timerEvent.events = EPOLLIN | EPOLLONESHOT; timerEvent.data.ptr = &contextPair; if (epoll_ctl(dispatcher->getEpoll(), EPOLL_CTL_MOD, timer, &timerEvent) == -1) { throw std::runtime_error("Timer::sleep, epoll_ctl failed, " + lastErrorMessage()); } dispatcher->getCurrentContext()->interruptProcedure = [&]() { assert(dispatcher != nullptr); assert(context != nullptr); OperationContext* timerContext = static_cast<OperationContext*>(context); if (!timerContext->interrupted) { uint64_t value = 0; if(::read(timer, &value, sizeof value) == -1 ){ #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wlogical-op" if(errno == EAGAIN || errno == EWOULDBLOCK) { #pragma GCC diagnostic pop timerContext->interrupted = true; dispatcher->pushContext(timerContext->context); } else { throw std::runtime_error("Timer::sleep, interrupt procedure, read failed, " + lastErrorMessage()); } } else { assert(value>0); dispatcher->pushContext(timerContext->context); } epoll_event timerEvent; timerEvent.events = EPOLLONESHOT; timerEvent.data.ptr = nullptr; if (epoll_ctl(dispatcher->getEpoll(), EPOLL_CTL_MOD, timer, &timerEvent) == -1) { throw std::runtime_error("Timer::sleep, interrupt procedure, epoll_ctl failed, " + lastErrorMessage()); } } }; context = &timerContext; dispatcher->dispatch(); dispatcher->getCurrentContext()->interruptProcedure = nullptr; assert(dispatcher != nullptr); assert(timerContext.context == dispatcher->getCurrentContext()); assert(contextPair.writeContext == nullptr); assert(context == &timerContext); context = nullptr; timerContext.context = nullptr; dispatcher->pushTimer(timer); if (timerContext.interrupted) { throw InterruptedException(); } } }
TcpConnection TcpConnector::connect(const Ipv4Address& address, uint16_t port) { assert(dispatcher != nullptr); assert(context == nullptr); if (dispatcher->interrupted()) { throw InterruptedException(); } std::string message; SOCKET connection = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if (connection == INVALID_SOCKET) { message = "socket failed, " + errorMessage(WSAGetLastError()); } else { sockaddr_in bindAddress; bindAddress.sin_family = AF_INET; bindAddress.sin_port = 0; bindAddress.sin_addr.s_addr = INADDR_ANY; if (bind(connection, reinterpret_cast<sockaddr*>(&bindAddress), sizeof bindAddress) != 0) { message = "bind failed, " + errorMessage(WSAGetLastError()); } else { GUID guidConnectEx = WSAID_CONNECTEX; DWORD read = sizeof connectEx; if (connectEx == nullptr && WSAIoctl(connection, SIO_GET_EXTENSION_FUNCTION_POINTER, &guidConnectEx, sizeof guidConnectEx, &connectEx, sizeof connectEx, &read, NULL, NULL) != 0) { message = "WSAIoctl failed, " + errorMessage(WSAGetLastError()); } else { assert(read == sizeof connectEx); if (CreateIoCompletionPort(reinterpret_cast<HANDLE>(connection), dispatcher->getCompletionPort(), 0, 0) != dispatcher->getCompletionPort()) { message = "CreateIoCompletionPort failed, " + lastErrorMessage(); } else { sockaddr_in addressData; addressData.sin_family = AF_INET; addressData.sin_port = htons(port); addressData.sin_addr.S_un.S_addr = htonl(address.getValue()); TcpConnectorContext context2; context2.hEvent = NULL; if (connectEx(connection, reinterpret_cast<sockaddr*>(&addressData), sizeof addressData, NULL, 0, NULL, &context2) == TRUE) { message = "ConnectEx returned immediately, which is not supported."; } else { int lastError = WSAGetLastError(); if (lastError != WSA_IO_PENDING) { message = "ConnectEx failed, " + errorMessage(lastError); } else { context2.context = dispatcher->getCurrentContext(); context2.connection = connection; context2.interrupted = false; context = &context2; dispatcher->getCurrentContext()->interruptProcedure = [&]() { assert(dispatcher != nullptr); assert(context != nullptr); TcpConnectorContext* context2 = static_cast<TcpConnectorContext*>(context); if (!context2->interrupted) { if (CancelIoEx(reinterpret_cast<HANDLE>(context2->connection), context2) != TRUE) { DWORD lastError = GetLastError(); if (lastError != ERROR_NOT_FOUND) { throw std::runtime_error("TcpConnector::stop, CancelIoEx failed, " + lastErrorMessage()); } context2->context->interrupted = true; } context2->interrupted = true; } }; dispatcher->dispatch(); dispatcher->getCurrentContext()->interruptProcedure = nullptr; assert(context2.context == dispatcher->getCurrentContext()); assert(context2.connection == connection); assert(dispatcher != nullptr); assert(context == &context2); context = nullptr; DWORD transferred; DWORD flags; if (WSAGetOverlappedResult(connection, &context2, &transferred, FALSE, &flags) != TRUE) { lastError = WSAGetLastError(); if (lastError != ERROR_OPERATION_ABORTED) { message = "ConnectEx failed, " + errorMessage(lastError); } else { assert(context2.interrupted); if (closesocket(connection) != 0) { throw std::runtime_error("TcpConnector::connect, closesocket failed, " + errorMessage(WSAGetLastError())); } else { throw InterruptedException(); } } } else { assert(transferred == 0); assert(flags == 0); DWORD value = 1; if (setsockopt(connection, SOL_SOCKET, SO_UPDATE_CONNECT_CONTEXT, reinterpret_cast<char*>(&value), sizeof(value)) != 0) { message = "setsockopt failed, " + errorMessage(WSAGetLastError()); } else { return TcpConnection(*dispatcher, connection); } } } } } } } int result = closesocket(connection); assert(result == 0); } throw std::runtime_error("TcpConnector::connect, " + message); }
TcpConnection TcpConnector::connect(const Ipv4Address& address, uint16_t port) { assert(dispatcher != nullptr); assert(context == nullptr); if (dispatcher->interrupted()) { throw InterruptedException(); } std::string message; int connection = ::socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if (connection == -1) { message = "socket failed, " + lastErrorMessage(); } else { sockaddr_in bindAddress; bindAddress.sin_family = AF_INET; bindAddress.sin_port = 0; bindAddress.sin_addr.s_addr = INADDR_ANY; if (bind(connection, reinterpret_cast<sockaddr*>(&bindAddress), sizeof bindAddress) != 0) { message = "bind failed, " + lastErrorMessage(); } else { int flags = fcntl(connection, F_GETFL, 0); if (flags == -1 || fcntl(connection, F_SETFL, flags | O_NONBLOCK) == -1) { message = "fcntl failed, " + lastErrorMessage(); } else { sockaddr_in addressData; addressData.sin_family = AF_INET; addressData.sin_port = htons(port); addressData.sin_addr.s_addr = htonl(address.getValue()); int result = ::connect(connection, reinterpret_cast<sockaddr *>(&addressData), sizeof addressData); if (result == -1) { if (errno == EINPROGRESS) { ConnectorContext connectorContext; connectorContext.context = dispatcher->getCurrentContext(); connectorContext.interrupted = false; connectorContext.connection = connection; struct kevent event; EV_SET(&event, connection, EVFILT_WRITE, EV_ADD | EV_ENABLE, 0, 0, &connectorContext); if (kevent(dispatcher->getKqueue(), &event, 1, NULL, 0, NULL) == -1) { message = "kevent failed, " + lastErrorMessage(); } else { context = &connectorContext; dispatcher->getCurrentContext()->interruptProcedure = [&] { assert(dispatcher != nullptr); assert(context != nullptr); ConnectorContext* connectorContext = static_cast<ConnectorContext*>(context); if (!connectorContext->interrupted) { if (close(connectorContext->connection) == -1) { throw std::runtime_error("TcpListener::stop, close failed, " + lastErrorMessage()); } dispatcher->pushContext(connectorContext->context); connectorContext->interrupted = true; } }; dispatcher->dispatch(); dispatcher->getCurrentContext()->interruptProcedure = nullptr; assert(dispatcher != nullptr); assert(connectorContext.context == dispatcher->getCurrentContext()); assert(context == &connectorContext); context = nullptr; connectorContext.context = nullptr; if (connectorContext.interrupted) { throw InterruptedException(); } struct kevent event; EV_SET(&event, connection, EVFILT_WRITE, EV_ADD | EV_DISABLE, 0, 0, NULL); if (kevent(dispatcher->getKqueue(), &event, 1, NULL, 0, NULL) == -1) { message = "kevent failed, " + lastErrorMessage(); } else { int retval = -1; socklen_t retValLen = sizeof(retval); int s = getsockopt(connection, SOL_SOCKET, SO_ERROR, &retval, &retValLen); if (s == -1) { message = "getsockopt failed, " + lastErrorMessage(); } else { if (retval != 0) { message = "getsockopt failed, " + lastErrorMessage(); } else { return TcpConnection(*dispatcher, connection); } } } } } } else { return TcpConnection(*dispatcher, connection); } } } int result = close(connection); if (result) {} assert(result != -1);; } throw std::runtime_error("TcpConnector::connect, " + message); }
/* * This function uses the vcs_MultiPhaseEquil interface to the * vcs solver. * The function uses the element abundance vector that is * currently consistent with the composition within the phases * themselves. Two other thermodynamic quantities, determined by the * XY string, are held constant during the equilibration. * * @param s The object to set to an equilibrium state * * @param XY An integer specifying the two properties to be held * constant. * * @param estimateEquil integer indicating whether the solver * should estimate its own initial condition. * If 0, the initial mole fraction vector * in the %ThermoPhase object is used as the * initial condition. * If 1, the initial mole fraction vector * is used if the element abundances are * satisfied. * if -1, the initial mole fraction vector * is thrown out, and an estimate is * formulated. * * @param printLvl Determines the amount of printing that * gets sent to stdout from the vcs package * (Note, you may have to compile with debug * flags to get some printing). * * @param maxsteps The maximum number of steps to take to find * the solution. * * @param maxiter For the MultiPhaseEquil solver only, this is * the maximum number of outer temperature or * pressure iterations to take when T and/or P is * not held fixed. * * @param loglevel Controls amount of diagnostic output. loglevel * = 0 suppresses diagnostics, and increasingly-verbose * messages are written as loglevel increases. The * messages are written to a file in HTML format for viewing * in a web browser. @see HTML_logs * * @ingroup equilfunctions */ int vcs_equilibrate_1(MultiPhase& s, int ixy, int estimateEquil, int printLvl, int solver, doublereal tol, int maxsteps, int maxiter, int loglevel) { static int counter = 0; int retn = 1; beginLogGroup("equilibrate",loglevel); addLogEntry("multiphase equilibrate function"); beginLogGroup("arguments"); addLogEntry("XY",ixy); addLogEntry("tol",tol); addLogEntry("maxsteps",maxsteps); addLogEntry("maxiter",maxiter); addLogEntry("loglevel",loglevel); endLogGroup("arguments"); int printLvlSub = std::max(0, printLvl-1); s.init(); if (solver == 2) { try { VCSnonideal::vcs_MultiPhaseEquil* eqsolve = new VCSnonideal::vcs_MultiPhaseEquil(&s, printLvlSub); int err = eqsolve->equilibrate(ixy, estimateEquil, printLvlSub, tol, maxsteps, loglevel); if (err != 0) { retn = -1; addLogEntry("vcs_equilibrate Error - ", err); } else { addLogEntry("vcs_equilibrate Success - ", err); } endLogGroup("equilibrate"); // hard code a csv output file. if (printLvl > 0) { string reportFile = "vcs_equilibrate_res.csv"; if (counter > 0) { reportFile = "vcs_equilibrate_res_" + int2str(counter) + ".csv"; } eqsolve->reportCSV(reportFile); counter++; } delete eqsolve; } catch (CanteraError& e) { e.save(); retn = -1; addLogEntry("Failure.", lastErrorMessage()); endLogGroup("equilibrate"); throw e; } } else if (solver == 1) { if (ixy == TP || ixy == HP || ixy == SP || ixy == TV) { try { double err = s.equilibrate(ixy, tol, maxsteps, maxiter, loglevel); addLogEntry("Success. Error",err); endLogGroup("equilibrate"); return 0; } catch (CanteraError& e) { e.save(); addLogEntry("Failure.",lastErrorMessage()); endLogGroup("equilibrate"); throw e; } } else { addLogEntry("multiphase equilibrium can be done only for TP, HP, SP, or TV"); endLogGroup("equilibrate"); throw CanteraError("equilibrate","unsupported option"); //return -1.0; } } else { throw CanteraError("vcs_equilibrate_1", "unknown solver"); } return retn; }
TcpConnection TcpListener::accept() { assert(dispatcher != nullptr); assert(context == nullptr); if (dispatcher->interrupted()) { throw InterruptedException(); } ContextPair contextPair; OperationContext listenerContext; listenerContext.interrupted = false; listenerContext.context = dispatcher->getCurrentContext(); contextPair.writeContext = nullptr; contextPair.readContext = &listenerContext; epoll_event listenEvent; listenEvent.events = EPOLLIN | EPOLLONESHOT; listenEvent.data.ptr = &contextPair; std::string message; if (epoll_ctl(dispatcher->getEpoll(), EPOLL_CTL_MOD, listener, &listenEvent) == -1) { message = "epoll_ctl failed, " + lastErrorMessage(); } else { context = &listenerContext; dispatcher->getCurrentContext()->interruptProcedure = [&]() { assert(dispatcher != nullptr); assert(context != nullptr); OperationContext* listenerContext = static_cast<OperationContext*>(context); if (!listenerContext->interrupted) { epoll_event listenEvent; listenEvent.events = 0; listenEvent.data.ptr = nullptr; if (epoll_ctl(dispatcher->getEpoll(), EPOLL_CTL_MOD, listener, &listenEvent) == -1) { throw std::runtime_error("TcpListener::stop, epoll_ctl failed, " + lastErrorMessage() ); } listenerContext->interrupted = true; dispatcher->pushContext(listenerContext->context); } }; dispatcher->dispatch(); dispatcher->getCurrentContext()->interruptProcedure = nullptr; assert(dispatcher != nullptr); assert(listenerContext.context == dispatcher->getCurrentContext()); assert(contextPair.writeContext == nullptr); assert(context == &listenerContext); context = nullptr; listenerContext.context = nullptr; if (listenerContext.interrupted) { throw InterruptedException(); } if((listenerContext.events & (EPOLLERR | EPOLLHUP)) != 0) { throw std::runtime_error("TcpListener::accept, accepting failed"); } sockaddr inAddr; socklen_t inLen = sizeof(inAddr); int connection = ::accept(listener, &inAddr, &inLen); if (connection == -1) { message = "accept failed, " + lastErrorMessage(); } else { int flags = fcntl(connection, F_GETFL, 0); if (flags == -1 || fcntl(connection, F_SETFL, flags | O_NONBLOCK) == -1) { message = "fcntl failed, " + lastErrorMessage(); } else { return TcpConnection(*dispatcher, connection); } int result = close(connection); assert(result != -1); } } throw std::runtime_error("TcpListener::accept, " + message); }