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
28
29
30 public class JGroupsCommandClient extends CompositeCommandSet implements CommandClient, Closeable {
31
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 }