/*
* Copyright (C) 2015 hops.io.
*
* 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 io.hops.leader_election.node;
import io.hops.leader_election.proto.ActiveNodeProtos.ActiveNodeProto;
import io.hops.leader_election.proto.ActiveNodeProtos.SortedActiveNodeListProto;
import io.hops.leader_election.proto.ActiveNodeProtos.SortedActiveNodeListProtoOrBuilder;
import java.net.InetSocketAddress;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Random;
//TODO change it to avoid going through the proto when it is not needed
public class SortedActiveNodeListPBImpl implements SortedActiveNodeList {
SortedActiveNodeListProto proto =
SortedActiveNodeListProto.getDefaultInstance();
SortedActiveNodeListProto.Builder builder = null;
boolean viaProto = false;
Random random = new Random();
public SortedActiveNodeListPBImpl(SortedActiveNodeListProto proto) {
this.proto = proto;
viaProto = true;
}
public SortedActiveNodeListPBImpl(List<ActiveNode> listActiveNodes) {
if (listActiveNodes == null) {
throw new NullPointerException("List of active namenodes was null");
}
maybeInitBuilder();
for (ActiveNode node : listActiveNodes) {
builder.addActiveNode(((ActiveNodePBImpl) node).getProto());
}
}
public SortedActiveNodeListProto getProto() {
mergeLocalToProto();
proto = viaProto ? proto : builder.build();
viaProto = true;
return proto;
}
private void mergeLocalToProto() {
if (viaProto) {
maybeInitBuilder();
}
proto = builder.build();
viaProto = true;
}
private void maybeInitBuilder() {
if (viaProto || builder == null) {
builder = SortedActiveNodeListProto.newBuilder(proto);
}
viaProto = false;
}
@Override
public int size() {
SortedActiveNodeListProtoOrBuilder p = viaProto ? proto : builder;
return p.getActiveNodeCount();
}
@Override
public boolean isEmpty() {
SortedActiveNodeListProtoOrBuilder p = viaProto ? proto : builder;
return p.getActiveNodeCount() == 0;
}
@Override
public List<ActiveNode> getSortedActiveNodes() {
SortedActiveNodeListProtoOrBuilder p = viaProto ? proto : builder;
List<ActiveNode> activeNodes = new ArrayList<ActiveNode>();
for (ActiveNodeProto nodeProto : p.getActiveNodeList()) {
activeNodes.add(new ActiveNodePBImpl(nodeProto));
}
Collections.sort(activeNodes);
return activeNodes;
}
@Override
public List<ActiveNode> getActiveNodes() {
SortedActiveNodeListProtoOrBuilder p = viaProto ? proto : builder;
List<ActiveNode> activeNodes = new ArrayList<ActiveNode>();
for (ActiveNodeProto nodeProto : p.getActiveNodeList()) {
activeNodes.add(new ActiveNodePBImpl(nodeProto));
}
return activeNodes;
}
@Override
public ActiveNode getActiveNode(InetSocketAddress address) {
SortedActiveNodeListProtoOrBuilder p = viaProto ? proto : builder;
for (ActiveNodeProto namenodeProto : p.getActiveNodeList()) {
ActiveNode namenode = new ActiveNodePBImpl(namenodeProto);
if (namenode.getInetSocketAddress().equals(address)) {
return namenode;
}
}
return null;
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder("Active Namenodes are ");
if (this.isEmpty()) {
sb.append(" EMPTY ");
} else {
for (int i = 0; i < this.size(); i++) {
ActiveNode ann = this.getSortedActiveNodes().get(i);
sb.append("[ id: ").append(ann.getId());
InetSocketAddress addr = ann.getInetSocketAddress();
sb.append(" addr: ").append(addr.getHostName()).append(":").append(addr.
getPort());
sb.append(" ] ");
}
}
return sb.toString();
}
@Override
public ActiveNode getLeader() {
//in our case the node wiht smallest id is the leader
if (this.isEmpty()) {
return null;
}
return this.getSortedActiveNodes().get(0);
}
}