This commit is contained in:
Gasper Jansa
2011-01-10 22:29:59 +01:00
30 changed files with 1287 additions and 827 deletions

View File

@@ -307,7 +307,6 @@
<buildTargets>
<target name="all" path="" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
<buildCommand>make</buildCommand>
<buildArguments/>
<buildTarget>all</buildTarget>
<stopOnError>true</stopOnError>
<useDefaultCommand>true</useDefaultCommand>
@@ -315,7 +314,6 @@
</target>
<target name="clean" path="" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
<buildCommand>make</buildCommand>
<buildArguments/>
<buildTarget>clean</buildTarget>
<stopOnError>true</stopOnError>
<useDefaultCommand>true</useDefaultCommand>
@@ -323,11 +321,20 @@
</target>
<target name="uninstall" path="" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
<buildCommand>make</buildCommand>
<buildArguments/>
<buildTarget>uninstall</buildTarget>
<stopOnError>true</stopOnError>
<useDefaultCommand>true</useDefaultCommand>
<runAllBuilders>false</runAllBuilders>
</target>
<target name="debug" path="" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
<buildCommand>make</buildCommand>
<buildArguments/>
<buildTarget>clean all DEBUG=1</buildTarget>
<stopOnError>true</stopOnError>
<useDefaultCommand>true</useDefaultCommand>
<runAllBuilders>false</runAllBuilders>
</target>
</buildTargets>
</storageModule>
</cconfiguration>

View File

@@ -24,4 +24,11 @@
# take effect.
#IOCS_APPL_TOP = </IOC/path/to/application/top>
USR_LDFLAGS += -lpthread
ifeq ($(DEBUG),1)
DEBUG_CFLAGS=-O0 -g -ggdb
endif
ifeq ($(EPICS_HOST_ARCH),linux-x86)
USR_LDFLAGS += -lpthread
endif

View File

@@ -67,6 +67,12 @@ LIBSRCS += blockingTCPConnector.cpp
LIBSRCS += blockingServerTCPTransport.cpp
LIBSRCS += blockingTCPAcceptor.cpp
LIBSRCS += channelSearchManager.cpp
LIBSRCS += abstractResponseHandler.cpp
SRC_DIRS += $(PVACCESS)/remoteClient
INC += clientContextImpl.h
LIBRARY = pvAccess
pvAccess_LIBS += Com

View File

@@ -0,0 +1,42 @@
/*
* abstractResponseHandler.cpp
*
* Created on: Jan 10, 2011
* Author: Miha Vitorovic
*/
#include "remote.h"
#include "hexDump.h"
#include <byteBuffer.h>
#include <osiSock.h>
#include <sstream>
using std::ostringstream;
using std::hex;
using namespace epics::pvData;
namespace epics {
namespace pvAccess {
void AbstractResponseHandler::handleResponse(osiSockAddr* responseFrom,
Transport* transport, int8 version, int8 command,
int payloadSize, ByteBuffer* payloadBuffer) {
if(_debug) {
char ipAddrStr[48];
ipAddrToDottedIP(&responseFrom->ia, ipAddrStr, sizeof(ipAddrStr));
ostringstream prologue;
prologue<<"Message [0x"<<hex<<(int)command<<", v0x"<<hex;
prologue<<(int)version<<"] received from "<<ipAddrStr;
hexDump(prologue.str(), _description,
(const int8*)payloadBuffer->getArray(),
payloadBuffer->getPosition(), payloadSize);
}
}
}
}

View File

@@ -18,8 +18,9 @@
using namespace epics::pvData;
namespace epics { namespace pvAccess {
//TODO delete this
class ClientContextImpl;
/**
* BeaconHandler
*/

View File

@@ -97,7 +97,7 @@ namespace epics {
if(_closed) return false;
char ipAddrStr[48];
ipAddrToA(&_socketAddress->ia, ipAddrStr, sizeof(ipAddrStr));
ipAddrToDottedIP(&_socketAddress->ia, ipAddrStr, sizeof(ipAddrStr));
errlogSevPrintf(errlogInfo, "Acquiring transport to %s.", ipAddrStr);
_ownersMutex->lock();
@@ -127,7 +127,7 @@ namespace epics {
int refs = _owners->size();
if(refs>0) {
char ipAddrStr[48];
ipAddrToA(&_socketAddress->ia, ipAddrStr, sizeof(ipAddrStr));
ipAddrToDottedIP(&_socketAddress->ia, ipAddrStr, sizeof(ipAddrStr));
errlogSevPrintf(
errlogInfo,
"Transport to %s still has %d client(s) active and closing...",
@@ -145,7 +145,7 @@ namespace epics {
if(_closed) return;
char ipAddrStr[48];
ipAddrToA(&_socketAddress->ia, ipAddrStr, sizeof(ipAddrStr));
ipAddrToDottedIP(&_socketAddress->ia, ipAddrStr, sizeof(ipAddrStr));
errlogSevPrintf(errlogInfo, "Releasing transport to %s.", ipAddrStr);

View File

@@ -52,14 +52,14 @@ namespace epics {
if(_channels->size()==0) return;
char ipAddrStr[64];
ipAddrToA(&_socketAddress->ia, ipAddrStr, sizeof(ipAddrStr));
ipAddrToDottedIP(&_socketAddress->ia, ipAddrStr, sizeof(ipAddrStr));
errlogSevPrintf(
errlogInfo,
"Transport to %s still has %d channel(s) active and closing...",
ipAddrStr, _channels->size());
map<int, ServerChannel*>::iterator it = _channels->begin();
map<pvAccessID, ServerChannel*>::iterator it = _channels->begin();
for(; it!=_channels->end(); it++)
it->second->destroy();
@@ -71,30 +71,30 @@ namespace epics {
destroyAllChannels();
}
int BlockingServerTCPTransport::preallocateChannelSID() {
pvAccessID BlockingServerTCPTransport::preallocateChannelSID() {
Lock lock(_channelsMutex);
// search first free (theoretically possible loop of death)
int sid = ++_lastChannelSID;
pvAccessID sid = ++_lastChannelSID;
while(_channels->find(sid)!=_channels->end())
sid = ++_lastChannelSID;
return sid;
}
void BlockingServerTCPTransport::registerChannel(int sid,
void BlockingServerTCPTransport::registerChannel(pvAccessID sid,
ServerChannel* channel) {
Lock lock(_channelsMutex);
(*_channels)[sid] = channel;
}
void BlockingServerTCPTransport::unregisterChannel(int sid) {
void BlockingServerTCPTransport::unregisterChannel(pvAccessID sid) {
Lock lock(_channelsMutex);
_channels->erase(sid);
}
ServerChannel* BlockingServerTCPTransport::getChannel(int sid) {
ServerChannel* BlockingServerTCPTransport::getChannel(pvAccessID sid) {
Lock lock(_channelsMutex);
map<int, ServerChannel*>::iterator it = _channels->find(sid);
map<pvAccessID, ServerChannel*>::iterator it = _channels->find(sid);
if(it!=_channels->end()) return it->second;
return NULL;

View File

@@ -547,13 +547,13 @@ namespace epics {
* Preallocate new channel SID.
* @return new channel server id (SID).
*/
virtual int preallocateChannelSID();
virtual pvAccessID preallocateChannelSID();
/**
* De-preallocate new channel SID.
* @param sid preallocated channel SID.
*/
virtual void depreallocateChannelSID(int sid) {
virtual void depreallocateChannelSID(pvAccessID sid) {
// noop
}
@@ -562,20 +562,20 @@ namespace epics {
* @param sid preallocated channel SID.
* @param channel channel to register.
*/
virtual void registerChannel(int sid, ServerChannel* channel);
virtual void registerChannel(pvAccessID sid, ServerChannel* channel);
/**
* Unregister a new channel (and deallocates its handle).
* @param sid SID
*/
virtual void unregisterChannel(int sid);
virtual void unregisterChannel(pvAccessID sid);
/**
* Get channel by its SID.
* @param sid channel SID
* @return channel with given SID, <code>NULL</code> otherwise
*/
virtual ServerChannel* getChannel(int sid);
virtual ServerChannel* getChannel(pvAccessID sid);
/**
* Get channel count.
@@ -640,12 +640,12 @@ namespace epics {
/**
* Last SID cache.
*/
volatile int _lastChannelSID;
volatile pvAccessID _lastChannelSID;
/**
* Channel table (SID -> channel mapping).
*/
std::map<int, ServerChannel*>* _channels;
std::map<pvAccessID, ServerChannel*>* _channels;
Mutex* _channelsMutex;

View File

@@ -51,7 +51,7 @@ namespace epics {
char strBuffer[64];
char ipAddrStr[48];
ipAddrToA(&_bindAddress->ia, ipAddrStr, sizeof(ipAddrStr));
ipAddrToDottedIP(&_bindAddress->ia, ipAddrStr, sizeof(ipAddrStr));
int tryCount = 0;
while(tryCount<2) {
@@ -150,7 +150,7 @@ namespace epics {
void BlockingTCPAcceptor::handleEvents() {
// rise level if port is assigned dynamically
char ipAddrStr[48];
ipAddrToA(&_bindAddress->ia, ipAddrStr, sizeof(ipAddrStr));
ipAddrToDottedIP(&_bindAddress->ia, ipAddrStr, sizeof(ipAddrStr));
errlogSevPrintf(errlogInfo, "Accepting connections at %s.",
ipAddrStr);
@@ -183,7 +183,8 @@ namespace epics {
_serverSocketChannel, &address.sa, &len);
if(newClient!=INVALID_SOCKET) {
// accept succeeded
ipAddrToA(&address.ia, ipAddrStr, sizeof(ipAddrStr));
ipAddrToDottedIP(&address.ia, ipAddrStr,
sizeof(ipAddrStr));
errlogSevPrintf(errlogInfo,
"Accepted connection from CA client: %s",
ipAddrStr);
@@ -273,7 +274,8 @@ namespace epics {
if(_serverSocketChannel!=INVALID_SOCKET) {
char ipAddrStr[48];
ipAddrToA(&_bindAddress->ia, ipAddrStr, sizeof(ipAddrStr));
ipAddrToDottedIP(&_bindAddress->ia, ipAddrStr,
sizeof(ipAddrStr));
errlogSevPrintf(errlogInfo,
"Stopped accepting connections at %s.", ipAddrStr);

View File

@@ -38,7 +38,7 @@ namespace epics {
if(tryCount>0) epicsThreadSleep(0.1);
char strBuffer[64];
ipAddrToA(&address.ia, strBuffer, sizeof(strBuffer));
ipAddrToDottedIP(&address.ia, strBuffer, sizeof(strBuffer));
errlogSevPrintf(errlogInfo,
"Opening socket to CA server %s, attempt %d.",
@@ -73,7 +73,7 @@ namespace epics {
SOCKET socket = INVALID_SOCKET;
char ipAddrStr[64];
ipAddrToA(&address.ia, ipAddrStr, sizeof(ipAddrStr));
ipAddrToDottedIP(&address.ia, ipAddrStr, sizeof(ipAddrStr));
// first try to check cache w/o named lock...
BlockingClientTCPTransport
@@ -106,6 +106,17 @@ namespace epics {
ipAddrStr);
socket = tryConnect(address, 3);
// verify
if(socket==INVALID_SOCKET) {
errlogSevPrintf(
errlogMajor,
"Connection to CA server %s failed.",
ipAddrStr);
ostringstream temp;
temp<<"Failed to verify TCP connection to '"<<ipAddrStr
<<"'.";
THROW_BASE_EXCEPTION(temp.str().c_str());
}
// use blocking channel
// socket is blocking bya default
@@ -138,7 +149,7 @@ namespace epics {
if(!transport->waitUntilVerified(3.0)) {
transport->close(true);
errlogSevPrintf(
errlogInfo,
errlogMinor,
"Connection to CA server %s failed to be validated, closing it.",
ipAddrStr);
ostringstream temp;

View File

@@ -24,216 +24,6 @@ using namespace epics::pvData;
namespace epics { namespace pvAccess {
typedef int32 pvAccessID;
enum QoS {
/**
* Default behavior.
*/
DEFAULT = 0x00,
/**
* Require reply (acknowledgment for reliable operation).
*/
REPLY_REQUIRED = 0x01,
/**
* Best-effort option (no reply).
*/
BESY_EFFORT = 0x02,
/**
* Process option.
*/
PROCESS = 0x04,
/**
* Initialize option.
*/
INIT = 0x08,
/**
* Destroy option.
*/
DESTROY = 0x10,
/**
* Share data option.
*/
SHARE = 0x20,
/**
* Get.
*/
GET = 0x40,
/**
* Get-put.
*/
GET_PUT =0x80
};
//TODO this will be deleted
class ChannelImpl;
class ChannelSearchManager;
class ClientContextImpl : public ClientContext
{
private:
Timer* _timer;
public:
ClientContextImpl()
{
_timer = new Timer("krneki",lowPriority);
}
virtual Version* getVersion() {
return NULL;
}
virtual ChannelProvider* getProvider() {
return NULL;
}
Timer* getTimer()
{
return _timer;
}
virtual void initialize() {
}
virtual void printInfo() {
}
virtual void printInfo(epics::pvData::StringBuilder out) {
}
virtual void destroy()
{
}
virtual void dispose()
{
}
BlockingUDPTransport* getSearchTransport()
{
return NULL;
}
/**
* Searches for a channel with given channel ID.
* @param channelID CID.
* @return channel with given CID, <code>0</code> if non-existent.
*/
ChannelImpl* getChannel(pvAccessID channelID)
{
return NULL;
}
~ClientContextImpl() { delete _timer;};
private:
void loadConfiguration() {
}
void internalInitialize() {
}
void initializeUDPTransport() {
}
void internalDestroy() {
}
void destroyAllChannels() {
}
/**
* Check channel name.
*/
void checkChannelName(String& name) {
}
/**
* Check context state and tries to establish necessary state.
*/
void checkState() {
}
/**
* Generate Client channel ID (CID).
* @return Client channel ID (CID).
*/
pvAccessID generateCID()
{
return 0;
}
/**
* Free generated channel ID (CID).
*/
void freeCID(int cid)
{
}
/**
* Get, or create if necessary, transport of given server address.
* @param serverAddress required transport address
* @param priority process priority.
* @return transport for given address
*/
Transport* getTransport(TransportClient* client, osiSockAddr* serverAddress, int16 minorRevision, int16 priority)
{
return NULL;
}
/**
* Internal create channel.
*/
// TODO no minor version with the addresses
// TODO what if there is an channel with the same name, but on different host!
Channel* createChannelInternal(String name, ChannelRequester* requester, short priority,
InetAddrVector* addresses) {
return NULL;
}
/**
* Destroy channel.
* @param channel
* @param force
* @throws CAException
* @throws IllegalStateException
*/
void destroyChannel(ChannelImpl* channel, bool force) {
}
/**
* Get channel search manager.
* @return channel search manager.
*/
ChannelSearchManager* getChannelSearchManager() {
return NULL;
}
};
//TODO check the const of paramerers
/**
@@ -250,13 +40,13 @@ public:
*
* @return channel ID.
*/
virtual pvAccessID getChannelID() = 0;
virtual pvAccessID getSearchInstanceID() = 0;
/**
* Return channel name.
* Return search instance, e.g. channel, name.
*
* @return channel channel name.
*/
virtual String getChannelName() = 0;
virtual String getSearchInstanceName() = 0;
/**
* Removes the owner of this search instance.
*/
@@ -303,8 +93,8 @@ class BaseSearchInstance : public SearchInstance
{
public:
virtual ~BaseSearchInstance() {};
virtual pvAccessID getChannelID() = 0;
virtual string getChannelName() = 0;
virtual pvAccessID getSearchInstanceID() = 0;
virtual String getSearchInstanceName() = 0;
virtual void unsetListOwnership();
virtual void addAndSetListOwnership(ArrayFIFO<SearchInstance*>* newOwner, Mutex* ownerMutex, int32 index);
virtual void removeAndUnsetListOwnership();
@@ -479,7 +269,7 @@ public:
* Constructor.
* @param context
*/
ChannelSearchManager(ClientContextImpl* context);
ChannelSearchManager(Context* context);
/**
* Constructor.
* @param context
@@ -533,7 +323,7 @@ private:
/**
* Context.
*/
ClientContextImpl* _context;
Context* _context;
/**
* Canceled flag.
*/

View File

@@ -11,7 +11,7 @@
#include "caConstants.h"
#include "transportRegistry.h"
#include "introspectionRegistry.h"
#include "serverContext.h"
#include "configuration.h"
#include <serialize.h>
#include <pvType.h>
@@ -31,6 +31,47 @@ namespace epics {
TCP, UDP, SSL
};
enum QoS {
/**
* Default behavior.
*/
DEFAULT = 0x00,
/**
* Require reply (acknowledgment for reliable operation).
*/
REPLY_REQUIRED = 0x01,
/**
* Best-effort option (no reply).
*/
BESY_EFFORT = 0x02,
/**
* Process option.
*/
PROCESS = 0x04,
/**
* Initialize option.
*/
INIT = 0x08,
/**
* Destroy option.
*/
DESTROY = 0x10,
/**
* Share data option.
*/
SHARE = 0x20,
/**
* Get.
*/
GET = 0x40,
/**
* Get-put.
*/
GET_PUT = 0x80
};
typedef int32 pvAccessID;
enum MessageCommands {
CMD_BEACON = 0, CMD_CONNECTION_VALIDATION = 1, CMD_ECHO = 2,
CMD_SEARCH = 3, CMD_SEARCH_RESPONSE = 4,
@@ -212,6 +253,35 @@ namespace epics {
};
class Channel;
/**
* Not public IF, used by Transports, etc.
*/
class Context {
public:
virtual ~Context() {
}
/**
* Get timer.
* @return timer.
*/
virtual Timer* getTimer() = 0;
/**
* Get transport (virtual circuit) registry.
* @return transport (virtual circuit) registry.
*/
virtual TransportRegistry* getTransportRegistry() = 0;
virtual Channel* getChannel(pvAccessID id) = 0;
virtual Transport* getSearchTransport() = 0;
virtual Configuration* getConfiguration() = 0;
};
/**
* Interface defining response handler.
* @author <a href="mailto:matej.sekoranjaATcosylab.com">Matej Sekoranja</a>
@@ -219,12 +289,9 @@ namespace epics {
*/
class ResponseHandler {
public:
virtual ~ResponseHandler() {
}
/**
* Handle response.
* @param[in] responseFrom remote address of the responder, <code>null</code> if unknown.
* @param[in] responseFrom remote address of the responder, <code>0</code> if unknown.
* @param[in] transport response source transport.
* @param[in] version message version.
* @param[in] payloadSize size of this message data available in the <code>payloadBuffer</code>.
@@ -248,9 +315,9 @@ namespace epics {
/**
* @param description
*/
AbstractResponseHandler(String description) :
_description(description), _debug(true) {
//debug = System.getProperties().containsKey(CAConstants.CAJ_DEBUG);
AbstractResponseHandler(Context* context, String description) :
_description(description),
_debug(context->getConfiguration()->getPropertyAsBoolean("PVACCESS_DEBUG", false)) {
}
virtual ~AbstractResponseHandler() {
@@ -332,23 +399,6 @@ namespace epics {
};
class Context {
public:
virtual ~Context() {
}
/**
* Get timer.
* @return timer.
*/
virtual Timer* getTimer() =0;
/**
* Get transport (virtual circuit) registry.
* @return transport (virtual circuit) registry.
*/
virtual TransportRegistry* getTransportRegistry() =0;
};
/**
* Interface defining reference counting transport IF.
* @author <a href="mailto:matej.sekoranjaATcosylab.com">Matej Sekoranja</a>
@@ -381,7 +431,7 @@ namespace epics {
* Get channel SID.
* @return channel SID.
*/
virtual int getSID() =0;
virtual pvAccessID getSID() =0;
/**
* Destroy server channel.
@@ -410,33 +460,34 @@ namespace epics {
* Preallocate new channel SID.
* @return new channel server id (SID).
*/
virtual int preallocateChannelSID() =0;
virtual pvAccessID preallocateChannelSID() =0;
/**
* De-preallocate new channel SID.
* @param sid preallocated channel SID.
*/
virtual void depreallocateChannelSID(int sid) =0;
virtual void depreallocateChannelSID(pvAccessID sid) =0;
/**
* Register a new channel.
* @param sid preallocated channel SID.
* @param channel channel to register.
*/
virtual void registerChannel(int sid, ServerChannel* channel) =0;
virtual void
registerChannel(pvAccessID sid, ServerChannel* channel) =0;
/**
* Unregister a new channel (and deallocates its handle).
* @param sid SID
*/
virtual void unregisterChannel(int sid) =0;
virtual void unregisterChannel(pvAccessID sid) =0;
/**
* Get channel by its SID.
* @param sid channel SID
* @return channel with given SID, <code>null</code> otherwise
*/
virtual ServerChannel* getChannel(int sid) =0;
virtual ServerChannel* getChannel(pvAccessID sid) =0;
/**
* Get channel count.
@@ -445,6 +496,44 @@ namespace epics {
virtual int getChannelCount() =0;
};
/**
* A request that expects an response.
* Responses identified by its I/O ID.
* This interface needs to be extended (to provide method called on response).
* @author <a href="mailto:matej.sekoranjaATcosylab.com">Matej Sekoranja</a>
*/
class ResponseRequest {
public:
/**
* Get I/O ID.
* @return ioid
*/
virtual pvAccessID getIOID() = 0;
/**
* Timeout notification.
*/
virtual void timeout() = 0;
/**
* Cancel response request (always to be called to complete/destroy).
*/
virtual void cancel() = 0;
/**
* Report status to clients (e.g. disconnected).
* @param status to report.
*/
virtual void reportStatus(epics::pvData::Status* status) = 0;
/**
* Get request requester.
* @return request requester.
*/
virtual epics::pvData::Requester* getRequester() = 0;
};
}
}

View File

@@ -0,0 +1,53 @@
/*
* clientContext.h
*
* Created on: Dec 21, 2010
* Author: msekoran
*/
#ifndef CLIENTCONTEXTIMPL_H_
#define CLIENTCONTEXTIMPL_H_
#include <pvAccess.h>
#include <remote.h>
#include <channelSearchManager.h>
namespace epics {
namespace pvAccess {
class ChannelImpl :
public Channel ,
public TransportClient,
public TransportSender,
public BaseSearchInstance
{
public:
virtual pvAccessID getChannelID() = 0;
virtual void destroyChannel(bool force) = 0;
virtual void connectionCompleted(pvAccessID sid/*, rights*/) = 0;
virtual void createChannelFailed() = 0;
};
class ClientContextImpl : public ClientContext, public Context
{
public:
virtual ChannelSearchManager* getChannelSearchManager() = 0;
virtual void checkChannelName(String& name) = 0;
virtual void registerChannel(ChannelImpl* channel) = 0;
virtual void unregisterChannel(ChannelImpl* channel) = 0;
virtual void destroyChannel(ChannelImpl* channel, bool force) = 0;
virtual ChannelImpl* createChannelInternal(String name, ChannelRequester* requester, short priority, InetAddrVector* addresses) = 0;
virtual Transport* getTransport(TransportClient* client, osiSockAddr* serverAddress, int16 minorRevision, int16 priority) = 0;
};
}
}
#endif /* CLIENTCONTEXTIMPL_H_ */

View File

@@ -24,23 +24,6 @@ using namespace epics::pvData;
namespace epics {
namespace pvAccess {
void AbstractResponseHandler::handleResponse(osiSockAddr* responseFrom,
Transport* transport, int8 version, int8 command,
int payloadSize, ByteBuffer* payloadBuffer) {
if(_debug) {
char ipAddrStr[48];
ipAddrToA(&responseFrom->ia, ipAddrStr, sizeof(ipAddrStr));
ostringstream prologue;
prologue<<"Message [0x"<<hex<<(int)command<<", v0x"<<hex;
prologue<<(int)version<<"] received from "<<ipAddrStr;
hexDump(prologue.str(), _description,
(const int8*)payloadBuffer->getArray(),
payloadBuffer->getPosition(), payloadSize);
}
}
void BadResponse::handleResponse(osiSockAddr* responseFrom,
Transport* transport, int8 version, int8 command,
int payloadSize, ByteBuffer* payloadBuffer) {
@@ -48,7 +31,7 @@ namespace epics {
transport, version, command, payloadSize, payloadBuffer);
char ipAddrStr[48];
ipAddrToA(&responseFrom->ia, ipAddrStr, sizeof(ipAddrStr));
ipAddrToDottedIP(&responseFrom->ia, ipAddrStr, sizeof(ipAddrStr));
errlogSevPrintf(errlogInfo,
"Undecipherable message (bad response type %d) from %s.",
@@ -56,16 +39,15 @@ namespace epics {
}
ServerResponseHandler::ServerResponseHandler(ServerContextImpl* context) :
_context(context) {
ServerResponseHandler::ServerResponseHandler(ServerContextImpl* context) {
BadResponse* badResponse = new BadResponse(context);
_handlerTable = new ResponseHandler*[HANDLER_TABLE_LENGTH];
// TODO add real handlers, as they are developed
_handlerTable[0] = new NoopResponse(_context, "Beacon");
_handlerTable[1] = new ConnectionValidationHandler(_context);
_handlerTable[2] = new EchoHandler(_context);
_handlerTable[0] = new NoopResponse(context, "Beacon");
_handlerTable[1] = new ConnectionValidationHandler(context);
_handlerTable[2] = new EchoHandler(context);
_handlerTable[3] = badResponse;
_handlerTable[4] = badResponse;
_handlerTable[5] = badResponse;

View File

@@ -8,6 +8,7 @@
#ifndef RESPONSEHANDLERS_H_
#define RESPONSEHANDLERS_H_
#include "serverContext.h"
#include "remote.h"
namespace epics {
@@ -18,20 +19,19 @@ namespace epics {
* @version $Id: AbstractServerResponseHandler.java,v 1.1 2010/05/03 14:45:39 mrkraimer Exp $
*/
class AbstractServerResponseHandler : public AbstractResponseHandler {
protected:
ServerContextImpl* _context;
public:
/**
* @param context
* @param description
*/
AbstractServerResponseHandler(ServerContextImpl* context,
String description) :
AbstractResponseHandler(description), _context(context) {
AbstractServerResponseHandler(ServerContextImpl* context, String description) :
AbstractResponseHandler(context, description), _context(context) {
}
virtual ~AbstractServerResponseHandler() {
}
protected:
ServerContextImpl* _context;
};
/**
@@ -77,11 +77,6 @@ namespace epics {
*/
ResponseHandler** _handlerTable;
/**
* Context instance.
*/
ServerContextImpl* _context;
};
/**

View File

@@ -8,11 +8,12 @@
#ifndef SERVERCONTEXT_H_
#define SERVERCONTEXT_H_
#include "remote.h"
namespace epics {
namespace pvAccess {
class ServerContextImpl {
class ServerContextImpl : public Context {
};

View File

@@ -243,7 +243,7 @@ namespace epics {
T ArrayFIFO<T>::pollFirst() {
Lock lock(&_mutex);
if(isEmpty()) THROW_BASE_EXCEPTION("ArrayFIFO empty");
if(isEmpty()) return 0;
T result = _elements[_head]; // Element is null if deque empty
_head = (_head+1)&(_size-1);
@@ -254,7 +254,7 @@ namespace epics {
T ArrayFIFO<T>::pollLast() {
Lock lock(&_mutex);
if(isEmpty()) THROW_BASE_EXCEPTION("ArrayFIFO empty");
if(isEmpty()) return 0;
_tail = (_tail-1)&(_size-1);
return _elements[_tail];
@@ -264,7 +264,7 @@ namespace epics {
T ArrayFIFO<T>::peekFirst() {
Lock lock(&_mutex);
if(isEmpty()) THROW_BASE_EXCEPTION("ArrayFIFO empty");
if(isEmpty()) return 0;
return _elements[_head];
}
@@ -273,7 +273,7 @@ namespace epics {
T ArrayFIFO<T>::peekLast() {
Lock lock(&_mutex);
if(isEmpty()) THROW_BASE_EXCEPTION("ArrayFIFO empty");
if(isEmpty()) return 0;
return _elements[(_tail-1)&(_size-1)];
}

View File

@@ -28,8 +28,8 @@ namespace epics {
* Create a GrowingCircularBuffer with the given capacity.
**/
GrowingCircularBuffer(size_t capacity = 16) :
_elements(new T[capacity]), _takePointer(0), _putPointer(0), _count(0), _size(capacity)
{
_elements(new T[capacity]), _takePointer(0), _putPointer(0),
_count(0), _size(capacity) {
}
~GrowingCircularBuffer() {
@@ -94,13 +94,9 @@ namespace epics {
size_t length);
};
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* g++ requires template definition inside a header file.
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
template<class T>
void GrowingCircularBuffer<T>::arraycopy(T* src, size_t srcPos, T* dest,
size_t destPos, size_t length) {
void GrowingCircularBuffer<T>::arraycopy(T* src, size_t srcPos,
T* dest, size_t destPos, size_t length) {
if(srcPos<destPos) // this takes care of same-buffer copy
for(int i = length-1; i>=0; i--)
dest[destPos+i] = src[srcPos+i];
@@ -111,17 +107,16 @@ namespace epics {
template<class T>
bool GrowingCircularBuffer<T>::insert(const T x) {
if (_count == _size)
{
if(_count==_size) {
// we are full, grow by factor 2
T* newElements = new T[_size * 2];
T* newElements = new T[_size*2];
// invariant: _takePointer < _size
size_t split = _size - _takePointer;
if (split > 0)
arraycopy(_elements, _takePointer, newElements, 0, split);
if (_takePointer != 0)
arraycopy(_elements, 0, newElements, split, _putPointer);
size_t split = _size-_takePointer;
if(split>0) arraycopy(_elements, _takePointer, newElements, 0,
split);
if(_takePointer!=0) arraycopy(_elements, 0, newElements, split,
_putPointer);
_takePointer = 0;
_putPointer = _size;
@@ -132,8 +127,8 @@ namespace epics {
_count++;
_elements[_putPointer] = x;
if (++_putPointer >= _size) _putPointer = 0;
return _count == 1;
if(++_putPointer>=_size) _putPointer = 0;
return _count==1;
}
template<class T>
@@ -146,6 +141,141 @@ namespace epics {
return old;
}
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/**
* Template specialization for pointers.
* Implementation of circular FIFO unbouded buffer.
* Instance is not thread safe.
* @author Miha Vitorovic
*/
template<class T>
class GrowingCircularBuffer<T*> {
public:
/**
* Create a GrowingCircularBuffer with the given capacity.
**/
GrowingCircularBuffer(size_t capacity = 16) :
_elements(new T*[capacity]), _takePointer(0), _putPointer(0),
_count(0), _size(capacity) {
}
~GrowingCircularBuffer() {
delete[] _elements;
}
/**
* Get number of elements in the buffer.
* @return number of elements in the buffer.
*/
inline size_t size() {
return _count;
}
/**
* Get current buffer capacity.
* @return buffer current capacity.
*/
inline size_t capacity() {
return _size;
}
/**
* Insert a new element in to the buffer.
* If buffer full the buffer is doubled.
*
* @param x element to insert.
* @return <code>true</code> if first element.
*/
bool insert(const T* x);
/**
* Extract the oldest element from the buffer.
* @return the oldest element from the buffer.
*/
T* extract();
private:
/**
* Array (circular buffer) of elements.
*/
T** _elements;
/**
* Take (read) pointer.
*/
size_t _takePointer;
/**
* Put (write) pointer.
*/
size_t _putPointer;
/**
* Number of elements in the buffer.
*/
size_t _count;
size_t _size;
void arraycopy(T** src, size_t srcPos, T** dest, size_t destPos,
size_t length);
};
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* g++ requires template definition inside a header file.
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
template<class T>
void GrowingCircularBuffer<T*>::arraycopy(T** src, size_t srcPos,
T** dest, size_t destPos, size_t length) {
if(srcPos<destPos) // this takes care of same-buffer copy
for(int i = length-1; i>=0; i--)
dest[destPos+i] = src[srcPos+i];
else
for(size_t i = 0; i<length; i++)
dest[destPos++] = src[srcPos++];
}
template<class T>
bool GrowingCircularBuffer<T*>::insert(const T* x) {
if(_count==_size) {
// we are full, grow by factor 2
T** newElements = new T*[_size*2];
// invariant: _takePointer < _size
size_t split = _size-_takePointer;
if(split>0) arraycopy(_elements, _takePointer, newElements, 0,
split);
if(_takePointer!=0) arraycopy(_elements, 0, newElements, split,
_putPointer);
_takePointer = 0;
_putPointer = _size;
_size *= 2;
delete[] _elements;
_elements = newElements;
}
_count++;
_elements[_putPointer] = const_cast<T*>(x);
if(++_putPointer>=_size) _putPointer = 0;
return _count==1;
}
template<class T>
T* GrowingCircularBuffer<T*>::extract() {
if(_count==0) return NULL;
_count--;
T* old = _elements[_takePointer];
if(++_takePointer>=_size) _takePointer = 0;
return old;
}
}
}
#endif /* GROWINGCIRCULARBUFFER_H_ */

View File

@@ -32,14 +32,25 @@ using namespace epics::pvData;
namespace epics {
namespace pvAccess {
void addDefaultBroadcastAddress(InetAddrVector* v, in_port_t p) {
osiSockAddr* pNewNode = new osiSockAddr;
pNewNode->ia.sin_family = AF_INET;
pNewNode->ia.sin_addr.s_addr = htonl(INADDR_BROADCAST);
pNewNode->ia.sin_port = htons(p);
v->push_back(pNewNode);
}
/* port of osiSockDiscoverBroadcastAddresses() in
* epics/base/src/libCom/osi/os/default/osdNetIntf.c
*/
InetAddrVector* getBroadcastAddresses(SOCKET sock) {
InetAddrVector* getBroadcastAddresses(SOCKET sock,
in_port_t defaultPort) {
static const unsigned nelem = 100;
int status;
struct ifconf ifconf;
struct ifreq* pIfreqList;
struct ifreq* pifreq;
struct ifreq ifrBuff;
osiSockAddr* pNewNode;
InetAddrVector* retVector = new InetAddrVector();
@@ -54,53 +65,72 @@ namespace epics {
if(!pIfreqList) {
errlogSevPrintf(errlogMajor,
"getBroadcastAddresses(): no memory to complete request");
addDefaultBroadcastAddress(retVector, defaultPort);
return retVector;
}
// get number of interfaces
ifconf.ifc_len = nelem*sizeof(ifreq);
ifconf.ifc_req = pIfreqList;
memset(ifconf.ifc_req, 0, ifconf.ifc_len);
status = ioctl(sock, SIOCGIFCONF, &ifconf);
if(status<0||ifconf.ifc_len==0) {
errlogSevPrintf(
errlogMinor,
errlogSevPrintf(errlogMinor,
"getBroadcastAddresses(): unable to fetch network interface configuration");
delete[] pIfreqList;
addDefaultBroadcastAddress(retVector, defaultPort);
return retVector;
}
errlogPrintf("Found %d interfaces\n", ifconf.ifc_len);
int maxNodes = ifconf.ifc_len/sizeof(ifreq);
//errlogPrintf("Found %d interfaces\n", maxNodes);
pifreq = pIfreqList;
for(int i = 0; i<maxNodes; i++) {
if(!(*pifreq->ifr_name)) break;
if(i>0) {
size_t n = pifreq->ifr_addr.sa_len+sizeof(pifreq->ifr_name);
if(n<sizeof(ifreq))
pifreq++;
else
pifreq = (struct ifreq *)((char *)pifreq+n);
}
for(int i = 0; i<=ifconf.ifc_len; i++) {
/*
* If its not an internet interface then dont use it
*/
if(pIfreqList[i].ifr_addr.sa_family!=AF_INET) continue;
if(pifreq->ifr_addr.sa_family!=AF_INET) continue;
status = ioctl(sock, SIOCGIFFLAGS, &pIfreqList[i]);
strncpy(ifrBuff.ifr_name, pifreq->ifr_name,
sizeof(ifrBuff.ifr_name));
status = ioctl(sock, SIOCGIFFLAGS, &ifrBuff);
if(status) {
errlogSevPrintf(
errlogMinor,
"getBroadcastAddresses(): net intf flags fetch for \"%s\" failed",
pIfreqList[i].ifr_name);
pifreq->ifr_name);
continue;
}
/*
* dont bother with interfaces that have been disabled
*/
if(!(pIfreqList[i].ifr_flags&IFF_UP)) continue;
if(!(ifrBuff.ifr_flags&IFF_UP)) continue;
/*
* dont use the loop back interface
*/
if(pIfreqList[i].ifr_flags&IFF_LOOPBACK) continue;
if(ifrBuff.ifr_flags&IFF_LOOPBACK) continue;
pNewNode = new osiSockAddr;
if(pNewNode==NULL) {
errlogSevPrintf(errlogMajor,
"getBroadcastAddresses(): no memory available for configuration");
delete[] pIfreqList;
if(retVector->size()==0) addDefaultBroadcastAddress(
retVector, defaultPort);
return retVector;
}
@@ -114,40 +144,45 @@ namespace epics {
* Otherwise CA will not query through the
* interface.
*/
if(pIfreqList[i].ifr_flags&IFF_BROADCAST) {
status = ioctl(sock, SIOCGIFBRDADDR, &pIfreqList[i]);
if(ifrBuff.ifr_flags&IFF_BROADCAST) {
strncpy(ifrBuff.ifr_name, pifreq->ifr_name,
sizeof(ifrBuff.ifr_name));
status = ioctl(sock, SIOCGIFBRDADDR, &ifrBuff);
if(status) {
errlogSevPrintf(
errlogMinor,
"getBroadcastAddresses(): net intf \"%s\": bcast addr fetch fail",
pIfreqList->ifr_name);
pifreq->ifr_name);
delete pNewNode;
continue;
}
pNewNode->sa = pIfreqList[i].ifr_broadaddr;
pNewNode->sa = ifrBuff.ifr_broadaddr;
}
#ifdef IFF_POINTOPOINT
else if(pIfreqList->ifr_flags&IFF_POINTOPOINT) {
status = ioctl(sock, SIOCGIFDSTADDR, &pIfreqList[i]);
else if(ifrBuff.ifr_flags&IFF_POINTOPOINT) {
strncpy(ifrBuff.ifr_name, pifreq->ifr_name,
sizeof(ifrBuff.ifr_name));
status = ioctl(sock, SIOCGIFDSTADDR, &ifrBuff);
if(status) {
errlogSevPrintf(
errlogMinor,
"getBroadcastAddresses(): net intf \"%s\": pt to pt addr fetch fail",
pIfreqList[i].ifr_name);
pifreq->ifr_name);
delete pNewNode;
continue;
}
pNewNode->sa = pIfreqList[i].ifr_dstaddr;
pNewNode->sa = ifrBuff.ifr_dstaddr;
}
#endif
else {
errlogSevPrintf(
errlogMinor,
"getBroadcastAddresses(): net intf \"%s\": not point to point or bcast?",
pIfreqList[i].ifr_name);
pifreq->ifr_name);
delete pNewNode;
continue;
}
pNewNode->ia.sin_port = htons(defaultPort);
retVector->push_back(pNewNode);
}

View File

@@ -33,8 +33,12 @@ namespace epics {
/**
* returns a vector containing all the IPv4 broadcast addresses
* on this machine. IPv6 doesn't have a local broadcast address.
*/
InetAddrVector* getBroadcastAddresses(SOCKET sock);
* Conversion of the defaultPort to network byte order performed by
* the function.
* TODO: Windows implementation of the function.
*/
InetAddrVector* getBroadcastAddresses(SOCKET sock,
in_port_t defaultPort);
/**
* Encode IPv4 address as IPv6 address.

View File

@@ -18,6 +18,8 @@ using namespace epics::pvData;
class DummyResponseHandler : public ResponseHandler
{
public:
DummyResponseHandler(Context* ctx) : ResponseHandler() {}
virtual void handleResponse(osiSockAddr* responseFrom,
Transport* transport, int8 version, int8 command, int payloadSize,
ByteBuffer* payloadBuffer)
@@ -27,9 +29,33 @@ public:
};
class ContextImpl : public Context {
public:
ContextImpl() :
_tr(new TransportRegistry()), _timer(new Timer("server thread",
lowPriority)), _conf(new SystemConfigurationImpl()) {
}
virtual ~ContextImpl() {
delete _tr;
delete _timer;
}
virtual Timer* getTimer() { return _timer; }
virtual TransportRegistry* getTransportRegistry() { return _tr; }
virtual Channel* getChannel(epics::pvAccess::pvAccessID) { return 0; }
virtual Transport* getSearchTransport() { return 0; }
virtual Configuration* getConfiguration() { return _conf; }
private:
TransportRegistry* _tr;
Timer* _timer;
Configuration* _conf;
};
void testBeaconEmitter()
{
DummyResponseHandler drh;
ContextImpl ctx;
DummyResponseHandler drh(&ctx);
/* SOCKET mysocket;
if ((mysocket = socket (AF_INET, SOCK_DGRAM, 0)) == -1)
{

View File

@@ -37,7 +37,7 @@ void decodeFromIPv6Address(ByteBuffer* buffer, osiSockAddr* address)
class BeaconResponseHandler : public ResponseHandler
{
public:
BeaconResponseHandler()
BeaconResponseHandler(Context* ctx) : ResponseHandler()
{
_pvDataCreate = getPVDataCreate();
}
@@ -103,9 +103,33 @@ private:
};
class ContextImpl : public Context {
public:
ContextImpl() :
_tr(new TransportRegistry()), _timer(new Timer("server thread",
lowPriority)), _conf(new SystemConfigurationImpl()) {
}
virtual ~ContextImpl() {
delete _tr;
delete _timer;
}
virtual Timer* getTimer() { return _timer; }
virtual TransportRegistry* getTransportRegistry() { return _tr; }
virtual Channel* getChannel(epics::pvAccess::pvAccessID) { return 0; }
virtual Transport* getSearchTransport() { return 0; }
virtual Configuration* getConfiguration() { return _conf; }
private:
TransportRegistry* _tr;
Timer* _timer;
Configuration* _conf;
};
void testBeaconHandler()
{
BeaconResponseHandler brh;
ContextImpl ctx;
BeaconResponseHandler brh(&ctx);
BlockingUDPConnector connector(false, NULL, true);
osiSockAddr bindAddr;

View File

@@ -29,26 +29,30 @@ using std::sscanf;
class ContextImpl : public Context {
public:
ContextImpl() :
_tr(new TransportRegistry()), _timer(new Timer("client thread",
lowPriority)) {
_tr(new TransportRegistry()), _timer(new Timer("server thread",
lowPriority)), _conf(new SystemConfigurationImpl()) {
}
virtual ~ContextImpl() {
delete _tr;
delete _timer;
}
virtual Timer* getTimer() {
return _timer;
}
virtual TransportRegistry* getTransportRegistry() {
return _tr;
}
virtual Timer* getTimer() { return _timer; }
virtual TransportRegistry* getTransportRegistry() { return _tr; }
virtual Channel* getChannel(epics::pvAccess::pvAccessID) { return 0; }
virtual Transport* getSearchTransport() { return 0; }
virtual Configuration* getConfiguration() { return _conf; }
private:
TransportRegistry* _tr;
Timer* _timer;
Configuration* _conf;
};
class DummyResponseHandler : public ResponseHandler {
public:
DummyResponseHandler(Context* ctx) : ResponseHandler() {
}
virtual void handleResponse(osiSockAddr* responseFrom,
Transport* transport, int8 version, int8 command, int payloadSize,
ByteBuffer* payloadBuffer) {
@@ -108,7 +112,7 @@ void testBlockingTCPSender() {
DummyTransportClient dtc;
DummyTransportSender dts;
DummyResponseHandler drh;
DummyResponseHandler drh(&ctx);
osiSockAddr srvAddr;

View File

@@ -8,6 +8,7 @@
#include "blockingTCP.h"
#include "remote.h"
#include "logger.h"
#include "configuration.h"
#include <iostream>
@@ -21,16 +22,22 @@ class ContextImpl : public Context {
public:
ContextImpl() :
_tr(new TransportRegistry()),
_timer(new Timer("server thread", lowPriority)) {}
_timer(new Timer("server thread", lowPriority)),
_conf(new SystemConfigurationImpl()) {}
virtual ~ContextImpl() {
delete _tr;
delete _timer;
}
virtual Timer* getTimer() { return _timer; }
virtual TransportRegistry* getTransportRegistry() { return _tr; }
virtual Channel* getChannel(epics::pvAccess::pvAccessID) { return 0; }
virtual Transport* getSearchTransport() { return 0; }
virtual Configuration* getConfiguration() { return _conf; }
private:
TransportRegistry* _tr;
Timer* _timer;
Configuration* _conf;
};
void testServerConnections() {
@@ -40,7 +47,7 @@ void testServerConnections() {
1024);
cout<<"Press any key to stop the server...";
char c = cin.peek();
cin.peek();
delete srv;
}

View File

@@ -26,8 +26,43 @@ using std::sscanf;
static osiSockAddr sendTo;
class ContextImpl : public Context {
public:
ContextImpl() :
_tr(new TransportRegistry()), _timer(new Timer("server thread",
lowPriority)), _conf(new SystemConfigurationImpl()) {
}
virtual ~ContextImpl() {
delete _tr;
delete _timer;
}
virtual Timer* getTimer() {
return _timer;
}
virtual TransportRegistry* getTransportRegistry() {
return _tr;
}
virtual Channel* getChannel(epics::pvAccess::pvAccessID) {
return 0;
}
virtual Transport* getSearchTransport() {
return 0;
}
virtual Configuration* getConfiguration() {
return _conf;
}
private:
TransportRegistry* _tr;
Timer* _timer;
Configuration* _conf;
};
class DummyResponseHandler : public ResponseHandler {
public:
DummyResponseHandler(Context* ctx)
{ }
virtual void handleResponse(osiSockAddr* responseFrom,
Transport* transport, int8 version, int8 command, int payloadSize,
ByteBuffer* payloadBuffer) {
@@ -69,9 +104,10 @@ private:
void testBlockingUDPSender() {
BlockingUDPConnector connector(false, NULL, true);
ContextImpl ctx;
DummyTransportSender dts;
DummyResponseHandler drh;
DummyResponseHandler drh(&ctx);
osiSockAddr bindAddr;

View File

@@ -21,10 +21,42 @@ using std::endl;
using std::hex;
using std::dec;
class ContextImpl : public Context {
public:
ContextImpl() :
_tr(new TransportRegistry()), _timer(new Timer("server thread",
lowPriority)), _conf(new SystemConfigurationImpl()) {
}
virtual ~ContextImpl() {
delete _tr;
delete _timer;
}
virtual Timer* getTimer() {
return _timer;
}
virtual TransportRegistry* getTransportRegistry() {
return _tr;
}
virtual Channel* getChannel(epics::pvAccess::pvAccessID) {
return 0;
}
virtual Transport* getSearchTransport() {
return 0;
}
virtual Configuration* getConfiguration() {
return _conf;
}
private:
TransportRegistry* _tr;
Timer* _timer;
Configuration* _conf;
};
class DummyResponseHandler : public ResponseHandler {
public:
DummyResponseHandler() :
packets(0) {
DummyResponseHandler(Context* context)
: packets(0) {
}
int getPackets() {
@@ -71,8 +103,9 @@ void DummyResponseHandler::handleResponse(osiSockAddr* responseFrom,
void testBlockingUDPConnector() {
BlockingUDPConnector connector(false, NULL, true);
ContextImpl ctx;
DummyResponseHandler drh;
DummyResponseHandler drh(&ctx);
osiSockAddr bindAddr;

File diff suppressed because it is too large Load Diff

View File

@@ -15,7 +15,9 @@ using namespace epics::pvAccess;
using std::cout;
using std::endl;
int main(int argc, char *argv[]) {
void testSimpleType() {
cout<<"\nTests for simple type template."<<endl;
ArrayFIFO<int> fifoInt;
assert(fifoInt.size()==0);
@@ -133,5 +135,137 @@ int main(int argc, char *argv[]) {
assert(fifoInt.isEmpty());
cout<<"\nPASSED!\n";
}
void testPointerType() {
cout<<"\nTests for pointer type template."<<endl;
int testVals[] = {0,1,2,3,4,5,6,7,8,9,11,12,13,14,15,16,17,18,19,20};
ArrayFIFO<int*> fifoInt;
assert(fifoInt.size()==0);
assert(fifoInt.isEmpty());
cout<<"Testing clear."<<endl;
fifoInt.push(&testVals[3]);
assert(fifoInt.size()==1);
fifoInt.clear();
assert(fifoInt.isEmpty());
cout<<"Testing push/pop."<<endl;
fifoInt.push(&testVals[5]);
fifoInt.push(&testVals[6]);
fifoInt.push(&testVals[7]);
assert(fifoInt.size()==3);
assert(fifoInt.pop()==&testVals[7]);
assert(fifoInt.size()==2);
assert(fifoInt.pop()==&testVals[6]);
assert(fifoInt.size()==1);
assert(fifoInt.pop()==&testVals[5]);
assert(fifoInt.size()==0);
cout<<"Testing FIFO ops (first/last)."<<endl;
fifoInt.addFirst(&testVals[1]);
fifoInt.addFirst(&testVals[2]);
fifoInt.addFirst(&testVals[3]);
fifoInt.addFirst(&testVals[4]);
fifoInt.addFirst(&testVals[5]);
assert(fifoInt.size()==5);
assert(fifoInt.pollLast()==&testVals[1]);
assert(fifoInt.pollLast()==&testVals[2]);
assert(fifoInt.pollLast()==&testVals[3]);
assert(fifoInt.pollLast()==&testVals[4]);
assert(fifoInt.pollLast()==&testVals[5]);
assert(fifoInt.isEmpty());
cout<<"Testing FIFO ops (last/first)."<<endl;
fifoInt.addLast(&testVals[7]);
fifoInt.addLast(&testVals[8]);
fifoInt.addLast(&testVals[9]);
fifoInt.addLast(&testVals[10]);
fifoInt.addLast(&testVals[11]);
assert(fifoInt.size()==5);
assert(fifoInt.pollFirst()==&testVals[7]);
assert(fifoInt.pollFirst()==&testVals[8]);
assert(fifoInt.pollFirst()==&testVals[9]);
assert(fifoInt.pollFirst()==&testVals[10]);
assert(fifoInt.pollFirst()==&testVals[11]);
assert(fifoInt.isEmpty());
cout<<"Testing remove, peek."<<endl;
fifoInt.addFirst(&testVals[1]);
fifoInt.addFirst(&testVals[2]);
fifoInt.addFirst(&testVals[3]);
fifoInt.addFirst(&testVals[4]);
fifoInt.addFirst(&testVals[5]);
fifoInt.addFirst(&testVals[6]);
fifoInt.addFirst(&testVals[7]);
// - - - - - - - - - - - -
fifoInt.addFirst(&testVals[8]);
fifoInt.addFirst(&testVals[9]);
fifoInt.addFirst(&testVals[10]);
assert(fifoInt.peekFirst()==&testVals[10]);
assert(fifoInt.peekLast()==&testVals[1]);
assert(fifoInt.size()==10);
assert(fifoInt.remove(&testVals[9]));
assert(fifoInt.size()==9);
assert(!fifoInt.remove(&testVals[15]));
assert(fifoInt.size()==9);
assert(fifoInt.pollLast()==&testVals[1]);
assert(fifoInt.pollLast()==&testVals[2]);
assert(fifoInt.pollLast()==&testVals[3]);
assert(fifoInt.pollLast()==&testVals[4]);
assert(fifoInt.pollLast()==&testVals[5]);
assert(fifoInt.pollLast()==&testVals[6]);
assert(fifoInt.pollLast()==&testVals[7]);
assert(fifoInt.pollLast()==&testVals[8]);
// - - - - - - - - - - - -
assert(fifoInt.pollLast()==&testVals[10]);
assert(fifoInt.isEmpty());
cout<<"Testing increase buffer."<<endl;
fifoInt.addLast(&testVals[2]);
fifoInt.addLast(&testVals[3]);
fifoInt.addLast(&testVals[4]);
fifoInt.addLast(&testVals[5]);
fifoInt.addLast(&testVals[6]);
fifoInt.addLast(&testVals[7]);
fifoInt.addLast(&testVals[8]);
fifoInt.addLast(&testVals[9]);
fifoInt.addLast(&testVals[10]);
fifoInt.addLast(&testVals[11]);
fifoInt.addLast(&testVals[12]);
fifoInt.addLast(&testVals[13]);
fifoInt.addLast(&testVals[14]);
fifoInt.addLast(&testVals[15]);
fifoInt.addLast(&testVals[16]);
fifoInt.addLast(&testVals[17]);
fifoInt.addLast(&testVals[18]);
fifoInt.addLast(&testVals[19]);
assert(fifoInt.size()==18);
fifoInt.debugState();
fifoInt.clear();
assert(fifoInt.isEmpty());
cout<<"\nPASSED!\n";
}
int main(int argc, char *argv[]) {
testSimpleType();
cout<<endl;
testPointerType();
return 0;
}

View File

@@ -16,19 +16,19 @@ using std::endl;
const size_t CAPACITY = 10;
int main(int argc, char *argv[]) {
void testSimpleType() {
GrowingCircularBuffer<int> cb(CAPACITY);
cout<<"Testing circular buffer."<<endl;
cout<<"Testing circular buffer simple type."<<endl;
assert(cb.capacity()==CAPACITY);
assert(cb.size()==0);
// insert, get test
bool first = cb.insert(1);
assert(first);
assert(cb.size()==1);
assert(cb.extract()==1);
assert(first);
assert(cb.size()==0);
for(size_t i = 0; i<2*CAPACITY; i++) {
@@ -45,6 +45,45 @@ int main(int argc, char *argv[]) {
assert(cb.size()==0);
cout<<"\nPASSED!\n";
return 0;
}
void testPointerType() {
GrowingCircularBuffer<int*> cb(CAPACITY);
int testVals[] = {0,1,2,3,4,5,6,7,8,9,11,12,13,14,15,16,17,18,19,20};
cout<<"Testing circular buffer pointer type."<<endl;
assert(cb.capacity()==CAPACITY);
assert(cb.size()==0);
// insert, get test
bool first = cb.insert(&testVals[1]);
assert(first);
assert(cb.size()==1);
assert(cb.extract()==&testVals[1]);
assert(cb.size()==0);
for(size_t i = 0; i<2*CAPACITY; i++) {
first = cb.insert(&testVals[i]);
assert(cb.size()==i+1);
assert((cb.size() == 1)==first);
}
assert(cb.size()==2*CAPACITY);
for(size_t i = 0; i<2*CAPACITY; i++) {
assert(cb.extract()==&testVals[i]);
assert(cb.size()==2*CAPACITY-i-1);
}
assert(cb.size()==0);
cout<<"\nPASSED!\n";
}
int main(int argc, char *argv[]) {
testSimpleType();
cout<<endl;
testPointerType();
return 0;
}

View File

@@ -6,6 +6,7 @@
*/
#include "inetAddressUtil.h"
#include "logger.h"
#include <byteBuffer.h>
#include <pvType.h>
@@ -23,6 +24,7 @@ using std::stringstream;
using std::hex;
int main(int argc, char *argv[]) {
createFileLogger("inetAddresUtils.log");
InetAddrVector *vec;
InetAddrVector *vec1;
@@ -127,11 +129,11 @@ int main(int argc, char *argv[]) {
cout<<"\nPASSED!\n";
SOCKET socket = epicsSocketCreate(AF_INET, SOCK_STREAM, IPPROTO_TCP);
InetAddrVector* broadcasts = getBroadcastAddresses(socket);
InetAddrVector* broadcasts = getBroadcastAddresses(socket,6678);
cout<<"Broadcast addresses: "<<broadcasts->size()<<endl;
for(size_t i = 0; i<broadcasts->size(); i++) {
cout<<"Broadcast address: ";
cout<<inetAddressToString(broadcasts->at(i), false)<<endl;
cout<<inetAddressToString(broadcasts->at(i))<<endl;
}
delete broadcasts;