All Downloads are FREE. Search and download functionalities are using the official Maven repository.

ch.dissem.bitmessage.repository.JdbcNodeRegistry Maven / Gradle / Ivy

Go to download

A Java implementation of the Bitmessage protocol. This contains JDBC implementations of the repositories.

There is a newer version: 2.0.4
Show newest version
package ch.dissem.bitmessage.repository;

import ch.dissem.bitmessage.entity.valueobject.NetworkAddress;
import ch.dissem.bitmessage.exception.ApplicationException;
import ch.dissem.bitmessage.ports.NodeRegistry;
import ch.dissem.bitmessage.utils.Collections;
import ch.dissem.bitmessage.utils.SqlStrings;
import ch.dissem.bitmessage.utils.Strings;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.sql.*;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;

import static ch.dissem.bitmessage.ports.NodeRegistryHelper.loadStableNodes;
import static ch.dissem.bitmessage.utils.UnixTime.*;

public class JdbcNodeRegistry extends JdbcHelper implements NodeRegistry {
    private static final Logger LOG = LoggerFactory.getLogger(JdbcNodeRegistry.class);
    private Map> stableNodes;

    public JdbcNodeRegistry(JdbcConfig config) {
        super(config);
        cleanUp();
    }

    private void cleanUp() {
        try (
            Connection connection = config.getConnection();
            PreparedStatement ps = connection.prepareStatement(
                "DELETE FROM Node WHERE time getKnownAddresses(int limit, long... streams) {
        List result = new LinkedList<>();
        String query =
            "SELECT stream, address, port, services, time" +
                " FROM Node WHERE stream IN (" + SqlStrings.join(streams) + ")" +
                " ORDER BY TIME DESC" +
                " LIMIT " + limit;
        try (
            Connection connection = config.getConnection();
            Statement stmt = connection.createStatement();
            ResultSet rs = stmt.executeQuery(query)
        ) {
            while (rs.next()) {
                result.add(
                    new NetworkAddress.Builder()
                        .stream(rs.getLong("stream"))
                        .ipv6(rs.getBytes("address"))
                        .port(rs.getInt("port"))
                        .services(rs.getLong("services"))
                        .time(rs.getLong("time"))
                        .build()
                );
            }
        } catch (Exception e) {
            LOG.error(e.getMessage(), e);
            throw new ApplicationException(e);
        }
        if (result.isEmpty()) {
            synchronized (this) {
                if (stableNodes == null) {
                    stableNodes = loadStableNodes();
                }
            }
            for (long stream : streams) {
                Set nodes = stableNodes.get(stream);
                if (nodes != null && !nodes.isEmpty()) {
                    result.add(Collections.selectRandom(nodes));
                }
            }
        }
        return result;
    }

    @Override
    public void offerAddresses(List nodes) {
        cleanUp();
        nodes.stream()
            .filter(node -> node.getTime() < now(+2 * MINUTE) && node.getTime() > now(-28 * DAY))
            .forEach(node -> {
                synchronized (this) {
                    NetworkAddress existing = loadExisting(node);
                    if (existing == null) {
                        insert(node);
                    } else if (node.getTime() > existing.getTime()) {
                        update(node);
                    }
                }
            });
    }

    private void insert(NetworkAddress node) {
        try (
            Connection connection = config.getConnection();
            PreparedStatement ps = connection.prepareStatement(
                "INSERT INTO Node (stream, address, port, services, time) " +
                    "VALUES (?, ?, ?, ?, ?)")
        ) {
            ps.setLong(1, node.getStream());
            ps.setBytes(2, node.getIPv6());
            ps.setInt(3, node.getPort());
            ps.setLong(4, node.getServices());
            ps.setLong(5, node.getTime());
            ps.executeUpdate();
        } catch (SQLException e) {
            LOG.error(e.getMessage(), e);
        }
    }

    private void update(NetworkAddress node) {
        try (
            Connection connection = config.getConnection();
            PreparedStatement ps = connection.prepareStatement(
                "UPDATE Node SET services=?, time=? WHERE stream=? AND address=? AND port=?")
        ) {
            ps.setLong(1, node.getServices());
            ps.setLong(2, node.getTime());
            ps.setLong(3, node.getStream());
            ps.setBytes(4, node.getIPv6());
            ps.setInt(5, node.getPort());
            ps.executeUpdate();
        } catch (SQLException e) {
            LOG.error(e.getMessage(), e);
        }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy