📄 udprotcl.c
字号:
NULL, NULL, &station_scanner);
}
if (lpTopic == (LPSTAT) NULL)
/* cannot access station structure, exit */
return;
/*************************************/
/* Check whether to report the value */
/* of the reserved point STATUS */
/*************************************/
UdprotCheckAndUpdateStatus (lpTopic);
/*******************************/
/* get pointer to message that */
/* needs servicing, if any */
/*******************************/
/* get pointer to first station write message, if any */
wMsg = (LPUDMSG) FindFirstItem (&lpTopic->statWriteMsgList,
SCAN_FROM_HEAD,
NULL, NULL, &message_scanner);
/* get pointer to current read message, if any */
startMsg = lpTopic->statCurReadMsg;
/* Set up scanner, find current read message on this station, if any
If none, find the first read message on this station, if any */
rMsg = (LPUDMSG) FindItemStartingAt ((LPCHAINLINK) startMsg,
&lpTopic->statReadMsgList,
SCAN_FROM_HEAD,
NULL, NULL, &message_scanner);
/* clear message pointer */
lpMsg = (LPUDMSG)NULL;
/* check whether to select write message or read message */
if ((lpTopic->statConsecWrites > 0) &&
(wMsg != (LPUDMSG) NULL)) {
/* time to retry write message,
decrement retry count and point to first station write message */
lpTopic->statConsecWrites--;
lpMsg = wMsg;
} else {
/* new message,
initialize count and point to current station read message, if any */
lpTopic->statConsecWrites = MAX_CONSEC_WRITES;
if (startMsg != (LPUDMSG) NULL) {
/* message available, point to it */
lpMsg = startMsg;
}
}
if (lpMsg == (LPUDMSG) NULL) {
/* no message selected, point to first station read message, if any */
lpMsg = startMsg = rMsg;
}
/************************************/
/* check whether to service message */
/* or switch to a different one */
/************************************/
/* skip the station if delaying or if no messages */
if ((lpTopic->statDelay == 0L) &&
(lpMsg != (LPUDMSG) NULL)) {
/* no delay and we have a message */
/* check whether currently updating message */
if (!lpMsg->mmRead) {
/* not updating, write msg still in queue - do it again */
found = TRUE;
} else {
/* updating, search through the read messages on this station */
done = FALSE;
while ((!found) && (!done)) {
/****************************************/
/* check whether to delete this message */
/****************************************/
if (lpMsg->mmActiveCt == 0) {
/* This message has no remaining active points.
It is just waiting to be deleted. */
/* unchain the message, unlock it, and free its memory */
UdprotUnchainMsg(lpTopic, lpMsg);
UdprotFreeMsg(lpMsg);
/* check message pointer */
if (lpMsg == startMsg) {
/* this is the message we started with,
indicate that the message has been dropped */
startMsg = (LPUDMSG) NULL;
}
}
/*******************************/
/* get pointer to next message */
/*******************************/
/* check scanner for end of list */
if (GetScannerNextItem (&message_scanner) != NULL) {
/* get next item from message list */
lpMsg = (LPUDMSG) FindNextItem (&message_scanner);
} else {
/* end of list reached, wrap around to beginning of list */
lpMsg = (LPUDMSG) FindFirstItem (&lpTopic->statReadMsgList,
SCAN_FROM_HEAD,
NULL, NULL,
&message_scanner);
}
/**************************************************/
/* check whether ready message found or loop done */
/**************************************************/
if (lpMsg == (LPUDMSG) NULL) {
/* no more read messages, indicate we are done */
done = TRUE;
} else {
/* check message status */
if (lpMsg->mmDue && lpMsg->mmActiveCt) {
/* pending and active, indicate message found */
found = TRUE;
} else {
/* not ready, check whether we dropped a message */
if (startMsg == (LPUDMSG) NULL) {
/* dropped, set start pointer to this message */
startMsg = lpMsg;
} else {
/* not cleared, compare pointers */
if (startMsg == lpMsg) {
/* back where we started, indicate we are done */
done = TRUE;
}
}
}
}
} /* while */
}
}
/** stop search if ready message found
or if we just finished checking the starting topic */
} while ((!found) && (lpTopic != startTopic));
if (found) {
/* ready message found, set port to talk to indicated station */
lpPort->mbCurTopic = lpTopic;
lpPort->mbCurMsg = lpMsg;
lpTopic->statCurMsg = lpMsg;
if (lpMsg->mmRead) {
/* currently updating message, set pointer */
lpTopic->statCurReadMsg = lpMsg;
}
/* set port message pointers and status */
lpPort->mbRetries = lpTopic->statPortRetries;
lpMsg->mmDue = FALSE;
lpMsg->mmChanged = FALSE;
lpPort->mbDoingRead = lpMsg->mmRead;
/* check for periodic write message */
if ((!lpMsg->mmRead) && (lpMsg->mmScanReload != 0)) {
/* write message and periodic - currently not in there */
}
/* send the indicated query */
UdprotSendQuery(lpPort, lpMsg);
} else {
/* no message found, indicate port is idle */
lpPort->mbState = PROT_IDLE;
}
} /* UdprotPoll */
/***********************************************************************/
/** Handle response error for indicated port.
When an error is detected in the response message, retry up to
retry limit. Then set STATUS item to failed. **/
void
WINAPI
UdprotHandleRspError(LPPORT lpPort)
{
LPSTAT lpTopic;
/* check the port for errors and log them */
checkEvents (lpPort);
if (ShowingErrors)
/* display data received so far */
showReceivedData(lpPort);
if (bFlushOnError)
/* flush port buffers */
FlushPort (lpPort, (LPSTR) "");
/* decrement message retries */
if (lpPort->mbRetries > 0)
lpPort->mbRetries--;
/* check whether the message retry limit has been reached */
if (lpPort->mbRetries > 0) {
/* retry limit not yet reached, try again */
UdprotSendQuery(lpPort, lpPort->mbCurMsg);
} else {
/* retry limit reached, indicate problem */
/* mark this message as DUE, since it failed */
lpTopic = lpPort->mbCurTopic;
if (lpTopic) {
/* decrement station retries */
if (lpTopic->statRetries > 0)
lpTopic->statRetries--;
/* check whether the station retry limit has been reached */
if (lpTopic->statRetries > 0) {
/* retry limit not yet reached, set station for error delay */
lpTopic->statDelay = (LONG) ERRORDELAY;
} else {
/* retries exhausted, set up for recovery mode */
lpTopic->statPortRetries = TOPIC_RECOVERY_RETRIES;
/* fail all stations on this port, since it had comm errors */
/* (This includes setting into slow poll mode) */
/* (It also includes deleting all writes if not retry indefinitely */
UdprotFailStationTopics (lpPort);
}
}
/* force poll of current station */
UdprotPoll(lpPort);
}
} /* UdprotHandleRspError */
/***********************************************************************/
/* fail all stations on indicated port */
static
void
WINAPI
UdprotFailStationTopics (LPPORT lpPort)
{
LPSTAT lpTopic;
CHAINSCANNER station_scanner;
/* check all stations */
lpTopic = (LPSTAT) FindFirstItem (&lpPort->mbTopicList, SCAN_FROM_HEAD,
NULL, NULL, &station_scanner);
while (lpTopic != (LPSTAT) NULL) {
/* indicate station has failed */
UdprotSetTopicStatus (lpPort, lpTopic, TRUE); /* true means failed */
/* get pointer to next station, if any */
lpTopic = (LPSTAT) FindNextItem (&station_scanner);
}
} /* UdprotFailStationTopics */
/***********************************************************************/
/** set STATUS item in station structure
return TRUE if status is changed **/
static
BOOL
WINAPI
UdprotSetTopicStatus (LPPORT lpPort, LPSTAT lpTopic, unsigned bFailed)
{
BOOL changed;
/* initialize return value */
changed = FALSE;
/* no change if pointer is NULL */
if (lpTopic != (LPSTAT) NULL) {
/* check current station status */
if (lpTopic->statFailed != bFailed) {
/* different from old status, update it */
changed = TRUE;
lpTopic->statFailed = bFailed;
/* check whether station is active */
if (lpTopic->statStatusActive) {
/* active, indicate that station STATUS is due */
lpTopic->statStatusDue = TRUE;
}
/* check whether new status is OK or failed */
if (bFailed) {
/* have logger indicate entering slow poll mode */
debug ("Entering slow poll mode on topic \"%Fs\" on port %Fs.",
lpTopic->statTopicName, lpPort->mbPortName);
/* report new STATUS value if necessary */
UdprotCheckAndUpdateStatus (lpTopic);
/* set "no communication" quality flags
for all points polled on topic */
UdprotSetTopicQuality (lpTopic, WW_SQ_NOCOMM);
} else {
/* have logger indicate leaving slow poll mode */
debug ("Leaving slow poll mode on topic \"%Fs\" on port %Fs.",
lpTopic->statTopicName, lpPort->mbPortName);
}
}
/* check whether station is failed */
if (bFailed) {
/* set up slow poll mode */
UdprotSetSlowPollMode (lpPort, lpTopic);
}
}
/* indicate whether station status changed */
return (changed);
} /* UdprotSetTopicStatus */
/***********************************************************************/
/* set up slow poll mode for station on indicated port */
static
void
WINAPI
UdprotSetSlowPollMode (LPPORT lpPort, LPSTAT lpTopic)
{
long new_delay;
LPUDMSG lpMsg;
CHAINSCANNER message_scanner;
/* no change if station pointer is NULL */
if (lpTopic != (LPSTAT) NULL) {
/* indicate station has failed */
lpTopic->statRetries = 0; /* indicate retries exhausted */
/* set up for recovery mode */
lpTopic->statPortRetries = TOPIC_RECOVERY_RETRIES;
/* slow poll delay = 15 times update interval */
/* constrain to reasonable range, though */
new_delay = (long) SLOW_POLL_MULTIPLIER * lpTopic->statUpdatePeriod;
if (new_delay > SLOW_POLL_MAX)
new_delay = SLOW_POLL_MAX;
if (new_delay < SLOW_POLL_MIN)
new_delay = SLOW_POLL_MIN;
lpTopic->statDelay = new_delay;
/* delete all writes if not indefinitely retry */
if (!IndefWriteRetry) {
/* remove all writes from the list */
lpMsg = (LPUDMSG) FindFirstItem (&lpTopic->statWriteMsgList,
SCAN_FROM_HEAD,
NULL, NULL, &message_scanner);
while (lpMsg != (LPUDMSG) NULL) {
/* check whether this is current message for port */
if (lpMsg == lpPort->mbCurMsg) {
/* remove port reference to message */
lpPort->mbCurMsg = (LPUDMSG) NULL;
/* indicate port is idle */
lpPort->mbState = PROT_IDLE;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -