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.util.ArrayList;
6   import java.util.Iterator;
7   import java.util.List;
8   import java.util.concurrent.Exchanger;
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.jgroups.View;
16  import org.lsst.ccs.command.BasicCommand;
17  import org.lsst.ccs.command.annotations.Command;
18  import org.lsst.ccs.command.Dictionary;
19  import org.lsst.ccs.command.CommandInvocationException;
20  import org.lsst.ccs.command.CommandSet;
21  import org.lsst.ccs.command.CommandSetBuilder;
22  import org.lsst.ccs.command.CompositeCommandSet;
23  import org.lsst.ccs.command.remote.CommandClient;
24  import org.lsst.ccs.command.remote.CommandResponse;
25  
26  /**
27   * A simple CommandClient using JGroups as the communication mechanism.  
28   * @author tonyj
29   */
30  public class JGroupsCommandClient extends CompositeCommandSet implements CommandClient, Closeable {
31      //FIXME: We should worry about thread safety of command set
32  
33      private static final Logger logger = Logger.getLogger(JGroupsCommandClient.class.getName());
34      private final JChannel channel;
35      private final Exchanger<CommandResponse> exchanger = new Exchanger<>();
36      private View view;
37  
38      public JGroupsCommandClient() throws Exception {
39          channel = new JChannel();
40          channel.setReceiver(new ClientReceiverAdapter());
41          channel.connect(JGroupsCommandServer.CCS_REMOTE_COMMAND_DEMO);
42          CommandSetBuilder builder = new CommandSetBuilder();
43          add(builder.buildCommandSet(new BuiltIns()));
44          channel.send(new Message(null, JGroupsCommandServer.HELLO));
45      }
46  
47      @Override
48      public void close() throws IOException {
49          channel.close();
50      }
51  
52      private class ClientReceiverAdapter extends ReceiverAdapter {
53  
54          @Override
55          public void viewAccepted(View view) {
56              JGroupsCommandClient.this.view = view;
57              List<CommandSetImplementation> maybeDelete = new ArrayList<>();
58              for (CommandSet set : getCommandSets()) {
59                  if (set instanceof CommandSetImplementation) {
60                      maybeDelete.add((CommandSetImplementation) set);
61                  }
62              }
63              for (Address address : view) {
64                  for (Iterator<CommandSetImplementation> it = maybeDelete.iterator(); it.hasNext();) {
65                      CommandSetImplementation set = it.next();
66                      if (set.getAddress().equals(address)) {
67                          it.remove();
68                      }
69                  }
70              }
71  
72              for (CommandSet set : maybeDelete) {
73                  remove(set);
74              }
75          }
76  
77          @Override
78          public void receive(Message msg) {
79              Object obj = msg.getObject();
80              if (obj instanceof Dictionary) {
81                  Address src = msg.getSrc();
82                  add(new CommandSetImplementation(src, (Dictionary) obj));
83              } else if (obj instanceof CommandResponse) {
84                  try {
85                      exchanger.exchange((CommandResponse) obj);
86                  } catch (InterruptedException ex) {
87                      logger.log(Level.SEVERE, "Interrupt while exchanging response", ex);
88                  }
89              }
90          }
91      }
92  
93      private class CommandSetImplementation implements CommandSet {
94  
95          private final Address src;
96          private final Dictionary dict;
97  
98          private CommandSetImplementation(Address src, Dictionary dict) {
99              this.src = src;
100             this.dict = dict;
101         }
102 
103         @Override
104         public Dictionary getCommandDictionary() {
105             return dict;
106         }
107 
108         @Override
109         public Object invoke(BasicCommand tc) throws CommandInvocationException {
110             try {
111                 Message msg = new Message(src, tc);
112                 channel.send(msg);
113                 return exchanger.exchange(null).getResult();
114             } catch (CommandInvocationException ex) {
115                 throw ex;
116             } catch (Exception ex) {
117                 throw new CommandInvocationException("Unable to send command", ex);
118             }
119         }
120 
121         private Object getAddress() {
122             return src;
123         }
124     }
125 
126     public class BuiltIns {
127 
128         @Command(description = "Show status of cluster")
129         public void status() {
130             for (Address address : view) {
131                 System.out.println(address);
132             }
133         }
134     }
135 }