Compare commits
2 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
ed7bb8bd69 | ||
|
d827e43a11 |
@ -100,7 +100,7 @@ void NoMsgHandler(QtMsgType type, const QMessageLogContext &/*context*/,
|
||||
const QString &msg)
|
||||
{
|
||||
if (type == QtFatalMsg) {
|
||||
fprintf(stderr, qPrintable(msg));
|
||||
fprintf(stderr, "%s\n", qPrintable(msg));
|
||||
fflush(stderr);
|
||||
abort();
|
||||
}
|
||||
|
@ -82,6 +82,9 @@ AbstractProtocol::AbstractProtocol(StreamBase *stream, AbstractProtocol *parent)
|
||||
protoSize = -1;
|
||||
_hasPayload = true;
|
||||
_cacheFlags |= FieldFrameBitOffsetCache;
|
||||
|
||||
// FIXME: temporary for testing only
|
||||
_frameValueCache.isEnabled = qEnvironmentVariableIsSet("PFVCACHE");
|
||||
}
|
||||
|
||||
/*!
|
||||
@ -173,6 +176,36 @@ void AbstractProtocol::commonProtoDataCopyFrom(const OstProto::Protocol &protoco
|
||||
this function. See the SampleProtocol for an example
|
||||
*/
|
||||
|
||||
/*!
|
||||
Update protocol's frame value cacheability based on current protocol
|
||||
configuration
|
||||
*/
|
||||
void AbstractProtocol::updateCacheability()
|
||||
{
|
||||
if (!_frameValueCache.isEnabled
|
||||
|| isProtocolFrameValueVariable()
|
||||
|| isProtocolFrameSizeVariable()
|
||||
|| isProtocolFrameHeaderValueVariable()
|
||||
|| isProtocolFramePayloadValueVariable()
|
||||
|| isProtocolFramePayloadSizeVariable())
|
||||
{
|
||||
// TODO: cache following cases
|
||||
// * isProtocolFrameHeaderValueVariable AND !hasTcpUdpCksum
|
||||
// * isProtocolFramePayloadValueVariable AND !hasPayloadDependentField
|
||||
// * isProtocolFramePayloadSizeVariable AND !hasPayloadDependentField
|
||||
// * External Variables AND !hasCksumField
|
||||
// * streamIndex == 0 for variable frames (value/size)
|
||||
qDebug("Stream %u %6s: FrameValue is NOT cacheable",
|
||||
mpStream->id(), qPrintable(shortName()));
|
||||
_cacheFlags &= ~FrameValueCache; // can't cache frame value
|
||||
}
|
||||
else {
|
||||
qDebug("Stream %u %6s: FrameValue is cacheable",
|
||||
mpStream->id(), qPrintable(shortName()));
|
||||
_cacheFlags |= FrameValueCache; // frame value is cacheable
|
||||
}
|
||||
_frameValueCache.isValid = false;
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns the full name of the protocol
|
||||
@ -517,7 +550,7 @@ quint32 AbstractProtocol::payloadProtocolId(ProtocolIdType type) const
|
||||
Returns the protocol's size in bytes
|
||||
|
||||
The default implementation sums up the individual field bit sizes and
|
||||
returns it. The default implementation calculates the caches the size on
|
||||
returns it. The default implementation calculates and caches the size on
|
||||
the first invocation and subsequently returns the cached size.
|
||||
|
||||
If the subclass protocol has a varying protocol size, it MUST reimplement
|
||||
@ -602,6 +635,17 @@ QByteArray AbstractProtocol::protocolFrameValue(int streamIndex, bool forCksum,
|
||||
QByteArray proto, field;
|
||||
uint bits, lastbitpos = 0;
|
||||
FieldFlags flags;
|
||||
bool cacheable = (_cacheFlags & FrameValueCache) && !forCksum;
|
||||
|
||||
qDebug("Stream %u %6s: In frameValue frameIdx %u forCksum %d cacheable %d",
|
||||
mpStream->id(), qPrintable(shortName()),
|
||||
streamIndex, forCksum, cacheable);
|
||||
if (cacheable && _frameValueCache.isValid)
|
||||
{
|
||||
qDebug("Stream %u %6s: frameIdx %u using FV cache",
|
||||
mpStream->id(), qPrintable(shortName()), streamIndex);
|
||||
return _frameValueCache.value;
|
||||
}
|
||||
|
||||
for (int i=0; i < fieldCount() ; i++)
|
||||
{
|
||||
@ -698,6 +742,17 @@ QByteArray AbstractProtocol::protocolFrameValue(int streamIndex, bool forCksum,
|
||||
varyProtocolFrameValue(proto, streamIndex, vf);
|
||||
}
|
||||
|
||||
if (cacheable)
|
||||
{
|
||||
qDebug("Stream %u %6s: frameIdx %d forCksum %d saving cache",
|
||||
mpStream->id(), qPrintable(shortName()), streamIndex, forCksum);
|
||||
_frameValueCache.value = proto;
|
||||
_frameValueCache.isValid = true;
|
||||
}
|
||||
|
||||
qDebug("Stream %u %6s: frameIdx %d forCksum %d return",
|
||||
mpStream->id(), qPrintable(shortName()), streamIndex, forCksum);
|
||||
|
||||
return proto;
|
||||
}
|
||||
|
||||
@ -777,6 +832,28 @@ bool AbstractProtocol::isProtocolFramePayloadValueVariable() const
|
||||
return false;
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns true if the header content for a protocol varies at run-time,
|
||||
false otherwise
|
||||
|
||||
This is useful for subclasses which have fields dependent on header content
|
||||
(e.g. UDP has a checksum field that varies if the IP header varies)
|
||||
*/
|
||||
bool AbstractProtocol::isProtocolFrameHeaderValueVariable() const
|
||||
{
|
||||
AbstractProtocol *p = prev;
|
||||
|
||||
if (p)
|
||||
{
|
||||
if (p->isProtocolFrameValueVariable())
|
||||
return true;
|
||||
}
|
||||
if (parent && parent->isProtocolFrameHeaderValueVariable())
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns true if the payload size for a protocol varies at run-time,
|
||||
false otherwise
|
||||
|
@ -20,6 +20,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
#ifndef _ABSTRACT_PROTOCOL_H
|
||||
#define _ABSTRACT_PROTOCOL_H
|
||||
|
||||
#include "cache.h"
|
||||
|
||||
#include <QByteArray>
|
||||
#include <QFlags>
|
||||
#include <QHash>
|
||||
@ -53,6 +55,7 @@ private:
|
||||
mutable int protoSize;
|
||||
mutable QString protoAbbr;
|
||||
mutable QHash<int, int> _fieldFrameBitOffset;
|
||||
mutable Cache<QByteArray> _frameValueCache;
|
||||
OstProto::Protocol _data;
|
||||
|
||||
protected:
|
||||
@ -66,7 +69,8 @@ protected:
|
||||
|
||||
//! Caching Control Flags
|
||||
enum CacheFlag {
|
||||
FieldFrameBitOffsetCache = 0x1
|
||||
FieldFrameBitOffsetCache = 0x1,
|
||||
FrameValueCache = 0x2
|
||||
};
|
||||
quint32 _cacheFlags;
|
||||
|
||||
@ -124,6 +128,8 @@ public:
|
||||
virtual void protoDataCopyInto(OstProto::Protocol &protocol) const = 0;
|
||||
virtual void protoDataCopyFrom(const OstProto::Protocol &protocol) = 0;
|
||||
|
||||
void updateCacheability();
|
||||
|
||||
virtual QString name() const;
|
||||
virtual QString shortName() const;
|
||||
|
||||
@ -157,6 +163,7 @@ public:
|
||||
virtual bool isProtocolFrameValueVariable() const;
|
||||
virtual bool isProtocolFrameSizeVariable() const;
|
||||
virtual int protocolFrameVariableCount() const;
|
||||
bool isProtocolFrameHeaderValueVariable() const;
|
||||
bool isProtocolFramePayloadValueVariable() const;
|
||||
bool isProtocolFramePayloadSizeVariable() const;
|
||||
int protocolFramePayloadVariableCount() const;
|
||||
|
31
common/cache.h
Normal file
31
common/cache.h
Normal file
@ -0,0 +1,31 @@
|
||||
/*
|
||||
Copyright (C) 2019 Srivats P.
|
||||
|
||||
This file is part of "Ostinato"
|
||||
|
||||
This is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
#ifndef _CACHE_H
|
||||
#define _CACHE_H
|
||||
|
||||
template <class T>
|
||||
struct Cache
|
||||
{
|
||||
bool isEnabled{false};
|
||||
bool isValid{false};
|
||||
T value;
|
||||
};
|
||||
|
||||
#endif
|
@ -108,6 +108,13 @@ void StreamBase::protoDataCopyFrom(const OstProto::Stream &stream)
|
||||
iter->insert(proto);
|
||||
}
|
||||
|
||||
iter->toFront();
|
||||
while (iter->hasNext())
|
||||
{
|
||||
AbstractProtocol *p = iter->next();
|
||||
p->updateCacheability();
|
||||
}
|
||||
|
||||
delete iter;
|
||||
}
|
||||
|
||||
|
@ -406,9 +406,13 @@ _error_exit2:
|
||||
return;
|
||||
}
|
||||
|
||||
bool logsEnabled = false;
|
||||
void RpcConnection::connIdMsgHandler(QtMsgType /*type*/,
|
||||
const QMessageLogContext &/*context*/, const QString &msg)
|
||||
{
|
||||
if (!logsEnabled)
|
||||
return;
|
||||
|
||||
if (connId.hasLocalData()) {
|
||||
QString newMsg(*connId.localData());
|
||||
newMsg.append(msg);
|
||||
|
@ -771,8 +771,10 @@ void AbstractPort::resolveDeviceNeighbors()
|
||||
for (int i = 0; i < streamList_.size(); i++)
|
||||
{
|
||||
const StreamBase *stream = streamList_.at(i);
|
||||
int frameCount = stream->frameVariableCount();
|
||||
if (!stream->isEnabled())
|
||||
continue;
|
||||
|
||||
int frameCount = stream->frameVariableCount();
|
||||
for (int j = 0; j < frameCount; j++) {
|
||||
// we need the packet contents only uptil the L3 header
|
||||
int pktLen = stream->frameValue(pktBuf_, kMaxL3PktSize, j);
|
||||
|
@ -116,7 +116,7 @@ void NoMsgHandler(QtMsgType type, const QMessageLogContext &/*context*/,
|
||||
const QString &msg)
|
||||
{
|
||||
if (type == QtFatalMsg) {
|
||||
fprintf(stderr, qPrintable(msg));
|
||||
fprintf(stderr, "%s\n", qPrintable(msg));
|
||||
fflush(stderr);
|
||||
abort();
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user