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

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

/*
 * 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.cas.ProcessVariable;
import gov.aps.jca.cas.ProcessVariableWriteCallback;
import gov.aps.jca.cas.ServerChannel;
import gov.aps.jca.dbr.DBR;
import gov.aps.jca.dbr.DBR_PutAckS;
import gov.aps.jca.dbr.DBR_PutAckT;
import gov.aps.jca.dbr.Severity;

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.CASTransport;
import com.cosylab.epics.caj.impl.DBRDecoder;
import com.cosylab.epics.caj.impl.Transport;

/**
 * CA write request handler.
 * @author Matej Sekoranja
 * @version $id$
 */
public class WriteResponse extends AbstractCASResponseHandler {

	/**
	 * @param context
	 */
	public WriteResponse(CAJServerContext context) {
		super(context, "Write 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], "get request");
			return;
		}	
		
		// check write access rights
		if (!channel.writeAccess())
		{
			CAStatus errorStatus = (transport.getMinorRevision() < 1) ? CAStatus.PUTFAIL : CAStatus.NOWTACCESS;
			sendException(transport, channel.getCID(), errorStatus, response[0], "write access denied");
			return;
		}
		
		// decode value
		DBR value = DBRDecoder.getDBR(null, dataType, dataCount, response[1]);

		// ackS/T support
		if (value instanceof DBR_PutAckT)
		{
			final short tValue = ((DBR_PutAckT)value).getShortValue()[0]; 
			channel.getProcessVariable().setAckT(tValue != 0);
			return;
		}
		else if (value instanceof DBR_PutAckS)
		{
			final short sValue = ((DBR_PutAckS)value).getShortValue()[0];
			final Severity severity = Severity.forValue(sValue);
			// check severity value
			if (severity != null)
				channel.getProcessVariable().setAckS(severity);
			else
				sendException(transport, channel.getCID(), CAStatus.PUTFAIL, response[0], "Invalid severity value");
			return;
		}
		
		// convert
		try
		{
			ProcessVariable pv = channel.getProcessVariable();
			value = value.convert(pv.getType(), pv.getEnumLabels());
		} catch (CAStatusException cse) {
			sendException(transport, channel.getCID(), cse.getStatus(), response[0], cse.getMessage());
			return;
		}
		
		CAStatus status = null;
		try
		{
			ProcessVariableWriteCallback pvwci = new ProcessVariableWriteCallbackImpl(transport, channel.getCID(), response[0]);
			status = channel.write(value, pvwci);
		} catch (Throwable th) {
			context.getLogger().log(Level.WARNING, "Exception caught when calling ServerChannel.write() for: " + channel.getProcessVariable().getName(), th);
			sendException(transport, channel.getCID(), CAStatus.DEFUNCT, response[0], th.getMessage());
			return;
		}
		
		if (status != null && status != CAStatus.NORMAL)
		{
			sendException(transport, channel.getCID(), status, response[0], null);
			return;
		}
		
	}
	
	
	/**
	 * Async. completion callback support.
	 * @author msekoranja
	 */
	class ProcessVariableWriteCallbackImpl implements ProcessVariableWriteCallback
	{
		private Transport transport;
		private int cid;
		private ByteBuffer previousHeader;
		
		/**
		 * @param transport
		 * @param cid
		 * @param previousHeader
		 */
		public ProcessVariableWriteCallbackImpl(Transport transport, int cid, ByteBuffer previousHeader) {
			this.transport = transport;
			this.cid = cid;
			// copy
			this.previousHeader = ByteBuffer.allocate(previousHeader.limit());
			this.previousHeader.get(previousHeader.array(), 0, previousHeader.limit());
			
		}

		/* (non-Javadoc)
		 * @see gov.aps.jca.cas.ProcessVariableWriteCallback#processVariableWriteCompleted(gov.aps.jca.CAStatus)
		 */
		public void processVariableWriteCompleted(CAStatus status) {
			if (status == null)
				sendException(transport, cid, CAStatus.DEFUNCT, previousHeader, "Non-null status expected.");
			else if (status != CAStatus.NORMAL)
				sendException(transport, cid, status, previousHeader, status.getMessage());
		}
		
		/* (non-Javadoc)
		 * @see gov.aps.jca.cas.CompletionCallback#canceled()
		 */
		public void canceled() {
			sendException(transport, cid, CAStatus.DEFUNCT, previousHeader, "Async IO canceled.");
		}

	}
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy