package io.craft.atom.rpc; import io.craft.atom.io.Channel; import io.craft.atom.io.IllegalChannelStateException; import io.craft.atom.protocol.ProtocolDecoder; import io.craft.atom.protocol.ProtocolEncoder; import io.craft.atom.protocol.rpc.model.RpcMessage; import io.craft.atom.rpc.spi.RpcChannel; import java.util.List; import java.util.Map; import lombok.Getter; import lombok.Setter; import lombok.ToString; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * @author mindwind * @version 1.0, Aug 22, 2014 */ @ToString(of = "channel") public class DefaultRpcChannel implements RpcChannel { private static final Logger LOG = LoggerFactory.getLogger(DefaultRpcChannel.class); @Getter @Setter private ProtocolEncoder<RpcMessage> encoder; @Getter @Setter private ProtocolDecoder<RpcMessage> decoder; @Getter @Setter private Channel<byte[]> channel; @Getter @Setter private Map<Long, RpcFuture<?>> futures; // ~ ------------------------------------------------------------------------------------------------------------- DefaultRpcChannel(Channel<byte[]> channel, ProtocolEncoder<RpcMessage> encoder, ProtocolDecoder<RpcMessage> decoder) { this.channel = channel; this.encoder = encoder; this.decoder = decoder; } // ~ ------------------------------------------------------------------------------------------------------------- @Override public void write(RpcMessage msg) throws RpcException { try { byte[] bytes = encoder.encode(msg); LOG.debug("[CRAFT-ATOM-RPC] Rpc channel write bytes, |length={}, bytes={}, channel={}|", bytes.length, bytes, channel); channel.write(bytes); } catch (IllegalChannelStateException e) { throw new RpcException(RpcException.NETWORK, "broken connection"); } } @Override public List<RpcMessage> read(byte[] bytes) { LOG.debug("[CRAFT-ATOM-RPC] Rpc channel read bytes, |length={}, bytes={}, channel={}|", bytes.length, bytes, channel); List<RpcMessage> msgs = decoder.decode(bytes); return msgs; } void close() { channel.close(); } boolean isOpen() { return channel.isOpen(); } long getId() { return channel.getId(); } void setRpcFuture(long mid, RpcFuture<?> future) { futures.put(mid, future); } void notifyRpcMessage(RpcMessage msg) { RpcFuture<?> future = futures.remove(msg.getId()); if (future == null) return; future.setResponse(msg); } void notifyRpcException(Exception e) { for (RpcFuture<?> future : futures.values()) { future.setException(e); } } int waitCount() { return channel.getWriteQueue().size(); } }