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