GOSSIP-26 Gossip shared data
This commit is contained in:
@ -34,9 +34,10 @@ import org.apache.gossip.model.ActiveGossipOk;
|
||||
import org.apache.gossip.model.GossipDataMessage;
|
||||
import org.apache.gossip.model.GossipMember;
|
||||
import org.apache.gossip.model.Response;
|
||||
import org.apache.gossip.model.SharedGossipDataMessage;
|
||||
import org.apache.gossip.udp.UdpActiveGossipMessage;
|
||||
import org.apache.gossip.udp.UdpGossipDataMessage;
|
||||
|
||||
import org.apache.gossip.udp.UdpSharedGossipDataMessage;
|
||||
import org.apache.log4j.Logger;
|
||||
import org.codehaus.jackson.map.ObjectMapper;
|
||||
|
||||
@ -70,7 +71,10 @@ public class ActiveGossipThread {
|
||||
() -> sendMembershipList(gossipManager.getMyself(), gossipManager.getDeadMembers()), 0,
|
||||
gossipManager.getSettings().getGossipInterval(), TimeUnit.MILLISECONDS);
|
||||
scheduledExecutorService.scheduleAtFixedRate(
|
||||
() -> sendData(gossipManager.getMyself(), gossipManager.getLiveMembers()), 0,
|
||||
() -> sendPerNodeData(gossipManager.getMyself(), gossipManager.getLiveMembers()), 0,
|
||||
gossipManager.getSettings().getGossipInterval(), TimeUnit.MILLISECONDS);
|
||||
scheduledExecutorService.scheduleAtFixedRate(
|
||||
() -> sendSharedData(gossipManager.getMyself(), gossipManager.getLiveMembers()), 0,
|
||||
gossipManager.getSettings().getGossipInterval(), TimeUnit.MILLISECONDS);
|
||||
}
|
||||
|
||||
@ -83,7 +87,39 @@ public class ActiveGossipThread {
|
||||
}
|
||||
}
|
||||
|
||||
public void sendData(LocalGossipMember me, List<LocalGossipMember> memberList){
|
||||
public void sendSharedData(LocalGossipMember me, List<LocalGossipMember> memberList){
|
||||
LocalGossipMember member = selectPartner(memberList);
|
||||
if (member == null) {
|
||||
LOGGER.debug("Send sendMembershipList() is called without action");
|
||||
return;
|
||||
}
|
||||
try (DatagramSocket socket = new DatagramSocket()) {
|
||||
socket.setSoTimeout(gossipManager.getSettings().getGossipInterval());
|
||||
for (Entry<String, SharedGossipDataMessage> innerEntry : this.gossipCore.getSharedData().entrySet()){
|
||||
UdpSharedGossipDataMessage message = new UdpSharedGossipDataMessage();
|
||||
message.setUuid(UUID.randomUUID().toString());
|
||||
message.setUriFrom(me.getId());
|
||||
message.setExpireAt(innerEntry.getValue().getExpireAt());
|
||||
message.setKey(innerEntry.getValue().getKey());
|
||||
message.setNodeId(innerEntry.getValue().getNodeId());
|
||||
message.setTimestamp(innerEntry.getValue().getTimestamp());
|
||||
message.setPayload(innerEntry.getValue().getPayload());
|
||||
message.setTimestamp(innerEntry.getValue().getTimestamp());
|
||||
byte[] json_bytes = MAPPER.writeValueAsString(message).getBytes();
|
||||
int packet_length = json_bytes.length;
|
||||
if (packet_length < GossipManager.MAX_PACKET_SIZE) {
|
||||
gossipCore.sendOneWay(message, member.getUri());
|
||||
} else {
|
||||
LOGGER.error("The length of the to be send message is too large ("
|
||||
+ packet_length + " > " + GossipManager.MAX_PACKET_SIZE + ").");
|
||||
}
|
||||
}
|
||||
} catch (IOException e1) {
|
||||
LOGGER.warn(e1);
|
||||
}
|
||||
}
|
||||
|
||||
public void sendPerNodeData(LocalGossipMember me, List<LocalGossipMember> memberList){
|
||||
LocalGossipMember member = selectPartner(memberList);
|
||||
if (member == null) {
|
||||
LOGGER.debug("Send sendMembershipList() is called without action");
|
||||
|
@ -7,6 +7,7 @@ import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.apache.gossip.model.GossipDataMessage;
|
||||
import org.apache.gossip.model.SharedGossipDataMessage;
|
||||
|
||||
/**
|
||||
* We wish to periodically sweep user data and remove entries past their timestamp. This
|
||||
@ -28,12 +29,21 @@ public class DataReaper {
|
||||
|
||||
public void init(){
|
||||
Runnable reapPerNodeData = () -> {
|
||||
runOnce();
|
||||
runPerNodeOnce();
|
||||
runSharedOnce();
|
||||
};
|
||||
scheduledExecutor.scheduleAtFixedRate(reapPerNodeData, 0, 5, TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
void runOnce(){
|
||||
void runSharedOnce(){
|
||||
for (Entry<String, SharedGossipDataMessage> entry : gossipCore.getSharedData().entrySet()){
|
||||
if (entry.getValue().getExpireAt() < clock.currentTimeMillis()){
|
||||
gossipCore.getSharedData().remove(entry.getKey(), entry.getValue());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void runPerNodeOnce(){
|
||||
for (Entry<String, ConcurrentHashMap<String, GossipDataMessage>> node : gossipCore.getPerNodeData().entrySet()){
|
||||
reapData(node.getValue());
|
||||
}
|
||||
|
@ -23,11 +23,13 @@ import org.apache.gossip.model.ActiveGossipMessage;
|
||||
import org.apache.gossip.model.Base;
|
||||
import org.apache.gossip.model.GossipDataMessage;
|
||||
import org.apache.gossip.model.Response;
|
||||
import org.apache.gossip.model.SharedGossipDataMessage;
|
||||
import org.apache.gossip.udp.Trackable;
|
||||
import org.apache.gossip.udp.UdpActiveGossipMessage;
|
||||
import org.apache.gossip.udp.UdpActiveGossipOk;
|
||||
import org.apache.gossip.udp.UdpGossipDataMessage;
|
||||
import org.apache.gossip.udp.UdpNotAMemberFault;
|
||||
import org.apache.gossip.udp.UdpSharedGossipDataMessage;
|
||||
import org.apache.log4j.Logger;
|
||||
import org.codehaus.jackson.map.ObjectMapper;
|
||||
|
||||
@ -39,24 +41,35 @@ public class GossipCore {
|
||||
private ConcurrentHashMap<String, Base> requests;
|
||||
private ExecutorService service;
|
||||
private final ConcurrentHashMap<String, ConcurrentHashMap<String, GossipDataMessage>> perNodeData;
|
||||
private final ConcurrentHashMap<String, SharedGossipDataMessage> sharedData;
|
||||
|
||||
public GossipCore(GossipManager manager){
|
||||
this.gossipManager = manager;
|
||||
requests = new ConcurrentHashMap<>();
|
||||
service = Executors.newFixedThreadPool(500);
|
||||
perNodeData = new ConcurrentHashMap<>();
|
||||
sharedData = new ConcurrentHashMap<>();
|
||||
}
|
||||
|
||||
public void addSharedData(SharedGossipDataMessage message){
|
||||
SharedGossipDataMessage previous = sharedData.get(message.getKey());
|
||||
if (previous == null){
|
||||
sharedData.putIfAbsent(message.getKey(), message);
|
||||
} else {
|
||||
if (previous.getTimestamp() < message.getTimestamp()){
|
||||
sharedData.replace(message.getKey(), previous, message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void addPerNodeData(GossipDataMessage message){
|
||||
ConcurrentHashMap<String,GossipDataMessage> nodeMap = new ConcurrentHashMap<>();
|
||||
nodeMap.put(message.getKey(), message);
|
||||
nodeMap = perNodeData.putIfAbsent(message.getNodeId(), nodeMap);
|
||||
if (nodeMap != null){
|
||||
//m.put(message.getKey(), message); //TODO only put if > ts
|
||||
GossipDataMessage current = nodeMap.get(message.getKey());
|
||||
if (current == null){
|
||||
nodeMap.replace(message.getKey(), null, message);
|
||||
nodeMap.putIfAbsent(message.getKey(), message);
|
||||
} else {
|
||||
if (current.getTimestamp() < message.getTimestamp()){
|
||||
nodeMap.replace(message.getKey(), current, message);
|
||||
@ -69,6 +82,10 @@ public class GossipCore {
|
||||
return perNodeData;
|
||||
}
|
||||
|
||||
public ConcurrentHashMap<String, SharedGossipDataMessage> getSharedData() {
|
||||
return sharedData;
|
||||
}
|
||||
|
||||
public void shutdown(){
|
||||
service.shutdown();
|
||||
try {
|
||||
@ -89,6 +106,10 @@ public class GossipCore {
|
||||
UdpGossipDataMessage message = (UdpGossipDataMessage) base;
|
||||
addPerNodeData(message);
|
||||
}
|
||||
if (base instanceof SharedGossipDataMessage){
|
||||
UdpSharedGossipDataMessage message = (UdpSharedGossipDataMessage) base;
|
||||
addSharedData(message);
|
||||
}
|
||||
if (base instanceof ActiveGossipMessage){
|
||||
List<GossipMember> remoteGossipMembers = new ArrayList<>();
|
||||
RemoteGossipMember senderMember = null;
|
||||
|
@ -44,6 +44,7 @@ import org.apache.gossip.event.GossipState;
|
||||
import org.apache.gossip.manager.impl.OnlyProcessReceivedPassiveGossipThread;
|
||||
|
||||
import org.apache.gossip.model.GossipDataMessage;
|
||||
import org.apache.gossip.model.SharedGossipDataMessage;
|
||||
|
||||
|
||||
public abstract class GossipManager implements NotificationListener {
|
||||
@ -235,7 +236,15 @@ public abstract class GossipManager implements NotificationListener {
|
||||
gossipCore.addPerNodeData(message);
|
||||
}
|
||||
|
||||
public GossipDataMessage findGossipData(String nodeId, String key){
|
||||
public void gossipSharedData(SharedGossipDataMessage message){
|
||||
Objects.nonNull(message.getKey());
|
||||
Objects.nonNull(message.getTimestamp());
|
||||
Objects.nonNull(message.getPayload());
|
||||
message.setNodeId(me.getId());
|
||||
gossipCore.addSharedData(message);
|
||||
}
|
||||
|
||||
public GossipDataMessage findPerNodeGossipData(String nodeId, String key){
|
||||
ConcurrentHashMap<String, GossipDataMessage> j = gossipCore.getPerNodeData().get(nodeId);
|
||||
if (j == null){
|
||||
return null;
|
||||
@ -250,6 +259,18 @@ public abstract class GossipManager implements NotificationListener {
|
||||
return l;
|
||||
}
|
||||
}
|
||||
|
||||
public SharedGossipDataMessage findSharedGossipData(String key){
|
||||
SharedGossipDataMessage l = gossipCore.getSharedData().get(key);
|
||||
if (l == null){
|
||||
return null;
|
||||
}
|
||||
if (l.getExpireAt() < clock.currentTimeMillis()){
|
||||
return null;
|
||||
} else {
|
||||
return l;
|
||||
}
|
||||
}
|
||||
|
||||
public DataReaper getDataReaper() {
|
||||
return dataReaper;
|
||||
|
Reference in New Issue
Block a user