package spimedb;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import jcog.Texts;
import jcog.Util;
import jcog.net.UDPeer;
import org.apache.commons.lang3.ArrayUtils;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import spimedb.index.SearchResult;
import spimedb.query.Query;
import spimedb.util.JSON;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.SocketException;
import static spimedb.NObjectConsumer.HashPredicate;
import static spimedb.NObjectConsumer.Tagged;
/**
* Created by me on 4/4/17.
*/
public class SpimeDBPeer extends UDPeer {
static final Logger logger = LoggerFactory.getLogger(SpimeDBPeer.class);
private final SpimeDB db;
public SpimeDBPeer(int port, SpimeDB db) throws SocketException {
super(port);
this.db = db;
db.on((nobject) -> {
if (isOnline() && isOriginal(nobject) && isPublic(nobject)) {
String[] tags = nobject.tags();
int numTags = tags.length;
if (numTags > 0) {
float totalNeed = 0;
for (String t : tags) {
totalNeed += need.pri(t);
}
float avgNeed = totalNeed / numTags;
if (totalNeed > 0) {
//TODO send to peers which need it (the most)
share(nobject, avgNeed);
}
}
}
});
db.on(
Tagged(
(e) -> {
byte[] message = e.get("udp");
if (message != null) {
say(new Msg(message), 1f, false);
} else {
believe(JSON.toJSONBytes(e), 3);
}
},
"")
);
db.on(
//#peer(<host>)
HashPredicate((PEER, addr) -> {
String[] hp = addr.split(":");
if (hp.length == 2) {
int pp = Texts.i(hp[1], -1);
String hh = hp[0];
if (pp != -1) {
ping(new InetSocketAddress(hh, pp));
}
}
}, "peer")
);
}
public boolean isOnline() {
return (!them.isEmpty());
}
protected void share(NObject n, float pri) {
try {
believe(Util.toBytes(n), 1 /* TODO pri */);
} catch (JsonProcessingException e) {
e.printStackTrace();
}
}
/**
* to filter the sharing of nobjects
*/
public boolean isPublic(NObject n) {
return true;
}
public boolean isOriginal(NObject n) {
return n.get("from")==null;
}
@Override
protected void onUpdateNeed() {
SearchResult r = db.get(new Query().limit((int)Math.ceil(16)).in(need.data.keySet().toArray(ArrayUtils.EMPTY_STRING_ARRAY)));
if (r!=null) {
r.forEach/*Document*/((d, s) -> {
share(d, 1f /* TODO: unitize(need.dotProduct(d.tags()) )) */);
return true;
});
r.close();
}
}
@Override
protected void onBelief(@Nullable UDProfile connected, @NotNull Msg m) {
JsonNode parsed = null;
try {
parsed = Util.fromBytes(m.data(), JsonNode.class);
JsonNode pi = parsed.get("I");
String id;
if (pi != null) {
id = pi.textValue();
} else {
id = SpimeDB.uuidString(); //TODO better
}
MutableNObject y = new MutableNObject(id).putAll(parsed).put("from", m.array());
logger.debug("{} recv {}", me, y);
db.add(y);
} catch (IOException e) {
e.printStackTrace();
}
}
public void ask(String xyz) {
}
}