/******************************************************************************
* Copyright © 2013-2016 The Nxt Core Developers. *
* *
* See the AUTHORS.txt, DEVELOPER-AGREEMENT.txt and LICENSE.txt files at *
* the top-level directory of this distribution for the individual copyright *
* holder information and the developer policies on copyright and licensing. *
* *
* Unless otherwise agreed in a custom licensing agreement, no part of the *
* Nxt software, including this file, may be copied, modified, propagated, *
* or distributed except according to the terms contained in the LICENSE.txt *
* file. *
* *
* Removal or modification of this copyright notice is prohibited. *
* *
******************************************************************************/
package nxt;
import nxt.db.DbIterator;
import nxt.db.DbKey;
import nxt.db.VersionedEntityDbTable;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
public class Hub {
public static class Hit implements Comparable<Hit> {
public final Hub hub;
public final long hitTime;
private Hit(Hub hub, long hitTime) {
this.hub = hub;
this.hitTime = hitTime;
}
@Override
public int compareTo(Hit hit) {
if (this.hitTime < hit.hitTime) {
return -1;
} else if (this.hitTime > hit.hitTime) {
return 1;
} else {
return Long.compare(this.hub.accountId, hit.hub.accountId);
}
}
}
private static final DbKey.LongKeyFactory<Hub> hubDbKeyFactory = null;
private static final VersionedEntityDbTable<Hub> hubTable = null;
static void addOrUpdateHub(Transaction transaction, Attachment.MessagingHubAnnouncement attachment) {
hubTable.insert(new Hub(transaction, attachment));
}
private static long lastBlockId;
private static List<Hit> lastHits;
public static List<Hit> getHubHits(Block block) {
synchronized (Hub.class) {
if (block.getId() == lastBlockId && lastHits != null) {
return lastHits;
}
List<Hit> currentHits = new ArrayList<>();
long currentLastBlockId;
BlockchainImpl.getInstance().readLock();
try {
currentLastBlockId = BlockchainImpl.getInstance().getLastBlock().getId();
if (currentLastBlockId != block.getId()) {
return Collections.emptyList();
}
try (DbIterator<Hub> hubs = hubTable.getAll(0, -1)) {
while (hubs.hasNext()) {
Hub hub = hubs.next();
Account account = Account.getAccount(hub.getAccountId());
if (account != null && account.getEffectiveBalanceNXT(block.getHeight()) >= Constants.MIN_HUB_EFFECTIVE_BALANCE
&& account.getPublicKey() != null) {
currentHits.add(new Hit(hub, Generator.getHitTime(account, block)));
}
}
}
} finally {
BlockchainImpl.getInstance().readUnlock();
}
Collections.sort(currentHits);
lastHits = currentHits;
lastBlockId = currentLastBlockId;
}
return lastHits;
}
static void init() {}
private final long accountId;
private final DbKey dbKey;
private final long minFeePerByteNQT;
private final List<String> uris;
private Hub(Transaction transaction, Attachment.MessagingHubAnnouncement attachment) {
this.accountId = transaction.getSenderId();
this.dbKey = hubDbKeyFactory.newKey(this.accountId);
this.minFeePerByteNQT = attachment.getMinFeePerByteNQT();
this.uris = Collections.unmodifiableList(Arrays.asList(attachment.getUris()));
}
private Hub(ResultSet rs) throws SQLException {
this.accountId = rs.getLong("account_id");
this.dbKey = hubDbKeyFactory.newKey(this.accountId);
this.minFeePerByteNQT = rs.getLong("min_fee_per_byte");
this.uris = Collections.unmodifiableList(Arrays.asList((String[])rs.getObject("uris")));
}
private void save(Connection con) throws SQLException {
try (PreparedStatement pstmt = con.prepareStatement("MERGE INTO hub (account_id, min_fee_per_byte, "
+ "uris, height, latest) KEY (account_id, height) VALUES (?, ?, ?, ?, TRUE)")) {
int i = 0;
pstmt.setLong(++i, this.getAccountId());
pstmt.setLong(++i, this.getMinFeePerByteNQT());
pstmt.setObject(++i, this.getUris().toArray(new String[this.getUris().size()]));
pstmt.setInt(++i, Nxt.getBlockchain().getHeight());
pstmt.executeUpdate();
}
}
public long getAccountId() {
return accountId;
}
public long getMinFeePerByteNQT() {
return minFeePerByteNQT;
}
public List<String> getUris() {
return uris;
}
}