001/** 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, software 013 * distributed under the License is distributed on an "AS IS" BASIS, 014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 015 * See the License for the specific language governing permissions and 016 * limitations under the License. 017 */ 018 019package org.apache.hadoop.hdfs.server.namenode; 020 021import java.io.IOException; 022import org.apache.hadoop.classification.InterfaceAudience; 023import org.apache.hadoop.classification.InterfaceStability; 024 025import org.apache.commons.logging.Log; 026import org.apache.commons.logging.LogFactory; 027 028/** Context data for an ongoing NameNode metadata recovery process. */ 029@InterfaceAudience.Private 030@InterfaceStability.Evolving 031public final class MetaRecoveryContext { 032 public static final Log LOG = LogFactory.getLog(MetaRecoveryContext.class.getName()); 033 public final static int FORCE_NONE = 0; 034 public final static int FORCE_FIRST_CHOICE = 1; 035 public final static int FORCE_ALL = 2; 036 private int force; 037 038 /** Exception thrown when the user has requested processing to stop. */ 039 static public class RequestStopException extends IOException { 040 private static final long serialVersionUID = 1L; 041 public RequestStopException(String msg) { 042 super(msg); 043 } 044 } 045 046 public MetaRecoveryContext(int force) { 047 this.force = force; 048 } 049 050 /** 051 * Display a prompt to the user and get his or her choice. 052 * 053 * @param prompt The prompt to display 054 * @param default First choice (will be taken if autoChooseDefault is 055 * true) 056 * @param choices Other choies 057 * 058 * @return The choice that was taken 059 * @throws IOException 060 */ 061 public String ask(String prompt, String firstChoice, String... choices) 062 throws IOException { 063 while (true) { 064 System.err.print(prompt); 065 if (force > FORCE_NONE) { 066 System.out.println("automatically choosing " + firstChoice); 067 return firstChoice; 068 } 069 StringBuilder responseBuilder = new StringBuilder(); 070 while (true) { 071 int c = System.in.read(); 072 if (c == -1 || c == '\r' || c == '\n') { 073 break; 074 } 075 responseBuilder.append((char)c); 076 } 077 String response = responseBuilder.toString(); 078 if (response.equalsIgnoreCase(firstChoice)) 079 return firstChoice; 080 for (String c : choices) { 081 if (response.equalsIgnoreCase(c)) { 082 return c; 083 } 084 } 085 System.err.print("I'm sorry, I cannot understand your response.\n"); 086 } 087 } 088 089 public static void editLogLoaderPrompt(String prompt, 090 MetaRecoveryContext recovery, String contStr) 091 throws IOException, RequestStopException 092 { 093 if (recovery == null) { 094 throw new IOException(prompt); 095 } 096 LOG.error(prompt); 097 String answer = recovery.ask("\nEnter 'c' to continue, " + contStr + "\n" + 098 "Enter 's' to stop reading the edit log here, abandoning any later " + 099 "edits\n" + 100 "Enter 'q' to quit without saving\n" + 101 "Enter 'a' to always select the first choice in the future " + 102 "without prompting. " + 103 "(c/s/q/a)\n", "c", "s", "q", "a"); 104 if (answer.equals("c")) { 105 LOG.info("Continuing"); 106 return; 107 } else if (answer.equals("s")) { 108 throw new RequestStopException("user requested stop"); 109 } else if (answer.equals("q")) { 110 recovery.quit(); 111 } else { 112 recovery.setForce(FORCE_FIRST_CHOICE); 113 return; 114 } 115 } 116 117 /** Log a message and quit */ 118 public void quit() { 119 LOG.error("Exiting on user request."); 120 System.exit(0); 121 } 122 123 public int getForce() { 124 return this.force; 125 } 126 127 public void setForce(int force) { 128 this.force = force; 129 } 130}