All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.cosylab.epics.caj.cas.handlers.EventAddResponse Maven / Gradle / Ivy

Go to download

JCA is an EPICS Channel Access library for Java. For more information concerning EPICS or Channel Access please refer to the <a href="http://www.aps.anl.gov/epics">EPICS Web pages</a> or read the <a href="http://www.aps.anl.gov/epics/base/R3-14/8-docs/CAref.html">Channel Access manual (3.14)</a>. <p>This module also includes CAJ, A 100% pure Java implementation of the EPICS Channel Access library.</p>

There is a newer version: 2.4.10
Show newest version
/*
 * Copyright (c) 2004 by Cosylab
 *
 * The full license specifying the redistribution, modification, usage and other
 * rights and obligations is included with the distribution of this project in
 * the file "LICENSE-CAJ". If the license is not included visit Cosylab web site,
 * .
 *
 * THIS SOFTWARE IS PROVIDED AS-IS WITHOUT WARRANTY OF ANY KIND, NOT EVEN THE
 * IMPLIED WARRANTY OF MERCHANTABILITY. THE AUTHOR OF THIS SOFTWARE, ASSUMES
 * _NO_ RESPONSIBILITY FOR ANY CONSEQUENCE RESULTING FROM THE USE, MODIFICATION,
 * OR REDISTRIBUTION OF THIS SOFTWARE.
 */

package com.cosylab.epics.caj.cas.handlers;

import gov.aps.jca.CAStatus;
import gov.aps.jca.CAStatusException;
import gov.aps.jca.Monitor;
import gov.aps.jca.cas.ProcessVariable;
import gov.aps.jca.cas.ProcessVariableReadCallback;
import gov.aps.jca.cas.ServerChannel;
import gov.aps.jca.dbr.ACK;
import gov.aps.jca.dbr.DBR;
import gov.aps.jca.dbr.DBRType;

import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.util.logging.Level;

import com.cosylab.epics.caj.cas.CAJServerContext;
import com.cosylab.epics.caj.cas.CASServerMonitor;
import com.cosylab.epics.caj.cas.CASTransport;
import com.cosylab.epics.caj.cas.requests.EventAddRequest;
import com.cosylab.epics.caj.impl.Transport;

/**
 * CA event add request handler.
 * @author Matej Sekoranja
 * @version $id$
 */
public class EventAddResponse extends AbstractCASResponseHandler {

	/**
	 * @param context CAJServerContext
	 */
	public EventAddResponse(CAJServerContext context) {
		super(context, "Event add request");
	}

	/**
	 * @see com.cosylab.epics.caj.impl.handlers.AbstractCAJResponseHandler#internalHandleResponse(java.net.InetSocketAddress, com.cosylab.epics.caj.impl.Transport, java.nio.ByteBuffer[])
	 */
	protected void internalHandleResponse(
		InetSocketAddress responseFrom,
		Transport transport,
		ByteBuffer[] response) {

		CASTransport casTransport = (CASTransport)transport;
		
		ServerChannel channel;
		try
		{
			channel = casTransport.getChannelAndVerifyRequest(parameter1, dataType, dataCount);
		} catch (CAStatusException cse) {
			channel = casTransport.getChannel(parameter1);
			int cid = (channel == null) ? 0 : channel.getCID();
			sendException(transport, cid, cse.getStatus(), response[0], "add event request");
			return;
		}

		// check monitor mask
		final int MASK_OFFSET = 12;
		short mask = response[1].getShort(MASK_OFFSET);
		if ((mask & (Monitor.ALARM | Monitor.LOG | Monitor.VALUE | Monitor.PROPERTY)) == 0)
		{
			sendException(transport, channel.getCID(), CAStatus.BADMASK, response[0], 
					"event add req with mask=" + Integer.toHexString(mask));
			return;
		}

		//
		// Attempt to read the first monitored value prior to creating
		// the monitor object so that if the server tool chooses
		// to postpone asynchronous IO we can safely restart this
		// request later.
		//

		// create DBR
		DBR value = createDBRforReading(channel.getProcessVariable(), dataType, dataCount);

		// check read rights
		if (!channel.readAccess())
		{
			eventAddFailureResponse(transport, dataType, dataCount, parameter1, parameter2, CAStatus.NORDACCESS, value);
			return;
		}

		CAStatus status = null;
		try
		{
			ProcessVariableReadCallback pvrc = new ProcessVariableReadCallbackImpl(channel, transport, dataType, dataCount, parameter1, parameter2, mask, value);
			status = channel.read(value, pvrc);
		} catch (Throwable th) {
			context.getLogger().log(Level.WARNING, "Exception caught when calling ServerChannel.read() for: " + channel.getProcessVariable().getName(), th);
			eventAddFailureResponse(transport, dataType, dataCount, parameter1, parameter2, CAStatus.DEFUNCT, value);
			return;
		}
		
		if (status == null)
		{
			// async, noop
			return;
		}
		else
			eventAddResponse(channel, transport, dataType, dataCount, parameter1, parameter2, mask, value, status);
	}

	/**
	 * @param channel
	 * @param transport
	 * @param dataType
	 * @param dataCount
	 * @param sid
	 * @param ioid
	 * @param mask
	 * @param value
	 * @param status
	 */
	private void eventAddResponse(ServerChannel channel, Transport transport, short dataType, int dataCount,
								  int sid, int ioid, short mask, DBR value, CAStatus status)
	{
		if (status != CAStatus.NORMAL)
		{
			eventAddFailureResponse(transport, dataType, dataCount, sid, ioid, status, value);
			return;
		}

		eventResponse(channel.getProcessVariable(), transport, dataType, dataCount, sid, ioid, value);

		// create monitor
		new CASServerMonitor(channel, ioid, mask, this, (CASTransport)transport, dataType, dataCount);
	}

	/**
	 * @param processVariable process variable
	 * @param transport  transport to be used when sending
	 * @param dataType data type
	 * @param dataCount data count
	 * @param sid sid
	 * @param ioid ioid
	 * @param value DBR value
	 */
	public void eventResponse(ProcessVariable processVariable, Transport transport, short dataType, int dataCount, int sid, int ioid, DBR value) {

		// convert to required type
		try
		{
			value = value.convert(DBRType.forValue(dataType));
		} catch (CAStatusException cse) {
			eventAddFailureResponse(transport, dataType, dataCount, sid, ioid, cse.getStatus(), value);
			return;
		}

		// ackS/T support
		if (value instanceof ACK)
		{
			ACK ack = (ACK)value;
			ack.setAckS(processVariable.getAckS());
			ack.setAckT(processVariable.isAckT());
		}

		try
		{
			new EventAddRequest(transport, ioid, dataType, dataCount, CAStatus.NORMAL, value).submit();
			
		} catch (Throwable th) {
			context.getLogger().log(Level.WARNING, "Exception caught when responding to event add request for channel with SID : " + sid, th);
		}
	}
	
	/**
	 * @param transport
	 * @param dataType
	 * @param dataCount
	 * @param sid
	 * @param ioid
	 * @param errorStatus
	 */
	private void eventAddFailureResponse(Transport transport, short dataType, int dataCount,
											int sid, int ioid, CAStatus errorStatus, DBR value)
	{
		try
		{
			new EventAddRequest(transport, ioid, dataType, dataCount, errorStatus, value).submit();
			
		} catch (Throwable th) {
			context.getLogger().log(Level.WARNING, "Exception caught when responding with error to event add request for channel with SID : " + sid, th);
		}
	}
	
	
	/**
	 * Async. completion callback support.
	 * @author msekoranja
	 */
	class ProcessVariableReadCallbackImpl implements ProcessVariableReadCallback
	{
		private ServerChannel channel;
		private Transport transport;
		private short dataType;
		private int dataCount;
		private int sid;
		private int ioid;
		private short mask;
		private DBR value;
		
		/**
		 * @param channel
		 * @param transport
		 * @param dataType
		 * @param dataCount
		 * @param sid
		 * @param ioid
		 * @param mask
		 * @param value
		 */
		public ProcessVariableReadCallbackImpl(ServerChannel channel, Transport transport, short dataType, int dataCount, int sid, int ioid, short mask, DBR value) {
			this.channel = channel;
			this.transport = transport;
			this.dataType = dataType;
			this.dataCount = dataCount;
			this.sid = sid;
			this.ioid = ioid;
			this.mask = mask;
			this.value = value;
		}
		
		/* (non-Javadoc)
		 * @see gov.aps.jca.cas.ProcessVariableReadCallback#processVariableReadCompleted(gov.aps.jca.CAStatus)
		 */
		public void processVariableReadCompleted(CAStatus status) {
			if (status == null)
				status = CAStatus.DEFUNCT;
			
			eventAddResponse(channel, transport, dataType, dataCount, sid, ioid, mask, value, status);
		}
		
		/* (non-Javadoc)
		 * @see gov.aps.jca.cas.CompletionCallback#canceled()
		 */
		public void canceled() {
			eventAddFailureResponse(transport, dataType, dataCount, sid, ioid, CAStatus.DEFUNCT, value);
		}	
		
	}
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy