Files
QTradeProgram/cleaned_source_code/Sqbase/qdatabuffer.cpp

256 lines
7.3 KiB
C++
Raw Normal View History

2026-02-25 23:01:42 +08:00
#include "qdatabuffer.h"
#include <QDebug>
#include <QThread>
#include <QDateTime>
QDataBuffer* QDataBuffer::instance()
{
static QDataBuffer instance;
return &instance;
}
QDataBuffer::QDataBuffer(QObject *parent)
: QObject(parent)
, m_cleanupTimer(new QTimer(this))
, m_statsUpdateTimer(new QTimer(this))
{
m_cleanupTimer->setInterval(30000);
connect(m_cleanupTimer, &QTimer::timeout, this, &QDataBuffer::cleanupExpiredPackets);
m_cleanupTimer->start();
m_statsUpdateTimer->setInterval(1000);
connect(m_statsUpdateTimer, &QTimer::timeout, this, &QDataBuffer::updateStatistics);
m_statsUpdateTimer->start();
m_rateTimer.start();
}
QDataBuffer::~QDataBuffer()
{
m_cleanupTimer->stop();
m_statsUpdateTimer->stop();
}
void QDataBuffer::setBufferSize(int maxSize)
{
QMutexLocker locker(&m_mutex);
m_maxBufferSize = maxSize;
}
void QDataBuffer::setFlowControlEnabled(bool enabled)
{
QMutexLocker locker(&m_mutex);
m_flowControlEnabled = enabled;
}
void QDataBuffer::setMaxPacketsPerSecond(int maxRate)
{
QMutexLocker locker(&m_mutex);
m_maxPacketsPerSecond = maxRate;
}
bool QDataBuffer::enqueue(const DataPacket& packet)
{
QMutexLocker locker(&m_mutex);
if (m_paused) {
emit packetDropped(packet, "Buffer paused");
return false;
}
if (shouldDropPacket(packet)) {
m_stats.droppedPackets++;
emit packetDropped(packet, "Flow control");
return false;
}
if (m_buffer.size() + m_highPriorityBuffer.size() >= m_maxBufferSize) {
m_stats.droppedPackets++;
emit bufferOverflow(packet.stockCode, packet.type);
emit packetDropped(packet, "Buffer overflow");
return false;
}
m_buffer.enqueue(packet);
m_stats.totalPackets++;
m_currentSecondPackets++;
m_notEmpty.wakeOne();
return true;
}
bool QDataBuffer::enqueueHighPriority(const DataPacket& packet)
{
QMutexLocker locker(&m_mutex);
if (m_paused) {
emit packetDropped(packet, "Buffer paused");
return false;
}
if (m_highPriorityBuffer.size() + m_buffer.size() >= m_maxBufferSize) {
m_stats.droppedPackets++;
emit bufferOverflow(packet.stockCode, packet.type);
emit packetDropped(packet, "Buffer overflow");
return false;
}
m_highPriorityBuffer.enqueue(packet);
m_stats.totalPackets++;
m_currentSecondPackets++;
m_notEmpty.wakeOne();
return true;
}
DataPacket QDataBuffer::dequeue(int timeoutMs)
{
QMutexLocker locker(&m_mutex);
while (m_highPriorityBuffer.isEmpty() && m_buffer.isEmpty() && !m_paused) {
if (!m_notEmpty.wait(&m_mutex, timeoutMs)) {
return DataPacket(DataPacketType::Unknown, "", QVariant());
}
}
if (!m_highPriorityBuffer.isEmpty()) {
DataPacket packet = m_highPriorityBuffer.dequeue();
m_stats.processedPackets++;
return packet;
}
if (!m_buffer.isEmpty()) {
DataPacket packet = m_buffer.dequeue();
m_stats.processedPackets++;
return packet;
}
return DataPacket(DataPacketType::Unknown, "", QVariant());
}
QList<DataPacket> QDataBuffer::dequeueBatch(int maxCount, int timeoutMs)
{
QMutexLocker locker(&m_mutex);
QList<DataPacket> result;
while (m_highPriorityBuffer.isEmpty() && m_buffer.isEmpty() && !m_paused) {
if (!m_notEmpty.wait(&m_mutex, timeoutMs)) {
return result;
}
}
while (!m_highPriorityBuffer.isEmpty() && result.size() < maxCount) {
result.append(m_highPriorityBuffer.dequeue());
m_stats.processedPackets++;
}
while (!m_buffer.isEmpty() && result.size() < maxCount) {
result.append(m_buffer.dequeue());
m_stats.processedPackets++;
}
return result;
}
bool QDataBuffer::isEmpty() const
{
QMutexLocker locker(&m_mutex);
return m_highPriorityBuffer.isEmpty() && m_buffer.isEmpty();
}
int QDataBuffer::size() const
{
QMutexLocker locker(&m_mutex);
return m_highPriorityBuffer.size() + m_buffer.size();
}
int QDataBuffer::getQueueSize(DataPacketType type) const
{
QMutexLocker locker(&m_mutex);
int count = 0;
for (const DataPacket& packet : m_highPriorityBuffer) {
if (packet.type == type) {
count++;
}
}
for (const DataPacket& packet : m_buffer) {
if (packet.type == type) {
count++;
}
}
return count;
}
FlowStatistics QDataBuffer::getStatistics() const
{
QMutexLocker locker(&m_mutex);
return m_stats;
}
void QDataBuffer::pause()
{
QMutexLocker locker(&m_mutex);
m_paused = true;
emit flowControlActivated(true);
}
void QDataBuffer::resume()
{
QMutexLocker locker(&m_mutex);
m_paused = false;
m_notEmpty.wakeAll();
emit flowControlActivated(false);
}
bool QDataBuffer::isPaused() const
{
QMutexLocker locker(&m_mutex);
return m_paused;
}
void QDataBuffer::clear()
{
QMutexLocker locker(&m_mutex);
m_highPriorityBuffer.clear();
m_buffer.clear();
}
void QDataBuffer::clearByType(DataPacketType type)
{
QMutexLocker locker(&m_mutex);
QQueue<DataPacket> newHighPriority;
for (const DataPacket& packet : m_highPriorityBuffer) {
if (packet.type != type) {
newHighPriority.enqueue(packet);
}
}
m_highPriorityBuffer = newHighPriority;
QQueue<DataPacket> newBuffer;
for (const DataPacket& packet : m_buffer) {
if (packet.type != type) {
newBuffer.enqueue(packet);
}
}
m_buffer = newBuffer;
}
void QDataBuffer::clearByStock(const QString& stockCode)
{
QMutexLocker locker(&m_mutex);
QQueue<DataPacket> newHighPriority;
for (const DataPacket& packet : m_highPriorityBuffer) {
if (packet.stockCode != stockCode) {
newHighPriority.enqueue(packet);
}
}
m_highPriorityBuffer = newHighPriority;
QQueue<DataPacket> newBuffer;
for (const DataPacket& packet : m_buffer) {
if (packet.stockCode != stockCode) {
newBuffer.enqueue(packet);
}
}
m_buffer = newBuffer;
}
void QDataBuffer::updateStatistics()
{
QMutexLocker locker(&m_mutex);
if (m_rateTimer.elapsed() >= 1000) {
m_stats.packetsPerSecond = static_cast<double>(m_currentSecondPackets) * 1000 / m_rateTimer.elapsed();
m_currentSecondPackets = 0;
m_rateTimer.restart();
}
m_stats.updateStats(m_stats.totalPackets, m_stats.droppedPackets, m_stats.processedPackets);
locker.unlock();
emit statisticsUpdated(m_stats);
}
bool QDataBuffer::shouldDropPacket(const DataPacket& packet) const
{
if (!m_flowControlEnabled) {
return false;
}
if (m_currentSecondPackets >= m_maxPacketsPerSecond) {
return true;
}
return false;
}
void QDataBuffer::cleanupExpiredPackets()
{
QMutexLocker locker(&m_mutex);
QDateTime now = QDateTime::currentDateTime();
QQueue<DataPacket> newHighPriority;
for (const DataPacket& packet : m_highPriorityBuffer) {
if (packet.timestamp.secsTo(now) < 300) {
newHighPriority.enqueue(packet);
}
}
m_highPriorityBuffer = newHighPriority;
QQueue<DataPacket> newBuffer;
for (const DataPacket& packet : m_buffer) {
if (packet.timestamp.secsTo(now) < 120) {
newBuffer.enqueue(packet);
}
}
m_buffer = newBuffer;
}