Major refactoring

This commit is contained in:
2015-05-19 19:16:20 +02:00
parent b143225af5
commit 1fbc4a1d74
45 changed files with 1447 additions and 444 deletions

15
repositories/build.gradle Normal file
View File

@ -0,0 +1,15 @@
apply plugin: 'java'
sourceCompatibility = 1.7
version = '1.0'
repositories {
mavenCentral()
}
dependencies {
compile project(':domain')
compile 'com.h2database:h2:1.4.187'
compile 'org.flywaydb:flyway-core:3.2.1'
testCompile 'junit:junit:4.11'
}

View File

@ -0,0 +1,170 @@
/*
* Copyright 2015 Christian Basler
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ch.dissem.bitmessage.repository;
import ch.dissem.bitmessage.entity.BitmessageAddress;
import ch.dissem.bitmessage.entity.payload.Pubkey;
import ch.dissem.bitmessage.entity.valueobject.PrivateKey;
import ch.dissem.bitmessage.factory.Factory;
import ch.dissem.bitmessage.ports.AddressRepository;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.sql.*;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
/**
* Created by chris on 23.04.15.
*/
public class JdbcAddressRepository extends JdbcHelper implements AddressRepository {
private static final Logger LOG = LoggerFactory.getLogger(JdbcAddressRepository.class);
@Override
public BitmessageAddress findContact(byte[] ripeOrTag) {
for (BitmessageAddress address : find("public_key is null")) {
if (address.getVersion() > 3) {
if (Arrays.equals(ripeOrTag, address.getTag())) return address;
} else {
if (Arrays.equals(ripeOrTag, address.getRipe())) return address;
}
}
return null;
}
@Override
public BitmessageAddress findIdentity(byte[] ripeOrTag) {
for (BitmessageAddress address : find("private_key is not null")) {
if (address.getVersion() > 3) {
if (Arrays.equals(ripeOrTag, address.getTag())) return address;
} else {
if (Arrays.equals(ripeOrTag, address.getRipe())) return address;
}
}
return null;
}
@Override
public List<BitmessageAddress> getIdentities() {
return find("private_signing_key IS NOT NULL");
}
@Override
public List<BitmessageAddress> getSubscriptions() {
return find("subscribed = '1'");
}
@Override
public List<BitmessageAddress> getContacts() {
return find("private_signing_key IS NULL");
}
private List<BitmessageAddress> find(String where) {
List<BitmessageAddress> result = new LinkedList<>();
try {
Statement stmt = getConnection().createStatement();
ResultSet rs = stmt.executeQuery("SELECT address, alias, public_key, private_key, subscribed FROM Address WHERE " + where);
while (rs.next()) {
BitmessageAddress address;
Blob privateKeyBlob = rs.getBlob("private_key");
if (privateKeyBlob != null) {
PrivateKey privateKey = PrivateKey.read(privateKeyBlob.getBinaryStream());
address = new BitmessageAddress(privateKey);
} else {
address = new BitmessageAddress(rs.getString("address"));
Blob publicKeyBlob = rs.getBlob("public_key");
if (publicKeyBlob != null) {
Pubkey pubkey = Factory.readPubkey(address.getVersion(), address.getStream(),
publicKeyBlob.getBinaryStream(), (int) publicKeyBlob.length());
address.setPubkey(pubkey);
}
}
address.setAlias(rs.getString("alias"));
address.setSubscribed(rs.getBoolean("subscribed"));
result.add(address);
}
} catch (IOException | SQLException e) {
LOG.error(e.getMessage(), e);
}
return result;
}
private boolean exists(BitmessageAddress address) {
try {
Statement stmt = getConnection().createStatement();
ResultSet rs = stmt.executeQuery("SELECT COUNT(*) FROM Address WHERE address='" + address.getAddress() + "'");
rs.next();
return rs.getInt(0) > 0;
} catch (SQLException e) {
LOG.error(e.getMessage(), e);
}
return false;
}
@Override
public void save(BitmessageAddress address) {
try {
if (exists(address)) {
update(address);
} else {
insert(address);
}
} catch (IOException | SQLException e) {
LOG.error(e.getMessage(), e);
}
}
private void update(BitmessageAddress address) throws IOException, SQLException {
PreparedStatement ps = getConnection().prepareStatement(
"UPDATE Address SET address=?, alias=?, public_key=?, private_key=?");
ps.setString(1, address.getAddress());
ps.setString(2, address.getAlias());
writeBlob(ps, 3, address.getPubkey());
writeBlob(ps, 4, address.getPrivateKey());
ps.executeUpdate();
}
private void insert(BitmessageAddress address) throws IOException, SQLException {
PreparedStatement ps = getConnection().prepareStatement(
"INSERT INTO Address (address, alias, public_key, private_key) VALUES (?, ?, ?, ?, ?)");
ps.setString(1, address.getAddress());
ps.setString(2, address.getAlias());
writeBlob(ps, 3, address.getPubkey());
writeBlob(ps, 4, address.getPrivateKey());
ps.executeUpdate();
}
@Override
public void remove(BitmessageAddress address) {
try {
Statement stmt = getConnection().createStatement();
stmt.executeUpdate("DELETE FROM Address WHERE address = '" + address.getAddress() + "'");
} catch (SQLException e) {
LOG.error(e.getMessage(), e);
}
}
@Override
public BitmessageAddress getAddress(String address) {
List<BitmessageAddress> result = find("address = '" + address + "'");
if (result.size() > 0) return result.get(0);
return null;
}
}

View File

@ -0,0 +1,63 @@
/*
* Copyright 2015 Christian Basler
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ch.dissem.bitmessage.repository;
import ch.dissem.bitmessage.entity.Streamable;
import org.flywaydb.core.Flyway;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;
/**
* Helper class that does Flyway migration, provides JDBC connections and some helper methods.
*/
abstract class JdbcHelper {
private static final Logger LOG = LoggerFactory.getLogger(JdbcHelper.class);
private static final String DB_URL = "jdbc:h2:~/jabit";
private static final String DB_USER = "sa";
private static final String DB_PWD = null;
static {
Flyway flyway = new Flyway();
flyway.setDataSource(DB_URL, DB_USER, DB_PWD);
flyway.migrate();
}
protected void writeBlob(PreparedStatement ps, int parameterIndex, Streamable data) throws SQLException, IOException {
ByteArrayOutputStream os = new ByteArrayOutputStream();
data.write(os);
ByteArrayInputStream is = new ByteArrayInputStream(os.toByteArray());
ps.setBlob(parameterIndex, is);
}
protected Connection getConnection() {
try {
return DriverManager.getConnection(DB_URL, DB_USER, DB_PWD);
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
}

View File

@ -0,0 +1,136 @@
/*
* Copyright 2015 Christian Basler
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ch.dissem.bitmessage.repository;
import ch.dissem.bitmessage.entity.ObjectMessage;
import ch.dissem.bitmessage.entity.payload.ObjectType;
import ch.dissem.bitmessage.entity.valueobject.InventoryVector;
import ch.dissem.bitmessage.factory.Factory;
import ch.dissem.bitmessage.ports.Inventory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.sql.*;
import java.util.LinkedList;
import java.util.List;
import static ch.dissem.bitmessage.utils.Strings.join;
import static ch.dissem.bitmessage.utils.UnixTime.now;
/**
* Created by chris on 24.04.15.
*/
public class JdbcInventory extends JdbcHelper implements Inventory {
private static final Logger LOG = LoggerFactory.getLogger(JdbcInventory.class);
@Override
public List<InventoryVector> getInventory(long... streams) {
List<InventoryVector> result = new LinkedList<>();
try {
Statement stmt = getConnection().createStatement();
ResultSet rs = stmt.executeQuery("SELECT hash FROM Inventory WHERE expires > " + now() +
" AND stream IN (" + join(streams) + ")");
while (rs.next()) {
result.add(new InventoryVector(rs.getBytes("hash")));
}
} catch (SQLException e) {
LOG.error(e.getMessage(), e);
}
return result;
}
@Override
public List<InventoryVector> getMissing(List<InventoryVector> offer, long... streams) {
offer.removeAll(getInventory(streams));
return offer;
}
@Override
public ObjectMessage getObject(InventoryVector vector) {
try {
Statement stmt = getConnection().createStatement();
ResultSet rs = stmt.executeQuery("SELECT data, version FROM Inventory WHERE hash = X'" + vector + "'");
if (rs.next()) {
Blob data = rs.getBlob("data");
return Factory.getObjectMessage(rs.getInt("version"), data.getBinaryStream(), (int) data.length());
} else {
LOG.info("Object requested that we don't have. IV: " + vector);
return null;
}
} catch (Exception e) {
LOG.error(e.getMessage(), e);
throw new RuntimeException(e);
}
}
@Override
public List<ObjectMessage> getObjects(long stream, long version, ObjectType type) {
try {
StringBuilder query = new StringBuilder("SELECT data, version FROM Inventory WHERE 1=1");
if (stream >= 0) {
query.append(" AND stream = ").append(stream);
}
if (version >= 0) {
query.append(" AND version = ").append(version);
}
if (type != null) {
query.append(" AND type = ").append(type.getNumber());
}
Statement stmt = getConnection().createStatement();
ResultSet rs = stmt.executeQuery(query.toString());
List<ObjectMessage> result = new LinkedList<>();
while (rs.next()) {
Blob data = rs.getBlob("data");
result.add(Factory.getObjectMessage(rs.getInt("version"), data.getBinaryStream(), (int) data.length()));
}
return result;
} catch (Exception e) {
LOG.error(e.getMessage(), e);
throw new RuntimeException(e);
}
}
@Override
public void storeObject(ObjectMessage object) {
try {
PreparedStatement ps = getConnection().prepareStatement("INSERT INTO Inventory (hash, stream, expires, data, type, version) VALUES (?, ?, ?, ?, ?, ?)");
InventoryVector iv = object.getInventoryVector();
LOG.trace("Storing object " + iv);
ps.setBytes(1, iv.getHash());
ps.setLong(2, object.getStream());
ps.setLong(3, object.getExpiresTime());
writeBlob(ps, 4, object);
ps.setLong(5, object.getType());
ps.setLong(6, object.getVersion());
ps.executeUpdate();
} catch (SQLException e) {
LOG.error("Error storing object of type " + object.getPayload().getClass().getSimpleName(), e);
} catch (Exception e) {
LOG.error(e.getMessage(), e);
}
}
@Override
public void cleanup() {
try {
// We delete only objects that expired 5 minutes ago or earlier, so we don't request objects we just deleted
getConnection().createStatement().executeUpdate("DELETE FROM Inventory WHERE expires < " + (now() - 300));
} catch (SQLException e) {
LOG.debug(e.getMessage(), e);
}
}
}

View File

@ -0,0 +1,192 @@
/*
* Copyright 2015 Christian Basler
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ch.dissem.bitmessage.repository;
import ch.dissem.bitmessage.InternalContext;
import ch.dissem.bitmessage.entity.BitmessageAddress;
import ch.dissem.bitmessage.entity.Plaintext;
import ch.dissem.bitmessage.entity.valueobject.Label;
import ch.dissem.bitmessage.ports.MessageRepository;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.sql.*;
import java.util.ArrayList;
import java.util.Collection;
import java.util.LinkedList;
import java.util.List;
public class JdbcMessageRepository extends JdbcHelper implements MessageRepository, InternalContext.ContextHolder {
private static final Logger LOG = LoggerFactory.getLogger(JdbcMessageRepository.class);
private InternalContext ctx;
@Override
public List<String> getLabels() {
List<String> result = new LinkedList<>();
try {
Statement stmt = getConnection().createStatement();
ResultSet rs = stmt.executeQuery("SELECT label FROM Label ORDER BY order");
while (rs.next()) {
result.add(rs.getString("label"));
}
} catch (SQLException e) {
LOG.error(e.getMessage(), e);
}
return result;
}
@Override
public List<Plaintext> findMessages(Label label) {
return find("id IN SELECT message_id FROM Message_Label WHERE label_id=" + label.getId());
}
@Override
public List<Plaintext> findMessages(Plaintext.Status status, BitmessageAddress recipient) {
return find("status='" + status.name() + "' AND to='" + recipient.getAddress() + "'");
}
@Override
public List<Plaintext> findMessages(Plaintext.Status status) {
return find("status='" + status.name() + "'");
}
private List<Plaintext> find(String where) {
List<Plaintext> result = new LinkedList<>();
try {
Statement stmt = getConnection().createStatement();
ResultSet rs = stmt.executeQuery("SELECT \"id\", \"from\", \"to\", \"data\", \"sent\", \"received\", \"status\" FROM Message WHERE " + where);
while (rs.next()) {
Blob data = rs.getBlob("data");
Plaintext.Builder builder = Plaintext.readWithoutSignature(data.getBinaryStream());
long id = rs.getLong("id");
builder.id(id);
builder.from(ctx.getAddressRepo().getAddress(rs.getString("from")));
builder.to(ctx.getAddressRepo().getAddress(rs.getString("to")));
builder.sent(rs.getLong("sent"));
builder.received(rs.getLong("received"));
builder.status(Plaintext.Status.valueOf(rs.getString("status")));
builder.labels(findLabels(id));
result.add(builder.build());
}
} catch (IOException | SQLException e) {
LOG.error(e.getMessage(), e);
}
return result;
}
private Collection<Label> findLabels(long messageId) {
List<Label> result = new ArrayList<>();
try {
Statement stmt = getConnection().createStatement();
ResultSet rs = stmt.executeQuery("SELECT \"label\", \"color\" FROM Label WHERE id IN SELECT label_id FROM Message_Label WHERE message_id=" + messageId);
while (rs.next()) {
result.add(new Label(rs.getString("label"), rs.getInt("color")));
}
} catch (SQLException e) {
LOG.error(e.getMessage(), e);
}
return result;
}
@Override
public void save(Plaintext message) {
// save from address if necessary
if (message.getId() == null) {
BitmessageAddress savedAddress = ctx.getAddressRepo().getAddress(message.getFrom().getAddress());
if (savedAddress.getPrivateKey() == null) {
if (savedAddress.getAlias() != null) {
message.getFrom().setAlias(savedAddress.getAlias());
}
ctx.getAddressRepo().save(message.getFrom());
}
}
Connection connection = getConnection();
try {
connection.setAutoCommit(false);
// save message
if (message.getId() == null) {
insert(connection, message);
// remove existing labels
Statement stmt = connection.createStatement();
stmt.executeUpdate("DELETE FROM Message_Label WHERE message_id=" + message.getId());
} else {
update(connection, message);
}
// save labels
PreparedStatement ps = connection.prepareStatement("INSERT INTO Message_Label VALUES (" + message.getId() + ", ?)");
for (Label label : message.getLabels()) {
ps.setLong(1, (Long) label.getId());
ps.executeUpdate();
}
connection.commit();
} catch (IOException | SQLException e) {
try {
connection.rollback();
} catch (SQLException e1) {
LOG.debug(e1.getMessage(), e);
}
throw new RuntimeException(e);
}
}
private void insert(Connection connection, Plaintext message) throws SQLException, IOException {
PreparedStatement ps = connection.prepareStatement(
"INSERT INTO Message (\"from\", \"to\", \"data\", \"sent\", \"received\", \"status\") VALUES (?, ?, ?, ?, ?, ?)", Statement.RETURN_GENERATED_KEYS);
ps.setString(1, message.getFrom().getAddress());
ps.setString(2, message.getTo().getAddress());
writeBlob(ps, 3, message);
ps.setLong(4, message.getSent());
ps.setLong(5, message.getReceived());
ps.setString(6, message.getStatus().name());
ps.executeUpdate();
// get generated id
ResultSet rs = ps.getGeneratedKeys();
rs.next();
message.setId(rs.getLong(1));
}
private void update(Connection connection, Plaintext message) throws SQLException, IOException {
PreparedStatement ps = connection.prepareStatement(
"UPDATE Message SET \"sent\"=?, \"received\"=?, \"status\"=?");
ps.setLong(1, message.getSent());
ps.setLong(2, message.getReceived());
ps.setString(3, message.getStatus().name());
ps.executeUpdate();
}
@Override
public void remove(Plaintext message) {
try {
Statement stmt = getConnection().createStatement();
stmt.executeUpdate("DELETE FROM Message WHERE id = " + message.getId());
} catch (SQLException e) {
LOG.error(e.getMessage(), e);
}
}
@Override
public void setContext(InternalContext context) {
this.ctx = context;
}
}

View File

@ -0,0 +1,95 @@
/*
* Copyright 2015 Christian Basler
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ch.dissem.bitmessage.repository;
import ch.dissem.bitmessage.entity.valueobject.NetworkAddress;
import ch.dissem.bitmessage.ports.NodeRegistry;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.sql.*;
import java.util.LinkedList;
import java.util.List;
import static ch.dissem.bitmessage.utils.Strings.join;
/**
* Created by chris on 24.04.15.
*/
public class JdbcNodeRegistry extends JdbcHelper implements NodeRegistry {
private static final Logger LOG = LoggerFactory.getLogger(JdbcNodeRegistry.class);
@Override
public List<NetworkAddress> getKnownAddresses(int limit, long... streams) {
List<NetworkAddress> result = new LinkedList<>();
try {
Statement stmt = getConnection().createStatement();
ResultSet rs = stmt.executeQuery("SELECT * FROM Node WHERE Stream IN (" + join(streams) + ")");
while (rs.next()) {
// result.add(new NetworkAddress.Builder()
// .ipv6(rs.getBytes("ip"))
// .port(rs.getByte("port"))
// .services(rs.getLong("services"))
// .stream(rs.getLong("stream"))
// .time(rs.getLong("time"))
// .build());
}
} catch (SQLException e) {
LOG.error(e.getMessage(), e);
}
if (result.isEmpty()) {
// FIXME: this is for testing purposes, remove it!
result.add(new NetworkAddress.Builder().ipv4(127, 0, 0, 1).port(8444).build());
}
return result;
}
@Override
public void offerAddresses(List<NetworkAddress> addresses) {
try {
Connection connection = getConnection();
PreparedStatement exists = connection.prepareStatement("SELECT port FROM Node WHERE ip = ? AND port = ? AND stream = ?");
PreparedStatement insert = connection.prepareStatement(
"INSERT INTO Node (ip, port, services, stream, time) VALUES (?, ?, ?, ?, ?)");
PreparedStatement update = connection.prepareStatement(
"UPDATE Node SET services = ?, time = ? WHERE ip = ? AND port = ? AND stream = ?");
for (NetworkAddress node : addresses) {
exists.setBytes(1, node.getIPv6());
exists.setInt(2, node.getPort());
exists.setLong(3, node.getStream());
if (exists.executeQuery().next()) {
update.setLong(1, node.getServices());
update.setLong(2, node.getTime());
update.setBytes(3, node.getIPv6());
update.setInt(4, node.getPort());
update.setLong(5, node.getStream());
update.executeUpdate();
} else {
insert.setBytes(1, node.getIPv6());
insert.setInt(2, node.getPort());
insert.setLong(3, node.getServices());
insert.setLong(4, node.getStream());
insert.setLong(5, node.getTime());
insert.executeUpdate();
}
}
} catch (SQLException e) {
LOG.error(e.getMessage(), e);
}
}
}

View File

@ -0,0 +1,61 @@
/*
* Copyright 2015 Christian Basler
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ch.dissem.bitmessage.repository;
import ch.dissem.bitmessage.entity.ObjectMessage;
import ch.dissem.bitmessage.entity.payload.ObjectType;
import ch.dissem.bitmessage.entity.valueobject.InventoryVector;
import ch.dissem.bitmessage.ports.Inventory;
import sun.reflect.generics.reflectiveObjects.NotImplementedException;
import java.util.LinkedList;
import java.util.List;
/**
* Created by chris on 06.04.15.
*/
public class SimpleInventory implements Inventory {
@Override
public List<InventoryVector> getInventory(long... streams) {
return new LinkedList<>();
}
@Override
public List<InventoryVector> getMissing(List<InventoryVector> offer, long... streams) {
return offer;
}
@Override
public ObjectMessage getObject(InventoryVector vector) {
throw new NotImplementedException();
}
@Override
public List<ObjectMessage> getObjects(long stream, long version, ObjectType type) {
return new LinkedList<>();
}
@Override
public void storeObject(ObjectMessage object) {
throw new NotImplementedException();
}
@Override
public void cleanup() {
throw new NotImplementedException();
}
}

View File

@ -0,0 +1,37 @@
/*
* Copyright 2015 Christian Basler
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ch.dissem.bitmessage.repository;
import ch.dissem.bitmessage.entity.valueobject.NetworkAddress;
import ch.dissem.bitmessage.ports.NodeRegistry;
import java.util.Collections;
import java.util.List;
/**
* Created by chris on 06.04.15.
*/
public class SimpleNodeRegistry implements NodeRegistry {
@Override
public List<NetworkAddress> getKnownAddresses(int limit, long... streams) {
return Collections.singletonList(new NetworkAddress.Builder().ipv4(127, 0, 0, 1).port(8444).build());
}
@Override
public void offerAddresses(List<NetworkAddress> addresses) {
}
}

View File

@ -0,0 +1,9 @@
CREATE TABLE Node (
"ip" BINARY(16) NOT NULL,
"port" INT NOT NULL,
"stream" BIGINT NOT NULL,
"services" BIGINT NOT NULL,
"time" BIGINT NOT NULL,
PRIMARY KEY ("ip", "port", "stream")
);

View File

@ -0,0 +1,8 @@
CREATE TABLE Inventory (
"hash" BINARY(32) NOT NULL PRIMARY KEY,
"stream" BIGINT NOT NULL,
"expires" BIGINT NOT NULL,
"data" BLOB NOT NULL,
"type" BIGINT NOT NULL,
"version" BIGINT NOT NULL
);

View File

@ -0,0 +1,7 @@
CREATE TABLE Address (
"address" VARCHAR(40) NOT NULL PRIMARY KEY,
"alias" VARCHAR(255),
"public_key" BLOB,
"private_key" BLOB,
"subscribed" BIT DEFAULT '0'
);

View File

@ -0,0 +1,32 @@
CREATE TABLE Message (
"id" BIGINT AUTO_INCREMENT PRIMARY KEY,
"from" VARCHAR(40) NOT NULL,
"to" VARCHAR(40) NOT NULL,
"data" BLOB NOT NULL,
"sent" BIGINT,
"received" BIGINT,
"status" VARCHAR(20) NOT NULL
);
CREATE TABLE Label (
"id" BIGINT AUTO_INCREMENT PRIMARY KEY,
"label" VARCHAR(255) NOT NULL,
"color" INT,
"order" BIGINT,
CONSTRAINT UC_label UNIQUE ("label"),
CONSTRAINT UC_order UNIQUE ("order")
);
CREATE TABLE Message_Label (
"message_id" BIGINT NOT NULL,
"label_id" BIGINT NOT NULL,
PRIMARY KEY ("message_id", "label_id"),
FOREIGN KEY ("message_id") REFERENCES Message ("id"),
FOREIGN KEY ("label_id") REFERENCES Label ("id")
);
INSERT INTO Label("label", "order") VALUES ('Inbox', 0);
INSERT INTO Label("label", "order") VALUES ('Sent', 10);
INSERT INTO Label("label", "order") VALUES ('Drafts', 20);
INSERT INTO Label("label", "order") VALUES ('Trash', 100);