Java tutorial
/** * Copyright (C) 2011-2012 Andrey Borisov <aandrey.borisov@gmail.com> * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.turbospaces.network; import java.util.Collection; import java.util.LinkedHashSet; import java.util.List; import java.util.Random; import javax.annotation.concurrent.ThreadSafe; import org.jgroups.Address; import org.jgroups.Message; import org.jgroups.MessageListener; import org.jgroups.Receiver; import org.jgroups.ReceiverAdapter; import org.jgroups.View; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.remoting.RemoteLookupFailureException; import com.google.common.collect.Lists; import com.turbospaces.api.AbstractSpaceConfiguration; import com.turbospaces.api.JSpace; import com.turbospaces.api.SpaceErrors; import com.turbospaces.api.SpaceException; import com.turbospaces.api.SpaceTopology; /** * central point for network communication over jgroups on the server side(minimalistic version instead of jgroups's * high-level building blocks for better performance and lower GC garbage allocations). * * @since 0.1 */ @ThreadSafe public class ServerCommunicationDispatcher extends ReceiverAdapter implements SpaceErrors { private final Logger logger = LoggerFactory.getLogger(getClass()); private final Random random = new Random(); private final Object monitor = new Object(); final AbstractSpaceConfiguration configuration; private volatile Address[] serverNodes = new Address[0]; private volatile Address[] clientNodes = new Address[0]; private final Collection<Receiver> delegates = new LinkedHashSet<Receiver>(); /** * create receiver over jchannel with given default network communication timeout. * * @param configuration * client or server configuration */ public ServerCommunicationDispatcher(final AbstractSpaceConfiguration configuration) { this.configuration = configuration; } /** * register message listener delegate * * @param delegate * message receiver delegate */ public void addMessageReceiver(final Receiver delegate) { delegates.add(delegate); } /** * un-register message listener delegate * * @param delegate * message receiver delegate */ public void removeMessageReceiver(final Receiver delegate) { delegates.remove(delegate); } @Override public final void viewAccepted(final View view) { List<Address> members = view.getMembers(); Address ownAddress = configuration.getJChannel().getAddress(); List<Address> newServersMembers = Lists.newArrayList(); List<Address> newClientMembers = Lists.newArrayList(); for (Address address : members) if (!ownAddress.equals(address)) { String logicalName = address.toString(); if (logicalName.startsWith(JSpace.SSC)) { logger.info("discovered jspace server member:" + address); newServersMembers.add(address); } else if (logicalName.startsWith(JSpace.SC)) { logger.info("discovered jspace client member:" + address); newClientMembers.add(address); } } serverNodes = newServersMembers.toArray(new Address[newServersMembers.size()]); clientNodes = newClientMembers.toArray(new Address[newClientMembers.size()]); if (serverNodes.length != 0) synchronized (monitor) { monitor.notifyAll(); } logger.info(view.toString()); for (Receiver r : delegates) r.viewAccepted(view); } /** * get the remove server nodes(block if 0 nodes discovered) * * @return the remote server side jspace nodes * @throws RemoteLookupFailureException * if no remote server nodes are discovered */ public final Address[] getServerNodes() throws RemoteLookupFailureException { Address[] nodes = serverNodes; long communicationTimeout = configuration.getCommunicationTimeoutInMillis(); if (nodes.length == 0) synchronized (monitor) { try { monitor.wait(communicationTimeout); } catch (InterruptedException e) { logger.error(e.getMessage(), e); Thread.currentThread().interrupt(); throw new SpaceException(e.getMessage(), e); } } if (nodes.length == 0) throw new RemoteLookupFailureException(String.format(LOOKUP_TIMEOUT, communicationTimeout)); return nodes; } /** * get server nodes(all) for partitioned topology or any one for synch replicated jspace. * * @param spaceTopology * jspace topology * @return appropriate server nodes(or node) for space topology */ public final Address[] getServerNodes(final SpaceTopology spaceTopology) { Address[] addresses = getServerNodes(); if (spaceTopology.isSynchReplicated()) return new Address[] { addresses[random.nextInt(addresses.length)] }; return addresses; } /** * @return server nodes as is (even if there are no connected server nodes) */ public final Address[] getRawServerNodes() { return serverNodes; } /** * @return client nodes as is (even if there are no connected server nodes) */ public final Address[] getRawClientNodes() { return clientNodes; } @Override public void receive(final Message msg) { for (MessageListener ml : delegates) ml.receive(msg); } @Override public void suspect(final Address mbr) { for (Receiver r : delegates) r.suspect(mbr); } }