1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.hadoop.hbase;
20
21 import java.util.Collection;
22 import java.util.Objects;
23
24 import org.apache.hadoop.hbase.classification.InterfaceAudience;
25 import org.apache.hadoop.hbase.client.RegionReplicaUtil;
26 import org.apache.hadoop.hbase.util.Bytes;
27
28
29
30
31
32
33
34 @InterfaceAudience.Private
35 public class RegionLocations {
36
37 private final int numNonNullElements;
38
39
40
41
42
43 private final HRegionLocation[] locations;
44
45
46
47
48
49
50
51
52 public RegionLocations(HRegionLocation... locations) {
53 int numNonNullElements = 0;
54 int maxReplicaId = -1;
55 int maxReplicaIdIndex = -1;
56 int index = 0;
57 for (HRegionLocation loc : locations) {
58 if (loc != null) {
59 if (loc.getServerName() != null) {
60 numNonNullElements++;
61 }
62 if (loc.getRegionInfo().getReplicaId() >= maxReplicaId) {
63 maxReplicaId = loc.getRegionInfo().getReplicaId();
64 maxReplicaIdIndex = index;
65 }
66 }
67 index++;
68 }
69 this.numNonNullElements = numNonNullElements;
70
71
72 maxReplicaId = maxReplicaId + (locations.length - (maxReplicaIdIndex + 1) );
73
74 if (maxReplicaId + 1 == locations.length) {
75 this.locations = locations;
76 } else {
77 this.locations = new HRegionLocation[maxReplicaId + 1];
78 for (HRegionLocation loc : locations) {
79 if (loc != null) {
80 this.locations[loc.getRegionInfo().getReplicaId()] = loc;
81 }
82 }
83 }
84 }
85
86 public RegionLocations(Collection<HRegionLocation> locations) {
87 this(locations.toArray(new HRegionLocation[locations.size()]));
88 }
89
90
91
92
93
94
95 public int size() {
96 return locations.length;
97 }
98
99
100
101
102
103 public int numNonNullElements() {
104 return numNonNullElements;
105 }
106
107
108
109
110
111 public boolean isEmpty() {
112 return numNonNullElements == 0;
113 }
114
115
116
117
118
119
120
121
122 public RegionLocations removeByServer(ServerName serverName) {
123 HRegionLocation[] newLocations = null;
124 for (int i = 0; i < locations.length; i++) {
125
126 if (locations[i] != null && serverName.equals(locations[i].getServerName())) {
127 if (newLocations == null) {
128 newLocations = new HRegionLocation[locations.length];
129 System.arraycopy(locations, 0, newLocations, 0, i);
130 }
131 newLocations[i] = null;
132 } else if (newLocations != null) {
133 newLocations[i] = locations[i];
134 }
135 }
136 return newLocations == null ? this : new RegionLocations(newLocations);
137 }
138
139
140
141
142
143
144
145 public RegionLocations remove(HRegionLocation location) {
146 if (location == null) return this;
147 if (location.getRegionInfo() == null) return this;
148 int replicaId = location.getRegionInfo().getReplicaId();
149 if (replicaId >= locations.length) return this;
150
151
152
153 if (locations[replicaId] == null
154 || !location.getRegionInfo().equals(locations[replicaId].getRegionInfo())
155 || !location.equals(locations[replicaId])) {
156 return this;
157 }
158
159 HRegionLocation[] newLocations = new HRegionLocation[locations.length];
160 System.arraycopy(locations, 0, newLocations, 0, locations.length);
161 newLocations[replicaId] = null;
162
163 return new RegionLocations(newLocations);
164 }
165
166
167
168
169
170
171
172 public RegionLocations remove(int replicaId) {
173 if (getRegionLocation(replicaId) == null) {
174 return this;
175 }
176
177 HRegionLocation[] newLocations = new HRegionLocation[locations.length];
178
179 System.arraycopy(locations, 0, newLocations, 0, locations.length);
180 if (replicaId < newLocations.length) {
181 newLocations[replicaId] = null;
182 }
183
184 return new RegionLocations(newLocations);
185 }
186
187
188
189
190
191
192
193
194
195
196 public RegionLocations mergeLocations(RegionLocations other) {
197 assert other != null;
198
199 HRegionLocation[] newLocations = null;
200
201
202
203 int max = other.locations.length;
204
205 HRegionInfo regionInfo = null;
206 for (int i = 0; i < max; i++) {
207 HRegionLocation thisLoc = this.getRegionLocation(i);
208 HRegionLocation otherLoc = other.getRegionLocation(i);
209 if (regionInfo == null && otherLoc != null && otherLoc.getRegionInfo() != null) {
210
211
212 regionInfo = otherLoc.getRegionInfo();
213 }
214
215 HRegionLocation selectedLoc = selectRegionLocation(thisLoc,
216 otherLoc, true, false);
217
218 if (!Objects.equals(selectedLoc, thisLoc)) {
219 if (newLocations == null) {
220 newLocations = new HRegionLocation[max];
221 System.arraycopy(locations, 0, newLocations, 0, i);
222 }
223 }
224 if (newLocations != null) {
225 newLocations[i] = selectedLoc;
226 }
227 }
228
229
230 if (newLocations != null && regionInfo != null) {
231 for (int i=0; i < newLocations.length; i++) {
232 if (newLocations[i] != null) {
233 if (!RegionReplicaUtil.isReplicasForSameRegion(regionInfo,
234 newLocations[i].getRegionInfo())) {
235 newLocations[i] = null;
236 }
237 }
238 }
239 }
240
241 return newLocations == null ? this : new RegionLocations(newLocations);
242 }
243
244 private HRegionLocation selectRegionLocation(HRegionLocation oldLocation,
245 HRegionLocation location, boolean checkForEquals, boolean force) {
246 if (location == null) {
247 return oldLocation == null ? null : oldLocation;
248 }
249
250 if (oldLocation == null) {
251 return location;
252 }
253
254 if (force
255 || isGreaterThan(location.getSeqNum(), oldLocation.getSeqNum(), checkForEquals)) {
256 return location;
257 }
258 return oldLocation;
259 }
260
261
262
263
264
265
266
267
268
269
270
271 public RegionLocations updateLocation(HRegionLocation location,
272 boolean checkForEquals, boolean force) {
273 assert location != null;
274
275 int replicaId = location.getRegionInfo().getReplicaId();
276
277 HRegionLocation oldLoc = getRegionLocation(location.getRegionInfo().getReplicaId());
278 HRegionLocation selectedLoc = selectRegionLocation(oldLoc, location,
279 checkForEquals, force);
280
281 if (Objects.equals(selectedLoc, oldLoc)) {
282 return this;
283 }
284 HRegionLocation[] newLocations = new HRegionLocation[Math.max(locations.length, replicaId +1)];
285 System.arraycopy(locations, 0, newLocations, 0, locations.length);
286 newLocations[replicaId] = location;
287
288 for (int i=0; i < newLocations.length; i++) {
289 if (newLocations[i] != null) {
290 if (!RegionReplicaUtil.isReplicasForSameRegion(location.getRegionInfo(),
291 newLocations[i].getRegionInfo())) {
292 newLocations[i] = null;
293 }
294 }
295 }
296 return new RegionLocations(newLocations);
297 }
298
299 private boolean isGreaterThan(long a, long b, boolean checkForEquals) {
300 return a > b || (checkForEquals && (a == b));
301 }
302
303 public HRegionLocation getRegionLocation(int replicaId) {
304 if (replicaId >= locations.length) {
305 return null;
306 }
307 return locations[replicaId];
308 }
309
310
311
312
313
314
315
316 public HRegionLocation getRegionLocationByRegionName(byte[] regionName) {
317 for (HRegionLocation loc : locations) {
318 if (loc != null) {
319 if (Bytes.equals(loc.getRegionInfo().getRegionName(), regionName)
320 || Bytes.equals(loc.getRegionInfo().getEncodedNameAsBytes(), regionName)) {
321 return loc;
322 }
323 }
324 }
325 return null;
326 }
327
328 public HRegionLocation[] getRegionLocations() {
329 return locations;
330 }
331
332 public HRegionLocation getDefaultRegionLocation() {
333 return locations[HRegionInfo.DEFAULT_REPLICA_ID];
334 }
335
336
337
338
339 public HRegionLocation getRegionLocation() {
340 for (HRegionLocation loc : locations) {
341 if (loc != null) {
342 return loc;
343 }
344 }
345 return null;
346 }
347
348 @Override
349 public String toString() {
350 StringBuilder builder = new StringBuilder("[");
351 for (HRegionLocation loc : locations) {
352 if (builder.length() > 1) {
353 builder.append(", ");
354 }
355 builder.append(loc == null ? "null" : loc);
356 }
357 builder.append("]");
358 return builder.toString();
359 }
360
361 }