Skip to content
Snippets Groups Projects
Commit c8381c4e authored by Benoit Lavenier's avatar Benoit Lavenier
Browse files

index currency/record : do not store peer (will be stored in ""<currency/name>/peer" later

parent 4cc2ea16
No related branches found
No related tags found
No related merge requests found
Showing
with 402 additions and 102 deletions
......@@ -24,7 +24,6 @@ package org.duniter.core.client.model.elasticsearch;
import org.duniter.core.client.model.bma.BlockchainParameters;
import org.duniter.core.client.model.local.Peer;
import java.io.Serializable;
......@@ -33,24 +32,23 @@ import java.io.Serializable;
*/
public class Currency implements Serializable {
public static final String PROPERTY_CURRENCY_NAME="currencyName";
public static final String PROPERTY_CURRENCY = "currency";
private String currencyName;
private String currency;
private Integer membersCount;
private String firstBlockSignature;
private Long lastUD;
private BlockchainParameters parameters;
private Peer peers[];
private String[] tags;
private String senderPubkey;
private String issuer;
public String getCurrencyName() {
return currencyName;
public String getCurrency() {
return currency;
}
public void setCurrencyName(String currencyName) {
this.currencyName = currencyName;
public void setCurrency(String currency) {
this.currency = currency;
}
public Integer getMembersCount() {
......@@ -85,14 +83,6 @@ public class Currency implements Serializable {
this.parameters = parameters;
}
public Peer[] getPeers() {
return peers;
}
public void setPeers(Peer[] peers) {
this.peers = peers;
}
public String[] getTags() {
return tags;
}
......@@ -101,11 +91,11 @@ public class Currency implements Serializable {
this.tags = tags;
}
public String getSenderPubkey() {
return senderPubkey;
public String getIssuer() {
return issuer;
}
public void setSenderPubkey(String senderPubkey) {
this.senderPubkey = senderPubkey;
public void setIssuer(String issuer) {
this.issuer = issuer;
}
}
\ No newline at end of file
package org.duniter.core.client.model.elasticsearch;
/*
* #%L
* UCoin Java Client :: Core API
* %%
* Copyright (C) 2014 - 2015 EIS
* %%
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public
* License along with this program. If not, see
* <http://www.gnu.org/licenses/gpl-3.0.html>.
* #L%
*/
import java.io.Serializable;
public class Peer implements Serializable {
private String currency;
private String host;
private int port;
private String path;
private String url;
public Peer() {
// default constructor, need for de-serialization
}
public Peer(String host, int port) {
this(host, port, null);
}
public Peer(String host, int port, String path) {
this.host = host;
this.port = port;
this.url = initUrl(host, port, path);
this.path = path;
}
public String getHost() {
return host;
}
public int getPort() {
return port;
}
public String getUrl() {
return url;
}
public String getCurrency() {
return currency;
}
public void setCurrency(String currency) {
this.currency = currency;
}
public void setPort(int port) {
this.port = port;
this.url = initUrl(host, port, path);
}
public void setHost(String host) {
this.host = host;
this.url = initUrl(host, port, path);
}
public String getPath() {
return path;
}
public void setPath(String path) {
this.path = path;
this.url = initUrl(host, port, path);
}
public String toString() {
return new StringBuilder().append(host)
.append(":")
.append(port)
.toString();
}
@Override
public boolean equals(Object o) {
if (o == null) {
return false;
}
if (currency != null && o instanceof Peer) {
if (!currency.equals(((Peer) o).getCurrency())) {
return false;
}
if (!getUrl().equals(((Peer) o).getUrl())) {
return false;
}
}
return super.equals(o);
}
/* -- Internal methods -- */
protected String initUrl(String host, int port, String path) {
return String.format("%s://%s:%s%s",
port == 443 ? "https" : "http",
host, port,
(path != null) ? path : "");
}
}
......@@ -23,6 +23,8 @@ package org.duniter.core.client.model.local;
*/
import com.fasterxml.jackson.annotation.JsonIgnore;
import java.io.Serializable;
public class Peer implements LocalEntity, Serializable {
......
......@@ -152,7 +152,7 @@ public interface BlockchainRemoteService extends Service {
BlockchainParameters getBlockchainParametersFromPeer(Peer peer);
/**
* Retrieve the last block with UD
* Retrieve the last emitted UD (or ud0 if not UD emitted yet)
*
* @param currencyId id of currency
* @return
......@@ -160,7 +160,7 @@ public interface BlockchainRemoteService extends Service {
long getLastUD(long currencyId);
/**
* Retrieve the last block with UD, from a peer
* Retrieve the last emitted UD, from a peer (or ud0 if not UD emitted yet)
*
* @param currencyId id of currency
* @return
......
......@@ -753,7 +753,12 @@ public class BlockchainRemoteServiceImpl extends BaseRemoteServiceImpl implement
return null;
}
String[] blockNumbers = json.substring(startIndex+arrayPrefix.length()+1,endIndex).trim().split(",");
String jsonArrayContent = json.substring(startIndex+arrayPrefix.length(),endIndex).trim();
if (jsonArrayContent.length() == 0) {
return null;
}
String[] blockNumbers = jsonArrayContent.split(",");
try {
int[] result = new int[blockNumbers.length];
......
......@@ -196,7 +196,7 @@ public class CurrencyServiceImpl implements CurrencyService, InitializingBean {
@Override
public Long load(final Long currencyId) {
// Retrieve the last UD from the blockchain
final long lastUD = blockchainRemoteService.getLastUD(currencyId);
final Long lastUD = blockchainRemoteService.getLastUD(currencyId);
// Update currency
Currency currency = getCurrencyById(currencyId);
......
......@@ -131,6 +131,16 @@ public class BlockchainRemoteServiceTest {
}
@Test
public void getLastUD() throws Exception {
Peer peer = createTestPeer();
// Get the last UD
BlockchainRemoteService blockchainRemoteService = ServiceLocator.instance().getBlockchainRemoteService();
long lastUD = blockchainRemoteService.getLastUD(peer);
}
@Test
public void addNewBlockListener() throws Exception {
......
#duniter4j.node.host=metab.ucoin.io
#duniter4j.node.host=metab.ucoin.fr
duniter4j.node.host=test-net.duniter.fr
duniter4j.node.port=9201
#duniter4j.node.host=cgeek.fr
#duniter4j.node.port=9330
duniter4j.node.host=gtest.duniter.fr
duniter4j.node.port=10900
duniter4j.node.elasticsearch.host=localhost
duniter4j.node.elasticsearch.port=9200
#duniter4j.node.elasticsearch.rest.host=www.data.ucoin.fr
#duniter4j.node.elasticsearch.rest.port=80
......@@ -125,8 +125,8 @@ duniter.blockchain.sync.enable: true
#
# Duniter node to synchronize
#
duniter.host: cgeek.fr
duniter.port: 9330
duniter.host: gtest.duniter.org
duniter.port: 10900
#
# ---------------------------------- Duniter4j security -------------------------
#
......@@ -172,7 +172,7 @@ duniter.mail.enable: false
#
# Mail subject prefix
#
#duniter.mail.subject.prefix: [Duniter4j ES]
#duniter.mail.subject.prefix: '[Duniter4j ES]'
duniter.changes.listenSource: '*/block'
duniter.ws.port: 9400
......@@ -15,14 +15,14 @@
# Use a descriptive name for your cluster:
#
# cluster.name: my-application
cluster.name: duniter4j-elasticsearch-TEST
cluster.name: gtest-duniter-es
#
# ------------------------------------ Node ------------------------------------
#
#
# Use a descriptive name for the node:
#
# node.name: node-1
node.name: EIS-DEV
#
# Add custom attributes to the node:
#
......@@ -126,13 +126,10 @@ duniter.blockchain.sync.enable: true
#
# Duniter node to synchronize
#
#duniter.host: cgeek.fr
#duniter.port: 9330
#duniter.host: test-net.duniter.fr
duniter.host: 192.168.0.5
duniter.port: 9201
#duniter.host: 192.168.0.28
#duniter.port: 21378
duniter.host: gtest.duniter.fr
duniter.port: 10900
#
# ---------------------------------- Duniter4j security -------------------------
#
......@@ -156,27 +153,27 @@ duniter.security.enable: true
#
# Should synchronize data using P2P
#
duniter.data.sync.enable: true
duniter.data.sync.host: data.duniter.fr
duniter.data.sync.port: 80
duniter.data.sync.enable: false
#duniter.data.sync.host: data.duniter.fr
#duniter.data.sync.port: 80
# ---------------------------------- Duniter4j SMTP server -------------------------
#
# SMTP server configuration (host and port)
#
#duniter.mail.enable: false
duniter.mail.enable: false
#duniter.mail.smtp.host: localhost
#duniter.mail.smtp.port: 25
#
# Mail 'from' address
#
#duniter.mail.from: no-reply@domain.com
duniter.mail.from: root@EIS-DEV
#duniter.mail.from: root@EIS-DEV
#
# Mail: admin address
#
#duniter.mail.admin: user@domain.com
duniter.mail.admin: blavenie@EIS-DEV
#duniter.mail.admin: blavenie@EIS-DEV
#
# Mail subject prefix
#
......
......@@ -118,8 +118,11 @@ public class PluginInit extends AbstractLifecycleComponent<PluginInit> {
// Add access to currency index
injector.getInstance(RestSecurityController.class).allowIndexType(RestRequest.Method.GET,
currency.getCurrencyName(),
currency.getCurrency(),
BlockchainService.BLOCK_TYPE);
injector.getInstance(RestSecurityController.class).allowIndexType(RestRequest.Method.GET,
currency.getCurrency(),
BlockchainService.PEER_TYPE);
// Index blocks (and listen if new block appear)
injector.getInstance(BlockchainService.class)
......
......@@ -24,7 +24,6 @@ package org.duniter.elasticsearch.model;
import org.duniter.core.client.model.bma.BlockchainParameters;
import org.duniter.core.client.model.local.Peer;
import java.io.Serializable;
......@@ -33,22 +32,23 @@ import java.io.Serializable;
*/
public class Currency implements Serializable {
private String currencyName;
public static final String PROPERTY_CURRENCY = "currency";
private String currency;
private Integer membersCount;
private String firstBlockSignature;
private Long lastUD;
private BlockchainParameters parameters;
private Peer peers[];
private String[] tags;
private String senderPubkey;
private String issuer;
public String getCurrencyName() {
return currencyName;
public String getCurrency() {
return currency;
}
public void setCurrencyName(String currencyName) {
this.currencyName = currencyName;
public void setCurrency(String currency) {
this.currency = currency;
}
public Integer getMembersCount() {
......@@ -83,14 +83,6 @@ public class Currency implements Serializable {
this.parameters = parameters;
}
public Peer[] getPeers() {
return peers;
}
public void setPeers(Peer[] peers) {
this.peers = peers;
}
public String[] getTags() {
return tags;
}
......@@ -99,11 +91,11 @@ public class Currency implements Serializable {
this.tags = tags;
}
public String getSenderPubkey() {
return senderPubkey;
public String getIssuer() {
return issuer;
}
public void setSenderPubkey(String senderPubkey) {
this.senderPubkey = senderPubkey;
public void setIssuer(String issuer) {
this.issuer = issuer;
}
}
\ No newline at end of file
package org.duniter.elasticsearch.model;
import java.io.Serializable;
public class Peer implements Serializable {
private String currency;
private String host;
private int port;
private String path;
private String url;
public Peer() {
// default constructor, need for de-serialization
}
public Peer(String host, int port) {
this(host, port, null);
}
public Peer(String host, int port, String path) {
this.host = host;
this.port = port;
this.url = initUrl(host, port, path);
this.path = path;
}
public String getHost() {
return host;
}
public int getPort() {
return port;
}
public String getUrl() {
return url;
}
public String getCurrency() {
return currency;
}
public void setCurrency(String currency) {
this.currency = currency;
}
public void setPort(int port) {
this.port = port;
this.url = initUrl(host, port, path);
}
public void setHost(String host) {
this.host = host;
this.url = initUrl(host, port, path);
}
public String getPath() {
return path;
}
public void setPath(String path) {
this.path = path;
this.url = initUrl(host, port, path);
}
public String toString() {
return new StringBuilder().append(host)
.append(":")
.append(port)
.toString();
}
@Override
public boolean equals(Object o) {
if (o == null) {
return false;
}
if (currency != null && o instanceof Peer) {
if (!currency.equals(((Peer) o).getCurrency())) {
return false;
}
if (!getUrl().equals(((Peer) o).getUrl())) {
return false;
}
}
return super.equals(o);
}
/* -- Internal methods -- */
protected String initUrl(String host, int port, String path) {
return String.format("%s://%s:%s%s",
port == 443 ? "https" : "http",
host, port,
(path != null) ? path : "");
}
}
......@@ -31,9 +31,9 @@ import com.google.common.collect.Lists;
import org.duniter.core.client.model.bma.BlockchainBlock;
import org.duniter.core.client.model.bma.BlockchainParameters;
import org.duniter.core.client.model.bma.EndpointProtocol;
import org.duniter.core.client.model.local.Peer;
import org.duniter.core.util.json.JsonAttributeParser;
import org.duniter.core.client.model.bma.jackson.JacksonUtils;
import org.duniter.core.client.model.local.Peer;
import org.duniter.core.client.service.bma.BlockchainRemoteService;
import org.duniter.core.client.service.bma.NetworkRemoteService;
import org.duniter.core.client.service.exception.BlockNotFoundException;
......@@ -82,6 +82,7 @@ import java.util.*;
public class BlockchainService extends AbstractService {
public static final String BLOCK_TYPE = "block";
public static final String PEER_TYPE = "peer";
public static final String CURRENT_BLOCK_ID = "current";
private static final int SYNC_MISSING_BLOCK_MAX_RETRY = 5;
......@@ -292,7 +293,8 @@ public class BlockchainService extends AbstractService {
//.put("analyzer", createDefaultAnalyzer())
.build();
createIndexRequestBuilder.setSettings(indexSettings);
createIndexRequestBuilder.addMapping(BLOCK_TYPE, createBlockType());
createIndexRequestBuilder.addMapping(BLOCK_TYPE, createBlockTypeMapping());
createIndexRequestBuilder.addMapping(PEER_TYPE, createPeerTypeMapping());
createIndexRequestBuilder.execute().actionGet();
}
......@@ -620,7 +622,7 @@ public class BlockchainService extends AbstractService {
/* -- Internal methods -- */
public XContentBuilder createBlockType() {
public XContentBuilder createBlockTypeMapping() {
try {
XContentBuilder mapping = XContentFactory.jsonBuilder()
.startObject()
......@@ -637,6 +639,12 @@ public class BlockchainService extends AbstractService {
.field("type", "string")
.endObject()
// issuer
.startObject("issuer")
.field("type", "string")
.field("index", "not_analyzed")
.endObject()
// previous hash
.startObject("previousHash")
.field("type", "string")
......@@ -652,9 +660,19 @@ public class BlockchainService extends AbstractService {
.field("type", "string")
.endObject()
// unitbase
.startObject("unitbase")
.field("type", "integer")
.endObject()
// membersChanges
.startObject("monetaryMass")
.field("type", "string")
.field("type", "long")
.endObject()
// dividend
.startObject("dividend")
.field("type", "integer")
.endObject()
// identities:
......@@ -671,6 +689,35 @@ public class BlockchainService extends AbstractService {
}
}
public XContentBuilder createPeerTypeMapping() {
try {
XContentBuilder mapping = XContentFactory.jsonBuilder()
.startObject()
.startObject(PEER_TYPE)
.startObject("properties")
// currency
.startObject("currency")
.field("type", "string")
.endObject()
// pubkey
.startObject("pubkey")
.field("type", "string")
.field("index", "not_analyzed")
.endObject()
.endObject()
.endObject().endObject();
return mapping;
}
catch(IOException ioe) {
throw new TechnicalException("Error while getting mapping for block index: " + ioe.getMessage(), ioe);
}
}
public BlockchainBlock getBlockByIdStr(String currencyName, String blockId) {
// Prepare request
......
......@@ -69,6 +69,7 @@ public class CurrencyService extends AbstractService {
public static final String INDEX = "currency";
public static final String RECORD_TYPE = "record";
public static final String PEER_TYPE = "peer";
private final ObjectMapper objectMapper;
private BlockchainRemoteService blockchainRemoteService;
......@@ -112,7 +113,7 @@ public class CurrencyService extends AbstractService {
//.put("analyzer", createDefaultAnalyzer())
.build();
createIndexRequestBuilder.setSettings(indexSettings);
createIndexRequestBuilder.addMapping(RECORD_TYPE, createCurrencyType());
createIndexRequestBuilder.addMapping(RECORD_TYPE, createRecordTypeMapping());
createIndexRequestBuilder.execute().actionGet();
return this;
......@@ -181,19 +182,20 @@ public class CurrencyService extends AbstractService {
BlockchainParameters parameters = blockchainRemoteService.getParameters(peer);
BlockchainBlock firstBlock = blockchainRemoteService.getBlock(peer, 0l);
BlockchainBlock currentBlock = blockchainRemoteService.getCurrentBlock(peer);
long lastUD = blockchainRemoteService.getLastUD(peer);
Long lastUD = blockchainRemoteService.getLastUD(peer);
Currency result = new Currency();
result.setCurrencyName(parameters.getCurrency());
result.setCurrency(parameters.getCurrency());
result.setFirstBlockSignature(firstBlock.getSignature());
result.setMembersCount(currentBlock.getMembersCount());
result.setLastUD(lastUD);
result.setParameters(parameters);
result.setPeers(new Peer[]{peer});
indexCurrency(result);
indexPeer(parameters.getCurrency(), peer);
return result;
}
......@@ -203,11 +205,11 @@ public class CurrencyService extends AbstractService {
*/
public void indexCurrency(Currency currency) {
try {
org.duniter.core.util.Preconditions.checkNotNull(currency.getCurrencyName());
Preconditions.checkNotNull(currency.getCurrency());
// Fill tags
if (ArrayUtils.isEmpty(currency.getTags())) {
String currencyName = currency.getCurrencyName();
String currencyName = currency.getCurrency();
String[] tags = currencyName.split(REGEX_WORD_SEPARATOR);
List<String> tagsList = Lists.newArrayList(tags);
......@@ -225,7 +227,7 @@ public class CurrencyService extends AbstractService {
// Preparing indexBlocksFromNode
IndexRequestBuilder indexRequest = client.prepareIndex(INDEX, RECORD_TYPE)
.setId(currency.getCurrencyName())
.setId(currency.getCurrency())
.setSource(json);
// Execute indexBlocksFromNode
......@@ -238,6 +240,27 @@ public class CurrencyService extends AbstractService {
}
}
public String indexPeer(String currency, Peer peer) {
Preconditions.checkNotNull(currency);
Preconditions.checkNotNull(peer);
try {
// Serialize into JSON
byte[] json = objectMapper.writeValueAsBytes(peer);
// Preparing index
IndexRequestBuilder indexRequest = client.prepareIndex(currency, PEER_TYPE)
.setSource(json);
// Execute index
return indexRequest
.setRefresh(true)
.execute().actionGet().getId();
} catch(JsonProcessingException e) {
throw new TechnicalException(e);
}
}
/**
* Get suggestions from a string query. Useful for web autocomplete field (e.g. text full search)
* @param query
......@@ -264,20 +287,20 @@ public class CurrencyService extends AbstractService {
/**
* Save a blockchain (update or create) into the blockchain index.
* @param currency
* @param senderPubkey
* @param issuer
* @throws DuplicateIndexIdException
* @throws AccessDeniedException if exists and user if not the original blockchain sender
*/
public void saveCurrency(Currency currency, String senderPubkey) throws DuplicateIndexIdException {
public void saveCurrency(Currency currency, String issuer) throws DuplicateIndexIdException {
Preconditions.checkNotNull(currency, "currency could not be null") ;
Preconditions.checkNotNull(currency.getCurrencyName(), "currency attribute 'currencyName' could not be null");
Preconditions.checkNotNull(currency.getCurrency(), "currency attribute 'currency' could not be null");
String previousSenderPubkey = getSenderPubkeyByCurrencyId(currency.getCurrencyName());
String previousIssuer = getSenderPubkeyByCurrencyId(currency.getCurrency());
// Currency not exists, so create it
if (previousSenderPubkey == null) {
if (previousIssuer == null) {
// make sure to fill the sender
currency.setSenderPubkey(senderPubkey);
currency.setIssuer(issuer);
// Save it
indexCurrency(currency);
......@@ -285,12 +308,12 @@ public class CurrencyService extends AbstractService {
// Exists, so check the owner signature
else {
if (!Objects.equals(senderPubkey, previousSenderPubkey)) {
if (!Objects.equals(issuer, previousIssuer)) {
throw new AccessDeniedException("Could not change the currency, because it has been registered by another public key.");
}
// Make sure the sender is not changed
currency.setSenderPubkey(previousSenderPubkey);
currency.setIssuer(previousIssuer);
// Save changes
indexCurrency(currency);
......@@ -319,7 +342,7 @@ public class CurrencyService extends AbstractService {
try {
currency = objectMapper.readValue(jsonCurrency, Currency.class);
Preconditions.checkNotNull(currency);
Preconditions.checkNotNull(currency.getCurrencyName());
Preconditions.checkNotNull(currency.getCurrency());
} catch(Throwable t) {
logger.error("Error while reading blockchain JSON: " + jsonCurrency);
throw new TechnicalException("Error while reading blockchain JSON: " + jsonCurrency, t);
......@@ -330,14 +353,20 @@ public class CurrencyService extends AbstractService {
/* -- Internal methods -- */
public XContentBuilder createCurrencyType() {
public XContentBuilder createRecordTypeMapping() {
try {
XContentBuilder mapping = XContentFactory.jsonBuilder().startObject().startObject(RECORD_TYPE)
.startObject("properties")
// blockchain name
.startObject("currencyName")
// currency
.startObject("currency")
.field("type", "string")
.endObject()
// firstBlockSignature
.startObject("firstBlockSignature")
.field("type", "string")
.field("index", "not_analyzed")
.endObject()
// member count
......@@ -345,6 +374,22 @@ public class CurrencyService extends AbstractService {
.field("type", "long")
.endObject()
// lastUD
.startObject("lastUD")
.field("type", "long")
.endObject()
// unitbase
.startObject("unitbase")
.field("type", "integer")
.endObject()
// issuer
.startObject("issuer")
.field("type", "string")
.field("index", "not_analyzed")
.endObject()
// tags
.startObject("tags")
.field("type", "completion")
......@@ -392,10 +437,10 @@ public class CurrencyService extends AbstractService {
for (SearchHit searchHit : searchHits) {
if (searchHit.source() != null) {
Currency currency = objectMapper.readValue(new String(searchHit.source(), "UTF-8"), Currency.class);
return currency.getSenderPubkey();
return currency.getIssuer();
}
else {
SearchHitField field = searchHit.getFields().get("senderPubkey");
SearchHitField field = searchHit.getFields().get("issuer");
return field.getValue().toString();
}
}
......
duniter.event.NODE_BMA_DOWN=Duniter node [%1$s\:%2$s] is DOWN: no access from ES node [%3$s]. Last connexion at %4$d. Blockchain indexation waiting.
duniter.event.NODE_BMA_DOWN=Duniter node [%1$s\:%2$s] is DOWN\: no access from ES node [%3$s]. Last connexion at %4$d. Blockchain indexation waiting.
duniter.event.NODE_BMA_UP=Duniter node [%1$s\:%2$s] is UP again.
duniter.event.NODE_STARTED=Node started on cluster Duniter4j ES [%s]
duniter.user.event.active=
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment