1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.hadoop.hbase.master.procedure;
19
20 import java.io.IOException;
21 import java.io.InputStream;
22 import java.io.InterruptedIOException;
23 import java.io.OutputStream;
24 import java.util.ArrayList;
25 import java.util.Collection;
26 import java.util.HashSet;
27 import java.util.List;
28 import java.util.Set;
29 import java.util.concurrent.locks.Lock;
30
31 import org.apache.commons.logging.Log;
32 import org.apache.commons.logging.LogFactory;
33 import org.apache.hadoop.hbase.HConstants;
34 import org.apache.hadoop.hbase.HRegionInfo;
35 import org.apache.hadoop.hbase.ServerName;
36 import org.apache.hadoop.hbase.client.ClusterConnection;
37 import org.apache.hadoop.hbase.client.RegionReplicaUtil;
38 import org.apache.hadoop.hbase.master.AssignmentManager;
39 import org.apache.hadoop.hbase.master.MasterFileSystem;
40 import org.apache.hadoop.hbase.master.MasterServices;
41 import org.apache.hadoop.hbase.master.RegionState;
42 import org.apache.hadoop.hbase.master.RegionStates;
43 import org.apache.hadoop.hbase.procedure2.ProcedureYieldException;
44 import org.apache.hadoop.hbase.procedure2.StateMachineProcedure;
45 import org.apache.hadoop.hbase.protobuf.ProtobufUtil;
46 import org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.RegionInfo;
47 import org.apache.hadoop.hbase.protobuf.generated.MasterProcedureProtos;
48 import org.apache.hadoop.hbase.protobuf.generated.MasterProcedureProtos.ServerCrashState;
49 import org.apache.hadoop.hbase.protobuf.generated.ZooKeeperProtos;
50 import org.apache.hadoop.hbase.protobuf.generated.ZooKeeperProtos.SplitLogTask.RecoveryMode;
51 import org.apache.hadoop.hbase.zookeeper.MetaTableLocator;
52 import org.apache.hadoop.hbase.zookeeper.ZKAssign;
53 import org.apache.hadoop.hbase.zookeeper.ZooKeeperWatcher;
54 import org.apache.hadoop.util.StringUtils;
55 import org.apache.zookeeper.KeeperException;
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73 public class ServerCrashProcedure
74 extends StateMachineProcedure<MasterProcedureEnv, ServerCrashState>
75 implements ServerProcedureInterface {
76 private static final Log LOG = LogFactory.getLog(ServerCrashProcedure.class);
77
78
79
80
81 public static final String KEY_SHORT_WAIT_ON_META =
82 "hbase.master.servercrash.short.wait.on.meta.ms";
83
84 public static final int DEFAULT_SHORT_WAIT_ON_META = 1000;
85
86
87
88
89
90 public static final String KEY_RETRIES_ON_META =
91 "hbase.master.servercrash.meta.retries";
92
93 public static final int DEFAULT_RETRIES_ON_META = 10;
94
95
96
97
98 public static final String KEY_WAIT_ON_RIT =
99 "hbase.master.servercrash.wait.on.rit.ms";
100
101 public static final int DEFAULT_WAIT_ON_RIT = 30000;
102
103 private static final Set<HRegionInfo> META_REGION_SET = new HashSet<HRegionInfo>();
104 static {
105 META_REGION_SET.add(HRegionInfo.FIRST_META_REGIONINFO);
106 }
107
108
109
110
111 private ServerName serverName;
112
113
114
115
116 private boolean notifiedDeadServer = false;
117
118
119
120
121 private Set<HRegionInfo> regionsOnCrashedServer;
122
123
124
125
126 private List<HRegionInfo> regionsAssigned;
127
128 private boolean distributedLogReplay = false;
129 private boolean carryingMeta = false;
130 private boolean shouldSplitWal;
131
132
133
134
135 private int cycles = 0;
136
137
138
139
140
141 private int previousState;
142
143
144
145
146
147
148
149 public ServerCrashProcedure(final ServerName serverName,
150 final boolean shouldSplitWal, final boolean carryingMeta) {
151 this.serverName = serverName;
152 this.shouldSplitWal = shouldSplitWal;
153 this.carryingMeta = carryingMeta;
154
155 }
156
157
158
159
160
161 public ServerCrashProcedure() {
162 super();
163 }
164
165 private void throwProcedureYieldException(final String msg) throws ProcedureYieldException {
166 String logMsg = msg + "; cycle=" + this.cycles + ", running for " +
167 StringUtils.formatTimeDiff(System.currentTimeMillis(), getStartTime());
168
169
170 if (LOG.isDebugEnabled()) LOG.debug(logMsg);
171 throw new ProcedureYieldException(logMsg);
172 }
173
174 @Override
175 protected Flow executeFromState(MasterProcedureEnv env, ServerCrashState state)
176 throws ProcedureYieldException {
177 if (LOG.isTraceEnabled()) {
178 LOG.trace(state);
179 }
180
181 if (state.ordinal() != this.previousState) {
182 this.previousState = state.ordinal();
183 this.cycles = 0;
184 } else {
185 this.cycles++;
186 }
187 MasterServices services = env.getMasterServices();
188
189 if (!services.getAssignmentManager().isFailoverCleanupDone()) {
190 throwProcedureYieldException("Waiting on master failover to complete");
191 }
192
193
194 if (!notifiedDeadServer) {
195 services.getServerManager().getDeadServers().notifyServer(serverName);
196 notifiedDeadServer = true;
197 }
198
199 try {
200 switch (state) {
201 case SERVER_CRASH_START:
202 LOG.info("Start processing crashed " + this.serverName);
203 start(env);
204
205 if (this.carryingMeta) setNextState(ServerCrashState.SERVER_CRASH_PROCESS_META);
206 else setNextState(ServerCrashState.SERVER_CRASH_GET_REGIONS);
207 break;
208
209 case SERVER_CRASH_GET_REGIONS:
210
211 if (!isMetaAssignedQuickTest(env)) {
212
213
214 long wait =
215 env.getMasterConfiguration().getLong(KEY_SHORT_WAIT_ON_META,
216 DEFAULT_SHORT_WAIT_ON_META);
217 wait = wait / 10;
218 Thread.sleep(wait);
219 throwProcedureYieldException("Waiting on hbase:meta assignment");
220 }
221 this.regionsOnCrashedServer =
222 services.getAssignmentManager().getRegionStates().getServerRegions(this.serverName);
223
224
225 if (!this.shouldSplitWal) {
226 setNextState(ServerCrashState.SERVER_CRASH_ASSIGN);
227 } else if (this.distributedLogReplay) {
228 setNextState(ServerCrashState.SERVER_CRASH_PREPARE_LOG_REPLAY);
229 } else {
230 setNextState(ServerCrashState.SERVER_CRASH_SPLIT_LOGS);
231 }
232 break;
233
234 case SERVER_CRASH_PROCESS_META:
235
236 if (!processMeta(env)) {
237 throwProcedureYieldException("Waiting on regions-in-transition to clear");
238 }
239 setNextState(ServerCrashState.SERVER_CRASH_GET_REGIONS);
240 break;
241
242 case SERVER_CRASH_PREPARE_LOG_REPLAY:
243 prepareLogReplay(env, this.regionsOnCrashedServer);
244 setNextState(ServerCrashState.SERVER_CRASH_ASSIGN);
245 break;
246
247 case SERVER_CRASH_SPLIT_LOGS:
248 splitLogs(env);
249
250 if (this.distributedLogReplay) setNextState(ServerCrashState.SERVER_CRASH_FINISH);
251 else setNextState(ServerCrashState.SERVER_CRASH_ASSIGN);
252 break;
253
254 case SERVER_CRASH_ASSIGN:
255 List<HRegionInfo> regionsToAssign = calcRegionsToAssign(env);
256
257
258
259
260
261
262 boolean regions = regionsToAssign != null && !regionsToAssign.isEmpty();
263 if (regions) {
264 this.regionsAssigned = regionsToAssign;
265 if (!assign(env, regionsToAssign)) {
266 throwProcedureYieldException("Failed assign; will retry");
267 }
268 }
269 if (this.shouldSplitWal && distributedLogReplay) {
270
271
272
273
274 setNextState(ServerCrashState.SERVER_CRASH_WAIT_ON_ASSIGN);
275 } else {
276 setNextState(ServerCrashState.SERVER_CRASH_FINISH);
277 }
278 break;
279
280 case SERVER_CRASH_WAIT_ON_ASSIGN:
281
282
283
284
285
286
287
288 if (this.regionsAssigned != null && !this.regionsAssigned.isEmpty()) {
289 if (!waitOnAssign(env, this.regionsAssigned)) {
290 throwProcedureYieldException("Waiting on region assign");
291 }
292 }
293 setNextState(ServerCrashState.SERVER_CRASH_SPLIT_LOGS);
294 break;
295
296 case SERVER_CRASH_FINISH:
297 LOG.info("Finished processing of crashed " + serverName);
298 services.getServerManager().getDeadServers().finish(serverName);
299 return Flow.NO_MORE_STATE;
300
301 default:
302 throw new UnsupportedOperationException("unhandled state=" + state);
303 }
304 } catch (ProcedureYieldException e) {
305 LOG.warn("Failed serverName=" + this.serverName + ", state=" + state + "; retry "
306 + e.getMessage());
307 throw e;
308 } catch (IOException e) {
309 LOG.warn("Failed serverName=" + this.serverName + ", state=" + state + "; retry", e);
310 } catch (InterruptedException e) {
311
312 LOG.warn("Interrupted serverName=" + this.serverName + ", state=" + state + "; retry", e);
313 Thread.currentThread().interrupt();
314 }
315 return Flow.HAS_MORE_STATE;
316 }
317
318
319
320
321
322
323 private void start(final MasterProcedureEnv env) throws IOException {
324 MasterFileSystem mfs = env.getMasterServices().getMasterFileSystem();
325
326 mfs.setLogRecoveryMode();
327 this.distributedLogReplay = mfs.getLogRecoveryMode() == RecoveryMode.LOG_REPLAY;
328 }
329
330
331
332
333
334
335
336 private boolean processMeta(final MasterProcedureEnv env)
337 throws IOException {
338 if (LOG.isDebugEnabled()) LOG.debug("Processing hbase:meta that was on " + this.serverName);
339 MasterServices services = env.getMasterServices();
340 MasterFileSystem mfs = services.getMasterFileSystem();
341 AssignmentManager am = services.getAssignmentManager();
342 HRegionInfo metaHRI = HRegionInfo.FIRST_META_REGIONINFO;
343 if (this.shouldSplitWal) {
344 if (this.distributedLogReplay) {
345 prepareLogReplay(env, META_REGION_SET);
346 } else {
347
348 mfs.splitMetaLog(serverName);
349 am.getRegionStates().logSplit(metaHRI);
350 }
351 }
352
353
354 boolean processed = true;
355 boolean shouldAssignMeta = false;
356 AssignmentManager.ServerHostRegion rsCarryingMetaRegion = am.isCarryingMeta(serverName);
357 switch (rsCarryingMetaRegion) {
358 case HOSTING_REGION:
359 LOG.info("Server " + serverName + " was carrying META. Trying to assign.");
360 am.regionOffline(HRegionInfo.FIRST_META_REGIONINFO);
361 shouldAssignMeta = true;
362 break;
363 case UNKNOWN:
364 if (!services.getMetaTableLocator().isLocationAvailable(services.getZooKeeper())) {
365
366
367
368 shouldAssignMeta = true;
369 break;
370 }
371
372 case NOT_HOSTING_REGION:
373 LOG.info("META has been assigned to otherwhere, skip assigning.");
374 break;
375 default:
376 throw new IOException("Unsupported action in MetaServerShutdownHandler");
377 }
378 if (shouldAssignMeta) {
379
380 verifyAndAssignMetaWithRetries(env);
381 if (this.shouldSplitWal && distributedLogReplay) {
382 int timeout = env.getMasterConfiguration().getInt(KEY_WAIT_ON_RIT, DEFAULT_WAIT_ON_RIT);
383 if (!waitOnRegionToClearRegionsInTransition(am, metaHRI, timeout)) {
384 processed = false;
385 } else {
386
387 mfs.splitMetaLog(serverName);
388 }
389 }
390 }
391 return processed;
392 }
393
394
395
396
397
398 private boolean waitOnRegionToClearRegionsInTransition(AssignmentManager am,
399 final HRegionInfo hri, final int timeout)
400 throws InterruptedIOException {
401 try {
402 if (!am.waitOnRegionToClearRegionsInTransition(hri, timeout)) {
403
404
405 LOG.warn("Region " + hri.getEncodedName() + " didn't complete assignment in time");
406 return false;
407 }
408 } catch (InterruptedException ie) {
409 throw new InterruptedIOException("Caught " + ie +
410 " during waitOnRegionToClearRegionsInTransition for " + hri);
411 }
412 return true;
413 }
414
415 private void prepareLogReplay(final MasterProcedureEnv env, final Set<HRegionInfo> regions)
416 throws IOException {
417 if (LOG.isDebugEnabled()) {
418 LOG.debug("Mark " + size(this.regionsOnCrashedServer) + " regions-in-recovery from " +
419 this.serverName);
420 }
421 MasterFileSystem mfs = env.getMasterServices().getMasterFileSystem();
422 AssignmentManager am = env.getMasterServices().getAssignmentManager();
423 mfs.prepareLogReplay(this.serverName, regions);
424 am.getRegionStates().logSplit(this.serverName);
425 }
426
427 private void splitLogs(final MasterProcedureEnv env) throws IOException {
428 if (LOG.isDebugEnabled()) {
429 LOG.debug("Splitting logs from " + serverName + "; region count=" +
430 size(this.regionsOnCrashedServer));
431 }
432 MasterFileSystem mfs = env.getMasterServices().getMasterFileSystem();
433 AssignmentManager am = env.getMasterServices().getAssignmentManager();
434
435 mfs.splitLog(this.serverName);
436 am.getRegionStates().logSplit(this.serverName);
437 }
438
439 static int size(final Collection<HRegionInfo> hris) {
440 return hris == null? 0: hris.size();
441 }
442
443
444
445
446
447
448
449 private List<HRegionInfo> calcRegionsToAssign(final MasterProcedureEnv env)
450 throws IOException {
451 AssignmentManager am = env.getMasterServices().getAssignmentManager();
452 List<HRegionInfo> regionsToAssignAggregator = new ArrayList<HRegionInfo>();
453 int replicaCount = env.getMasterConfiguration().getInt(HConstants.META_REPLICAS_NUM,
454 HConstants.DEFAULT_META_REPLICA_NUM);
455 for (int i = 1; i < replicaCount; i++) {
456 HRegionInfo metaHri =
457 RegionReplicaUtil.getRegionInfoForReplica(HRegionInfo.FIRST_META_REGIONINFO, i);
458 if (am.isCarryingMetaReplica(this.serverName, metaHri) ==
459 AssignmentManager.ServerHostRegion.HOSTING_REGION) {
460 if (LOG.isDebugEnabled()) {
461 LOG.debug("Reassigning meta replica" + metaHri + " that was on " + this.serverName);
462 }
463 regionsToAssignAggregator.add(metaHri);
464 }
465 }
466
467 List<HRegionInfo> regionsInTransition = am.cleanOutCrashedServerReferences(serverName);
468 if (LOG.isDebugEnabled()) {
469 LOG.debug("Reassigning " + size(this.regionsOnCrashedServer) +
470 " region(s) that " + (serverName == null? "null": serverName) +
471 " was carrying (and " + regionsInTransition.size() +
472 " regions(s) that were opening on this server)");
473 }
474 regionsToAssignAggregator.addAll(regionsInTransition);
475
476
477 if (this.regionsOnCrashedServer != null && !this.regionsOnCrashedServer.isEmpty()) {
478 RegionStates regionStates = am.getRegionStates();
479 for (HRegionInfo hri: this.regionsOnCrashedServer) {
480 if (regionsInTransition.contains(hri)) continue;
481 String encodedName = hri.getEncodedName();
482 Lock lock = am.acquireRegionLock(encodedName);
483 try {
484 RegionState rit = regionStates.getRegionTransitionState(hri);
485 if (processDeadRegion(hri, am)) {
486 ServerName addressFromAM = regionStates.getRegionServerOfRegion(hri);
487 if (addressFromAM != null && !addressFromAM.equals(this.serverName)) {
488
489
490
491 LOG.info("Skip assigning " + hri.getRegionNameAsString()
492 + " because opened on " + addressFromAM.getServerName());
493 continue;
494 }
495 if (rit != null) {
496 if (rit.getServerName() != null && !rit.isOnServer(this.serverName)) {
497
498 LOG.info("Skip assigning region in transition on other server" + rit);
499 continue;
500 }
501 LOG.info("Reassigning region " + rit + " and clearing zknode if exists");
502 try {
503
504 ZKAssign.deleteNodeFailSilent(env.getMasterServices().getZooKeeper(), hri);
505 } catch (KeeperException e) {
506
507
508 env.getMasterServices().abort("Unexpected error deleting RIT " + hri, e);
509 throw new IOException(e);
510 }
511 regionStates.updateRegionState(hri, RegionState.State.OFFLINE);
512 } else if (regionStates.isRegionInState(
513 hri, RegionState.State.SPLITTING_NEW, RegionState.State.MERGING_NEW)) {
514 regionStates.updateRegionState(hri, RegionState.State.OFFLINE);
515 }
516 regionsToAssignAggregator.add(hri);
517
518 } else if (rit != null) {
519 if ((rit.isPendingCloseOrClosing() || rit.isOffline())
520 && am.getTableStateManager().isTableState(hri.getTable(),
521 ZooKeeperProtos.Table.State.DISABLED, ZooKeeperProtos.Table.State.DISABLING) ||
522 am.getReplicasToClose().contains(hri)) {
523
524
525
526
527
528 regionStates.updateRegionState(hri, RegionState.State.OFFLINE);
529 am.deleteClosingOrClosedNode(hri, rit.getServerName());
530 am.offlineDisabledRegion(hri);
531 } else {
532 LOG.warn("THIS SHOULD NOT HAPPEN: unexpected region in transition "
533 + rit + " not to be assigned by SSH of server " + serverName);
534 }
535 }
536 } finally {
537 lock.unlock();
538 }
539 }
540 }
541 return regionsToAssignAggregator;
542 }
543
544 private boolean assign(final MasterProcedureEnv env, final List<HRegionInfo> hris)
545 throws InterruptedIOException {
546 AssignmentManager am = env.getMasterServices().getAssignmentManager();
547 try {
548 am.assign(hris);
549 } catch (InterruptedException ie) {
550 LOG.error("Caught " + ie + " during round-robin assignment");
551 throw (InterruptedIOException)new InterruptedIOException().initCause(ie);
552 } catch (IOException ioe) {
553 LOG.info("Caught " + ioe + " during region assignment, will retry");
554 return false;
555 }
556 return true;
557 }
558
559 private boolean waitOnAssign(final MasterProcedureEnv env, final List<HRegionInfo> hris)
560 throws InterruptedIOException {
561 int timeout = env.getMasterConfiguration().getInt(KEY_WAIT_ON_RIT, DEFAULT_WAIT_ON_RIT);
562 for (HRegionInfo hri: hris) {
563
564 if (!waitOnRegionToClearRegionsInTransition(env.getMasterServices().getAssignmentManager(),
565 hri, timeout)) {
566 return false;
567 }
568 }
569 return true;
570 }
571
572 @Override
573 protected void rollbackState(MasterProcedureEnv env, ServerCrashState state)
574 throws IOException {
575
576 throw new UnsupportedOperationException("unhandled state=" + state);
577 }
578
579 @Override
580 protected ServerCrashState getState(int stateId) {
581 return ServerCrashState.valueOf(stateId);
582 }
583
584 @Override
585 protected int getStateId(ServerCrashState state) {
586 return state.getNumber();
587 }
588
589 @Override
590 protected ServerCrashState getInitialState() {
591 return ServerCrashState.SERVER_CRASH_START;
592 }
593
594 @Override
595 protected boolean abort(MasterProcedureEnv env) {
596
597 return false;
598 }
599
600 @Override
601 protected boolean acquireLock(final MasterProcedureEnv env) {
602 if (env.waitServerCrashProcessingEnabled(this)) return false;
603 return env.getProcedureQueue().tryAcquireServerExclusiveLock(this, getServerName());
604 }
605
606 @Override
607 protected void releaseLock(final MasterProcedureEnv env) {
608 env.getProcedureQueue().releaseServerExclusiveLock(this, getServerName());
609 }
610
611 @Override
612 public void toStringClassDetails(StringBuilder sb) {
613 sb.append(getClass().getSimpleName());
614 sb.append(" serverName=");
615 sb.append(this.serverName);
616 sb.append(", shouldSplitWal=");
617 sb.append(shouldSplitWal);
618 sb.append(", carryingMeta=");
619 sb.append(carryingMeta);
620 }
621
622 @Override
623 public void serializeStateData(final OutputStream stream) throws IOException {
624 super.serializeStateData(stream);
625
626 MasterProcedureProtos.ServerCrashStateData.Builder state =
627 MasterProcedureProtos.ServerCrashStateData.newBuilder().
628 setServerName(ProtobufUtil.toServerName(this.serverName)).
629 setDistributedLogReplay(this.distributedLogReplay).
630 setCarryingMeta(this.carryingMeta).
631 setShouldSplitWal(this.shouldSplitWal);
632 if (this.regionsOnCrashedServer != null && !this.regionsOnCrashedServer.isEmpty()) {
633 for (HRegionInfo hri: this.regionsOnCrashedServer) {
634 state.addRegionsOnCrashedServer(HRegionInfo.convert(hri));
635 }
636 }
637 if (this.regionsAssigned != null && !this.regionsAssigned.isEmpty()) {
638 for (HRegionInfo hri: this.regionsAssigned) {
639 state.addRegionsAssigned(HRegionInfo.convert(hri));
640 }
641 }
642 state.build().writeDelimitedTo(stream);
643 }
644
645 @Override
646 public void deserializeStateData(final InputStream stream) throws IOException {
647 super.deserializeStateData(stream);
648
649 MasterProcedureProtos.ServerCrashStateData state =
650 MasterProcedureProtos.ServerCrashStateData.parseDelimitedFrom(stream);
651 this.serverName = ProtobufUtil.toServerName(state.getServerName());
652 this.distributedLogReplay = state.hasDistributedLogReplay()?
653 state.getDistributedLogReplay(): false;
654 this.carryingMeta = state.hasCarryingMeta()? state.getCarryingMeta(): false;
655
656 this.shouldSplitWal = state.getShouldSplitWal();
657 int size = state.getRegionsOnCrashedServerCount();
658 if (size > 0) {
659 this.regionsOnCrashedServer = new HashSet<HRegionInfo>(size);
660 for (RegionInfo ri: state.getRegionsOnCrashedServerList()) {
661 this.regionsOnCrashedServer.add(HRegionInfo.convert(ri));
662 }
663 }
664 size = state.getRegionsAssignedCount();
665 if (size > 0) {
666 this.regionsAssigned = new ArrayList<HRegionInfo>(size);
667 for (RegionInfo ri: state.getRegionsOnCrashedServerList()) {
668 this.regionsAssigned.add(HRegionInfo.convert(ri));
669 }
670 }
671 }
672
673
674
675
676
677
678
679
680
681 private static boolean processDeadRegion(HRegionInfo hri, AssignmentManager assignmentManager)
682 throws IOException {
683 boolean tablePresent = assignmentManager.getTableStateManager().isTablePresent(hri.getTable());
684 if (!tablePresent) {
685 LOG.info("The table " + hri.getTable() + " was deleted. Hence not proceeding.");
686 return false;
687 }
688
689 boolean disabled = assignmentManager.getTableStateManager().isTableState(hri.getTable(),
690 ZooKeeperProtos.Table.State.DISABLED);
691 if (disabled){
692 LOG.info("The table " + hri.getTable() + " was disabled. Hence not proceeding.");
693 return false;
694 }
695 if (hri.isOffline() && hri.isSplit()) {
696
697
698
699 return false;
700 }
701 boolean disabling = assignmentManager.getTableStateManager().isTableState(hri.getTable(),
702 ZooKeeperProtos.Table.State.DISABLING);
703 if (disabling) {
704 LOG.info("The table " + hri.getTable() + " is disabled. Hence not assigning region" +
705 hri.getEncodedName());
706 return false;
707 }
708 return true;
709 }
710
711
712
713
714
715 private void verifyAndAssignMetaWithRetries(final MasterProcedureEnv env) throws IOException {
716 MasterServices services = env.getMasterServices();
717 int iTimes = services.getConfiguration().getInt(KEY_RETRIES_ON_META, DEFAULT_RETRIES_ON_META);
718
719 long waitTime =
720 services.getConfiguration().getLong(KEY_SHORT_WAIT_ON_META, DEFAULT_SHORT_WAIT_ON_META);
721 int iFlag = 0;
722 while (true) {
723 try {
724 verifyAndAssignMeta(env);
725 break;
726 } catch (KeeperException e) {
727 services.abort("In server shutdown processing, assigning meta", e);
728 throw new IOException("Aborting", e);
729 } catch (Exception e) {
730 if (iFlag >= iTimes) {
731 services.abort("verifyAndAssignMeta failed after" + iTimes + " retries, aborting", e);
732 throw new IOException("Aborting", e);
733 }
734 try {
735 Thread.sleep(waitTime);
736 } catch (InterruptedException e1) {
737 LOG.warn("Interrupted when is the thread sleep", e1);
738 Thread.currentThread().interrupt();
739 throw (InterruptedIOException)new InterruptedIOException().initCause(e1);
740 }
741 iFlag++;
742 }
743 }
744 }
745
746
747
748
749
750
751
752 private void verifyAndAssignMeta(final MasterProcedureEnv env)
753 throws InterruptedException, IOException, KeeperException {
754 MasterServices services = env.getMasterServices();
755 if (!isMetaAssignedQuickTest(env)) {
756 services.getAssignmentManager().assignMeta(HRegionInfo.FIRST_META_REGIONINFO);
757 } else if (serverName.equals(services.getMetaTableLocator().
758 getMetaRegionLocation(services.getZooKeeper()))) {
759
760
761 services.getAssignmentManager().assignMeta(HRegionInfo.FIRST_META_REGIONINFO);
762 } else {
763 LOG.info("Skip assigning hbase:meta because it is online at "
764 + services.getMetaTableLocator().getMetaRegionLocation(services.getZooKeeper()));
765 }
766 }
767
768
769
770
771
772
773
774 private boolean isMetaAssignedQuickTest(final MasterProcedureEnv env)
775 throws InterruptedException, IOException {
776 ZooKeeperWatcher zkw = env.getMasterServices().getZooKeeper();
777 MetaTableLocator mtl = env.getMasterServices().getMetaTableLocator();
778 boolean metaAssigned = false;
779
780 if (mtl.isLocationAvailable(zkw)) {
781 ClusterConnection connection = env.getMasterServices().getConnection();
782
783 long timeout =
784 env.getMasterConfiguration().getLong(KEY_SHORT_WAIT_ON_META, DEFAULT_SHORT_WAIT_ON_META);
785 if (mtl.verifyMetaRegionLocation(connection, zkw, timeout)) {
786 metaAssigned = true;
787 }
788 }
789 return metaAssigned;
790 }
791
792 @Override
793 public ServerName getServerName() {
794 return this.serverName;
795 }
796
797 @Override
798 public boolean hasMetaTableRegion() {
799 return this.carryingMeta;
800 }
801
802 @Override
803 public ServerOperationType getServerOperationType() {
804 return ServerOperationType.CRASH_HANDLER;
805 }
806
807
808
809
810
811
812
813
814 @Override
815 protected boolean isYieldBeforeExecuteFromState(MasterProcedureEnv env, ServerCrashState state) {
816 return true;
817 }
818
819 @Override
820 protected boolean shouldWaitClientAck(MasterProcedureEnv env) {
821
822
823 return false;
824 }
825 }