|
@@ -11,15 +11,17 @@ namespace Riddle {
|
|
|
private SocketService service;
|
|
|
private Gee.HashMap<string, Invercargill.Sequence<Registration>> registrations = new Gee.HashMap<string, Invercargill.Sequence<Registration>>();
|
|
|
private Gee.HashMap<string, RiddleEnvelope> riddles = new Gee.HashMap<string, RiddleEnvelope>();
|
|
|
- private Gee.HashMap<string, NameInfo> names = new Gee.HashMap<string, NameInfo>();
|
|
|
+ private NameInfoStore names;
|
|
|
private Client client;
|
|
|
|
|
|
- private AsyncQueue<Gossip> gossip = new AsyncQueue<Gossip>();
|
|
|
+ private Fifo<Gossip> gossip = new Fifo<Gossip>();
|
|
|
+ private Gee.HashSet<string> gossip_idempotency_tokens = new Gee.HashSet<string>();
|
|
|
private Thread<bool> gossip_thread;
|
|
|
private uint16 port;
|
|
|
|
|
|
|
|
|
- public Server(string address, uint16 port) throws Error {
|
|
|
+ public Server(string address, uint16 port, NameInfoStore name_store) throws Error {
|
|
|
+ this.names = name_store;
|
|
|
this.port = port;
|
|
|
var add = new InetAddress.from_string(address);
|
|
|
service = new SocketService ();
|
|
@@ -64,14 +66,15 @@ namespace Riddle {
|
|
|
}
|
|
|
|
|
|
private bool spread_gossip() {
|
|
|
- while (true) {
|
|
|
+ foreach (var goss in gossip) {
|
|
|
// What's the goss?
|
|
|
- var goss = gossip.pop();
|
|
|
var members = get_group_registrations(goss.group).select<InetSocketAddress>(r => r.address);
|
|
|
+
|
|
|
print("Spreading gossip!\n");
|
|
|
client.raw_request(goss.message, members, 30000);
|
|
|
Thread.usleep(GOSSIP_INTERVAL_US);
|
|
|
}
|
|
|
+ return true;
|
|
|
}
|
|
|
|
|
|
private Message service_message(Message msg, InetSocketAddress origin) throws Error {
|
|
@@ -122,6 +125,7 @@ namespace Riddle {
|
|
|
private Message handle_propogate(Message msg) throws Error {
|
|
|
var name = msg.arguments[0];
|
|
|
var ttl = int.parse(msg.arguments[1]);
|
|
|
+ var token = msg.arguments[2];
|
|
|
var encoded_name_info = msg.items[0];
|
|
|
|
|
|
try {
|
|
@@ -151,7 +155,7 @@ namespace Riddle {
|
|
|
|
|
|
if(ttl > 0) {
|
|
|
msg.arguments[1] = (ttl - 1).to_string();
|
|
|
- gossip_to(RIDDLE_SERVER_GROUP, msg);
|
|
|
+ gossip_to(RIDDLE_SERVER_GROUP, msg, token);
|
|
|
}
|
|
|
|
|
|
return new Message(MessageType.OK, new string[0], new string[0]);
|
|
@@ -189,7 +193,7 @@ namespace Riddle {
|
|
|
|
|
|
var to_forward = riddle_envelope.forward(port);
|
|
|
if(to_forward != null) {
|
|
|
- gossip_to(riddle_envelope.group_name, to_forward.to_message());
|
|
|
+ gossip_to(riddle_envelope.group_name, to_forward.to_message(), riddle_envelope.identifier);
|
|
|
}
|
|
|
|
|
|
// Pass to application to solve then compact when done.
|
|
@@ -265,18 +269,18 @@ namespace Riddle {
|
|
|
|
|
|
private bool add_name_info_if_latest(NameInfo info) {
|
|
|
lock(names) {
|
|
|
- if(names.has_key(info.name) && names[info.name].effective.difference(info.effective) > 0) {
|
|
|
+ if(!names.is_outdated(info.name, info.effective)) {
|
|
|
return false;
|
|
|
}
|
|
|
- names.set(info.name, info);
|
|
|
+ names.save_name(info);
|
|
|
}
|
|
|
return true;
|
|
|
}
|
|
|
|
|
|
private NameInfo? get_name_info(string name) {
|
|
|
lock(names) {
|
|
|
- if(names.has_key(name)) {
|
|
|
- return names[name];
|
|
|
+ if(names.has_name(name)) {
|
|
|
+ return names.get_name(name);
|
|
|
}
|
|
|
}
|
|
|
return null;
|
|
@@ -291,20 +295,32 @@ namespace Riddle {
|
|
|
return null;
|
|
|
}
|
|
|
|
|
|
- private void gossip_to(string group, Message message) {
|
|
|
- var g = new Gossip() {
|
|
|
- message = message,
|
|
|
- group = group
|
|
|
- };
|
|
|
- gossip.push(g);
|
|
|
+ private void gossip_to(string group, Message message, string token) {
|
|
|
+ lock(gossip) {
|
|
|
+ if(gossip_idempotency_tokens.contains(token)){
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ var g = new Gossip() {
|
|
|
+ message = message,
|
|
|
+ group = group,
|
|
|
+ };
|
|
|
+ gossip.push(g);
|
|
|
+ gossip_idempotency_tokens.add(token);
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
- private void gossip_next(string group, Message message) {
|
|
|
- var g = new Gossip() {
|
|
|
- message = message,
|
|
|
- group = group
|
|
|
- };
|
|
|
- gossip.push_front(g);
|
|
|
+ private void gossip_next(string group, Message message, string token) {
|
|
|
+ lock(gossip) {
|
|
|
+ if(gossip_idempotency_tokens.contains(token)){
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ var g = new Gossip() {
|
|
|
+ message = message,
|
|
|
+ group = group
|
|
|
+ };
|
|
|
+ gossip.push_start(g);
|
|
|
+ gossip_idempotency_tokens.add(token);
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
}
|