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