Mercurial > lbo > hg > clusterrpc-java
view src/main/java/net/borgac/clusterrpc/client/ClientChannel.java @ 5:117cb812e28a
Implement several lower-level classes (networking/framing)
author | Lewin Bormann <lbo@spheniscida.de> |
---|---|
date | Fri, 23 Sep 2016 22:01:17 +0200 |
parents | |
children | 0e608c466a58 |
line wrap: on
line source
package net.borgac.clusterrpc.client; import java.io.Closeable; import java.time.Instant; import java.util.HashMap; import java.util.Map; import java.util.Random; /** * ClientChannel implements the transport of RPC calls to the server. * * It's mainly responsible for peer management. Framing and error handling are * mostly handled in SocketWrapper. * * @author lbo */ public final class ClientChannel implements Closeable { // Simple seed is good enough here. private static final Random CHANNEL_ID_GENERATOR = new Random( Instant.now().getEpochSecond()); private SocketWrapper sock; private int peerCounter; private Map<PeerHandle, PeerAddress> peers; private final long channelId; /** * Initialize a ClientChannel with no connections. */ public ClientChannel() { this.sock = new SocketWrapper(); this.peerCounter = 0; this.peers = new HashMap<>(); this.channelId = CHANNEL_ID_GENERATOR.nextLong(); } /** * Initialize a ClientChannel, and connect to `address`. * * @param address Address of the first peer to connect to. */ public ClientChannel(PeerAddress address) { this(); connect(address); } /** * Connect to an RPC server. * * This method can be called multiple times to connect to multiple peers. If * a channel is connected to multiple peers, requests are sent in a * round-robin manner. While possible, it is not recommended to use this as * debugging may become difficult in case one or more of the peers * disappear. * * @param address * @return A PeerHandle that can be used to later disconnect from that peer. */ public PeerHandle connect(PeerAddress address) { PeerHandle handle = new PeerHandle(channelId, peerCounter); this.peerCounter++; peers.put(handle, address); sock.connect(address); return handle; } /** * Disconnect the channel from a peer. * * @param handle A handle returned by `connect()`. * @return True if the peer could be disconnected, otherwise false. */ public boolean disconnect(PeerHandle handle) { if (handle.associatedChannel == channelId) { PeerAddress address = peers.get(handle); if (address != null) { sock.disconnect(address); peers.remove(handle); return true; } } return false; } @Override public void close() { sock.close(); } }