mirror of
https://github.com/XTXMarkets/ternfs.git
synced 2025-12-30 23:39:46 -06:00
127 lines
3.6 KiB
C++
127 lines
3.6 KiB
C++
// Copyright 2025 XTX Markets Technologies Limited
|
|
//
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
|
|
#include "XmonAgent.hpp"
|
|
#include "Assert.hpp"
|
|
|
|
#include <iostream>
|
|
#include <fcntl.h>
|
|
|
|
struct XmonRequestHeader {
|
|
int64_t alertId;
|
|
Duration quietPeriod;
|
|
XmonRequestType msgType;
|
|
XmonAppType appType;
|
|
bool binnable;
|
|
uint16_t messageLen;
|
|
};
|
|
|
|
void XmonRequest::write(int fd) const {
|
|
ALWAYS_ASSERT(message.size() < 1<<16);
|
|
XmonRequestHeader header = {
|
|
.alertId = alertId,
|
|
.quietPeriod = quietPeriod,
|
|
.msgType = msgType,
|
|
.appType = appType,
|
|
.binnable = binnable,
|
|
.messageLen = (uint16_t)message.size(),
|
|
};
|
|
static thread_local char buf[PIPE_BUF];
|
|
ALWAYS_ASSERT(sizeof(header) + header.messageLen < PIPE_BUF);
|
|
memcpy(buf, &header, sizeof(header));
|
|
memcpy(buf+sizeof(header), message.data(), header.messageLen);
|
|
{
|
|
// pipe writes of < PIPE_BUF are guaranteed to be atomic, see pipe(7)
|
|
int written = ::write(fd, buf, sizeof(header)+header.messageLen);
|
|
if (written != sizeof(header)+header.messageLen) {
|
|
throw SYSCALL_EXCEPTION("write");
|
|
}
|
|
}
|
|
}
|
|
|
|
bool XmonRequest::read(int fd) {
|
|
static thread_local char buf[PIPE_BUF];
|
|
XmonRequestHeader header;
|
|
int read = ::read(fd, buf, sizeof(header));
|
|
if (read != sizeof(header)) {
|
|
throw SYSCALL_EXCEPTION("read");
|
|
}
|
|
memcpy(&header, buf, sizeof(header));
|
|
appType = header.appType;
|
|
msgType = header.msgType;
|
|
alertId = header.alertId;
|
|
quietPeriod = header.quietPeriod;
|
|
binnable = header.binnable;
|
|
read = ::read(fd, buf, header.messageLen);
|
|
if (read != header.messageLen) {
|
|
throw SYSCALL_EXCEPTION("read");
|
|
}
|
|
buf[header.messageLen] = '\0';
|
|
message = std::string(buf);
|
|
return true;
|
|
}
|
|
|
|
int64_t XmonAgent::_createAlert(XmonAppType appType, bool binnable, Duration quietPeriod, const std::string& message) {
|
|
int64_t aid = _alertId.fetch_add(1);
|
|
XmonRequest req;
|
|
req.appType = appType;
|
|
req.msgType = XmonRequestType::CREATE;
|
|
req.alertId = aid;
|
|
req.binnable = binnable;
|
|
req.message = message;
|
|
req.quietPeriod = quietPeriod;
|
|
req.write(_pipe[1]);
|
|
return aid;
|
|
}
|
|
|
|
XmonAgent::XmonAgent() : _alertId(1) {
|
|
if (pipe(_pipe) < 0) {
|
|
throw SYSCALL_EXCEPTION("pipe");
|
|
}
|
|
if (fcntl(readFd(), F_SETFL, O_NONBLOCK) < 0) {
|
|
throw SYSCALL_EXCEPTION("fcntl");
|
|
}
|
|
}
|
|
|
|
XmonAgent::~XmonAgent() {
|
|
if (close(_pipe[0]) < 0) {
|
|
std::cerr << "Could not close read end of pipe pipe (" << errno << ")" << std::endl;
|
|
}
|
|
if (close(_pipe[1]) < 0) {
|
|
std::cerr << "Could not close write end of pipe pipe (" << errno << ")" << std::endl;
|
|
}
|
|
}
|
|
|
|
void XmonAgent::raiseAlert(XmonAppType appType, const std::string& message) {
|
|
_createAlert(appType, true, 0, message);
|
|
}
|
|
|
|
void XmonAgent::updateAlert(XmonNCAlert& aid, const std::string& message) {
|
|
if (aid.alertId < 0) {
|
|
aid.alertId = _createAlert(aid.appType, false, aid.quietPeriod, message);
|
|
} else {
|
|
XmonRequest req;
|
|
req.appType = aid.appType;
|
|
req.msgType = XmonRequestType::UPDATE;
|
|
req.alertId = aid.alertId;
|
|
req.binnable = false;
|
|
req.message = message;
|
|
req.quietPeriod = 0;
|
|
req.write(_pipe[1]);
|
|
}
|
|
}
|
|
|
|
void XmonAgent::clearAlert(XmonNCAlert& aid) {
|
|
if (likely(aid.alertId < 0)) { return; }
|
|
XmonRequest req;
|
|
req.appType = aid.appType;
|
|
req.msgType = XmonRequestType::CLEAR;
|
|
req.alertId = aid.alertId;
|
|
req.binnable = false;
|
|
req.message = {};
|
|
req.quietPeriod = 0;
|
|
req.write(_pipe[1]);
|
|
aid.alertId = -1;
|
|
}
|