[ox] Add logconn for Bullock logging
This commit is contained in:
34
deps/ox/src/ox/logconn/CMakeLists.txt
vendored
Normal file
34
deps/ox/src/ox/logconn/CMakeLists.txt
vendored
Normal file
@@ -0,0 +1,34 @@
|
||||
cmake_minimum_required(VERSION 3.10)
|
||||
|
||||
add_library(
|
||||
OxLogConn
|
||||
logconn.cpp
|
||||
)
|
||||
|
||||
set_property(
|
||||
TARGET
|
||||
OxLogConn
|
||||
PROPERTY
|
||||
POSITION_INDEPENDENT_CODE ON
|
||||
)
|
||||
|
||||
target_link_libraries(
|
||||
OxLogConn PUBLIC
|
||||
OxStd
|
||||
OxMetalClaw
|
||||
)
|
||||
|
||||
install(
|
||||
FILES
|
||||
circularbuff.hpp
|
||||
logconn.hpp
|
||||
DESTINATION
|
||||
include/ox/logconn
|
||||
)
|
||||
|
||||
install(
|
||||
TARGETS
|
||||
OxLogConn
|
||||
LIBRARY DESTINATION lib/ox
|
||||
ARCHIVE DESTINATION lib/ox
|
||||
)
|
99
deps/ox/src/ox/logconn/circularbuff.hpp
vendored
Normal file
99
deps/ox/src/ox/logconn/circularbuff.hpp
vendored
Normal file
@@ -0,0 +1,99 @@
|
||||
/*
|
||||
* Copyright 2015 - 2022 gary@drinkingtea.net
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <ox/std/assert.hpp>
|
||||
#include <ox/std/buffer.hpp>
|
||||
#include <ox/std/units.hpp>
|
||||
|
||||
namespace ox::detail {
|
||||
|
||||
class CirculerBuffer {
|
||||
private:
|
||||
std::size_t m_readPt = 0;
|
||||
std::size_t m_writePt = 0;
|
||||
ox::Buffer m_buff = ox::Buffer(ox::units::MB);
|
||||
|
||||
private:
|
||||
[[nodiscard]]
|
||||
constexpr auto avail() const noexcept {
|
||||
if (m_writePt >= m_readPt) {
|
||||
return m_buff.size() - (m_writePt - m_readPt);
|
||||
} else {
|
||||
return (m_buff.size() - m_writePt) - (m_buff.size() - m_readPt);
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
constexpr ox::Error put(char v) noexcept {
|
||||
return write(&v, 1);
|
||||
if (1 > avail()) {
|
||||
return OxError(1, "Insufficient space in buffer");
|
||||
}
|
||||
m_buff[m_writePt] = v;
|
||||
++m_writePt;
|
||||
return {};
|
||||
}
|
||||
|
||||
constexpr ox::Error write(const char *buff, std::size_t sz) noexcept {
|
||||
if (sz > avail()) {
|
||||
return OxError(1, "Insufficient space in buffer");
|
||||
}
|
||||
// write seg 1
|
||||
const auto seg1Sz = ox::min(sz, m_buff.size() - m_writePt);
|
||||
ox_memcpy(&m_buff[m_writePt], &buff[0], seg1Sz);
|
||||
m_writePt += sz;
|
||||
if (seg1Sz != sz) {
|
||||
m_writePt -= m_buff.size();
|
||||
// write seg 2
|
||||
const auto seg2Sz = sz - seg1Sz;
|
||||
ox_memcpy(&m_buff[0], &buff[seg1Sz], seg2Sz);
|
||||
oxAssert(m_buff[0] == buff[seg1Sz], "break");
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
constexpr ox::Error seekp(std::size_t bytesFwd) noexcept {
|
||||
if (bytesFwd > avail()) {
|
||||
return OxError(1, "Insufficient space in buffer to seek that far ahead");
|
||||
}
|
||||
m_writePt += bytesFwd;
|
||||
if (m_writePt > m_buff.size()) {
|
||||
m_writePt -= m_buff.size();
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
constexpr ox::Error seekp(int, ios_base::seekdir) {
|
||||
return OxError(1, "Unimplemented");
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr std::size_t tellp() const noexcept {
|
||||
return m_buff.size() - avail();
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr std::size_t read(char *out, std::size_t outSize) noexcept {
|
||||
const auto bytesRead = ox::min(outSize, m_buff.size() - avail());
|
||||
// read seg 1
|
||||
const auto seg1Sz = ox::min(bytesRead, m_buff.size() - m_readPt);
|
||||
ox_memcpy(&out[0], &m_buff[m_readPt], seg1Sz);
|
||||
m_readPt += bytesRead;
|
||||
if (seg1Sz != bytesRead) {
|
||||
m_readPt -= m_buff.size();
|
||||
// read seg 2
|
||||
const auto seg2Sz = bytesRead - seg1Sz;
|
||||
ox_memcpy(&out[seg1Sz], &m_buff[0], seg2Sz);
|
||||
}
|
||||
return bytesRead;
|
||||
}
|
||||
};
|
||||
|
||||
}
|
90
deps/ox/src/ox/logconn/logconn.cpp
vendored
Normal file
90
deps/ox/src/ox/logconn/logconn.cpp
vendored
Normal file
@@ -0,0 +1,90 @@
|
||||
/*
|
||||
* Copyright 2015 - 2022 gary@drinkingtea.net
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
#ifdef OX_USE_STDLIB
|
||||
#include <sys/socket.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <netinet/in.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
#include <cstdio>
|
||||
|
||||
#include <ox/std/bit.hpp>
|
||||
|
||||
#include "logconn.hpp"
|
||||
|
||||
namespace ox {
|
||||
|
||||
using namespace trace;
|
||||
|
||||
LoggerConn::LoggerConn() noexcept: m_netThread([this]{this->msgSend();}) {
|
||||
}
|
||||
|
||||
LoggerConn::~LoggerConn() noexcept {
|
||||
m_running = false;
|
||||
m_waitCond.notify_one();
|
||||
m_netThread.join();
|
||||
if (m_socket) {
|
||||
close(m_socket);
|
||||
}
|
||||
}
|
||||
|
||||
ox::Error LoggerConn::initConn(const char *appName) noexcept {
|
||||
sockaddr_in addr{};
|
||||
addr.sin_family = AF_INET;
|
||||
addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
|
||||
addr.sin_port = htons(5590);
|
||||
m_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
|
||||
oxReturnError(OxError(connect(m_socket, reinterpret_cast<sockaddr*>(&addr), sizeof(addr))));
|
||||
return sendInit({.appName = appName});
|
||||
}
|
||||
|
||||
ox::Error LoggerConn::send(const char *buff, std::size_t len) const noexcept {
|
||||
std::size_t totalSent = 0;
|
||||
while (totalSent < len) {
|
||||
//std::fprintf(stdout, "Sending %lu/%lu bytes on socket %d\n", len, totalSent, m_socket);
|
||||
const auto sent = ::send(m_socket, buff, len, 0);
|
||||
if (sent < 0) {
|
||||
std::fprintf(stderr, "Could not send msg\n");
|
||||
return OxError(1, "Could not send msg");
|
||||
}
|
||||
totalSent += static_cast<std::size_t>(sent);
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
ox::Error LoggerConn::send(const TraceMsg &msg) noexcept {
|
||||
return send(MsgId::TraceEvent, msg);
|
||||
}
|
||||
|
||||
ox::Error LoggerConn::sendInit(const InitTraceMsg &msg) noexcept {
|
||||
return send(MsgId::Init, msg);
|
||||
}
|
||||
|
||||
void LoggerConn::msgSend() noexcept {
|
||||
while (true) {
|
||||
std::unique_lock lk(m_waitMut);
|
||||
m_waitCond.wait(lk);
|
||||
if (!m_running) {
|
||||
break;
|
||||
}
|
||||
std::lock_guard buffLk(m_buffMut);
|
||||
while (true) {
|
||||
ox::Array<char, ox::units::KB> tmp;
|
||||
const auto read = m_buff.read(tmp.data(), tmp.size());
|
||||
if (!read) {
|
||||
break;
|
||||
}
|
||||
//std::printf("LoggerConn: sending %lu bytes\n", read);
|
||||
oxIgnoreError(send(tmp.data(), read));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
#endif
|
78
deps/ox/src/ox/logconn/logconn.hpp
vendored
Normal file
78
deps/ox/src/ox/logconn/logconn.hpp
vendored
Normal file
@@ -0,0 +1,78 @@
|
||||
/*
|
||||
* Copyright 2015 - 2022 gary@drinkingtea.net
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifdef OX_USE_STDLIB
|
||||
#include <condition_variable>
|
||||
#include <mutex>
|
||||
#include <thread>
|
||||
#endif
|
||||
|
||||
#include <ox/mc/write.hpp>
|
||||
#include <ox/std/trace.hpp>
|
||||
|
||||
#include "circularbuff.hpp"
|
||||
|
||||
namespace ox {
|
||||
|
||||
#ifdef OX_USE_STDLIB
|
||||
class LoggerConn: public trace::Logger {
|
||||
private:
|
||||
int m_socket = 0;
|
||||
detail::CirculerBuffer m_buff;
|
||||
std::thread m_netThread;
|
||||
std::condition_variable m_waitCond;
|
||||
std::mutex m_waitMut;
|
||||
std::mutex m_buffMut;
|
||||
bool m_running = true;
|
||||
public:
|
||||
LoggerConn() noexcept;
|
||||
LoggerConn(const LoggerConn&) noexcept = delete;
|
||||
~LoggerConn() noexcept override;
|
||||
LoggerConn &operator=(const LoggerConn&) noexcept = delete;
|
||||
ox::Error send(const trace::TraceMsg&) noexcept final;
|
||||
ox::Error sendInit(const trace::InitTraceMsg&) noexcept final;
|
||||
ox::Error initConn(const char *appName = "") noexcept;
|
||||
ox::Error send(const char *buff, std::size_t len) const noexcept;
|
||||
private:
|
||||
void msgSend() noexcept;
|
||||
ox::Error send(trace::MsgId msgId, const auto &msg) noexcept {
|
||||
ox::Array<char, 10 * ox::units::KB> buff;
|
||||
std::size_t sz = 0;
|
||||
oxReturnError(ox::writeMC(&buff[0], buff.size(), &msg, &sz));
|
||||
//std::printf("sz: %lu\n", sz);
|
||||
oxRequire(szBuff, serialize(static_cast<uint32_t>(sz)));
|
||||
std::unique_lock buffLk(m_buffMut);
|
||||
oxReturnError(m_buff.put(static_cast<char>(msgId)));
|
||||
oxReturnError(m_buff.write(szBuff.data(), szBuff.size()));
|
||||
oxReturnError(m_buff.write(buff.data(), sz));
|
||||
buffLk.unlock();
|
||||
m_waitCond.notify_one();
|
||||
return {};
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
#else
|
||||
|
||||
class LoggerConn: public trace::Logger {
|
||||
private:
|
||||
public:
|
||||
constexpr LoggerConn() noexcept = default;
|
||||
LoggerConn(const LoggerConn&) noexcept = delete;
|
||||
constexpr ~LoggerConn() noexcept override = default;
|
||||
LoggerConn &operator=(const LoggerConn&) noexcept = delete;
|
||||
ox::Error send(const trace::TraceMsg&) noexcept final { return {}; }
|
||||
static ox::Error initConn() noexcept { return {}; }
|
||||
static ox::Error send(const char*, std::size_t) noexcept { return {}; }
|
||||
};
|
||||
#endif
|
||||
|
||||
}
|
||||
|
Reference in New Issue
Block a user