
com.gitee.yanfanvip.replicate.AcrossClusterDispatch Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of rocksdb Show documentation
Show all versions of rocksdb Show documentation
RocksDB Cluster and Replication cluster
The newest version!
package com.gitee.yanfanvip.replicate;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.net.Socket;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.function.Consumer;
import org.jgroups.annotations.MBean;
import org.jgroups.stack.Protocol;
import org.jgroups.util.Util;
import org.rocksdb.RocksDBException;
import com.gitee.yanfanvip.cluster.ClusterDatabase;
import com.gitee.yanfanvip.cluster.ClusterDatabase.Notification;
import com.gitee.yanfanvip.model.Frame;
import com.gitee.yanfanvip.model.FrameEnum;
import com.gitee.yanfanvip.model.ReciveEnum;
import com.gitee.yanfanvip.model.Row;
import com.gitee.yanfanvip.single.SingleDatabase;
@MBean(description="Server side PULL Database protocol, STOMP clients can connect to it")
public class AcrossClusterDispatch extends Protocol implements Notification{
protected List sites = new ArrayList();
protected ClusterDatabase database;
protected SingleDatabase SYSTEM;
protected String cluster;
public AcrossClusterDispatch(String cluster) {
this.cluster = cluster;
}
@Override
public void start() throws Exception {
database = getProtocolStack().findProtocol(ClusterDatabase.class);
SYSTEM = SingleDatabase.getSystem();
database.setListener(this);
sites.forEach(site->{
Thread thread = getThreadFactory().newThread(site, "Across Cluster Producer connection");
thread.setDaemon(true);
thread.start();
});
new Timer().schedule(new TimerTask() {
@Override
public void run() {
sites.forEach(site->{
try { site.send(new Frame(FrameEnum.PING)); } catch (Exception e) { }
});
}
}, 30000);
}
public AcrossClusterDispatch addSite(String cluster, String nodes) {
if(!cluster.equals(this.cluster)) {
sites.add(new Site(cluster, nodes));
}
return this;
}
private void handleFailMessage(String cluster, long sequence, Frame frame){
if(frame.getType() == FrameEnum.PUT ||
frame.getType() == FrameEnum.PUTALL ||
frame.getType() == FrameEnum.REMOVE ||
frame.getType() == FrameEnum.CLEAR){
try {
SYSTEM.put("MESSAGE:" + cluster, sequence + "", frame.getByte());
} catch (RocksDBException e) {
e.printStackTrace();
}
}
}
private void handleSequenceMessage(String cluster, Consumer consumer){
try {
SYSTEM.forEach("MESSAGE:" + cluster, (k, v)->{
Frame frame = new Frame(v);
try { SYSTEM.remove("MESSAGE:" + cluster, k); } catch (RocksDBException e) { e.printStackTrace(); }
consumer.accept(frame);
});
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
public void put(String keyspaces, String key, byte[] value) {
sites.forEach(site->{
site.send(FrameEnum.PUT, new Row(keyspaces, key, value));
});
}
@Override
public void putAll(String keyspaces, Map datas) {
sites.forEach(site->{
site.send(FrameEnum.PUTALL, new Row(keyspaces, datas));
});
}
@Override
public void remove(String keyspaces, String key) {
sites.forEach(site->{
site.send(FrameEnum.REMOVE, new Row(keyspaces, key));
});
}
@Override
public void clear(String keyspaces) {
sites.forEach(site->{
site.send(FrameEnum.CLEAR, new Row(keyspaces));
});
}
/**
* 负责发送响应消息给需要同步的服务器
* @author fy68
*/
public class Site implements Runnable, AutoCloseable{
String cluster;
Socket socket;
DataInputStream input;
DataOutputStream output;
List server;
boolean connected = false;
protected Long sequence;
Lock lock = new ReentrantLock();
long getSequence(){
try {
if(sequence == null){
Row row = SYSTEM.getLastData("MESSAGE:" + cluster);
if(row == null){
sequence = 0L;
}else{
sequence = Long.valueOf(row.getKey());
}
}
sequence++;
} catch (Exception e) {
if(sequence == null){ sequence = 0L; }
sequence++;
}
return sequence;
}
public Site(String cluster, String node) {
this.cluster = cluster;
String[] nodes = node.split(",");
this.server = Arrays.asList(nodes);
}
@Override
public void run() {
while(true){
connect();
read();
}
}
private void read() {
try {
while(connected){
ReciveEnum enum1 = ReciveEnum.get(input);
if(enum1 != null) {
switch (enum1) {
case PING: break;
case PULLDATA:{
handleSequenceMessage(cluster, f->{ send(f.getType(), f.getData()); });
send(new Frame(FrameEnum.PULL_MESSAGE_COMPLETE));
break;
}
case SYNC:{
send(new Frame(FrameEnum.SYNC_START));
database.forEach(data->{
try {
send(new Frame(FrameEnum.PUT, data));
} catch (Exception e) {
throw new RuntimeException(e);
}
});
send(new Frame(FrameEnum.SYNC_COMPLETE));
break;
}
default:throw new RuntimeException("bad request");
}
}
}
} catch (Exception e) {
System.out.println("dispatch close");
disconnect();
}
}
void connect() {
if(socket == null){ disconnect(); }
while(!connected){
for (String address : server) {
int index = address.lastIndexOf(':');
String host = address.substring(0, index);
int port = Integer.parseInt(address.substring(index+1));
try {
socket = new Socket(host, port);
input = new DataInputStream(socket.getInputStream());
output =new DataOutputStream(socket.getOutputStream());
send(new Frame(FrameEnum.PING));
connected = true;
break;
} catch(Exception ex) {
disconnect();
}
}
if(!connected){ try { Thread.sleep(30000); } catch (InterruptedException e) { }}
}
}
public void send(FrameEnum type, Row row) {
Frame frame = new Frame(type, row);
if(!connected){
handleFailMessage(cluster, getSequence(), frame);
return;
}
try { send(frame); } catch (Exception e) { handleFailMessage(cluster, getSequence(), frame); }
}
private void send(Frame frame) throws Exception {
lock.lock();
try {
output.write(frame.getByte());
output.flush();
} catch (Exception e) {
disconnect();
throw e;
}finally {
lock.unlock();
}
}
private void disconnect() {
connected = false;
Util.close(input);
Util.close(output);
Util.close(socket);
}
@Override
public void close() {
disconnect();
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy