View Javadoc

1   package org.lsst.ccs.command.demo.remote.jgroups;
2   
3   import java.io.Closeable;
4   import java.io.IOException;
5   import java.io.Serializable;
6   import java.util.concurrent.ExecutorService;
7   import java.util.concurrent.Executors;
8   import java.util.concurrent.TimeUnit;
9   import java.util.logging.Level;
10  import java.util.logging.Logger;
11  import org.jgroups.Address;
12  import org.jgroups.JChannel;
13  import org.jgroups.Message;
14  import org.jgroups.ReceiverAdapter;
15  import org.lsst.ccs.command.CommandInvocationException;
16  import org.lsst.ccs.command.CommandSet;
17  import org.lsst.ccs.command.TokenizedCommand;
18  import org.lsst.ccs.command.remote.CommandResponse;
19  import org.lsst.ccs.command.remote.CommandServer;
20  
21  /**
22   * A server to make a CommandSet available remotely using JGroups.
23   * @author tonyj
24   */
25  public class JGroupsCommandServer extends CommandServer implements Closeable {
26  
27      private static final Logger logger = Logger.getLogger(JGroupsCommandServer.class.getName());
28      static final String CCS_REMOTE_COMMAND_DEMO = "CCSRemoteCommandDemo";
29      static final String HELLO = "Hello";
30      private final JChannel channel;
31      private final ExecutorService executor = Executors.newSingleThreadExecutor();
32  
33      /** Make commands available to a jgroups cluster.
34       * @param set The commands to publish
35       * @throws Exception If something goes wrong setting up the connection.
36       */
37      public JGroupsCommandServer(CommandSet set) throws Exception {
38          super(set);
39          channel = new JChannel();
40          channel.setReceiver(new ReceiverAdapterImpl());
41          channel.connect(CCS_REMOTE_COMMAND_DEMO);
42          Message msg = new Message(null, set.getCommandDictionary());
43          channel.send(msg);
44      }
45  
46      @Override
47      public void close() throws IOException {
48          executor.shutdown();
49          try {
50              executor.awaitTermination(0, TimeUnit.SECONDS);
51          } catch (InterruptedException ex) {
52              logger.log(Level.INFO, "Interrupted while closing server", ex);
53          }
54          channel.close();
55      }
56  
57      private class ReceiverAdapterImpl extends ReceiverAdapter {
58  
59          @Override
60          public void receive(Message msg) {
61              final Object obj = msg.getObject();
62              if (HELLO.equals(obj)) {
63                  Runnable runnable = new Runnable() {
64                      @Override
65                      public void run() {
66                          Message msg = new Message(null, getCommandSet().getCommandDictionary());
67                          send(msg);
68                      }
69                  };
70                  executor.submit(runnable);
71              } else if (obj instanceof TokenizedCommand) {
72                  final Address src = msg.getSrc();
73                  Runnable runnable = new Runnable() {
74                      @Override
75                      public void run() {
76                          try {
77                              Object result = getCommandSet().invoke((TokenizedCommand) obj);
78                              CommandResponse response = new CommandResponse((Serializable) result);
79                              send(new Message(src, response));
80                          } catch (                CommandInvocationException ex) {
81                              send(new Message(src, new CommandResponse(ex)));
82                          }
83                      }
84                  };
85                  executor.submit(runnable);
86              }
87          }
88      }
89  
90      private void send(Message msg) {
91          try {
92              channel.send(msg);
93          } catch (Exception ex) {
94              logger.log(Level.SEVERE, "Error while sending message", ex);
95          }
96      }
97  
98  }