diff --git a/pvAccessApp/remote/codec.cpp b/pvAccessApp/remote/codec.cpp index f523737..72d6304 100644 --- a/pvAccessApp/remote/codec.cpp +++ b/pvAccessApp/remote/codec.cpp @@ -153,7 +153,13 @@ namespace epics { if (!readToBuffer(PVA_MESSAGE_HEADER_SIZE, false)) { return; } - + + /* + hexDump("Header", (const int8*)_socketBuffer->getArray(), + _socketBuffer->getPosition(), PVA_MESSAGE_HEADER_SIZE); + + */ + // read header fields processHeader(); bool isControl = ((_flags & 0x01) == 0x01); @@ -166,8 +172,13 @@ namespace epics { bool notFirstSegment = (_flags & 0x20) != 0; if (notFirstSegment) { + // not-first segmented message with zero payload is "kind of" valid + // TODO this should check if previous message was first- or middle-segmented message + if (_payloadSize == 0) + continue; + LOG(logLevelWarn, - "Not-a-frst segmented message received in normal mode" + "Not-a-first segmented message received in normal mode" " from the client at %s:%d: %s, disconnecting...", __FILE__, __LINE__, inetAddressToString(*getLastReadBufferSocketAddress()).c_str()); invalidDataStreamHandler(); diff --git a/pvAccessApp/server/responseHandlers.cpp b/pvAccessApp/server/responseHandlers.cpp index fda46aa..d1b94da 100644 --- a/pvAccessApp/server/responseHandlers.cpp +++ b/pvAccessApp/server/responseHandlers.cpp @@ -1610,7 +1610,7 @@ void ServerArrayHandler::handleResponse(osiSockAddr* responseFrom, ServerChannelArrayRequesterImpl::ServerChannelArrayRequesterImpl( ServerContextImpl::shared_pointer const & context, ServerChannelImpl::shared_pointer const & channel, const pvAccessID ioid, Transport::shared_pointer const & transport): - BaseChannelRequester(context, channel, ioid, transport), _channelArray(), _pvArray() + BaseChannelRequester(context, channel, ioid, transport) { } @@ -1643,7 +1643,7 @@ void ServerChannelArrayRequesterImpl::channelArrayConnect(const Status& status, if (status.isSuccess()) { - _pvArray = std::tr1::static_pointer_cast(reuseOrCreatePVField(_array, _pvArray)); + _pvPutArray = std::tr1::static_pointer_cast(reuseOrCreatePVField(_array, _pvPutArray)); } TransportSender::shared_pointer thisSender = shared_from_this(); @@ -1738,7 +1738,7 @@ ChannelArray::shared_pointer ServerChannelArrayRequesterImpl::getChannelArray() PVArray::shared_pointer ServerChannelArrayRequesterImpl::getPVArray() { //Lock guard(_mutex); - return _pvArray; + return _pvPutArray; } void ServerChannelArrayRequesterImpl::send(ByteBuffer* buffer, TransportSendControl* control) diff --git a/pvAccessApp/server/responseHandlers.h b/pvAccessApp/server/responseHandlers.h index 66d7e3c..01d23aa 100644 --- a/pvAccessApp/server/responseHandlers.h +++ b/pvAccessApp/server/responseHandlers.h @@ -605,7 +605,13 @@ namespace pvAccess { private: ChannelArray::shared_pointer _channelArray; epics::pvData::Array::const_shared_pointer _array; + + // reference store epics::pvData::PVArray::shared_pointer _pvArray; + + // data container + epics::pvData::PVArray::shared_pointer _pvPutArray; + std::size_t _length; std::size_t _capacity; epics::pvData::Status _status; diff --git a/testApp/remote/channelAccessIFTest.cpp b/testApp/remote/channelAccessIFTest.cpp index bbc5f32..b5999b0 100755 --- a/testApp/remote/channelAccessIFTest.cpp +++ b/testApp/remote/channelAccessIFTest.cpp @@ -1823,7 +1823,7 @@ void ChannelAccessIFTest::test_channelArray() { // first get to get pvArray bool succStatus = arrayReq->syncGet(false, 0, 0, getTimeoutSec()); if (!succStatus) { - testFail("%s: an array syncGet failed (3) ", CURRENT_FUNCTION); + testFail("%s: an array syncGet failed (0) ", CURRENT_FUNCTION); return; } diff --git a/testApp/remote/testServer.cpp b/testApp/remote/testServer.cpp index b0b8fed..bbc7db2 100644 --- a/testApp/remote/testServer.cpp +++ b/testApp/remote/testServer.cpp @@ -19,6 +19,7 @@ #include #include +#include // TODO temp #include "testADCSim.cpp" @@ -921,7 +922,7 @@ static ChannelProcess::shared_pointer getChannelProcess( Channel::shared_pointer const & channel, PVStructure::shared_pointer const & pvRequest) { - PVScalar::shared_pointer pvScalar = pvRequest->getSubField("record._options.process"); + PVScalar::shared_pointer pvScalar = pvRequest->getSubField("record.process"); if (pvScalar && pvScalar->getAs()) { std::tr1::shared_ptr cpr(new ChannelProcessRequesterImpl()); @@ -1089,6 +1090,7 @@ protected: m_channelProcess(getChannelProcess(channel, pvRequest)) { PVACCESS_REFCOUNT_MONITOR_CONSTRUCT(mockChannelPut); + m_bitSet->set(0); // TODO } public: @@ -1112,7 +1114,14 @@ public: virtual void put(PVStructure::shared_pointer const & pvPutStructure, BitSet::shared_pointer const & putBitSet) { - // TODO data - do an actual put !!! + // TODO use putBitSet and do not copy all + // (note that server code has already not deserialized fields whose bits are not set) + if (putBitSet->cardinality()) + { + lock(); + getConvert()->copy(pvPutStructure, m_pvStructure); + unlock(); + } if (m_channelProcess) m_channelProcess->process(); @@ -1127,6 +1136,7 @@ public: virtual void get() { + // NOTE: alwasy returns entire m_bitSet m_channelPutRequester->getDone(Status::Ok, shared_from_this(), m_pvStructure, m_bitSet); if (m_lastRequest.get()) @@ -1226,7 +1236,14 @@ public: virtual void putGet(PVStructure::shared_pointer const & pvPutStructure, BitSet::shared_pointer const & putBitSet) { - // TODO !!! copy what was put... + // TODO use putBitSet and do not copy all + // (note that server code has already not deserialized fields whose bits are not set) + if (putBitSet->cardinality()) + { + lock(); + getConvert()->copy(pvPutStructure, m_putStructure); + unlock(); + } if (m_channelProcess) m_channelProcess->process(); @@ -1902,9 +1919,12 @@ public: { if (capacity > 0) { m_pvStructureArray->setCapacity(capacity); + m_pvStructureArray->setLength(length > capacity ? capacity : length); + } + else + { + m_pvStructureArray->setLength(length); } - - m_pvStructureArray->setLength(length); m_channelArrayRequester->setLengthDone(Status::Ok, shared_from_this());