mirror of
https://github.com/ChronosX88/JGUN.git
synced 2024-11-09 16:51:02 +00:00
Implemented key-lookup
This commit is contained in:
parent
33574c69a5
commit
791f29a177
@ -10,6 +10,7 @@ import java.net.URISyntaxException;
|
||||
|
||||
public class Client extends WebSocketClient {
|
||||
private Dup dup = new Dup();
|
||||
private Graph graph = new Graph();
|
||||
|
||||
public Client(InetAddress address, int port) throws URISyntaxException {
|
||||
super(new URI("ws://" + address.getHostAddress() + ":" + port));
|
||||
@ -20,31 +21,53 @@ public class Client extends WebSocketClient {
|
||||
System.out.println("Connection open. Status: " + handshakeData.getHttpStatus());
|
||||
Utils.setTimeout(() -> {
|
||||
JSONObject msg = new JSONObject();
|
||||
msg.put("#", dup.track(Dup.random(3)));
|
||||
msg
|
||||
.put("#", dup.track(Dup.random()))
|
||||
.put("get", new JSONObject()
|
||||
.put("#", "FDSA")
|
||||
.put(".", "species"));
|
||||
this.send(msg.toString());
|
||||
}, 2000);
|
||||
|
||||
Utils.setTimeout(() -> {
|
||||
JSONObject msg = new JSONObject();
|
||||
msg.put("#", dup.track(Dup.random()));
|
||||
msg.put("put", new JSONObject()
|
||||
.put("ASDF", Utils.newNode("ASDF", new JSONObject()
|
||||
.put("name", "Mark Nadal")
|
||||
.put("boss", new JSONObject().put("#", "FDSA"))).toJSONObject())
|
||||
.put("FDSA", Utils.newNode("FDSA", new JSONObject().put("name", "Fluffy").put("species", "a kitty").put("slave", new JSONObject().put("#", "ASDF"))).toJSONObject()));
|
||||
this.send(msg.toString());
|
||||
}, 1000);
|
||||
}, (int) (1000 * Math.random()));
|
||||
Utils.setTimeout(() -> {
|
||||
JSONObject msg = new JSONObject();
|
||||
msg.put("#", dup.track(Dup.random(3)));
|
||||
msg.put("#", dup.track(Dup.random()));
|
||||
msg.put("put", new JSONObject()
|
||||
.put("ASDF", Utils.newNode("ASDF", new JSONObject()
|
||||
.put("name", "Mark")).toJSONObject())
|
||||
.put("FDSA", Utils.newNode("FDSA", new JSONObject().put("species", "felis silvestris").put("color", "ginger")).toJSONObject()));
|
||||
this.send(msg.toString());
|
||||
}, 2000);
|
||||
}, (int) (1000 * Math.random()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMessage(String message) {
|
||||
JSONObject msg = new JSONObject(message);
|
||||
if(dup.check(msg.getString("#"))) { return; }
|
||||
if(dup.check(msg.getString("#"))){ return; }
|
||||
dup.track(msg.getString("#"));
|
||||
System.out.println(msg.toString());
|
||||
if(msg.opt("put") != null) {
|
||||
HAM.mix(new Graph(msg.getJSONObject("put")), graph);
|
||||
}
|
||||
if(msg.opt("get") != null) {
|
||||
Graph getResults = Utils.getRequest(msg.getJSONObject("get"), graph);
|
||||
JSONObject ack = new JSONObject()
|
||||
.put("#", dup.track(Dup.random()))
|
||||
.put("@", msg.getString("#"))
|
||||
.put("put", getResults.toJSONObject());
|
||||
this.send(ack.toString());
|
||||
}
|
||||
System.out.println("---------------");
|
||||
System.out.println(msg.toString(2));
|
||||
this.send(message);
|
||||
}
|
||||
|
||||
|
@ -2,10 +2,11 @@ package io.github.chronosx88.GunJava;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Random;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
public class Dup {
|
||||
private static char[] randomPack = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ".toCharArray();
|
||||
private static char[] randomSeed = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ".toCharArray();
|
||||
private static Random random = new Random(System.currentTimeMillis());
|
||||
private Map<String, Long> s = new ConcurrentHashMap<>();
|
||||
private DupOpt opt = new DupOpt();
|
||||
@ -40,11 +41,7 @@ public class Dup {
|
||||
}
|
||||
}
|
||||
|
||||
public static String random(int len) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (int i = 0; i < len; i++) {
|
||||
sb.append(randomPack[random.nextInt(randomPack.length)]);
|
||||
}
|
||||
return sb.toString();
|
||||
public static String random() {
|
||||
return UUID.randomUUID().toString();
|
||||
}
|
||||
}
|
||||
|
@ -35,6 +35,8 @@ public class Graph {
|
||||
return nodes.entrySet();
|
||||
}
|
||||
|
||||
public Collection<Node> nodes() { return nodes.values(); }
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
JSONObject jsonObject = new JSONObject();
|
||||
@ -59,4 +61,8 @@ public class Graph {
|
||||
}
|
||||
return jsonObject;
|
||||
}
|
||||
|
||||
public boolean isEmpty() {
|
||||
return nodes.isEmpty();
|
||||
}
|
||||
}
|
@ -2,10 +2,11 @@ package io.github.chronosx88.GunJava;
|
||||
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
|
||||
public class HAM {
|
||||
private static long defer = Long.MAX_VALUE;
|
||||
|
||||
static class HAMResult {
|
||||
public boolean defer = false;
|
||||
public boolean historical = false;
|
||||
@ -52,7 +53,7 @@ public class HAM {
|
||||
return result;
|
||||
}
|
||||
|
||||
public static Graph mix(Graph change, Graph graph) {
|
||||
public static Graph mix(Graph change, Graph data) {
|
||||
long machine = System.currentTimeMillis();
|
||||
Graph diff = null;
|
||||
for(Map.Entry<String, Node> entry : change.entries()) {
|
||||
@ -63,21 +64,23 @@ public class HAM {
|
||||
long state = node.states.getLong(key);
|
||||
long was = -1;
|
||||
Object known = null;
|
||||
if(graph == null) {
|
||||
graph = new Graph();
|
||||
if(data == null) {
|
||||
data = new Graph();
|
||||
}
|
||||
if(graph.hasNode(node.soul)) {
|
||||
if(graph.getNode(node.soul).states.opt(key) != null) {
|
||||
was = graph.getNode(node.soul).states.getLong(key);
|
||||
if(data.hasNode(node.soul)) {
|
||||
if(data.getNode(node.soul).states.opt(key) != null) {
|
||||
was = data.getNode(node.soul).states.getLong(key);
|
||||
}
|
||||
known = graph.getNode(node.soul).values.opt(key) == null ? 0 : graph.getNode(node.soul).values.opt(key);
|
||||
known = data.getNode(node.soul).values.opt(key) == null ? 0 : data.getNode(node.soul).values.opt(key);
|
||||
}
|
||||
|
||||
HAMResult ham = ham(machine, state, was, value, known);
|
||||
if(!ham.incoming) {
|
||||
if(ham.defer) {
|
||||
System.out.println("DEFER: " + key + " " + value);
|
||||
// FIXME
|
||||
// Hack for accessing value in lambda without making the variable final
|
||||
Graph[] graph = new Graph[] {data};
|
||||
Utils.setTimeout(() -> mix(node, graph[0]), (int) (state - System.currentTimeMillis()));
|
||||
}
|
||||
continue;
|
||||
}
|
||||
@ -90,18 +93,70 @@ public class HAM {
|
||||
diff.addNode(node.soul, Utils.newNode(node.soul, new JSONObject()));
|
||||
}
|
||||
|
||||
if(!graph.hasNode(node.soul)) {
|
||||
graph.addNode(node.soul, Utils.newNode(node.soul, new JSONObject()));
|
||||
if(!data.hasNode(node.soul)) {
|
||||
data.addNode(node.soul, Utils.newNode(node.soul, new JSONObject()));
|
||||
}
|
||||
|
||||
graph.getNode(node.soul).values.put(key, value);
|
||||
data.getNode(node.soul).values.put(key, value);
|
||||
diff.getNode(node.soul).values.put(key, value);
|
||||
|
||||
diff.getNode(node.soul).states.put(key, state);
|
||||
graph.getNode(node.soul).states.put(key, state);
|
||||
data.getNode(node.soul).states.put(key, state);
|
||||
}
|
||||
}
|
||||
|
||||
return diff;
|
||||
}
|
||||
|
||||
public static Graph mix(Node incomingNode, Graph data) {
|
||||
long machine = System.currentTimeMillis();
|
||||
Graph diff = null;
|
||||
|
||||
for(String key : incomingNode.values.keySet()) {
|
||||
Object value = incomingNode.values.get(key);
|
||||
if ("_".equals(key)) { continue; }
|
||||
long state = incomingNode.states.getLong(key);
|
||||
long was = -1;
|
||||
Object known = null;
|
||||
if(data == null) {
|
||||
data = new Graph();
|
||||
}
|
||||
if(data.hasNode(incomingNode.soul)) {
|
||||
if(data.getNode(incomingNode.soul).states.opt(key) != null) {
|
||||
was = data.getNode(incomingNode.soul).states.getLong(key);
|
||||
}
|
||||
known = data.getNode(incomingNode.soul).values.opt(key) == null ? 0 : data.getNode(incomingNode.soul).values.opt(key);
|
||||
}
|
||||
|
||||
HAMResult ham = ham(machine, state, was, value, known);
|
||||
if(!ham.incoming) {
|
||||
if(ham.defer) {
|
||||
System.out.println("DEFER: " + key + " " + value);
|
||||
// Hack for accessing value in lambda without making the variable final
|
||||
Graph[] graph = new Graph[] {data};
|
||||
Utils.setTimeout(() -> mix(incomingNode, graph[0]), (int) (state - System.currentTimeMillis()));
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if(diff == null) {
|
||||
diff = new Graph();
|
||||
}
|
||||
|
||||
if(!diff.hasNode(incomingNode.soul)) {
|
||||
diff.addNode(incomingNode.soul, Utils.newNode(incomingNode.soul, new JSONObject()));
|
||||
}
|
||||
|
||||
if(!data.hasNode(incomingNode.soul)) {
|
||||
data.addNode(incomingNode.soul, Utils.newNode(incomingNode.soul, new JSONObject()));
|
||||
}
|
||||
|
||||
data.getNode(incomingNode.soul).values.put(key, value);
|
||||
diff.getNode(incomingNode.soul).values.put(key, value);
|
||||
|
||||
diff.getNode(incomingNode.soul).states.put(key, state);
|
||||
data.getNode(incomingNode.soul).states.put(key, state);
|
||||
}
|
||||
return diff;
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,15 @@
|
||||
package io.github.chronosx88.GunJava;
|
||||
|
||||
import java.net.Inet4Address;
|
||||
import java.net.InetAddress;
|
||||
import java.net.URISyntaxException;
|
||||
import java.net.UnknownHostException;
|
||||
|
||||
public class MainClientServer {
|
||||
public static void main(String[] args) throws URISyntaxException, UnknownHostException {
|
||||
Server server = new Server(21334);
|
||||
server.start();
|
||||
Client client = new Client(Inet4Address.getByAddress(new byte[]{127, 0, 0, 1}), 21334);
|
||||
client.connect();
|
||||
}
|
||||
}
|
@ -4,8 +4,8 @@ import org.json.JSONObject;
|
||||
|
||||
public class Node implements Comparable<Node> {
|
||||
public JSONObject values; // Data
|
||||
public final JSONObject states; // Metadata for diff
|
||||
public final String soul; // i.e. ID of node
|
||||
public JSONObject states; // Metadata for diff
|
||||
public String soul; // i.e. ID of node
|
||||
|
||||
/**
|
||||
* Create a Node from a JSON object.
|
||||
@ -13,7 +13,7 @@ public class Node implements Comparable<Node> {
|
||||
* @param rawData JSON object, which contains the data
|
||||
*/
|
||||
public Node(JSONObject rawData) {
|
||||
this.values = rawData;
|
||||
this.values = new JSONObject(rawData.toString());
|
||||
this.states = values.getJSONObject("_").getJSONObject(">");
|
||||
this.soul = values.getJSONObject("_").getString("#");
|
||||
values.remove("_");
|
||||
@ -61,4 +61,15 @@ public class Node implements Comparable<Node> {
|
||||
jsonObject.put("_", new JSONObject().put("#", soul).put(">", states));
|
||||
return jsonObject;
|
||||
}
|
||||
|
||||
public JSONObject getMetadata() {
|
||||
JSONObject jsonObject = new JSONObject();
|
||||
jsonObject.put("_", new JSONObject().put("#", soul).put(">", states));
|
||||
return jsonObject;
|
||||
}
|
||||
|
||||
public void setMetadata(JSONObject metadata) {
|
||||
soul = metadata.getJSONObject("_").getString("#");
|
||||
states = metadata.getJSONObject("_").getJSONObject(">");
|
||||
}
|
||||
}
|
@ -6,27 +6,26 @@ import org.java_websocket.server.WebSocketServer;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.net.InetSocketAddress;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Timer;
|
||||
|
||||
public class Server extends WebSocketServer {
|
||||
private Timer timer = new Timer(true);
|
||||
private Dup dup = new Dup();
|
||||
private ArrayList<WebSocket> peers = new ArrayList<>();
|
||||
private Graph graph = new Graph();
|
||||
|
||||
public Server(int port) {
|
||||
super(new InetSocketAddress(port));
|
||||
setReuseAddr(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onOpen(WebSocket conn, ClientHandshake handshake) {
|
||||
peers.add(conn);
|
||||
System.out.println("Connected new peer: " + conn.getRemoteSocketAddress().toString());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClose(WebSocket conn, int code, String reason, boolean remote) {
|
||||
//
|
||||
System.out.println("Peer " + conn.getRemoteSocketAddress().toString() + " closed the connection for reason (code): " + reason + " (" + code + ")");
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -36,13 +35,20 @@ public class Server extends WebSocketServer {
|
||||
dup.track(msg.getString("#"));
|
||||
if(msg.opt("put") != null) {
|
||||
HAM.mix(new Graph(msg.getJSONObject("put")), graph);
|
||||
System.out.println("----------------");
|
||||
System.out.println(graph.toPrettyString());
|
||||
}
|
||||
for (WebSocket peer : peers) {
|
||||
peer.send(message);
|
||||
if(msg.opt("get") != null) {
|
||||
Graph result = Utils.getRequest(msg.optJSONObject("get"), graph);
|
||||
if(!result.isEmpty()) {
|
||||
JSONObject ack = new JSONObject();
|
||||
emit(ack
|
||||
.put("#", dup.track(Dup.random()))
|
||||
.put("@", msg.getString("#"))
|
||||
.put("put", result.toJSONObject())
|
||||
.toString());
|
||||
}
|
||||
}
|
||||
emit(message);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(WebSocket conn, Exception ex) {
|
||||
@ -51,6 +57,12 @@ public class Server extends WebSocketServer {
|
||||
|
||||
@Override
|
||||
public void onStart() {
|
||||
//
|
||||
System.out.println("Server started on port: " + getPort());
|
||||
}
|
||||
|
||||
public void emit(String data) {
|
||||
for(WebSocket conn : this.getConnections()) {
|
||||
conn.send(data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -25,4 +25,29 @@ public class Utils {
|
||||
data.put("_", new JSONObject().put("#", soul).put(">", states));
|
||||
return new Node(data);
|
||||
}
|
||||
|
||||
public static Graph getRequest(JSONObject lex, Graph graph) {
|
||||
String soul = lex.getString("#");
|
||||
String key = lex.optString(".", null);
|
||||
Node node = graph.getNode(soul);
|
||||
Object tmp;
|
||||
if(node == null) {
|
||||
return new Graph();
|
||||
}
|
||||
if(key != null) {
|
||||
tmp = node.values.opt(key);
|
||||
if(tmp == null) {
|
||||
return new Graph();
|
||||
}
|
||||
Node node1 = new Node(node.toJSONObject());
|
||||
node = Utils.newNode(node.soul, new JSONObject());
|
||||
node.setMetadata(node1.getMetadata());
|
||||
node.values.put(key, tmp);
|
||||
JSONObject tmpStates = node1.states;
|
||||
node.states.put(key, tmpStates.get(key));
|
||||
}
|
||||
Graph ack = new Graph();
|
||||
ack.addNode(soul, node);
|
||||
return ack;
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user