Compare commits

...

12 Commits

Author SHA1 Message Date
9b9726b800 patchlevel fixed 2013-11-06 13:29:42 +00:00
b139221f0b error messages improved 2013-11-06 10:22:51 +00:00
b0ab8a7a8b write error message on write timeout 2013-11-06 09:52:39 +00:00
ddac589676 newline in report output fixed 2013-11-06 09:44:18 +00:00
5b380cdaad No connection checking before locking device. Multi-devices (GPIB) behave strangely. Get an error when device is disconnected. 2013-11-05 14:48:53 +00:00
cc9adc77fa patchlevel updated 2013-10-23 14:38:28 +00:00
2b38f7bcfa . 2013-10-23 14:36:35 +00:00
0ceada70b5 status information added 2013-10-23 14:35:08 +00:00
7bf91b403d status information added
error messages improved
dont mark device as BusOwner when locking fails
2013-10-23 14:34:53 +00:00
bf5c359649 status information added
use class for status strings to make array overrun impossible
2013-10-23 14:33:15 +00:00
c41ac44bd1 typo in comment 2013-10-23 14:31:35 +00:00
e36013d64e error messages improved
Do not queue lock request when not connected
Do not call lock callback when unlock fails
2013-10-23 14:31:00 +00:00
9 changed files with 118 additions and 73 deletions

View File

@ -22,11 +22,6 @@
#include "StreamError.h"
#include "StreamBuffer.h"
#include <epicsVersion.h>
#ifdef BASE_VERSION
#define EPICS_3_13
#endif
#ifdef EPICS_3_13
#include <assert.h>
#include <wdLib.h>
@ -376,9 +371,11 @@ supportsEvent()
intrCallbackInt32, this, &intrPvtInt32);
return true;
}
error("%s: port does not allow to register for "
const char *portname;
pasynManager->getPortName(pasynUser, &portname);
error("%s: port %s does not allow to register for "
"Int32 interrupts: %s\n",
clientName(), pasynUser->errorMessage);
clientName(), portname, pasynUser->errorMessage);
pasynInt32 = NULL;
intrPvtInt32 = NULL;
}
@ -402,9 +399,11 @@ supportsEvent()
intrCallbackUInt32, this, 0xFFFFFFFF, &intrPvtInt32);
return true;
}
error("%s: port does not allow to register for "
const char *portname;
pasynManager->getPortName(pasynUser, &portname);
error("%s: port %s does not allow to register for "
"UInt32 interrupts: %s\n",
clientName(), pasynUser->errorMessage);
clientName(), portname, pasynUser->errorMessage);
pasynUInt32 = NULL;
intrPvtUInt32 = NULL;
}
@ -423,9 +422,15 @@ supportsAsyncRead()
intrCallbackOctet, this, &intrPvtOctet) != asynSuccess)
{
const char *portname;
int addr;
pasynManager->getPortName(pasynUser, &portname);
error("%s: asyn port %s does not support asynchronous input: %s\n",
clientName(), portname, pasynUser->errorMessage);
pasynManager->getAddr(pasynUser, &addr);
if (addr >= 0)
error("%s: asyn port %s addr %d does not support asynchronous input: %s\n",
clientName(), portname, addr, pasynUser->errorMessage);
else
error("%s: asyn port %s does not support asynchronous input: %s\n",
clientName(), portname, pasynUser->errorMessage);
return false;
}
return true;
@ -490,23 +495,14 @@ connectToBus(const char* portname, int addr)
bool AsynDriverInterface::
lockRequest(unsigned long lockTimeout_ms)
{
int connected;
asynStatus status;
debug("AsynDriverInterface::lockRequest(%s, %ld msec)\n",
clientName(), lockTimeout_ms);
lockTimeout = lockTimeout_ms ? lockTimeout_ms*0.001 : -1.0;
ioAction = Lock;
status = pasynManager->isConnected(pasynUser, &connected);
if (status != asynSuccess)
{
error("%s: pasynManager->isConnected() failed: %s\n",
clientName(), pasynUser->errorMessage);
return false;
}
status = pasynManager->queueRequest(pasynUser,
connected ? priority() : asynQueuePriorityConnect,
lockTimeout);
priority(), lockTimeout);
if (status != asynSuccess)
{
error("%s lockRequest: pasynManager->queueRequest() failed: %s\n",
@ -534,7 +530,7 @@ connectToAsynPort()
connected ? "yes" : "no");
if (status != asynSuccess)
{
error("%s: pasynManager->isConnected() failed: %s\n",
error("%s connectToAsynPort: pasynManager->isConnected() failed: %s\n",
clientName(), pasynUser->errorMessage);
return false;
}
@ -578,7 +574,7 @@ connectToAsynPort()
clientName(), asynStatusStr[status]);
if (status != asynSuccess)
{
error("%s: pasynCommon->connect() failed: %s\n",
error("%s connectToAsynPort: pasynCommon->connect() failed: %s\n",
clientName(), pasynUser->errorMessage);
return false;
}
@ -597,25 +593,14 @@ void AsynDriverInterface::
lockHandler()
{
asynStatus status;
int connected;
debug("AsynDriverInterface::lockHandler(%s)\n",
clientName());
status = pasynManager->isConnected(pasynUser, &connected);
if (status != asynSuccess)
{
error("%s: pasynManager->isConnected() failed: %s\n",
clientName(), pasynUser->errorMessage);
lockCallback(StreamIoFault);
return;
}
if (!connected) lockCallback(StreamIoFault);
status = pasynManager->blockProcessCallback(pasynUser, false);
if (status != asynSuccess)
{
error("%s: pasynManager->blockProcessCallback() failed: %s\n",
error("%s lockHandler: pasynManager->blockProcessCallback() failed: %s\n",
clientName(), pasynUser->errorMessage);
lockCallback(StreamIoFault);
return;
@ -634,9 +619,8 @@ unlock()
status = pasynManager->unblockProcessCallback(pasynUser, false);
if (status != asynSuccess)
{
error("%s: pasynManager->unblockProcessCallback() failed: %s\n",
error("%s unlock: pasynManager->unblockProcessCallback() failed: %s\n",
clientName(), pasynUser->errorMessage);
lockCallback(StreamIoFault);
return false;
}
return true;
@ -682,15 +666,18 @@ writeHandler()
size_t written = 0;
pasynUser->timeout = 0;
if (pasynGpib)
pasynOctet->flush(pvtOctet, pasynUser);
else
if (!pasynGpib)
// discard any early input, but forward it to potential async records
// thus do not use pasynOctet->flush()
// unfortunately we cannot do this with GPIB because addressing a device as talker
// when it has nothing to say is an error. Also timeout=0 does not help here (would need
// a change in asynGPIB), thus use flush() for GPIB.
do {
char buffer [256];
size_t received = 0;
int eomReason = 0;
debug("AsynDriverInterface::writeHandler(%s): reading old input\n",
clientName());
status = pasynOctet->read(pvtOctet, pasynUser,
buffer, sizeof(buffer), &received, &eomReason);
if (received == 0) break;
@ -699,6 +686,12 @@ writeHandler()
clientName(), (long)received, StreamBuffer(buffer, received).expand()());
#endif
} while (status == asynSuccess);
else
{
debug("AsynDriverInterface::writeHandler(%s): flushing old input\n",
clientName());
pasynOctet->flush(pvtOctet, pasynUser);
}
// discard any early events
receivedEvent = 0;
@ -733,6 +726,12 @@ writeHandler()
clientName(), (long)outputSize, (long)written,
pasynUser->timeout, asynStatusStr[status]);
if (oldeoslen >= 0) // restore asyn terminator
{
pasynOctet->setOutputEos(pvtOctet, pasynUser,
oldeos, oldeoslen);
}
// Up to asyn 4.17 I can't see when the server has disconnected. Why?
int connected;
pasynManager->isConnected(pasynUser, &connected);
@ -740,17 +739,12 @@ writeHandler()
"device is %sconnected\n",
clientName(),connected?"":"dis");
if (!connected) {
error("%s: connection closed in write\n",
error("%s: write failed because connection was closed by device\n",
clientName());
writeCallback(StreamIoFault);
return;
}
if (oldeoslen >= 0) // restore asyn terminator
{
pasynOctet->setOutputEos(pvtOctet, pasynUser,
oldeos, oldeoslen);
}
switch (status)
{
case asynSuccess:
@ -775,32 +769,34 @@ writeHandler()
writeCallback(StreamIoSuccess);
return;
case asynTimeout:
error("%s: asynTimeout (%g sec) in write. Asyn says: %s\n",
clientName(), pasynUser->timeout, pasynUser->errorMessage);
writeCallback(StreamIoTimeout);
return;
case asynOverflow:
error("%s: asynOverflow in write: %s\n",
error("%s: asynOverflow in write. Asyn driver says: %s\n",
clientName(), pasynUser->errorMessage);
writeCallback(StreamIoFault);
return;
case asynError:
error("%s: asynError in write: %s\n",
error("%s: asynError in write. Asyn driver says: %s\n",
clientName(), pasynUser->errorMessage);
writeCallback(StreamIoFault);
return;
#ifdef ASYN_VERSION // asyn >= 4.14
case asynDisconnected:
error("%s: asynDisconnected in write: %s\n",
error("%s: asynDisconnected in write. Asyn driver says: %s\n",
clientName(), pasynUser->errorMessage);
writeCallback(StreamIoFault);
return;
case asynDisabled:
error("%s: asynDisconnected in write: %s\n",
error("%s: asynDisconnected in write. Asyn driver says: %s\n",
clientName(), pasynUser->errorMessage);
writeCallback(StreamIoFault);
return;
#endif
default:
error("%s: unknown asyn error in write: %s\n",
error("%s: unknown asyn error in write. Asyn driver says: %s\n",
clientName(), pasynUser->errorMessage);
writeCallback(StreamIoFault);
return;
@ -1098,29 +1094,29 @@ readHandler()
}
peeksize = inputBuffer.capacity();
// deliver whatever we could save
error("%s: asynOverflow in read: %s\n",
error("%s: asynOverflow in read. Asyn driver says: %s\n",
clientName(), pasynUser->errorMessage);
readCallback(StreamIoFault, buffer, received);
break;
case asynError:
error("%s: asynError in read: %s\n",
error("%s: asynError in read. Asyn driver says: %s\n",
clientName(), pasynUser->errorMessage);
readCallback(StreamIoFault, buffer, received);
break;
#ifdef ASYN_VERSION // asyn >= 4.14
case asynDisconnected:
error("%s: asynDisconnected in read: %s\n",
error("%s: asynDisconnected in read. Asyn driver says: %s\n",
clientName(), pasynUser->errorMessage);
readCallback(StreamIoFault);
return;
case asynDisabled:
error("%s: asynDisconnected in read: %s\n",
error("%s: asynDisconnected in read. Asyn driver says: %s\n",
clientName(), pasynUser->errorMessage);
readCallback(StreamIoFault);
return;
#endif
default:
error("%s: unknown asyn error in read: %s\n",
error("%s: unknown asyn error in read. Asyn driver says: %s\n",
clientName(), pasynUser->errorMessage);
readCallback(StreamIoFault);
return;

View File

@ -130,7 +130,7 @@ public:
StreamBuffer& append(const StreamBuffer& s)
{return append(s.buffer+s.offs, s.len);}
// operator += alias for set
// operator += alias for append
StreamBuffer& operator+=(char c)
{return append(c);}

View File

@ -20,13 +20,7 @@
#include "StreamBusInterface.h"
#include "StreamError.h"
const char* StreamIoStatusStr[] = {
"StreamIoSuccess",
"StreamIoTimeout",
"StreamIoNoReply",
"StreamIoEnd",
"StreamIoFault"
};
StreamIoStatusStrClass StreamIoStatusStr;
StreamBusInterfaceRegistrarBase* StreamBusInterfaceRegistrarBase::first;

View File

@ -21,13 +21,26 @@
#define StreamBusInterface_h
#include <stddef.h>
#include <StreamBuffer.h>
enum StreamIoStatus {
StreamIoSuccess, StreamIoTimeout, StreamIoNoReply,
StreamIoEnd, StreamIoFault
};
extern const char* StreamIoStatusStr[];
class StreamIoStatusStrClass {
public:
const char* operator [] (int index) {
switch (index) {
case StreamIoSuccess: return "StreamIoSuccess";
case StreamIoTimeout: return "StreamIoTimeout";
case StreamIoNoReply: return "StreamIoNoReply";
case StreamIoEnd: return "StreamIoEnd";
case StreamIoFault: return "StreamIoFault";
default: return "illegal status";
}
}
} extern StreamIoStatusStr;
class StreamBusInterface
{
@ -89,6 +102,9 @@ public:
bool busDisconnect() {
return businterface && businterface->disconnectRequest();
}
void busPrintStatus(StreamBuffer& buffer) {
if (businterface) businterface->printStatus(buffer);
}
};
private:
@ -137,6 +153,7 @@ protected:
virtual bool connectRequest(unsigned long connecttimeout_ms);
virtual bool disconnectRequest();
virtual void finish();
virtual void printStatus(StreamBuffer& buffer) {};
// pure virtual
virtual bool lockRequest(unsigned long timeout_ms) = 0;

View File

@ -59,7 +59,7 @@ static char* printCommands(StreamBuffer& buffer, const char* c)
break;
case wait_cmd:
timeout = extract<unsigned long>(c);
buffer.print(" wait %ld;\n # ms", timeout);
buffer.print(" wait %ld; # ms\n", timeout);
break;
case event_cmd:
eventnumber = extract<unsigned long>(c);
@ -818,7 +818,7 @@ lockCallback(StreamIoStatus status)
{
MutexLock lock(this);
debug("StreamCore::lockCallback(%s, status=%s)\n",
name(), status ? "Timeout" : "Success");
name(), StreamIoStatusStr[status]);
if (!(flags & LockPending))
{
error("StreamCore::lockCallback(%s) called unexpectedly\n",
@ -832,11 +832,21 @@ lockCallback(StreamIoStatus status)
case StreamIoSuccess:
break;
case StreamIoTimeout:
error("%s: Cannot lock device within %ld ms\n",
error("%s: Cannot lock device within %ld ms, device seems to be busy\n",
name(), lockTimeout);
flags &= ~BusOwner;
finishProtocol(LockTimeout);
return;
case StreamIoFault:
error("%s: Locking failed because of a device fault\n",
name());
flags &= ~BusOwner;
finishProtocol(LockTimeout);
return;
default:
error("StreamCore::lockCallback(%s) unexpected status %s\n",
name(), StreamIoStatusStr[status]);
flags &= ~BusOwner;
finishProtocol(Fault);
return;
}
@ -1309,8 +1319,8 @@ normal_format:
inputLine.length()-consumedInput > 20 ? "..." : "",
formatstring());
else
error("%s: Format \"%%%s\" has data type %s which does not match variable \"%s\".\n",
name(), formatstring(), StreamFormatTypeStr[fmt.type], fieldName);
error("%s: Format \"%%%s\" has data type %s which does not match the type of \"%s\".\n",
name(), formatstring(), StreamFormatTypeStr[fmt.type], fieldAddress ? fieldName : name());
}
return false;
}
@ -1740,4 +1750,25 @@ disconnectCallback(StreamIoStatus status)
}
}
void StreamCore::
printStatus(StreamBuffer& buffer)
{
buffer.print("active command=%s ",
activeCommand ? commandName(*activeCommand) : "NULL");
buffer.print("flags=0x%04lx ", flags);
if (flags & IgnoreExtraInput) buffer.append("IgnoreExtraInput ");
if (flags & InitRun) buffer.append("InitRun ");
if (flags & AsyncMode) buffer.append("AsyncMode ");
if (flags & GotValue) buffer.append("GotValue ");
if (flags & BusOwner) buffer.append("BusOwner ");
if (flags & Separator) buffer.append("Separator ");
if (flags & ScanTried) buffer.append("ScanTried ");
if (flags & AcceptInput) buffer.append("AcceptInput ");
if (flags & AcceptEvent) buffer.append("AcceptEvent ");
if (flags & LockPending) buffer.append("LockPending ");
if (flags & WritePending) buffer.append("WritePending ");
if (flags & WaitPending) buffer.append("WaitPending ");
busPrintStatus(buffer);
}
#include "streamReferences"

View File

@ -219,6 +219,7 @@ public:
bool parse(const char* filename, const char* protocolname);
void printProtocol();
const char* name() { return streamname; }
void printStatus(StreamBuffer& buffer);
};
#endif

View File

@ -350,6 +350,12 @@ report(int interest)
{
printf(" %s: %s\n", pstream->name(),
pstream->ioLink->value.instio.string);
if (interest == 3)
{
StreamBuffer buffer;
pstream->printStatus(buffer);
printf(" %s\n", buffer());
}
}
}
return OK;

View File

@ -23,7 +23,7 @@
#define STREAM_MAJOR 2
#define STREAM_MINOR 6
#define STREAM_PATCHLEVEL 3
#define STREAM_PATCHLEVEL 6
#if defined(__vxworks) || defined(vxWorks)
#include <vxWorks.h>

View File

@ -91,7 +91,7 @@ proc receiveHandler {sock} {
"start" {
set wait [checkNum [lindex $l 1]]
set ::counter 0
after $wait sendAsync $wait [list [lrange $l 2 end-1]]
after $wait [list sendAsync $wait "[string range $a [string wordend $a 7] end]"]
sendReply $sock "Started\n"
}
"stop" {
@ -133,7 +133,7 @@ proc receiveHandler {sock} {
proc sendAsync {wait message} {
if {$::counter < 0} return
foreach term [array names ::socket] {
sendReply $::socket($term) "Message number [incr ::counter] $message\n";
sendReply $::socket($term) "Message number [incr ::counter]$message";
}
after $wait sendAsync $wait [list $message]
}