1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.hadoop.hbase.master;
19
20 import java.io.IOException;
21 import java.util.ArrayList;
22 import java.util.Collections;
23 import java.util.HashMap;
24 import java.util.HashSet;
25 import java.util.Iterator;
26 import java.util.List;
27 import java.util.Map;
28 import java.util.Set;
29 import java.util.TreeMap;
30
31 import org.apache.commons.logging.Log;
32 import org.apache.commons.logging.LogFactory;
33 import org.apache.hadoop.hbase.classification.InterfaceAudience;
34 import org.apache.hadoop.conf.Configuration;
35 import org.apache.hadoop.hbase.HConstants;
36 import org.apache.hadoop.hbase.HRegionInfo;
37 import org.apache.hadoop.hbase.RegionTransition;
38 import org.apache.hadoop.hbase.Server;
39 import org.apache.hadoop.hbase.ServerLoad;
40 import org.apache.hadoop.hbase.ServerName;
41 import org.apache.hadoop.hbase.TableName;
42 import org.apache.hadoop.hbase.catalog.MetaReader;
43 import org.apache.hadoop.hbase.master.RegionState.State;
44 import org.apache.hadoop.hbase.util.Bytes;
45 import org.apache.hadoop.hbase.util.FSUtils;
46 import org.apache.hadoop.hbase.util.Pair;
47 import org.apache.hadoop.hbase.zookeeper.ZKAssign;
48 import org.apache.hadoop.hbase.zookeeper.ZooKeeperWatcher;
49 import org.apache.zookeeper.KeeperException;
50
51 import com.google.common.base.Preconditions;
52
53
54
55
56
57
58
59 @InterfaceAudience.Private
60 public class RegionStates {
61 private static final Log LOG = LogFactory.getLog(RegionStates.class);
62
63
64
65
66 final HashMap<String, RegionState> regionsInTransition;
67
68
69
70
71
72 private final HashMap<String, RegionState> regionStates;
73
74
75
76
77 private final Map<TableName, Map<String, RegionState>> regionStatesTableIndex =
78 new HashMap<TableName, Map<String, RegionState>>();
79
80
81
82
83
84 private final Map<ServerName, Set<HRegionInfo>> serverHoldings;
85
86
87
88
89
90 private final TreeMap<HRegionInfo, ServerName> regionAssignments;
91
92
93
94
95
96
97
98
99
100
101
102 private final HashMap<String, ServerName> lastAssignments;
103
104
105
106
107
108
109 private final HashMap<String, Long> deadServers;
110
111
112
113
114
115
116
117
118 private final HashMap<ServerName, Long> processedServers;
119 private long lastProcessedServerCleanTime;
120
121 private final RegionStateStore regionStateStore;
122 private final ServerManager serverManager;
123 private final Server server;
124
125
126 static final String LOG_SPLIT_TIME = "hbase.master.maximum.logsplit.keeptime";
127 static final long DEFAULT_LOG_SPLIT_TIME = 7200000L;
128
129 RegionStates(final Server master,
130 final ServerManager serverManager, final RegionStateStore regionStateStore) {
131 regionStates = new HashMap<String, RegionState>();
132 regionsInTransition = new HashMap<String, RegionState>();
133 serverHoldings = new HashMap<ServerName, Set<HRegionInfo>>();
134 regionAssignments = new TreeMap<HRegionInfo, ServerName>();
135 lastAssignments = new HashMap<String, ServerName>();
136 processedServers = new HashMap<ServerName, Long>();
137 deadServers = new HashMap<String, Long>();
138 this.regionStateStore = regionStateStore;
139 this.serverManager = serverManager;
140 this.server = master;
141 }
142
143
144
145
146 public synchronized Map<HRegionInfo, ServerName> getRegionAssignments() {
147 return Collections.unmodifiableMap(regionAssignments);
148 }
149
150 public synchronized ServerName getRegionServerOfRegion(HRegionInfo hri) {
151 return regionAssignments.get(hri);
152 }
153
154
155
156
157 @SuppressWarnings("unchecked")
158 public synchronized Map<String, RegionState> getRegionsInTransition() {
159 return (Map<String, RegionState>)regionsInTransition.clone();
160 }
161
162
163
164
165 public synchronized boolean isRegionInTransition(final HRegionInfo hri) {
166 return regionsInTransition.containsKey(hri.getEncodedName());
167 }
168
169
170
171
172 public synchronized boolean isRegionInTransition(final String encodedName) {
173 return regionsInTransition.containsKey(encodedName);
174 }
175
176
177
178
179 public synchronized boolean isRegionsInTransition() {
180 return !regionsInTransition.isEmpty();
181 }
182
183
184
185
186 public synchronized boolean isRegionOnline(final HRegionInfo hri) {
187 return !isRegionInTransition(hri) && regionAssignments.containsKey(hri);
188 }
189
190
191
192
193
194 public synchronized boolean isRegionOffline(final HRegionInfo hri) {
195 return getRegionState(hri) == null || (!isRegionInTransition(hri)
196 && isRegionInState(hri, State.OFFLINE, State.CLOSED));
197 }
198
199
200
201
202 public boolean isRegionInState(
203 final HRegionInfo hri, final State... states) {
204 return isRegionInState(hri.getEncodedName(), states);
205 }
206
207
208
209
210 public boolean isRegionInState(
211 final String encodedName, final State... states) {
212 RegionState regionState = getRegionState(encodedName);
213 return isOneOfStates(regionState, states);
214 }
215
216
217
218
219 public synchronized void waitForUpdate(
220 final long timeout) throws InterruptedException {
221 this.wait(timeout);
222 }
223
224
225
226
227 public RegionState getRegionTransitionState(final HRegionInfo hri) {
228 return getRegionTransitionState(hri.getEncodedName());
229 }
230
231
232
233
234 public synchronized RegionState
235 getRegionTransitionState(final String encodedName) {
236 return regionsInTransition.get(encodedName);
237 }
238
239
240
241
242
243
244 public void createRegionStates(
245 final List<HRegionInfo> hris) {
246 for (HRegionInfo hri: hris) {
247 createRegionState(hri);
248 }
249 }
250
251
252
253
254
255
256
257 public RegionState createRegionState(final HRegionInfo hri) {
258 return createRegionState(hri, null, null);
259 }
260
261
262
263
264
265
266 public synchronized RegionState createRegionState(
267 final HRegionInfo hri, State newState, ServerName serverName) {
268 if (newState == null || (newState == State.OPEN && serverName == null)) {
269 newState = State.OFFLINE;
270 }
271 if (hri.isOffline() && hri.isSplit()) {
272 newState = State.SPLIT;
273 serverName = null;
274 }
275 String encodedName = hri.getEncodedName();
276 RegionState regionState = regionStates.get(encodedName);
277 if (regionState != null) {
278 LOG.warn("Tried to create a state for a region already in RegionStates, "
279 + "used existing: " + regionState + ", ignored new: " + newState);
280 } else {
281 regionState = new RegionState(hri, newState, serverName);
282 putRegionState(regionState);
283 if (newState == State.OPEN) {
284 regionAssignments.put(hri, serverName);
285 lastAssignments.put(encodedName, serverName);
286 Set<HRegionInfo> regions = serverHoldings.get(serverName);
287 if (regions == null) {
288 regions = new HashSet<HRegionInfo>();
289 serverHoldings.put(serverName, regions);
290 }
291 regions.add(hri);
292 } else if (!regionState.isUnassignable()) {
293 regionsInTransition.put(encodedName, regionState);
294 }
295 }
296 return regionState;
297 }
298
299 private RegionState putRegionState(RegionState regionState) {
300 HRegionInfo hri = regionState.getRegion();
301 String encodedName = hri.getEncodedName();
302 TableName table = hri.getTable();
303 RegionState oldState = regionStates.put(encodedName, regionState);
304 Map<String, RegionState> map = regionStatesTableIndex.get(table);
305 if (map == null) {
306 map = new HashMap<String, RegionState>();
307 regionStatesTableIndex.put(table, map);
308 }
309 map.put(encodedName, regionState);
310 return oldState;
311 }
312
313
314
315
316 public RegionState updateRegionState(
317 final HRegionInfo hri, final State state) {
318 RegionState regionState = getRegionState(hri.getEncodedName());
319 return updateRegionState(hri, state,
320 regionState == null ? null : regionState.getServerName());
321 }
322
323
324
325
326
327
328
329 public RegionState updateRegionState(
330 final RegionTransition transition, final State state) {
331 byte [] regionName = transition.getRegionName();
332 HRegionInfo regionInfo = getRegionInfo(regionName);
333 if (regionInfo == null) {
334 String prettyRegionName = HRegionInfo.prettyPrint(
335 HRegionInfo.encodeRegionName(regionName));
336 LOG.warn("Failed to find region " + prettyRegionName
337 + " in updating its state to " + state
338 + " based on region transition " + transition);
339 return null;
340 }
341 return updateRegionState(regionInfo, state,
342 transition.getServerName());
343 }
344
345
346
347
348 public synchronized RegionState transitionOpenFromPendingOpenOrOpeningOnServer(
349 final RegionTransition transition, final RegionState fromState, final ServerName sn) {
350 if(fromState.isPendingOpenOrOpeningOnServer(sn)){
351 return updateRegionState(transition, State.OPEN);
352 }
353 return null;
354 }
355
356
357
358
359 public RegionState updateRegionState(
360 final HRegionInfo hri, final State state, final ServerName serverName) {
361 return updateRegionState(hri, state, serverName, HConstants.NO_SEQNUM);
362 }
363
364 public void regionOnline(
365 final HRegionInfo hri, final ServerName serverName) {
366 regionOnline(hri, serverName, HConstants.NO_SEQNUM);
367 }
368
369
370
371
372
373
374 public void regionOnline(final HRegionInfo hri,
375 final ServerName serverName, long openSeqNum) {
376 if (!serverManager.isServerOnline(serverName)) {
377
378
379
380
381 LOG.warn("Ignored, " + hri.getEncodedName()
382 + " was opened on a dead server: " + serverName);
383 return;
384 }
385 updateRegionState(hri, State.OPEN, serverName, openSeqNum);
386
387 synchronized (this) {
388 regionsInTransition.remove(hri.getEncodedName());
389 ServerName oldServerName = regionAssignments.put(hri, serverName);
390 if (!serverName.equals(oldServerName)) {
391 LOG.info("Onlined " + hri.getShortNameToLog() + " on " + serverName);
392 Set<HRegionInfo> regions = serverHoldings.get(serverName);
393 if (regions == null) {
394 regions = new HashSet<HRegionInfo>();
395 serverHoldings.put(serverName, regions);
396 }
397 regions.add(hri);
398 if (oldServerName != null) {
399 LOG.info("Offlined " + hri.getShortNameToLog() + " from " + oldServerName);
400 Set<HRegionInfo> oldRegions = serverHoldings.get(oldServerName);
401 oldRegions.remove(hri);
402 if (oldRegions.isEmpty()) {
403 serverHoldings.remove(oldServerName);
404 }
405 }
406 }
407 }
408 }
409
410
411
412
413
414 public synchronized void logSplit(final ServerName serverName) {
415 for (Iterator<Map.Entry<String, ServerName>> it
416 = lastAssignments.entrySet().iterator(); it.hasNext();) {
417 Map.Entry<String, ServerName> e = it.next();
418 if (e.getValue().equals(serverName)) {
419 it.remove();
420 }
421 }
422 long now = System.currentTimeMillis();
423 if (LOG.isDebugEnabled()) {
424 LOG.debug("Adding to processed servers " + serverName);
425 }
426 processedServers.put(serverName, Long.valueOf(now));
427 Configuration conf = server.getConfiguration();
428 long obsoleteTime = conf.getLong(LOG_SPLIT_TIME, DEFAULT_LOG_SPLIT_TIME);
429
430 if (now > lastProcessedServerCleanTime + obsoleteTime) {
431 lastProcessedServerCleanTime = now;
432 long cutoff = now - obsoleteTime;
433 for (Iterator<Map.Entry<ServerName, Long>> it
434 = processedServers.entrySet().iterator(); it.hasNext();) {
435 Map.Entry<ServerName, Long> e = it.next();
436 if (e.getValue().longValue() < cutoff) {
437 if (LOG.isDebugEnabled()) {
438 LOG.debug("Removed from processed servers " + e.getKey());
439 }
440 it.remove();
441 }
442 }
443 }
444 }
445
446
447
448
449 public void logSplit(final HRegionInfo region) {
450 clearLastAssignment(region);
451 }
452
453 public synchronized void clearLastAssignment(final HRegionInfo region) {
454 lastAssignments.remove(region.getEncodedName());
455 }
456
457
458
459
460 public void regionOffline(final HRegionInfo hri) {
461 regionOffline(hri, null);
462 }
463
464
465
466
467
468
469 public void regionOffline(
470 final HRegionInfo hri, final State expectedState) {
471 Preconditions.checkArgument(expectedState == null
472 || RegionState.isUnassignable(expectedState),
473 "Offlined region should not be " + expectedState);
474 if (isRegionInState(hri, State.SPLITTING_NEW, State.MERGING_NEW)) {
475
476 deleteRegion(hri);
477 return;
478 }
479 State newState =
480 expectedState == null ? State.OFFLINE : expectedState;
481 updateRegionState(hri, newState);
482
483 synchronized (this) {
484 regionsInTransition.remove(hri.getEncodedName());
485 ServerName oldServerName = regionAssignments.remove(hri);
486 if (oldServerName != null && serverHoldings.containsKey(oldServerName)) {
487 LOG.info("Offlined " + hri.getShortNameToLog() + " from " + oldServerName);
488 Set<HRegionInfo> oldRegions = serverHoldings.get(oldServerName);
489 oldRegions.remove(hri);
490 if (oldRegions.isEmpty()) {
491 serverHoldings.remove(oldServerName);
492 }
493 }
494 }
495 }
496
497
498
499
500 public List<HRegionInfo> serverOffline(final ZooKeeperWatcher watcher, final ServerName sn) {
501
502 List<HRegionInfo> rits = new ArrayList<HRegionInfo>();
503 Set<HRegionInfo> regionsToCleanIfNoMetaEntry = new HashSet<HRegionInfo>();
504 synchronized (this) {
505 Set<HRegionInfo> assignedRegions = serverHoldings.get(sn);
506 if (assignedRegions == null) {
507 assignedRegions = new HashSet<HRegionInfo>();
508 }
509
510
511 Set<HRegionInfo> regionsToOffline = new HashSet<HRegionInfo>();
512 for (HRegionInfo region : assignedRegions) {
513
514 if (isRegionOnline(region)) {
515 regionsToOffline.add(region);
516 } else {
517 if (isRegionInState(region, State.SPLITTING, State.MERGING)) {
518 LOG.debug("Offline splitting/merging region " + getRegionState(region));
519 try {
520
521 ZKAssign.deleteNodeFailSilent(watcher, region);
522 regionsToOffline.add(region);
523 } catch (KeeperException ke) {
524 server.abort("Unexpected ZK exception deleting node " + region, ke);
525 }
526 }
527 }
528 }
529
530 for (RegionState state : regionsInTransition.values()) {
531 HRegionInfo hri = state.getRegion();
532 if (assignedRegions.contains(hri)) {
533
534
535
536 LOG.info("Transitioning " + state + " will be handled by SSH for " + sn);
537 } else if (sn.equals(state.getServerName())) {
538
539
540
541
542
543
544
545 if (state.isPendingOpenOrOpening() || state.isFailedClose() || state.isOffline()) {
546 LOG.info("Found region in " + state + " to be reassigned by SSH for " + sn);
547 rits.add(hri);
548 } else if(state.isSplittingNew()) {
549 regionsToCleanIfNoMetaEntry.add(state.getRegion());
550 } else {
551 LOG.warn("THIS SHOULD NOT HAPPEN: unexpected " + state);
552 }
553 }
554 }
555
556 for (HRegionInfo hri : regionsToOffline) {
557 regionOffline(hri);
558 }
559
560 this.notifyAll();
561 }
562 cleanIfNoMetaEntry(regionsToCleanIfNoMetaEntry);
563 return rits;
564 }
565
566
567
568
569
570 private void cleanIfNoMetaEntry(Set<HRegionInfo> hris) {
571 if (hris.isEmpty()) return;
572 for (HRegionInfo hri: hris) {
573 try {
574
575
576
577 if (MetaReader.getRegion(server.getCatalogTracker(), hri.getEncodedNameAsBytes()) ==
578 null) {
579 regionOffline(hri);
580 FSUtils.deleteRegionDir(server.getConfiguration(), hri);
581 }
582 } catch (IOException e) {
583 LOG.warn("Got exception while deleting " + hri + " directories from file system.", e);
584 }
585 }
586 }
587
588
589
590
591
592
593
594
595
596
597
598 public synchronized List<HRegionInfo> getRegionsOfTable(TableName tableName) {
599 List<HRegionInfo> tableRegions = new ArrayList<HRegionInfo>();
600
601
602 HRegionInfo boundary = new HRegionInfo(tableName, null, null, false, 0L);
603 for (HRegionInfo hri: regionAssignments.tailMap(boundary).keySet()) {
604 if(!hri.getTable().equals(tableName)) break;
605 tableRegions.add(hri);
606 }
607 return tableRegions;
608 }
609
610
611
612
613
614
615
616
617
618
619 public synchronized Map<RegionState.State, List<HRegionInfo>>
620 getRegionByStateOfTable(TableName tableName) {
621 Map<RegionState.State, List<HRegionInfo>> tableRegions =
622 new HashMap<State, List<HRegionInfo>>();
623 for (State state : State.values()) {
624 tableRegions.put(state, new ArrayList<HRegionInfo>());
625 }
626 Map<String, RegionState> indexMap = regionStatesTableIndex.get(tableName);
627 if (indexMap == null)
628 return tableRegions;
629 for (RegionState regionState : indexMap.values()) {
630 tableRegions.get(regionState.getState()).add(regionState.getRegion());
631 }
632 return tableRegions;
633 }
634
635
636
637
638
639
640
641 public synchronized void waitOnRegionToClearRegionsInTransition(
642 final HRegionInfo hri) throws InterruptedException {
643 if (!isRegionInTransition(hri)) return;
644
645 while(!server.isStopped() && isRegionInTransition(hri)) {
646 RegionState rs = getRegionState(hri);
647 LOG.info("Waiting on " + rs + " to clear regions-in-transition");
648 waitForUpdate(100);
649 }
650
651 if (server.isStopped()) {
652 LOG.info("Giving up wait on region in " +
653 "transition because stoppable.isStopped is set");
654 }
655 }
656
657
658
659
660
661 public void tableDeleted(final TableName tableName) {
662 Set<HRegionInfo> regionsToDelete = new HashSet<HRegionInfo>();
663 synchronized (this) {
664 for (RegionState state: regionStates.values()) {
665 HRegionInfo region = state.getRegion();
666 if (region.getTable().equals(tableName)) {
667 regionsToDelete.add(region);
668 }
669 }
670 }
671 for (HRegionInfo region: regionsToDelete) {
672 deleteRegion(region);
673 }
674 }
675
676
677
678
679
680
681
682
683
684
685
686 synchronized boolean wasRegionOnDeadServer(final String encodedName) {
687 ServerName server = lastAssignments.get(encodedName);
688 return isServerDeadAndNotProcessed(server);
689 }
690
691 synchronized boolean isServerDeadAndNotProcessed(ServerName server) {
692 if (server == null) return false;
693 if (serverManager.isServerOnline(server)) {
694 String hostAndPort = server.getHostAndPort();
695 long startCode = server.getStartcode();
696 Long deadCode = deadServers.get(hostAndPort);
697 if (deadCode == null || startCode > deadCode.longValue()) {
698 if (serverManager.isServerReachable(server)) {
699 return false;
700 }
701
702 deadServers.put(hostAndPort, Long.valueOf(startCode));
703 }
704
705
706
707
708
709
710
711 LOG.warn("Couldn't reach online server " + server);
712 }
713
714 return !processedServers.containsKey(server);
715 }
716
717
718
719
720
721 synchronized ServerName getLastRegionServerOfRegion(final String encodedName) {
722 return lastAssignments.get(encodedName);
723 }
724
725 synchronized void setLastRegionServerOfRegions(
726 final ServerName serverName, final List<HRegionInfo> regionInfos) {
727 for (HRegionInfo hri: regionInfos) {
728 setLastRegionServerOfRegion(serverName, hri.getEncodedName());
729 }
730 }
731
732 synchronized void setLastRegionServerOfRegion(
733 final ServerName serverName, final String encodedName) {
734 lastAssignments.put(encodedName, serverName);
735 }
736
737 synchronized void closeAllUserRegions(Set<TableName> excludedTables) {
738 Set<HRegionInfo> toBeClosed = new HashSet<HRegionInfo>(regionStates.size());
739 for(RegionState state: regionStates.values()) {
740 HRegionInfo hri = state.getRegion();
741 TableName tableName = hri.getTable();
742 if (!hri.isSplit() && !hri.isMetaRegion()
743 && !excludedTables.contains(tableName)) {
744 toBeClosed.add(hri);
745 }
746 }
747 for (HRegionInfo hri: toBeClosed) {
748 updateRegionState(hri, State.CLOSED);
749 }
750 }
751
752
753
754
755
756
757
758 protected synchronized double getAverageLoad() {
759 int numServers = 0, totalLoad = 0;
760 for (Map.Entry<ServerName, Set<HRegionInfo>> e: serverHoldings.entrySet()) {
761 Set<HRegionInfo> regions = e.getValue();
762 ServerName serverName = e.getKey();
763 int regionCount = regions.size();
764 if (serverManager.isServerOnline(serverName)) {
765 totalLoad += regionCount;
766 numServers++;
767 }
768 }
769 return numServers == 0 ? 0.0 :
770 (double)totalLoad / (double)numServers;
771 }
772
773
774
775
776
777
778
779
780
781 protected Map<TableName, Map<ServerName, List<HRegionInfo>>>
782 getAssignmentsByTable() {
783 Map<TableName, Map<ServerName, List<HRegionInfo>>> result =
784 new HashMap<TableName, Map<ServerName,List<HRegionInfo>>>();
785 synchronized (this) {
786 if (!server.getConfiguration().getBoolean("hbase.master.loadbalance.bytable", false)) {
787 Map<ServerName, List<HRegionInfo>> svrToRegions =
788 new HashMap<ServerName, List<HRegionInfo>>(serverHoldings.size());
789 for (Map.Entry<ServerName, Set<HRegionInfo>> e: serverHoldings.entrySet()) {
790 svrToRegions.put(e.getKey(), new ArrayList<HRegionInfo>(e.getValue()));
791 }
792 result.put(TableName.valueOf("ensemble"), svrToRegions);
793 } else {
794 for (Map.Entry<ServerName, Set<HRegionInfo>> e: serverHoldings.entrySet()) {
795 for (HRegionInfo hri: e.getValue()) {
796 if (hri.isMetaRegion()) continue;
797 TableName tablename = hri.getTable();
798 Map<ServerName, List<HRegionInfo>> svrToRegions = result.get(tablename);
799 if (svrToRegions == null) {
800 svrToRegions = new HashMap<ServerName, List<HRegionInfo>>(serverHoldings.size());
801 result.put(tablename, svrToRegions);
802 }
803 List<HRegionInfo> regions = svrToRegions.get(e.getKey());
804 if (regions == null) {
805 regions = new ArrayList<HRegionInfo>();
806 svrToRegions.put(e.getKey(), regions);
807 }
808 regions.add(hri);
809 }
810 }
811 }
812 }
813
814 Map<ServerName, ServerLoad>
815 onlineSvrs = serverManager.getOnlineServers();
816
817 List<ServerName> drainingServers = this.serverManager.getDrainingServersList();
818 for (Map<ServerName, List<HRegionInfo>> map: result.values()) {
819 for (ServerName svr: onlineSvrs.keySet()) {
820 if (!map.containsKey(svr)) {
821 map.put(svr, new ArrayList<HRegionInfo>());
822 }
823 }
824 map.keySet().removeAll(drainingServers);
825 }
826 return result;
827 }
828
829 protected RegionState getRegionState(final HRegionInfo hri) {
830 return getRegionState(hri.getEncodedName());
831 }
832
833 protected synchronized RegionState getRegionState(final String encodedName) {
834 return regionStates.get(encodedName);
835 }
836
837
838
839
840
841
842
843 protected HRegionInfo getRegionInfo(final byte [] regionName) {
844 String encodedName = HRegionInfo.encodeRegionName(regionName);
845 RegionState regionState = getRegionState(encodedName);
846 if (regionState != null) {
847 return regionState.getRegion();
848 }
849
850 try {
851 Pair<HRegionInfo, ServerName> p =
852 MetaReader.getRegion(server.getCatalogTracker(), regionName);
853 HRegionInfo hri = p == null ? null : p.getFirst();
854 if (hri != null) {
855 createRegionState(hri);
856 }
857 return hri;
858 } catch (IOException e) {
859 server.abort("Aborting because error occoured while reading "
860 + Bytes.toStringBinary(regionName) + " from hbase:meta", e);
861 return null;
862 }
863 }
864
865 static boolean isOneOfStates(RegionState regionState, State... states) {
866 State s = regionState != null ? regionState.getState() : null;
867 for (State state: states) {
868 if (s == state) return true;
869 }
870 return false;
871 }
872
873
874
875
876 private RegionState updateRegionState(final HRegionInfo hri,
877 final State state, final ServerName serverName, long openSeqNum) {
878 if (state == State.FAILED_CLOSE || state == State.FAILED_OPEN) {
879 LOG.warn("Failed to open/close " + hri.getShortNameToLog()
880 + " on " + serverName + ", set to " + state);
881 }
882
883 String encodedName = hri.getEncodedName();
884 RegionState regionState = new RegionState(
885 hri, state, System.currentTimeMillis(), serverName);
886 RegionState oldState = getRegionState(encodedName);
887 if (!regionState.equals(oldState)) {
888 LOG.info("Transition " + oldState + " to " + regionState);
889
890 regionStateStore.updateRegionState(openSeqNum, regionState, oldState);
891 }
892
893 synchronized (this) {
894 regionsInTransition.put(encodedName, regionState);
895 putRegionState(regionState);
896
897
898
899 if ((state == State.CLOSED || state == State.MERGED
900 || state == State.SPLIT) && lastAssignments.containsKey(encodedName)) {
901 ServerName last = lastAssignments.get(encodedName);
902 if (last.equals(serverName)) {
903 lastAssignments.remove(encodedName);
904 } else {
905 LOG.warn(encodedName + " moved to " + state + " on "
906 + serverName + ", expected " + last);
907 }
908 }
909
910
911 if (serverName != null && state == State.OPEN) {
912 ServerName last = lastAssignments.get(encodedName);
913 if (!serverName.equals(last)) {
914 lastAssignments.put(encodedName, serverName);
915 if (last != null && isServerDeadAndNotProcessed(last)) {
916 LOG.warn(encodedName + " moved to " + serverName
917 + ", while it's previous host " + last
918 + " is dead but not processed yet");
919 }
920 }
921 }
922
923
924 this.notifyAll();
925 }
926 return regionState;
927 }
928
929
930
931
932 private synchronized void deleteRegion(final HRegionInfo hri) {
933 String encodedName = hri.getEncodedName();
934 regionsInTransition.remove(encodedName);
935 regionStates.remove(encodedName);
936 lastAssignments.remove(encodedName);
937 ServerName sn = regionAssignments.remove(hri);
938 if (sn != null) {
939 Set<HRegionInfo> regions = serverHoldings.get(sn);
940 regions.remove(hri);
941 }
942 }
943 }