Drools support for kafka topics
[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-2021 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 java.util.Arrays;
24 import java.util.HashSet;
25 import java.util.Set;
26 import lombok.Getter;
27 import lombok.NoArgsConstructor;
28 import lombok.Setter;
29 import org.onap.policy.drools.pooling.PoolingFeatureException;
30 import org.slf4j.Logger;
31 import org.slf4j.LoggerFactory;
32
33 /**
34  * Bucket assignments, which is simply an array of host names.
35  */
36 @Getter
37 @Setter
38 @NoArgsConstructor
39 public class BucketAssignments {
40
41     private static final Logger logger = LoggerFactory.getLogger(BucketAssignments.class);
42
43     /**
44      * The number of bits in the maximum number of buckets.
45      */
46     private static final int MAX_BUCKET_BITS = 10;
47
48     /**
49      * Maximum number of buckets. Must be a power of two.
50      */
51     public static final int MAX_BUCKETS = 1 << MAX_BUCKET_BITS;
52
53     /**
54      * Used to ensure that a hash code is not negative.
55      */
56     private static final int MAX_BUCKETS_MASK = MAX_BUCKETS - 1;
57
58     /**
59      * Identifies the host serving a particular bucket.
60      */
61     private String[] hostArray = null;
62
63
64     /**
65      * Constructor.
66      *
67      * @param hostArray maps a bucket number (i.e., array index) to a host. All values
68      *        must be non-null
69      */
70     public BucketAssignments(String[] hostArray) {
71         this.hostArray = hostArray;
72     }
73
74     /**
75      * Gets the leader, which is the host with the minimum UUID.
76      *
77      * @return the assignment leader
78      */
79     public String getLeader() {
80         if (hostArray == null) {
81             return null;
82         }
83
84         String leader = null;
85
86         for (String host : hostArray) {
87             if (host != null && (leader == null || host.compareTo(leader) < 0)) {
88                 leader = host;
89             }
90         }
91
92         return leader;
93
94     }
95
96     /**
97      * Determines if a host has an assignment.
98      *
99      * @param host host to be checked
100      * @return {@code true} if the host has an assignment, {@code false} otherwise
101      */
102     public boolean hasAssignment(String host) {
103         if (hostArray == null) {
104             return false;
105         }
106
107         for (String host2 : hostArray) {
108             if (host.equals(host2)) {
109                 return true;
110             }
111         }
112
113         return false;
114     }
115
116     /**
117      * Gets all of the hosts that have an assignment.
118      *
119      * @return all of the hosts that have an assignment
120      */
121     public Set<String> getAllHosts() {
122         Set<String> set = new HashSet<>();
123         if (hostArray == null) {
124             return set;
125         }
126
127         for (String host : hostArray) {
128             if (host != null) {
129                 set.add(host);
130             }
131         }
132
133         return set;
134     }
135
136     /**
137      * Gets the host assigned to a given bucket.
138      *
139      * @param hashCode hash code of the item whose assignment is desired
140      * @return the assigned host, or {@code null} if the item has no assigned host
141      */
142     public String getAssignedHost(int hashCode) {
143         if (hostArray == null || hostArray.length == 0) {
144             logger.error("no buckets have been assigned");
145             return null;
146         }
147
148         return hostArray[(Math.abs(hashCode) & MAX_BUCKETS_MASK) % hostArray.length];
149     }
150
151     /**
152      * Gets the number of buckets.
153      *
154      * @return the number of buckets
155      */
156     public int size() {
157         return (hostArray != null ? hostArray.length : 0);
158     }
159
160     /**
161      * Checks the validity of the assignments, verifying that all buckets have been
162      * assigned to a host.
163      *
164      * @throws PoolingFeatureException if the assignments are invalid
165      */
166     public void checkValidity() throws PoolingFeatureException {
167         if (hostArray == null || hostArray.length == 0) {
168             throw new PoolingFeatureException("missing hosts in message bucket assignments");
169         }
170
171         if (hostArray.length > MAX_BUCKETS) {
172             throw new PoolingFeatureException("too many hosts in message bucket assignments");
173         }
174
175         for (var x = 0; x < hostArray.length; ++x) {
176             if (hostArray[x] == null) {
177                 throw new PoolingFeatureException("bucket " + x + " has no assignment");
178             }
179         }
180     }
181
182     @Override
183     public int hashCode() {
184         final var prime = 31;
185         var result = 1;
186         result = prime * result + Arrays.hashCode(hostArray);
187         return result;
188     }
189
190     @Override
191     public boolean equals(Object obj) {
192         if (this == obj) {
193             return true;
194         }
195         if (obj == null) {
196             return false;
197         }
198         if (getClass() != obj.getClass()) {
199             return false;
200         }
201         BucketAssignments other = (BucketAssignments) obj;
202         return Arrays.equals(hostArray, other.hostArray);
203     }
204 }