Skip to content
This repository was archived by the owner on Apr 22, 2025. It is now read-only.

Commit c4957fd

Browse files
FAB-5632 Implement Network Config
Change-Id: I49617d84bea3b5d5654aa6f7abc5ae880b8d8d56 Signed-off-by: Chris Murphy <chrism@fast.au.fujitsu.com>
1 parent bf94912 commit c4957fd

File tree

17 files changed

+3306
-137
lines changed

17 files changed

+3306
-137
lines changed

src/main/java/org/hyperledger/fabric/sdk/Channel.java

Lines changed: 122 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
import java.util.Arrays;
2828
import java.util.Collection;
2929
import java.util.Collections;
30+
import java.util.EnumSet;
3031
import java.util.HashMap;
3132
import java.util.HashSet;
3233
import java.util.LinkedHashMap;
@@ -35,7 +36,6 @@
3536
import java.util.Map;
3637
import java.util.Objects;
3738
import java.util.Set;
38-
import java.util.Vector;
3939
import java.util.concurrent.BlockingQueue;
4040
import java.util.concurrent.CompletableFuture;
4141
import java.util.concurrent.ExecutionException;
@@ -87,6 +87,7 @@
8787
import org.hyperledger.fabric.protos.peer.Query.ChaincodeQueryResponse;
8888
import org.hyperledger.fabric.protos.peer.Query.ChannelQueryResponse;
8989
import org.hyperledger.fabric.sdk.BlockEvent.TransactionEvent;
90+
import org.hyperledger.fabric.sdk.Peer.PeerRole;
9091
import org.hyperledger.fabric.sdk.exception.CryptoException;
9192
import org.hyperledger.fabric.sdk.exception.EventHubException;
9293
import org.hyperledger.fabric.sdk.exception.InvalidArgumentException;
@@ -138,7 +139,18 @@ public class Channel implements Serializable {
138139
private final String name;
139140

140141
// The peers on this channel to which the client can connect
141-
final Collection<Peer> peers = new Vector<>();
142+
private final Collection<Peer> peers = Collections.synchronizedSet(new HashSet<>());
143+
// final Set<Peer> eventingPeers = Collections.synchronizedSet(new HashSet<>());
144+
145+
private final Map<PeerRole, Set<Peer>> peerRoleSetMap = Collections.synchronizedMap(new HashMap<>());
146+
147+
{
148+
for (Peer.PeerRole peerRole : PeerRole.ALL) {
149+
150+
peerRoleSetMap.put(peerRole, Collections.synchronizedSet(new HashSet<>()));
151+
152+
}
153+
}
142154

143155
// Temporary variables to control how long to wait for deploy and invoke to complete before
144156
// emitting events. This will be removed when the SDK is able to receive events from the
@@ -507,6 +519,66 @@ public String getName() {
507519
*/
508520
public Channel addPeer(Peer peer) throws InvalidArgumentException {
509521

522+
return addPeer(peer, PeerOptions.create());
523+
524+
}
525+
526+
/**
527+
* Options for the peer.
528+
* <p>
529+
* Note: This code pasted from: https://gerrit.hyperledger.org/r/#/c/13895/ - WIP FAB-6066 Channelservice for events
530+
*/
531+
public static class PeerOptions { // allows for future options with less likelihood of breaking api.
532+
533+
private EnumSet<PeerRole> peerRoles;
534+
private String blockType = "Filter"; // not yet used.
535+
536+
private PeerOptions() {
537+
538+
}
539+
540+
EnumSet<PeerRole> getPeerRoles() {
541+
if (peerRoles == null) {
542+
return PeerRole.ALL;
543+
}
544+
return peerRoles;
545+
}
546+
547+
String getBlockType() {
548+
return blockType;
549+
}
550+
551+
public PeerOptions setPeerRoles(EnumSet<PeerRole> peerRoles) {
552+
this.peerRoles = peerRoles;
553+
return this;
554+
}
555+
556+
public PeerOptions addPeerRole(PeerRole peerRole) {
557+
558+
if (peerRoles == null) {
559+
peerRoles = EnumSet.noneOf(PeerRole.class);
560+
561+
}
562+
peerRoles.add(peerRole);
563+
return this;
564+
}
565+
566+
public static PeerOptions create() {
567+
return new PeerOptions();
568+
}
569+
570+
}
571+
572+
/**
573+
* Add a peer to the channel
574+
*
575+
* @param peer The Peer to add.
576+
* @param peerOptions see {@link PeerRole}
577+
* @return Channel The current channel added.
578+
* @throws InvalidArgumentException
579+
*/
580+
public Channel addPeer(Peer peer, PeerOptions peerOptions) throws InvalidArgumentException {
581+
510582
if (shutdown) {
511583
throw new InvalidArgumentException(format("Channel %s has been shutdown.", name));
512584
}
@@ -515,14 +587,32 @@ public Channel addPeer(Peer peer) throws InvalidArgumentException {
515587
throw new InvalidArgumentException("Peer is invalid can not be null.");
516588
}
517589

590+
if (peer.getChannel() != null && peer.getChannel() != this) {
591+
throw new InvalidArgumentException(format("Peer already connected to channel %s", peer.getChannel().getName()));
592+
}
593+
594+
if (null == peerOptions) {
595+
throw new InvalidArgumentException("Peer is invalid can not be null.");
596+
}
597+
518598
peer.setChannel(this);
519599

520600
peers.add(peer);
521601

602+
for (Map.Entry<PeerRole, Set<Peer>> peerRole : peerRoleSetMap.entrySet()) {
603+
if (peerOptions.getPeerRoles().contains(peerRole.getKey())) {
604+
peerRole.getValue().add(peer);
605+
}
606+
}
522607
return this;
523608
}
524609

610+
525611
public Channel joinPeer(Peer peer) throws ProposalException {
612+
return joinPeer(peer, PeerOptions.create());
613+
}
614+
615+
public Channel joinPeer(Peer peer, PeerOptions peerOptions) throws ProposalException {
526616

527617
logger.debug(format("Channel %s joining peer %s, url: %s", name, peer.getName(), peer.getUrl()));
528618

@@ -558,7 +648,7 @@ public Channel joinPeer(Peer peer) throws ProposalException {
558648
SignedProposal signedProposal = getSignedProposal(transactionContext, joinProposal);
559649
logger.debug("Got signed proposal.");
560650

561-
addPeer(peer); //need to add peer.
651+
addPeer(peer, peerOptions); //need to add peer.
562652

563653
Collection<ProposalResponse> resp = sendProposalToPeers(new ArrayList<>(Collections.singletonList(peer)),
564654
signedProposal, transactionContext);
@@ -568,27 +658,33 @@ public Channel joinPeer(Peer peer) throws ProposalException {
568658
if (pro.getStatus() == ProposalResponse.Status.SUCCESS) {
569659
logger.info(format("Peer %s joined into channel %s", peer.getName(), name));
570660
} else {
571-
peers.remove(peer);
572-
peer.unsetChannel();
661+
removePeer(peer);
573662
throw new ProposalException(format("Join peer to channel %s failed. Status %s, details: %s",
574663
name, pro.getStatus().toString(), pro.getMessage()));
575664

576665
}
577666
} catch (ProposalException e) {
578-
peers.remove(peer);
579-
peer.unsetChannel();
667+
removePeer(peer);
580668
logger.error(e);
581669
throw e;
582670
} catch (Exception e) {
583671
peers.remove(peer);
584-
peer.unsetChannel();
585672
logger.error(e);
586673
throw new ProposalException(e.getMessage(), e);
587674
}
588675

589676
return this;
590677
}
591678

679+
private void removePeer(Peer peer) {
680+
peers.remove(peer);
681+
682+
for (Set<Peer> peerRoleSet : peerRoleSetMap.values()) {
683+
peerRoleSet.remove(peer);
684+
}
685+
peer.unsetChannel();
686+
}
687+
592688
/**
593689
* Add an Orderer to this channel.
594690
*
@@ -648,6 +744,21 @@ public Collection<Peer> getPeers() {
648744
return Collections.unmodifiableCollection(peers);
649745
}
650746

747+
/**
748+
* Get the peers for this channel.
749+
*
750+
* @return the peers.
751+
*/
752+
public Collection<Peer> getPeers(EnumSet<PeerRole> roles) {
753+
754+
Set<Peer> ret = new HashSet<>(getPeers().size());
755+
756+
for (PeerRole peerRole : roles) {
757+
ret.addAll(peerRoleSetMap.get(peerRole));
758+
}
759+
return Collections.unmodifiableCollection(ret);
760+
}
761+
651762
/**
652763
* Get the deploy wait time in seconds.
653764
*
@@ -2155,11 +2266,12 @@ public Collection<ProposalResponse> sendTransactionProposal(TransactionProposalR
21552266
* @throws InvalidArgumentException
21562267
* @throws ProposalException
21572268
*/
2158-
21592269
public Collection<ProposalResponse> queryByChaincode(QueryByChaincodeRequest queryByChaincodeRequest) throws InvalidArgumentException, ProposalException {
2160-
return sendProposal(queryByChaincodeRequest, peers);
2270+
return queryByChaincode(queryByChaincodeRequest, peers);
21612271
}
21622272

2273+
2274+
21632275
/**
21642276
* Send Query proposal
21652277
*

src/main/java/org/hyperledger/fabric/sdk/HFClient.java

Lines changed: 34 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
import org.hyperledger.fabric.protos.peer.Query.ChaincodeInfo;
3737
import org.hyperledger.fabric.sdk.exception.CryptoException;
3838
import org.hyperledger.fabric.sdk.exception.InvalidArgumentException;
39+
import org.hyperledger.fabric.sdk.exception.NetworkConfigurationException;
3940
import org.hyperledger.fabric.sdk.exception.ProposalException;
4041
import org.hyperledger.fabric.sdk.exception.TransactionException;
4142
import org.hyperledger.fabric.sdk.helper.Utils;
@@ -115,6 +116,35 @@ public static HFClient createNewInstance() {
115116
return new HFClient();
116117
}
117118

119+
/**
120+
* Configures a channel based on information loaded from a Network Config file.
121+
* Note that it is up to the caller to initialize the returned channel.
122+
*
123+
* @param channelName The name of the channel to be configured
124+
* @param networkConfig The network configuration to use to configure the channel
125+
* @return The configured channel, or null if the channel is not defined in the configuration
126+
* @throws InvalidArgumentException
127+
*/
128+
public Channel loadChannelFromConfig(String channelName, NetworkConfig networkConfig) throws InvalidArgumentException, NetworkConfigurationException {
129+
clientCheck();
130+
131+
// Sanity checks
132+
if (channelName == null || channelName.isEmpty()) {
133+
throw new InvalidArgumentException("channelName must be specified");
134+
}
135+
136+
if (networkConfig == null) {
137+
throw new InvalidArgumentException("networkConfig must be specified");
138+
}
139+
140+
if (channels.containsKey(channelName)) {
141+
throw new InvalidArgumentException(format("Channel with name %s already exists", channelName));
142+
}
143+
144+
return networkConfig.loadChannel(this, channelName);
145+
}
146+
147+
118148
/**
119149
* newChannel - already configured channel.
120150
*
@@ -132,7 +162,7 @@ public Channel newChannel(String name) throws InvalidArgumentException {
132162
synchronized (channels) {
133163

134164
if (channels.containsKey(name)) {
135-
throw new InvalidArgumentException(format("Channel by the name %s already exits", name));
165+
throw new InvalidArgumentException(format("Channel by the name %s already exists", name));
136166
}
137167
logger.trace("Creating channel :" + name);
138168
Channel newChannel = Channel.createNewInstance(name, this);
@@ -303,8 +333,8 @@ public Peer newPeer(String name, String grpcURL) throws InvalidArgumentException
303333
/**
304334
* getChannel by name
305335
*
306-
* @param name
307-
* @return a channel
336+
* @param name The channel name
337+
* @return a channel (or null if the channel does not exist)
308338
*/
309339

310340
public Channel getChannel(String name) {
@@ -611,6 +641,7 @@ public Collection<ProposalResponse> sendInstallProposal(InstallProposalRequest i
611641

612642
}
613643

644+
614645
private void clientCheck() throws InvalidArgumentException {
615646

616647
if (null == cryptoSuite) {

0 commit comments

Comments
 (0)