This commit is contained in:
2024-11-30 19:03:49 +08:00
commit 1e6763c160
3806 changed files with 737676 additions and 0 deletions

View File

@@ -0,0 +1,255 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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 org.apache.catalina.tribes.demos;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.Properties;
import org.apache.catalina.tribes.Channel;
import org.apache.catalina.tribes.ManagedChannel;
import org.apache.catalina.tribes.Member;
import org.apache.catalina.tribes.group.GroupChannel;
import org.apache.catalina.tribes.group.interceptors.DomainFilterInterceptor;
import org.apache.catalina.tribes.group.interceptors.FragmentationInterceptor;
import org.apache.catalina.tribes.group.interceptors.GzipInterceptor;
import org.apache.catalina.tribes.group.interceptors.MessageDispatchInterceptor;
import org.apache.catalina.tribes.group.interceptors.OrderInterceptor;
import org.apache.catalina.tribes.group.interceptors.StaticMembershipInterceptor;
import org.apache.catalina.tribes.group.interceptors.TcpFailureDetector;
import org.apache.catalina.tribes.group.interceptors.ThroughputInterceptor;
import org.apache.catalina.tribes.membership.McastService;
import org.apache.catalina.tribes.membership.MemberImpl;
import org.apache.catalina.tribes.transport.MultiPointSender;
import org.apache.catalina.tribes.transport.ReceiverBase;
import org.apache.catalina.tribes.transport.ReplicationTransmitter;
/**
* <p>Title: </p>
*
* <p>Description: </p>
*
*
* <p>Company: </p>
*
* @version 1.0
*/
public class ChannelCreator {
public static StringBuilder usage() {
StringBuilder buf = new StringBuilder();
buf.append("\n\t\t[-bind tcpbindaddress]")
.append("\n\t\t[-tcpselto tcpselectortimeout]")
.append("\n\t\t[-tcpthreads tcpthreadcount]")
.append("\n\t\t[-port tcplistenport]")
.append("\n\t\t[-autobind tcpbindtryrange]")
.append("\n\t\t[-ackto acktimeout]")
.append("\n\t\t[-receiver org.apache.catalina.tribes.transport.nio.NioReceiver|org.apache.catalina.tribes.transport.bio.BioReceiver|]")
.append("\n\t\t[-transport org.apache.catalina.tribes.transport.nio.PooledParallelSender|org.apache.catalina.tribes.transport.bio.PooledMultiSender]")
.append("\n\t\t[-transport.xxx transport specific property]")
.append("\n\t\t[-maddr multicastaddr]")
.append("\n\t\t[-mport multicastport]")
.append("\n\t\t[-mbind multicastbindaddr]")
.append("\n\t\t[-mfreq multicastfrequency]")
.append("\n\t\t[-mdrop multicastdroptime]")
.append("\n\t\t[-gzip]")
.append("\n\t\t[-static hostname:port (-static localhost:9999 -static 127.0.0.1:8888 can be repeated)]")
.append("\n\t\t[-order]")
.append("\n\t\t[-ordersize maxorderqueuesize]")
.append("\n\t\t[-frag]")
.append("\n\t\t[-fragsize maxmsgsize]")
.append("\n\t\t[-throughput]")
.append("\n\t\t[-failuredetect]")
.append("\n\t\t[-async]")
.append("\n\t\t[-asyncsize maxqueuesizeinkilobytes]");
return buf;
}
public static Channel createChannel(String[] args) throws Exception {
String bind = "auto";
int port = 4001;
String mbind = null;
boolean gzip = false;
int tcpseltimeout = 5000;
int tcpthreadcount = 4;
int acktimeout = 15000;
String mcastaddr = "228.0.0.5";
int mcastport = 45565;
long mcastfreq = 500;
long mcastdrop = 2000;
boolean order = false;
int ordersize = Integer.MAX_VALUE;
boolean frag = false;
int fragsize = 1024;
int autoBind = 10;
ArrayList<Member> staticMembers = new ArrayList<>();
Properties transportProperties = new Properties();
String transport = "org.apache.catalina.tribes.transport.nio.PooledParallelSender";
String receiver = "org.apache.catalina.tribes.transport.nio.NioReceiver";
boolean async = false;
int asyncsize = 1024*1024*50; //50MB
boolean throughput = false;
boolean failuredetect = false;
for (int i = 0; i < args.length; i++) {
if ("-bind".equals(args[i])) {
bind = args[++i];
} else if ("-port".equals(args[i])) {
port = Integer.parseInt(args[++i]);
} else if ("-autobind".equals(args[i])) {
autoBind = Integer.parseInt(args[++i]);
} else if ("-tcpselto".equals(args[i])) {
tcpseltimeout = Integer.parseInt(args[++i]);
} else if ("-tcpthreads".equals(args[i])) {
tcpthreadcount = Integer.parseInt(args[++i]);
} else if ("-gzip".equals(args[i])) {
gzip = true;
} else if ("-async".equals(args[i])) {
async = true;
} else if ("-failuredetect".equals(args[i])) {
failuredetect = true;
} else if ("-asyncsize".equals(args[i])) {
asyncsize = Integer.parseInt(args[++i]);
System.out.println("Setting MessageDispatchInterceptor.maxQueueSize="+asyncsize);
} else if ("-static".equals(args[i])) {
String d = args[++i];
String h = d.substring(0,d.indexOf(':'));
String p = d.substring(h.length()+1);
Member m = new MemberImpl(h,Integer.parseInt(p),2000);
staticMembers.add(m);
} else if ("-throughput".equals(args[i])) {
throughput = true;
} else if ("-order".equals(args[i])) {
order = true;
} else if ("-ordersize".equals(args[i])) {
ordersize = Integer.parseInt(args[++i]);
System.out.println("Setting OrderInterceptor.maxQueue="+ordersize);
} else if ("-frag".equals(args[i])) {
frag = true;
} else if ("-fragsize".equals(args[i])) {
fragsize = Integer.parseInt(args[++i]);
System.out.println("Setting FragmentationInterceptor.maxSize="+fragsize);
} else if ("-ackto".equals(args[i])) {
acktimeout = Integer.parseInt(args[++i]);
} else if ("-transport".equals(args[i])) {
transport = args[++i];
} else if (args[i]!=null && args[i].startsWith("transport.")) {
String key = args[i];
String val = args[++i];
transportProperties.setProperty(key,val);
} else if ("-receiver".equals(args[i])) {
receiver = args[++i];
} else if ("-maddr".equals(args[i])) {
mcastaddr = args[++i];
} else if ("-mport".equals(args[i])) {
mcastport = Integer.parseInt(args[++i]);
} else if ("-mfreq".equals(args[i])) {
mcastfreq = Long.parseLong(args[++i]);
} else if ("-mdrop".equals(args[i])) {
mcastdrop = Long.parseLong(args[++i]);
} else if ("-mbind".equals(args[i])) {
mbind = args[++i];
}
}
System.out.println("Creating receiver class="+receiver);
Class<?> cl = Class.forName(receiver, true,
ChannelCreator.class.getClassLoader());
ReceiverBase rx = (ReceiverBase)cl.getConstructor().newInstance();
rx.setAddress(bind);
rx.setPort(port);
rx.setSelectorTimeout(tcpseltimeout);
rx.setMaxThreads(tcpthreadcount);
rx.setMinThreads(tcpthreadcount);
rx.getBind();
rx.setRxBufSize(43800);
rx.setTxBufSize(25188);
rx.setAutoBind(autoBind);
ReplicationTransmitter ps = new ReplicationTransmitter();
System.out.println("Creating transport class="+transport);
MultiPointSender sender = (MultiPointSender)Class.forName(
transport,true,ChannelCreator.class.getClassLoader()).getConstructor().newInstance();
sender.setTimeout(acktimeout);
sender.setMaxRetryAttempts(2);
sender.setRxBufSize(43800);
sender.setTxBufSize(25188);
Iterator<Object> i = transportProperties.keySet().iterator();
while ( i.hasNext() ) {
String key = (String)i.next();
IntrospectionUtils.setProperty(sender,key,transportProperties.getProperty(key));
}
ps.setTransport(sender);
McastService service = new McastService();
service.setAddress(mcastaddr);
if (mbind != null) service.setMcastBindAddress(mbind);
service.setFrequency(mcastfreq);
service.setMcastDropTime(mcastdrop);
service.setPort(mcastport);
ManagedChannel channel = new GroupChannel();
channel.setChannelReceiver(rx);
channel.setChannelSender(ps);
channel.setMembershipService(service);
if ( throughput ) channel.addInterceptor(new ThroughputInterceptor());
if (gzip) channel.addInterceptor(new GzipInterceptor());
if ( frag ) {
FragmentationInterceptor fi = new FragmentationInterceptor();
fi.setMaxSize(fragsize);
channel.addInterceptor(fi);
}
if (order) {
OrderInterceptor oi = new OrderInterceptor();
oi.setMaxQueue(ordersize);
channel.addInterceptor(oi);
}
if ( async ) {
MessageDispatchInterceptor mi = new MessageDispatchInterceptor();
mi.setMaxQueueSize(asyncsize);
channel.addInterceptor(mi);
System.out.println("Added MessageDispatchInterceptor");
}
if ( failuredetect ) {
TcpFailureDetector tcpfi = new TcpFailureDetector();
channel.addInterceptor(tcpfi);
}
if ( staticMembers.size() > 0 ) {
StaticMembershipInterceptor smi = new StaticMembershipInterceptor();
for (int x=0; x<staticMembers.size(); x++ ) {
smi.addStaticMember(staticMembers.get(x));
}
channel.addInterceptor(smi);
}
byte[] domain = new byte[] {1,2,3,4,5,6,7,8,9,0};
((McastService)channel.getMembershipService()).setDomain(domain);
DomainFilterInterceptor filter = new DomainFilterInterceptor();
filter.setDomain(domain);
channel.addInterceptor(filter);
return channel;
}
}

View File

@@ -0,0 +1,378 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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 org.apache.catalina.tribes.demos;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.StringTokenizer;
import org.apache.catalina.tribes.Channel;
import org.apache.catalina.tribes.Member;
import org.apache.catalina.tribes.group.GroupChannel;
import org.apache.catalina.tribes.group.interceptors.MessageDispatchInterceptor;
import org.apache.catalina.tribes.group.interceptors.NonBlockingCoordinator;
import org.apache.catalina.tribes.group.interceptors.TcpFailureDetector;
import org.apache.catalina.tribes.transport.ReceiverBase;
import org.apache.catalina.tribes.util.Arrays;
public class CoordinationDemo {
static int CHANNEL_COUNT = 5;
static int SCREEN_WIDTH = 120;
static long SLEEP_TIME = 10;
static int CLEAR_SCREEN = 30;
static boolean MULTI_THREAD = false;
static boolean[] VIEW_EVENTS = new boolean[255];
StringBuilder statusLine = new StringBuilder();
Status[] status = null;
BufferedReader reader = null;
/**
* Construct and show the application.
*/
public CoordinationDemo() {
// Default constructor
}
public void init() {
reader = new BufferedReader(new InputStreamReader(System.in));
status = new Status[CHANNEL_COUNT];
}
public void clearScreen() {
StringBuilder buf = new StringBuilder(700);
for (int i=0; i<CLEAR_SCREEN; i++ ) buf.append("\n");
System.out.println(buf);
}
public void printMenuOptions() {
System.out.println("Commands:");
System.out.println("\tstart [member id]");
System.out.println("\tstop [member id]");
System.out.println("\tprint (refresh)");
System.out.println("\tquit");
System.out.print("Enter command:");
}
public synchronized void printScreen() {
clearScreen();
System.out.println(" ###."+getHeader());
for ( int i=0; i<status.length; i++ ) {
System.out.print(leftfill(String.valueOf(i+1)+".",5," "));
if ( status[i] != null ) System.out.print(status[i].getStatusLine());
}
System.out.println("\n\n");
System.out.println("Overall status:"+statusLine);
printMenuOptions();
}
public String getHeader() {
//member - 30
//running- 10
//coord - 30
//view-id - 24
//view count - 8
StringBuilder buf = new StringBuilder();
buf.append(leftfill("Member",30," "));
buf.append(leftfill("Running",10," "));
buf.append(leftfill("Coord",30," "));
buf.append(leftfill("View-id(short)",24," "));
buf.append(leftfill("Count",8," "));
buf.append("\n");
buf.append(rightfill("==="+new java.sql.Timestamp(System.currentTimeMillis()).toString(),SCREEN_WIDTH,"="));
buf.append("\n");
return buf.toString();
}
public String[] tokenize(String line) {
StringTokenizer tz = new StringTokenizer(line," ");
String[] result = new String[tz.countTokens()];
for (int i=0; i<result.length; i++ ) result[i] = tz.nextToken();
return result;
}
public void waitForInput() throws IOException {
for ( int i=0; i<status.length; i++ ) status[i] = new Status(this);
printScreen();
String l = reader.readLine();
String[] args;
if (l == null) {
args = new String[] {};
} else {
args = tokenize(l);
}
while ( args.length >= 1 && (!"quit".equalsIgnoreCase(args[0]))) {
if ("start".equalsIgnoreCase(args[0])) {
cmdStart(args);
} else if ("stop".equalsIgnoreCase(args[0])) {
cmdStop(args);
}
printScreen();
l = reader.readLine();
if (l != null) {
args = tokenize(l);
}
}
for ( int i=0; i<status.length; i++ ) status[i].stop();
}
private void cmdStop(String[] args) {
if ( args.length == 1 ) {
setSystemStatus("System shutting down...");
Thread[] t = new Thread[CHANNEL_COUNT];
for (int i = 0; i < status.length; i++) {
final int j = i;
t[j] = new Thread() {
@Override
public void run() {
status[j].stop();
}
};
}
for (int i = 0; i < status.length; i++) if (MULTI_THREAD ) t[i].start(); else t[i].run();
setSystemStatus("System stopped.");
} else {
int index = -1;
try { index = Integer.parseInt(args[1])-1;}catch ( Exception x ) {setSystemStatus("Invalid index:"+args[1]);}
if ( index >= 0 ) {
setSystemStatus("Stopping member:"+(index+1));
status[index].stop();
setSystemStatus("Member stopped:"+(index+1));
}
}
}
private void cmdStart(String[] args) {
if ( args.length == 1 ) {
setSystemStatus("System starting up...");
Thread[] t = new Thread[CHANNEL_COUNT];
for (int i = 0; i < status.length; i++) {
final int j = i;
t[j] = new Thread() {
@Override
public void run() {
status[j].start();
}
};
}
for (int i = 0; i < status.length; i++) if (MULTI_THREAD ) t[i].start(); else t[i].run();
setSystemStatus("System started.");
} else {
int index = -1;
try { index = Integer.parseInt(args[1])-1;}catch ( Exception x ) {setSystemStatus("Invalid index:"+args[1]);}
if ( index >= 0 ) {
setSystemStatus("Starting member:"+(index+1));
status[index].start();
setSystemStatus("Member started:"+(index+1));
}
}
}
public void setSystemStatus(String status) {
statusLine.delete(0,statusLine.length());
statusLine.append(status);
}
public static void setEvents(String events) {
java.util.Arrays.fill(VIEW_EVENTS,false);
StringTokenizer t = new StringTokenizer(events,",");
while (t.hasMoreTokens() ) {
int idx = Integer.parseInt(t.nextToken());
VIEW_EVENTS[idx] = true;
}
}
public static void run(String[] args,CoordinationDemo demo) throws Exception {
usage();
java.util.Arrays.fill(VIEW_EVENTS,true);
for (int i=0; i<args.length; i++ ) {
if ( "-c".equals(args[i]) )
CHANNEL_COUNT = Integer.parseInt(args[++i]);
else if ( "-t".equals(args[i]) )
MULTI_THREAD = Boolean.parseBoolean(args[++i]);
else if ( "-s".equals(args[i]) )
SLEEP_TIME = Long.parseLong(args[++i]);
else if ( "-sc".equals(args[i]) )
CLEAR_SCREEN = Integer.parseInt(args[++i]);
else if ( "-p".equals(args[i]) )
setEvents(args[++i]);
else if ( "-h".equals(args[i]) ) System.exit(0);
}
demo.init();
demo.waitForInput();
}
private static void usage() {
System.out.println("Usage:");
System.out.println("\tjava org.apache.catalina.tribes.demos.CoordinationDemo -c channel-count(int) -t multi-thread(true|false) -s sleep-time(ms) -sc clear-screen(int) -p view_events_csv(1,2,5,7)");
System.out.println("Example:");
System.out.println("\tjava o.a.c.t.d.CoordinationDemo -> starts demo single threaded start/stop with 5 channels");
System.out.println("\tjava o.a.c.t.d.CoordinationDemo -c 10 -> starts demo single threaded start/stop with 10 channels");
System.out.println("\tjava o.a.c.t.d.CoordinationDemo -c 7 -t true -s 1000 -sc 50-> starts demo multi threaded start/stop with 7 channels and 1 second sleep time between events and 50 lines to clear screen");
System.out.println("\tjava o.a.c.t.d.CoordinationDemo -t true -p 12 -> starts demo multi threaded start/stop with 5 channels and only prints the EVT_CONF_RX event");
System.out.println();
}
public static void main(String[] args) throws Exception {
CoordinationDemo demo = new CoordinationDemo();
run(args,demo);
}
public static String leftfill(String value, int length, String ch) {
return fill(value,length,ch,true);
}
public static String rightfill(String value, int length, String ch) {
return fill(value,length,ch,false);
}
public static String fill(String value, int length, String ch, boolean left) {
StringBuilder buf = new StringBuilder();
if ( !left ) buf.append(value.trim());
for (int i=value.trim().length(); i<length; i++ ) buf.append(ch);
if ( left ) buf.append(value.trim());
return buf.toString();
}
public static class Status {
public CoordinationDemo parent;
public GroupChannel channel;
NonBlockingCoordinator interceptor = null;
public String status;
public Exception error;
public String startstatus = "new";
public Status(CoordinationDemo parent) {
this.parent = parent;
}
public String getStatusLine() {
//member - 30
//running- 10
//coord - 30
//view-id - 24
//view count - 8
StringBuilder buf = new StringBuilder();
String local = "";
String coord = "";
String viewId = "";
String count = "0";
if ( channel != null ) {
Member lm = channel.getLocalMember(false);
local = lm!=null?lm.getName():"";
coord = interceptor!=null && interceptor.getCoordinator()!=null?interceptor.getCoordinator().getName():"";
if (interceptor != null) {
viewId = getByteString(interceptor.getViewId()!=null?interceptor.getViewId().getBytes():new byte[0]);
count = String.valueOf(interceptor.getView().length);
}
}
buf.append(leftfill(local,30," "));
buf.append(leftfill(startstatus, 10, " "));
buf.append(leftfill(coord, 30, " "));
buf.append(leftfill(viewId, 24, " "));
buf.append(leftfill(count, 8, " "));
buf.append("\n");
buf.append("Status:"+status);
buf.append("\n");
return buf.toString();
}
public String getByteString(byte[] b) {
if ( b == null ) return "{}";
return Arrays.toString(b,0,Math.min(b.length,4));
}
public void start() {
try {
if ( channel == null ) {
channel = createChannel();
startstatus = "starting";
channel.start(Channel.DEFAULT);
startstatus = "running";
} else {
status = "Channel already started.";
}
} catch ( Exception x ) {
synchronized (System.err) {
System.err.println("Start failed:");
StackTraceElement[] els = x.getStackTrace();
for (int i = 0; i < els.length; i++) System.err.println(els[i].toString());
}
status = "Start failed:"+x.getMessage();
error = x;
startstatus = "failed";
try { channel.stop(Channel.DEFAULT);}catch(Exception ignore){
// Ignore
}
channel = null;
interceptor = null;
}
}
public void stop() {
try {
if ( channel != null ) {
channel.stop(Channel.DEFAULT);
status = "Channel Stopped";
} else {
status = "Channel Already Stopped";
}
}catch ( Exception x ) {
synchronized (System.err) {
System.err.println("Stop failed:");
StackTraceElement[] els = x.getStackTrace();
for (int i = 0; i < els.length; i++) System.err.println(els[i].toString());
}
status = "Stop failed:"+x.getMessage();
error = x;
}finally {
startstatus = "stopped";
channel = null;
interceptor = null;
}
}
public GroupChannel createChannel() {
channel = new GroupChannel();
((ReceiverBase)channel.getChannelReceiver()).setAutoBind(100);
interceptor = new NonBlockingCoordinator() {
@Override
public void fireInterceptorEvent(InterceptorEvent event) {
status = event.getEventTypeDesc();
int type = event.getEventType();
boolean display = VIEW_EVENTS[type];
if ( display ) parent.printScreen();
try { Thread.sleep(SLEEP_TIME); }catch ( Exception x){
// Ignore
}
}
};
channel.addInterceptor(interceptor);
channel.addInterceptor(new TcpFailureDetector());
channel.addInterceptor(new MessageDispatchInterceptor());
return channel;
}
}
}

View File

@@ -0,0 +1,206 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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 org.apache.catalina.tribes.demos;
import java.io.Serializable;
import org.apache.catalina.tribes.Channel;
import org.apache.catalina.tribes.ManagedChannel;
import org.apache.catalina.tribes.Member;
import org.apache.catalina.tribes.group.Response;
import org.apache.catalina.tribes.group.RpcCallback;
import org.apache.catalina.tribes.group.RpcChannel;
public class EchoRpcTest implements RpcCallback, Runnable {
Channel channel;
int count;
String message;
long pause;
RpcChannel rpc;
int options;
long timeout;
String name;
public EchoRpcTest(Channel channel, String name, int count, String message, long pause, int options, long timeout) {
this.channel = channel;
this.count = count;
this.message = message;
this.pause = pause;
this.options = options;
this.rpc = new RpcChannel(name.getBytes(),channel,this);
this.timeout = timeout;
this.name = name;
}
/**
* If the reply has already been sent to the requesting thread, the rpc
* callback can handle any data that comes in after the fact.
*
* @param msg Serializable
* @param sender Member
*/
@Override
public void leftOver(Serializable msg, Member sender) {
System.out.println("Received a left over message from ["+sender.getName()+"] with data ["+msg+"]");
}
/**
*
* @param msg Serializable
* @param sender Member
* @return Serializable - null if no reply should be sent
*/
@Override
public Serializable replyRequest(Serializable msg, Member sender) {
System.out.println("Received a reply request message from ["+sender.getName()+"] with data ["+msg+"]");
return "Reply("+name+"):"+msg;
}
@Override
public void run() {
long counter = 0;
while (counter<count) {
String msg = message + " cnt="+(++counter);
try {
System.out.println("Sending ["+msg+"]");
long start = System.currentTimeMillis();
Response[] resp = rpc.send(channel.getMembers(),msg,options,Channel.SEND_OPTIONS_DEFAULT,timeout);
System.out.println("Send of ["+msg+"] completed. Nr of responses="+resp.length+" Time:"+(System.currentTimeMillis()-start)+" ms.");
for ( int i=0; i<resp.length; i++ ) {
System.out.println("Received a response message from ["+resp[i].getSource().getName()+"] with data ["+resp[i].getMessage()+"]");
}
Thread.sleep(pause);
}catch(Exception x){
// Ignore
}
}
}
public static void usage() {
System.out.println("Tribes RPC tester.");
System.out.println("Usage:\n\t"+
"java EchoRpcTest [options]\n\t"+
"Options:\n\t\t"+
"[-mode all|first|majority] \n\t\t"+
"[-debug] \n\t\t"+
"[-count messagecount] \n\t\t"+
"[-timeout timeoutinms] \n\t\t"+
"[-stats statinterval] \n\t\t"+
"[-pause nrofsecondstopausebetweensends] \n\t\t"+
"[-message message] \n\t\t"+
"[-name rpcname] \n\t\t"+
"[-break (halts execution on exception)]\n"+
"\tChannel options:"+
ChannelCreator.usage()+"\n\n"+
"Example:\n\t"+
"java EchoRpcTest -port 4004\n\t"+
"java EchoRpcTest -bind 192.168.0.45 -port 4005\n\t"+
"java EchoRpcTest -bind 192.168.0.45 -port 4005 -mbind 192.168.0.45 -count 100 -stats 10\n");
}
public static void main(String[] args) throws Exception {
long pause = 3000;
int count = 1000000;
int stats = 10000;
String name = "EchoRpcId";
int options = RpcChannel.ALL_REPLY;
long timeout = 15000;
String message = "EchoRpcMessage";
if (args.length == 0) {
usage();
System.exit(1);
}
for (int i = 0; i < args.length; i++) {
if ("-threads".equals(args[i])) {
// Not used
} else if ("-count".equals(args[i])) {
count = Integer.parseInt(args[++i]);
System.out.println("Sending "+count+" messages.");
} else if ("-pause".equals(args[i])) {
pause = Long.parseLong(args[++i])*1000;
} else if ("-break".equals(args[i])) {
// Not used
} else if ("-stats".equals(args[i])) {
stats = Integer.parseInt(args[++i]);
System.out.println("Stats every "+stats+" message");
} else if ("-timeout".equals(args[i])) {
timeout = Long.parseLong(args[++i]);
} else if ("-message".equals(args[i])) {
message = args[++i];
} else if ("-name".equals(args[i])) {
name = args[++i];
} else if ("-mode".equals(args[i])) {
if ( "all".equals(args[++i]) ) options = RpcChannel.ALL_REPLY;
else if ( "first".equals(args[i]) ) options = RpcChannel.FIRST_REPLY;
else if ( "majority".equals(args[i]) ) options = RpcChannel.MAJORITY_REPLY;
} else if ("-debug".equals(args[i])) {
// Not used
} else if ("-help".equals(args[i])) {
usage();
System.exit(1);
}
}
ManagedChannel channel = (ManagedChannel)ChannelCreator.createChannel(args);
EchoRpcTest test = new EchoRpcTest(channel,name,count,message,pause,options,timeout);
channel.start(Channel.DEFAULT);
Runtime.getRuntime().addShutdownHook(new Shutdown(channel));
test.run();
System.out.println("System test complete, sleeping to let threads finish.");
Thread.sleep(60*1000*60);
}
public static class Shutdown extends Thread {
ManagedChannel channel = null;
public Shutdown(ManagedChannel channel) {
this.channel = channel;
}
@Override
public void run() {
System.out.println("Shutting down...");
SystemExit exit = new SystemExit(5000);
exit.setDaemon(true);
exit.start();
try {
channel.stop(Channel.DEFAULT);
}catch ( Exception x ) {
x.printStackTrace();
}
System.out.println("Channel stopped.");
}
}
public static class SystemExit extends Thread {
private long delay;
public SystemExit(long delay) {
this.delay = delay;
}
@Override
public void run () {
try {
Thread.sleep(delay);
}catch ( Exception x ) {
x.printStackTrace();
}
System.exit(0);
}
}}

View File

@@ -0,0 +1,216 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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 org.apache.catalina.tribes.demos;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.Hashtable;
import org.apache.juli.logging.Log;
import org.apache.juli.logging.LogFactory;
/**
* Utils for introspection and reflection
*/
public final class IntrospectionUtils {
private static final Log log = LogFactory.getLog(IntrospectionUtils.class);
/*
* Find a method with the right name If found, call the method ( if param is
* int or boolean we'll convert value to the right type before) - that means
* you can have setDebug(1).
*/
@SuppressWarnings("null")
public static boolean setProperty(Object o, String name, String value) {
if (log.isDebugEnabled())
log.debug("IntrospectionUtils: setProperty(" +
o.getClass() + " " + name + "=" + value + ")");
String setter = "set" + capitalize(name);
try {
Method methods[] = findMethods(o.getClass());
Method setPropertyMethodVoid = null;
Method setPropertyMethodBool = null;
// First, the ideal case - a setFoo( String ) method
for (int i = 0; i < methods.length; i++) {
Class<?> paramT[] = methods[i].getParameterTypes();
if (setter.equals(methods[i].getName()) && paramT.length == 1
&& "java.lang.String".equals(paramT[0].getName())) {
methods[i].invoke(o, new Object[] { value });
return true;
}
}
// Try a setFoo ( int ) or ( boolean )
for (int i = 0; i < methods.length; i++) {
boolean ok = true;
if (setter.equals(methods[i].getName())
&& methods[i].getParameterTypes().length == 1) {
// match - find the type and invoke it
Class<?> paramType = methods[i].getParameterTypes()[0];
Object params[] = new Object[1];
// Try a setFoo ( int )
if ("java.lang.Integer".equals(paramType.getName())
|| "int".equals(paramType.getName())) {
try {
params[0] = Integer.valueOf(value);
} catch (NumberFormatException ex) {
ok = false;
}
// Try a setFoo ( long )
}else if ("java.lang.Long".equals(paramType.getName())
|| "long".equals(paramType.getName())) {
try {
params[0] = Long.valueOf(value);
} catch (NumberFormatException ex) {
ok = false;
}
// Try a setFoo ( boolean )
} else if ("java.lang.Boolean".equals(paramType.getName())
|| "boolean".equals(paramType.getName())) {
params[0] = Boolean.valueOf(value);
// Try a setFoo ( InetAddress )
} else if ("java.net.InetAddress".equals(paramType
.getName())) {
try {
params[0] = InetAddress.getByName(value);
} catch (UnknownHostException exc) {
if (log.isDebugEnabled())
log.debug("IntrospectionUtils: Unable to resolve host name:" + value);
ok = false;
}
// Unknown type
} else {
if (log.isDebugEnabled())
log.debug("IntrospectionUtils: Unknown type " +
paramType.getName());
}
if (ok) {
methods[i].invoke(o, params);
return true;
}
}
// save "setProperty" for later
if ("setProperty".equals(methods[i].getName())) {
if (methods[i].getReturnType()==Boolean.TYPE){
setPropertyMethodBool = methods[i];
}else {
setPropertyMethodVoid = methods[i];
}
}
}
// Ok, no setXXX found, try a setProperty("name", "value")
if (setPropertyMethodBool != null || setPropertyMethodVoid != null) {
Object params[] = new Object[2];
params[0] = name;
params[1] = value;
if (setPropertyMethodBool != null) {
try {
return ((Boolean) setPropertyMethodBool.invoke(o,
params)).booleanValue();
}catch (IllegalArgumentException biae) {
//the boolean method had the wrong
//parameter types. lets try the other
if (setPropertyMethodVoid!=null) {
setPropertyMethodVoid.invoke(o, params);
return true;
}else {
throw biae;
}
}
} else {
setPropertyMethodVoid.invoke(o, params);
return true;
}
}
} catch (IllegalArgumentException ex2) {
log.warn("IAE " + o + " " + name + " " + value, ex2);
} catch (SecurityException ex1) {
if (log.isDebugEnabled())
log.debug("IntrospectionUtils: SecurityException for " +
o.getClass() + " " + name + "=" + value + ")", ex1);
} catch (IllegalAccessException iae) {
if (log.isDebugEnabled())
log.debug("IntrospectionUtils: IllegalAccessException for " +
o.getClass() + " " + name + "=" + value + ")", iae);
} catch (InvocationTargetException ie) {
Throwable cause = ie.getCause();
if (cause instanceof ThreadDeath) {
throw (ThreadDeath) cause;
}
if (cause instanceof VirtualMachineError) {
throw (VirtualMachineError) cause;
}
if (log.isDebugEnabled())
log.debug("IntrospectionUtils: InvocationTargetException for " +
o.getClass() + " " + name + "=" + value + ")", ie);
}
return false;
}
/*
* Reverse of Introspector.decapitalize
*/
public static String capitalize(String name) {
if (name == null || name.length() == 0) {
return name;
}
char chars[] = name.toCharArray();
chars[0] = Character.toUpperCase(chars[0]);
return new String(chars);
}
// -------------------- other utils --------------------
/**
* @deprecated Not used, but code must be updated to call it
*/
@Deprecated
public static void clear() {
objectMethods.clear();
}
static Hashtable<Class<?>,Method[]> objectMethods = new Hashtable<>();
public static Method[] findMethods(Class<?> c) {
Method methods[] = objectMethods.get(c);
if (methods != null)
return methods;
methods = c.getMethods();
objectMethods.put(c, methods);
return methods;
}
}

View File

@@ -0,0 +1,409 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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 org.apache.catalina.tribes.demos;
import java.io.Serializable;
import java.util.Random;
import org.apache.catalina.tribes.ByteMessage;
import org.apache.catalina.tribes.Channel;
import org.apache.catalina.tribes.ChannelException;
import org.apache.catalina.tribes.ChannelListener;
import org.apache.catalina.tribes.ManagedChannel;
import org.apache.catalina.tribes.Member;
import org.apache.catalina.tribes.MembershipListener;
import org.apache.juli.logging.Log;
import org.apache.juli.logging.LogFactory;
public class LoadTest implements MembershipListener,ChannelListener, Runnable {
private static final Log log = LogFactory.getLog(LoadTest.class);
public static int size = 24000;
public static final Object mutex = new Object();
public boolean doRun = true;
public long bytesReceived = 0;
public float mBytesReceived = 0;
public int messagesReceived = 0;
public boolean send = true;
public boolean debug = false;
public int msgCount = 100;
ManagedChannel channel=null;
public int statsInterval = 10000;
public long pause = 0;
public boolean breakonChannelException = false;
public boolean async = false;
public long receiveStart = 0;
public int channelOptions = Channel.SEND_OPTIONS_DEFAULT;
static int messageSize = 0;
public static long messagesSent = 0;
public static long messageStartSendTime = 0;
public static long messageEndSendTime = 0;
public static int threadCount = 0;
public static synchronized void startTest() {
threadCount++;
if ( messageStartSendTime == 0 ) messageStartSendTime = System.currentTimeMillis();
}
public static synchronized void endTest() {
threadCount--;
if ( messageEndSendTime == 0 && threadCount==0 ) messageEndSendTime = System.currentTimeMillis();
}
public static synchronized long addSendStats(long count) {
messagesSent+=count;
return 0l;
}
private static void printSendStats(long counter, int messageSize) {
float cnt = counter;
float size = messageSize;
float time = (System.currentTimeMillis()-messageStartSendTime) / 1000f;
log.info("****SEND STATS-"+Thread.currentThread().getName()+"*****"+
"\n\tMessage count:"+counter+
"\n\tTotal bytes :"+(long)(size*cnt)+
"\n\tTotal seconds:"+(time)+
"\n\tBytes/second :"+(size*cnt/time)+
"\n\tMBytes/second:"+(size*cnt/time/1024f/1024f));
}
public LoadTest(ManagedChannel channel,
boolean send,
int msgCount,
boolean debug,
long pause,
int stats,
boolean breakOnEx) {
this.channel = channel;
this.send = send;
this.msgCount = msgCount;
this.debug = debug;
this.pause = pause;
this.statsInterval = stats;
this.breakonChannelException = breakOnEx;
}
@Override
public void run() {
long counter = 0;
long total = 0;
LoadMessage msg = new LoadMessage();
try {
startTest();
while (total < msgCount) {
if (channel.getMembers().length == 0 || (!send)) {
synchronized (mutex) {
try {
mutex.wait();
} catch (InterruptedException x) {
log.info("Thread interrupted from wait");
}
}
} else {
try {
//msg.setMsgNr((int)++total);
counter++;
if (debug) {
printArray(msg.getMessage());
}
channel.send(channel.getMembers(), msg, channelOptions);
if ( pause > 0 ) {
if ( debug) System.out.println("Pausing sender for "+pause+" ms.");
Thread.sleep(pause);
}
} catch (ChannelException x) {
if ( debug ) log.error("Unable to send message:"+x.getMessage(),x);
log.error("Unable to send message:"+x.getMessage());
ChannelException.FaultyMember[] faulty = x.getFaultyMembers();
for (int i=0; i<faulty.length; i++ ) log.error("Faulty: "+faulty[i]);
--counter;
if ( this.breakonChannelException ) throw x;
}
}
if ( (counter % statsInterval) == 0 && (counter > 0)) {
//add to the global counter
counter = addSendStats(counter);
//print from the global counter
//printSendStats(LoadTest.messagesSent, LoadTest.messageSize, LoadTest.messageSendTime);
printSendStats(LoadTest.messagesSent, LoadTest.messageSize);
}
}
}catch ( Exception x ) {
log.error("Captured error while sending:"+x.getMessage());
if ( debug ) log.error("",x);
printSendStats(LoadTest.messagesSent, LoadTest.messageSize);
}
endTest();
}
/**
* memberAdded
*
* @param member Member
* TODO Implement this org.apache.catalina.tribes.MembershipListener
* method
*/
@Override
public void memberAdded(Member member) {
log.info("Member added:"+member);
synchronized (mutex) {
mutex.notifyAll();
}
}
/**
* memberDisappeared
*
* @param member Member
* TODO Implement this org.apache.catalina.tribes.MembershipListener
* method
*/
@Override
public void memberDisappeared(Member member) {
log.info("Member disappeared:"+member);
}
@Override
public boolean accept(Serializable msg, Member mbr){
return (msg instanceof LoadMessage) || (msg instanceof ByteMessage);
}
@Override
public void messageReceived(Serializable msg, Member mbr){
if ( receiveStart == 0 ) receiveStart = System.currentTimeMillis();
if ( debug ) {
if ( msg instanceof LoadMessage ) {
printArray(((LoadMessage)msg).getMessage());
}
}
if ( msg instanceof ByteMessage && !(msg instanceof LoadMessage)) {
LoadMessage tmp = new LoadMessage();
tmp.setMessage(((ByteMessage)msg).getMessage());
msg = tmp;
tmp = null;
}
bytesReceived+=((LoadMessage)msg).getMessage().length;
mBytesReceived+=(((LoadMessage)msg).getMessage().length)/1024f/1024f;
messagesReceived++;
if ( (messagesReceived%statsInterval)==0 || (messagesReceived==msgCount)) {
float bytes = (((LoadMessage)msg).getMessage().length*messagesReceived);
float seconds = (System.currentTimeMillis()-receiveStart) / 1000f;
log.info("****RECEIVE STATS-"+Thread.currentThread().getName()+"*****"+
"\n\tMessage count :"+(long)messagesReceived+
"\n\tMessage/sec :"+messagesReceived/seconds+
"\n\tTotal bytes :"+(long)bytes+
"\n\tTotal mbytes :"+(long)mBytesReceived+
"\n\tTime since 1st:"+seconds+" seconds"+
"\n\tBytes/second :"+(bytes/seconds)+
"\n\tMBytes/second :"+(mBytesReceived/seconds)+"\n");
}
}
public static void printArray(byte[] data) {
System.out.print("{");
for (int i=0; i<data.length; i++ ) {
System.out.print(data[i]);
System.out.print(",");
}
System.out.println("} size:"+data.length);
}
public static class LoadMessage extends ByteMessage {
public static byte[] outdata = new byte[size];
public static final Random r = new Random();
public static int getMessageSize (LoadMessage msg) {
return msg.getMessage().length;
}
static {
r.nextBytes(outdata);
}
protected byte[] message = getMessage();
public LoadMessage() {
// Default constructor
}
@Override
public byte[] getMessage() {
if ( message == null ) {
message = outdata;
}
return message;
}
@Override
public void setMessage(byte[] data) {
this.message = data;
}
}
public static void usage() {
System.out.println("Tribes Load tester.");
System.out.println("The load tester can be used in sender or received mode or both");
System.out.println("Usage:\n\t"+
"java LoadTest [options]\n\t"+
"Options:\n\t\t"+
"[-mode receive|send|both] \n\t\t"+
"[-startoptions startflags (default is Channel.DEFAULT) ] \n\t\t"+
"[-debug] \n\t\t"+
"[-count messagecount] \n\t\t"+
"[-stats statinterval] \n\t\t"+
"[-pause nrofsecondstopausebetweensends] \n\t\t"+
"[-threads numberofsenderthreads] \n\t\t"+
"[-size messagesize] \n\t\t"+
"[-sendoptions channeloptions] \n\t\t"+
"[-break (halts execution on exception)]\n"+
"[-shutdown (issues a channel.stop() command after send is completed)]\n"+
"\tChannel options:"+
ChannelCreator.usage()+"\n\n"+
"Example:\n\t"+
"java LoadTest -port 4004\n\t"+
"java LoadTest -bind 192.168.0.45 -port 4005\n\t"+
"java LoadTest -bind 192.168.0.45 -port 4005 -mbind 192.168.0.45 -count 100 -stats 10\n");
}
public static void main(String[] args) throws Exception {
boolean send = true;
boolean debug = false;
long pause = 0;
int count = 1000000;
int stats = 10000;
boolean breakOnEx = false;
int threads = 1;
boolean shutdown = false;
int startoptions = Channel.DEFAULT;
int channelOptions = Channel.SEND_OPTIONS_DEFAULT;
if ( args.length == 0 ) {
args = new String[] {"-help"};
}
for (int i = 0; i < args.length; i++) {
if ("-threads".equals(args[i])) {
threads = Integer.parseInt(args[++i]);
} else if ("-count".equals(args[i])) {
count = Integer.parseInt(args[++i]);
System.out.println("Sending "+count+" messages.");
} else if ("-pause".equals(args[i])) {
pause = Long.parseLong(args[++i])*1000;
} else if ("-break".equals(args[i])) {
breakOnEx = true;
} else if ("-shutdown".equals(args[i])) {
shutdown = true;
} else if ("-stats".equals(args[i])) {
stats = Integer.parseInt(args[++i]);
System.out.println("Stats every "+stats+" message");
} else if ("-sendoptions".equals(args[i])) {
channelOptions = Integer.parseInt(args[++i]);
System.out.println("Setting send options to "+channelOptions);
} else if ("-startoptions".equals(args[i])) {
startoptions = Integer.parseInt(args[++i]);
System.out.println("Setting start options to "+startoptions);
} else if ("-size".equals(args[i])) {
size = Integer.parseInt(args[++i])-4;
System.out.println("Message size will be:"+(size+4)+" bytes");
} else if ("-mode".equals(args[i])) {
if ( "receive".equals(args[++i]) ) send = false;
} else if ("-debug".equals(args[i])) {
debug = true;
} else if ("-help".equals(args[i]))
{
usage();
System.exit(1);
}
}
ManagedChannel channel = (ManagedChannel)ChannelCreator.createChannel(args);
LoadTest test = new LoadTest(channel,send,count,debug,pause,stats,breakOnEx);
test.channelOptions = channelOptions;
LoadMessage msg = new LoadMessage();
messageSize = LoadMessage.getMessageSize(msg);
channel.addChannelListener(test);
channel.addMembershipListener(test);
channel.start(startoptions);
Runtime.getRuntime().addShutdownHook(new Shutdown(channel));
while ( threads > 1 ) {
Thread t = new Thread(test);
t.setDaemon(true);
t.start();
threads--;
test = new LoadTest(channel,send,count,debug,pause,stats,breakOnEx);
test.channelOptions = channelOptions;
}
test.run();
if ( shutdown && send ) channel.stop(Channel.DEFAULT);
System.out.println("System test complete, sleeping to let threads finish.");
Thread.sleep(60*1000*60);
}
public static class Shutdown extends Thread {
ManagedChannel channel = null;
public Shutdown(ManagedChannel channel) {
this.channel = channel;
}
@Override
public void run() {
System.out.println("Shutting down...");
SystemExit exit = new SystemExit(5000);
exit.setDaemon(true);
exit.start();
try {
channel.stop(Channel.DEFAULT);
}catch ( Exception x ) {
x.printStackTrace();
}
System.out.println("Channel stopped.");
}
}
public static class SystemExit extends Thread {
private long delay;
public SystemExit(long delay) {
this.delay = delay;
}
@Override
public void run () {
try {
Thread.sleep(delay);
}catch ( Exception x ) {
x.printStackTrace();
}
System.exit(0);
}
}
}

View File

@@ -0,0 +1,552 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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 org.apache.catalina.tribes.demos;
import java.awt.Color;
import java.awt.Component;
import java.awt.ComponentOrientation;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.io.Serializable;
import java.util.Random;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.TableColumn;
import org.apache.catalina.tribes.Channel;
import org.apache.catalina.tribes.ChannelListener;
import org.apache.catalina.tribes.ManagedChannel;
import org.apache.catalina.tribes.Member;
import org.apache.catalina.tribes.MembershipListener;
import org.apache.catalina.tribes.tipis.LazyReplicatedMap;
/**
* Example of how the lazy replicated map works, also shows how the BackupManager
* works in a Tomcat cluster
* @version 1.1
*/
public class MapDemo implements ChannelListener, MembershipListener{
/**
* The Map containing the replicated data
*/
protected LazyReplicatedMap<String,StringBuilder> map;
/**
* Table to be displayed in Swing
*/
protected SimpleTableDemo table;
/**
* Constructs a map demo object.
* @param channel - the Tribes channel object to be used for communication
* @param mapName - the name of this map
*/
public MapDemo(Channel channel, String mapName ) {
//instantiate the replicated map
map = new LazyReplicatedMap<>(null, channel, 5000, mapName, null);
//create a gui, name it with the member name of this JVM
table = SimpleTableDemo.createAndShowGUI(map,channel.getLocalMember(false).getName());
//add ourself as a listener for messages
channel.addChannelListener(this);
//add ourself as a listener for memberships
channel.addMembershipListener(this);
//initialize the map by receiving a fake message
this.messageReceived(null,null);
}
/**
* Decides if the messageReceived should be invoked
* will always return false since we rely on the
* lazy map to do all the messaging for us
*/
@Override
public boolean accept(Serializable msg, Member source) {
//simple refresh the table model
table.dataModel.getValueAt(-1,-1);
return false;
}
/**
* Invoked if accept returns true.
* No op for now
* @param msg - the message received
* @param source - the sending member
*/
@Override
public void messageReceived(Serializable msg, Member source) {
// NOOP
}
/**
* Invoked when a member is added to the group
*/
@Override
public void memberAdded(Member member) {
// NOOP
}
/**
* Invoked when a member leaves the group
*/
@Override
public void memberDisappeared(Member member) {
//just refresh the table model
table.dataModel.getValueAt(-1,-1);
}
/**
* Prints usage
*/
public static void usage() {
System.out.println("Tribes MapDemo.");
System.out.println("Usage:\n\t" +
"java MapDemo [channel options] mapName\n\t" +
"\tChannel options:" +
ChannelCreator.usage());
}
@SuppressWarnings("unused")
public static void main(String[] args) throws Exception {
long start = System.currentTimeMillis();
//create a channel object
ManagedChannel channel = (ManagedChannel) ChannelCreator.createChannel(args);
//define a map name, unless one is defined as a parameters
String mapName = "MapDemo";
if ( args.length > 0 && (!args[args.length-1].startsWith("-"))) {
mapName = args[args.length-1];
}
//start the channel
channel.start(Channel.DEFAULT);
//listen for shutdown
Runtime.getRuntime().addShutdownHook(new Shutdown(channel));
//create a map demo object
new MapDemo(channel,mapName);
//put the main thread to sleep until we are done
System.out.println("System test complete, time to start="+(System.currentTimeMillis()-start)+" ms. Sleeping to let threads finish.");
Thread.sleep(60 * 1000 * 60);
}
/**
* Listens for shutdown events, and stops this instance
*/
public static class Shutdown extends Thread {
//the channel running in this demo
ManagedChannel channel = null;
public Shutdown(ManagedChannel channel) {
this.channel = channel;
}
@Override
public void run() {
System.out.println("Shutting down...");
//create an exit thread that forces a shutdown if the JVM wont exit cleanly
SystemExit exit = new SystemExit(5000);
exit.setDaemon(true);
exit.start();
try {
//stop the channel
channel.stop(Channel.DEFAULT);
} catch (Exception x) {
x.printStackTrace();
}
System.out.println("Channel stopped.");
}
}
public static class SystemExit extends Thread {
private long delay;
public SystemExit(long delay) {
this.delay = delay;
}
@Override
public void run() {
try {
Thread.sleep(delay);
} catch (Exception x) {
x.printStackTrace();
}
System.exit(0);
}
}
public static class SimpleTableDemo extends JPanel
implements ActionListener {
private static final long serialVersionUID = 1L;
private static int WIDTH = 550;
private LazyReplicatedMap<String,StringBuilder> map;
private boolean DEBUG = false;
AbstractTableModel dataModel = new AbstractTableModel() {
private static final long serialVersionUID = 1L;
String[] columnNames = {
"Rownum",
"Key",
"Value",
"Primary Node",
"Backup Node",
"isPrimary",
"isProxy",
"isBackup"};
@Override
public int getColumnCount() { return columnNames.length; }
@Override
public int getRowCount() {return map.sizeFull() +1; }
public StringBuilder getMemberNames(Member[] members){
StringBuilder buf = new StringBuilder();
if ( members!=null ) {
for (int i=0;i<members.length; i++ ) {
buf.append(members[i].getName());
buf.append("; ");
}
}
return buf;
}
@Override
public Object getValueAt(int row, int col) {
if ( row==-1 ) {
update();
return "";
}
if ( row == 0 ) return columnNames[col];
Object[] keys = map.keySetFull().toArray();
String key = (String)keys [row-1];
LazyReplicatedMap.MapEntry<String,StringBuilder> entry =
map.getInternal(key);
switch (col) {
case 0: return String.valueOf(row);
case 1: return entry.getKey();
case 2: return entry.getValue();
case 3: return entry.getPrimary()!=null?entry.getPrimary().getName():"null";
case 4: return getMemberNames(entry.getBackupNodes());
case 5: return Boolean.valueOf(entry.isPrimary());
case 6: return Boolean.valueOf(entry.isProxy());
case 7: return Boolean.valueOf(entry.isBackup());
default: return "";
}
}
public void update() {
fireTableDataChanged();
}
};
JTextField txtAddKey = new JTextField(20);
JTextField txtAddValue = new JTextField(20);
JTextField txtRemoveKey = new JTextField(20);
JTextField txtChangeKey = new JTextField(20);
JTextField txtChangeValue = new JTextField(20);
JTable table = null;
public SimpleTableDemo(LazyReplicatedMap<String,StringBuilder> map) {
super();
this.map = map;
this.setComponentOrientation(ComponentOrientation.LEFT_TO_RIGHT);
//final JTable table = new JTable(data, columnNames);
table = new JTable(dataModel);
table.setPreferredScrollableViewportSize(new Dimension(WIDTH, 150));
for ( int i=0; i<table.getColumnCount(); i++ ) {
TableColumn tm = table.getColumnModel().getColumn(i);
tm.setCellRenderer(new ColorRenderer());
}
if (DEBUG) {
table.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
printDebugData(table);
}
});
}
//setLayout(new GridLayout(5, 0));
setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
//Create the scroll pane and add the table to it.
JScrollPane scrollPane = new JScrollPane(table);
//Add the scroll pane to this panel.
add(scrollPane);
//create a add value button
JPanel addpanel = new JPanel();
addpanel.setPreferredSize(new Dimension(WIDTH,30));
addpanel.add(createButton("Add","add"));
addpanel.add(txtAddKey);
addpanel.add(txtAddValue);
addpanel.setMaximumSize(new Dimension(WIDTH,30));
add(addpanel);
//create a remove value button
JPanel removepanel = new JPanel( );
removepanel.setPreferredSize(new Dimension(WIDTH,30));
removepanel.add(createButton("Remove","remove"));
removepanel.add(txtRemoveKey);
removepanel.setMaximumSize(new Dimension(WIDTH,30));
add(removepanel);
//create a change value button
JPanel changepanel = new JPanel( );
changepanel.add(createButton("Change","change"));
changepanel.add(txtChangeKey);
changepanel.add(txtChangeValue);
changepanel.setPreferredSize(new Dimension(WIDTH,30));
changepanel.setMaximumSize(new Dimension(WIDTH,30));
add(changepanel);
//create sync button
JPanel syncpanel = new JPanel( );
syncpanel.add(createButton("Synchronize","sync"));
syncpanel.add(createButton("Replicate","replicate"));
syncpanel.add(createButton("Random","random"));
syncpanel.setPreferredSize(new Dimension(WIDTH,30));
syncpanel.setMaximumSize(new Dimension(WIDTH,30));
add(syncpanel);
}
public JButton createButton(String text, String command) {
JButton button = new JButton(text);
button.setActionCommand(command);
button.addActionListener(this);
return button;
}
@Override
public void actionPerformed(ActionEvent e) {
System.out.println(e.getActionCommand());
if ( "add".equals(e.getActionCommand()) ) {
System.out.println("Add key:"+txtAddKey.getText()+" value:"+txtAddValue.getText());
map.put(txtAddKey.getText(),new StringBuilder(txtAddValue.getText()));
}
if ( "change".equals(e.getActionCommand()) ) {
System.out.println("Change key:"+txtChangeKey.getText()+" value:"+txtChangeValue.getText());
StringBuilder buf = map.get(txtChangeKey.getText());
if ( buf!=null ) {
buf.delete(0,buf.length());
buf.append(txtChangeValue.getText());
map.replicate(txtChangeKey.getText(),true);
} else {
buf = new StringBuilder();
buf.append(txtChangeValue.getText());
map.put(txtChangeKey.getText(),buf);
}
}
if ( "remove".equals(e.getActionCommand()) ) {
System.out.println("Remove key:"+txtRemoveKey.getText());
map.remove(txtRemoveKey.getText());
}
if ( "sync".equals(e.getActionCommand()) ) {
System.out.println("Syncing from another node.");
map.transferState();
}
if ( "random".equals(e.getActionCommand()) ) {
Thread t = new Thread() {
@Override
public void run() {
for (int i = 0; i < 5; i++) {
String key = random(5,0,0,true,true,null);
map.put(key, new StringBuilder(key));
dataModel.fireTableDataChanged();
table.paint(table.getGraphics());
try {
Thread.sleep(500);
} catch (InterruptedException x) {
Thread.interrupted();
}
}
}
};
t.start();
}
if ( "replicate".equals(e.getActionCommand()) ) {
System.out.println("Replicating out to the other nodes.");
map.replicate(true);
}
dataModel.getValueAt(-1,-1);
}
public static final Random random = new Random();
public static String random(int count, int start, int end, boolean letters, boolean numbers,
char[] chars ) {
if (count == 0) {
return "";
} else if (count < 0) {
throw new IllegalArgumentException("Requested random string length " + count + " is less than 0.");
}
if ((start == 0) && (end == 0)) {
end = 'z' + 1;
start = ' ';
if (!letters && !numbers) {
start = 0;
end = Integer.MAX_VALUE;
}
}
char[] buffer = new char[count];
int gap = end - start;
while (count-- != 0) {
char ch;
if (chars == null) {
ch = (char) (random.nextInt(gap) + start);
} else {
ch = chars[random.nextInt(gap) + start];
}
if ((letters && Character.isLetter(ch))
|| (numbers && Character.isDigit(ch))
|| (!letters && !numbers))
{
if(ch >= 56320 && ch <= 57343) {
if(count == 0) {
count++;
} else {
// low surrogate, insert high surrogate after putting it in
buffer[count] = ch;
count--;
buffer[count] = (char) (55296 + random.nextInt(128));
}
} else if(ch >= 55296 && ch <= 56191) {
if(count == 0) {
count++;
} else {
// high surrogate, insert low surrogate before putting it in
buffer[count] = (char) (56320 + random.nextInt(128));
count--;
buffer[count] = ch;
}
} else if(ch >= 56192 && ch <= 56319) {
// private high surrogate, no effing clue, so skip it
count++;
} else {
buffer[count] = ch;
}
} else {
count++;
}
}
return new String(buffer);
}
private void printDebugData(JTable table) {
int numRows = table.getRowCount();
int numCols = table.getColumnCount();
javax.swing.table.TableModel model = table.getModel();
System.out.println("Value of data: ");
for (int i = 0; i < numRows; i++) {
System.out.print(" row " + i + ":");
for (int j = 0; j < numCols; j++) {
System.out.print(" " + model.getValueAt(i, j));
}
System.out.println();
}
System.out.println("--------------------------");
}
/*
* Create the GUI and show it. For thread safety,
* this method should be invoked from the
* event-dispatching thread.
*/
public static SimpleTableDemo createAndShowGUI(
LazyReplicatedMap<String,StringBuilder> map, String title) {
//Make sure we have nice window decorations.
JFrame.setDefaultLookAndFeelDecorated(true);
//Create and set up the window.
JFrame frame = new JFrame("SimpleTableDemo - "+title);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//Create and set up the content pane.
SimpleTableDemo newContentPane = new SimpleTableDemo(map);
newContentPane.setOpaque(true); //content panes must be opaque
frame.setContentPane(newContentPane);
//Display the window.
frame.setSize(450,250);
newContentPane.setSize(450,300);
frame.pack();
frame.setVisible(true);
return newContentPane;
}
}
static class ColorRenderer extends DefaultTableCellRenderer {
private static final long serialVersionUID = 1L;
public ColorRenderer() {
super();
}
@Override
public Component getTableCellRendererComponent
(JTable table, Object value, boolean isSelected,
boolean hasFocus, int row, int column) {
Component cell = super.getTableCellRendererComponent
(table, value, isSelected, hasFocus, row, column);
cell.setBackground(Color.WHITE);
if ( row > 0 ) {
Color color = null;
boolean primary = ( (Boolean) table.getValueAt(row, 5)).booleanValue();
boolean proxy = ( (Boolean) table.getValueAt(row, 6)).booleanValue();
boolean backup = ( (Boolean) table.getValueAt(row, 7)).booleanValue();
if (primary) color = Color.GREEN;
else if (proxy) color = Color.RED;
else if (backup) color = Color.BLUE;
if ( color != null ) cell.setBackground(color);
}
return cell;
}
}
}

View File

@@ -0,0 +1,123 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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 org.apache.catalina.tribes.demos;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.Properties;
import org.apache.catalina.tribes.Channel;
import org.apache.catalina.tribes.ManagedChannel;
import org.apache.catalina.tribes.Member;
import org.apache.catalina.tribes.MembershipListener;
import org.apache.catalina.tribes.util.Arrays;
import org.apache.catalina.tribes.util.UUIDGenerator;
public class MembersWithProperties implements MembershipListener{
static Thread main;
public MembersWithProperties(Channel channel, Properties props) throws IOException {
channel.addMembershipListener(this);
ManagedChannel mchannel = (ManagedChannel)channel;
mchannel.getMembershipService().setPayload(getPayload(props));
}
byte[] getPayload(Properties props) throws IOException {
ByteArrayOutputStream bout = new ByteArrayOutputStream();
props.store(bout,"");
return bout.toByteArray();
}
Properties getProperties(byte[] payload) throws IOException {
ByteArrayInputStream bin = new ByteArrayInputStream(payload);
Properties props = new Properties();
props.load(bin);
return props;
}
@Override
public void memberAdded(Member member) {
try {
System.out.println("Received member added:"+member);
System.out.println("Payload["+member+"] :");
getProperties(member.getPayload()).store(System.out,"");
}catch ( Exception x ) {
x.printStackTrace();
}
}
@Override
public void memberDisappeared(Member member) {
try {
System.out.println("Received member disappeared:"+member);
System.out.println("Payload["+member+"] :");
getProperties(member.getPayload()).store(System.out,"");
}catch ( Exception x ) {
x.printStackTrace();
}
}
public static void usage() {
System.out.println("Tribes Member Properties demo.");
System.out.println("Usage:\n\t" +
"java MemberWithProperties \n\t" +
"Channel options:" +
ChannelCreator.usage() + "\n\n" +
"Example:\n\t" +
"java MembersWithProperties -port 4004\n\t" +
"java MembersWithProperties -bind 192.168.0.45 -port 4005\n\t" +
"java MembersWithProperties -bind 192.168.0.45 -port 4005 -mbind 192.168.0.45 -count 100 -stats 10\n");
}
@SuppressWarnings("unused")
public static void main(String[] args) throws Exception {
if (args.length==0) usage();
main = Thread.currentThread();
ManagedChannel channel = (ManagedChannel) ChannelCreator.createChannel(args);
Properties props = new Properties();
props.setProperty("mydomainkey","mydomainvalue");
props.setProperty("someotherkey", Arrays.toString(UUIDGenerator.randomUUID(true)));
new MembersWithProperties(channel, props);
channel.start(Channel.DEFAULT);
Runtime.getRuntime().addShutdownHook(new Shutdown(channel));
try {
Thread.sleep(Long.MAX_VALUE);
}catch(InterruptedException ix) {
Thread.sleep(5000);//allow everything to shutdown
}
}
public static class Shutdown extends Thread {
ManagedChannel channel = null;
public Shutdown(ManagedChannel channel) {
this.channel = channel;
}
@Override
public void run() {
System.out.println("Shutting down...");
try {
channel.stop(Channel.DEFAULT);
} catch (Exception x) {
x.printStackTrace();
}
System.out.println("Channel stopped.");
main.interrupt();
}
}
}