b5b64693b6588d71832a1ee016d3c6ad50c9d5e3
[policy/drools-pdp.git] / feature-pooling-dmaap / src / main / java / org / onap / policy / drools / pooling / message / BucketAssignments.java
1 /*
2  * ============LICENSE_START=======================================================
3  * ONAP
4  * ================================================================================
5  * Copyright (C) 2018 AT&T Intellectual Property. All rights reserved.
6  * ================================================================================
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  * 
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  * 
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  * ============LICENSE_END=========================================================
19  */
20
21 package org.onap.policy.drools.pooling.message;
22
23 import com.fasterxml.jackson.annotation.JsonIgnore;
24 import java.util.Arrays;
25 import java.util.HashSet;
26 import java.util.Set;
27 import org.onap.policy.drools.pooling.PoolingFeatureException;
28 import org.slf4j.Logger;
29 import org.slf4j.LoggerFactory;
30
31 /**
32  * Bucket assignments, which is simply an array of host names.
33  */
34 public class BucketAssignments {
35
36     @JsonIgnore
37     private static final Logger logger = LoggerFactory.getLogger(BucketAssignments.class);
38
39     /**
40      * The number of bits in the maximum number of buckets.
41      */
42     private static final int MAX_BUCKET_BITS = 10;
43
44     /**
45      * Maximum number of buckets. Must be a power of two.
46      */
47     public static final int MAX_BUCKETS = 1 << MAX_BUCKET_BITS;
48
49     /**
50      * Used to ensure that a hash code is not negative.
51      */
52     private static final int MAX_BUCKETS_MASK = MAX_BUCKETS - 1;
53
54     /**
55      * Identifies the host serving a particular bucket.
56      */
57     private String[] hostArray = null;
58
59     /**
60      * Constructor.
61      */
62     public BucketAssignments() {
63         super();
64     }
65
66     /**
67      * Constructor.
68      * 
69      * @param hostArray maps a bucket number (i.e., array index) to a host. All values
70      *        must be non-null
71      */
72     public BucketAssignments(String[] hostArray) {
73         this.hostArray = hostArray;
74     }
75
76     public String[] getHostArray() {
77         return hostArray;
78     }
79
80     public void setHostArray(String[] hostArray) {
81         this.hostArray = hostArray;
82     }
83
84     /**
85      * Gets the leader, which is the host with the minimum UUID.
86      * 
87      * @return the assignment leader
88      */
89     @JsonIgnore
90     public String getLeader() {
91         if (hostArray == null) {
92             return null;
93         }
94
95         String leader = null;
96
97         for (String host : hostArray) {
98             if (host != null && (leader == null || host.compareTo(leader) < 0)) {
99                 leader = host;
100             }
101         }
102
103         return leader;
104
105     }
106
107     /**
108      * Determines if a host has an assignment.
109      * 
110      * @param host host to be checked
111      * @return {@code true} if the host has an assignment, {@code false} otherwise
112      */
113     @JsonIgnore
114     public boolean hasAssignment(String host) {
115         if (hostArray == null) {
116             return false;
117         }
118
119         for (String host2 : hostArray) {
120             if (host.equals(host2)) {
121                 return true;
122             }
123         }
124
125         return false;
126     }
127
128     /**
129      * Gets all of the hosts that have an assignment.
130      * 
131      * @return all of the hosts that have an assignment
132      */
133     @JsonIgnore
134     public Set<String> getAllHosts() {
135         Set<String> set = new HashSet<>();
136         if (hostArray == null) {
137             return set;
138         }
139
140         for (String host : hostArray) {
141             if (host != null) {
142                 set.add(host);
143             }
144         }
145
146         return set;
147     }
148
149     /**
150      * Gets the host assigned to a given bucket.
151      * 
152      * @param hashCode hash code of the item whose assignment is desired
153      * @return the assigned host, or {@code null} if the item has no assigned host
154      */
155     @JsonIgnore
156     public String getAssignedHost(int hashCode) {
157         if (hostArray == null || hostArray.length == 0) {
158             logger.error("no buckets have been assigned");
159             return null;
160         }
161
162         return hostArray[(hashCode & MAX_BUCKETS_MASK) % hostArray.length];
163     }
164
165     /**
166      * Gets the number of buckets.
167      * 
168      * @return the number of buckets
169      */
170     @JsonIgnore
171     public int size() {
172         return (hostArray != null ? hostArray.length : 0);
173     }
174
175     /**
176      * Checks the validity of the assignments, verifying that all buckets have been
177      * assigned to a host.
178      * 
179      * @throws PoolingFeatureException if the assignments are invalid
180      */
181     @JsonIgnore
182     public void checkValidity() throws PoolingFeatureException {
183         if (hostArray == null || hostArray.length == 0) {
184             throw new PoolingFeatureException("missing hosts in message bucket assignments");
185         }
186
187         if (hostArray.length > MAX_BUCKETS) {
188             throw new PoolingFeatureException("too many hosts in message bucket assignments");
189         }
190
191         for (int x = 0; x < hostArray.length; ++x) {
192             if (hostArray[x] == null) {
193                 throw new PoolingFeatureException("bucket " + x + " has no assignment");
194             }
195         }
196     }
197
198     @Override
199     public int hashCode() {
200         final int prime = 31;
201         int result = 1;
202         result = prime * result + Arrays.hashCode(hostArray);
203         return result;
204     }
205
206     @Override
207     public boolean equals(Object obj) {
208         if (this == obj) {
209             return true;
210         }
211         if (obj == null) {
212             return false;
213         }
214         if (getClass() != obj.getClass()) {
215             return false;
216         }
217         BucketAssignments other = (BucketAssignments) obj;
218         return Arrays.equals(hostArray, other.hostArray);
219     }
220 }