org.apache.hadoop.hbase.master.procedure.ProcedureSyncWait.java Source code

Java tutorial

Introduction

Here is the source code for org.apache.hadoop.hbase.master.procedure.ProcedureSyncWait.java

Source

/**
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.apache.hadoop.hbase.master.procedure;

import java.io.IOException;
import java.io.InterruptedIOException;
import java.util.List;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.hbase.CoordinatedStateException;
import org.apache.hadoop.hbase.HRegionInfo;
import org.apache.hadoop.hbase.MetaTableAccessor;
import org.apache.hadoop.hbase.NotAllMetaRegionsOnlineException;
import org.apache.hadoop.hbase.ServerName;
import org.apache.hadoop.hbase.TableName;
import org.apache.hadoop.hbase.classification.InterfaceAudience;
import org.apache.hadoop.hbase.classification.InterfaceStability;
import org.apache.hadoop.hbase.exceptions.TimeoutIOException;
import org.apache.hadoop.hbase.master.AssignmentManager;
import org.apache.hadoop.hbase.master.RegionStates;
import org.apache.hadoop.hbase.master.RegionState.State;
import org.apache.hadoop.hbase.master.ServerManager;
import org.apache.hadoop.hbase.procedure2.Procedure;
import org.apache.hadoop.hbase.procedure2.ProcedureExecutor;
import org.apache.hadoop.hbase.procedure2.ProcedureResult;
import org.apache.hadoop.hbase.quotas.MasterQuotaManager;
import org.apache.hadoop.hbase.util.EnvironmentEdgeManager;
import org.apache.hadoop.hbase.util.Threads;
import org.apache.hadoop.hbase.zookeeper.MetaTableLocator;

/**
 * Helper to synchronously wait on conditions.
 * This will be removed in the future (mainly when the AssignmentManager will be
 * replaced with a Procedure version) by using ProcedureYieldException,
 * and the queue will handle waiting and scheduling based on events.
 */
@InterfaceAudience.Private
@InterfaceStability.Evolving
public final class ProcedureSyncWait {
    private static final Log LOG = LogFactory.getLog(ProcedureSyncWait.class);

    private ProcedureSyncWait() {
    }

    @InterfaceAudience.Private
    public interface Predicate<T> {
        T evaluate() throws IOException;
    }

    public static byte[] submitAndWaitProcedure(ProcedureExecutor<MasterProcedureEnv> procExec,
            final Procedure proc) throws IOException {
        long procId = procExec.submitProcedure(proc);
        return waitForProcedureToComplete(procExec, procId);
    }

    public static byte[] waitForProcedureToComplete(ProcedureExecutor<MasterProcedureEnv> procExec,
            final long procId) throws IOException {
        while (!procExec.isFinished(procId) && procExec.isRunning()) {
            // TODO: add a config to make it tunable
            // Dev Consideration: are we waiting forever, or we can set up some timeout value?
            Threads.sleepWithoutInterrupt(250);
        }
        ProcedureResult result = procExec.getResult(procId);
        if (result != null) {
            if (result.isFailed()) {
                // If the procedure fails, we should always have an exception captured. Throw it.
                throw result.getException().unwrapRemoteException();
            }
            return result.getResult();
        } else {
            if (procExec.isRunning()) {
                throw new IOException("Procedure " + procId + "not found");
            } else {
                throw new IOException("The Master is Aborting");
            }
        }
    }

    public static <T> T waitFor(MasterProcedureEnv env, String purpose, Predicate<T> predicate) throws IOException {
        final Configuration conf = env.getMasterConfiguration();
        final long waitTime = conf.getLong("hbase.master.wait.on.region", 5 * 60 * 1000);
        final long waitingTimeForEvents = conf.getInt("hbase.master.event.waiting.time", 1000);
        return waitFor(env, waitTime, waitingTimeForEvents, purpose, predicate);
    }

    public static <T> T waitFor(MasterProcedureEnv env, long waitTime, long waitingTimeForEvents, String purpose,
            Predicate<T> predicate) throws IOException {
        final long done = EnvironmentEdgeManager.currentTime() + waitTime;
        do {
            T result = predicate.evaluate();
            if (result != null && !result.equals(Boolean.FALSE)) {
                return result;
            }
            try {
                Thread.sleep(waitingTimeForEvents);
            } catch (InterruptedException e) {
                LOG.warn("Interrupted while sleeping, waiting on " + purpose);
                throw (InterruptedIOException) new InterruptedIOException().initCause(e);
            }
            LOG.debug("Waiting on " + purpose);
        } while (EnvironmentEdgeManager.currentTime() < done && env.isRunning());

        throw new TimeoutIOException("Timed out while waiting on " + purpose);
    }

    protected static void waitMetaRegions(final MasterProcedureEnv env) throws IOException {
        int timeout = env.getMasterConfiguration().getInt("hbase.client.catalog.timeout", 10000);
        try {
            if (env.getMasterServices().getMetaTableLocator()
                    .waitMetaRegionLocation(env.getMasterServices().getZooKeeper(), timeout) == null) {
                throw new NotAllMetaRegionsOnlineException();
            }
        } catch (InterruptedException e) {
            throw (InterruptedIOException) new InterruptedIOException().initCause(e);
        }
    }

    protected static void waitRegionServers(final MasterProcedureEnv env) throws IOException {
        final ServerManager sm = env.getMasterServices().getServerManager();
        ProcedureSyncWait.waitFor(env, "server to assign region(s)", new ProcedureSyncWait.Predicate<Boolean>() {
            @Override
            public Boolean evaluate() throws IOException {
                List<ServerName> servers = sm.createDestinationServersList();
                return servers != null && !servers.isEmpty();
            }
        });
    }

    protected static List<HRegionInfo> getRegionsFromMeta(final MasterProcedureEnv env, final TableName tableName)
            throws IOException {
        return ProcedureSyncWait.waitFor(env, "regions of table=" + tableName + " from meta",
                new ProcedureSyncWait.Predicate<List<HRegionInfo>>() {
                    @Override
                    public List<HRegionInfo> evaluate() throws IOException {
                        if (TableName.META_TABLE_NAME.equals(tableName)) {
                            return new MetaTableLocator().getMetaRegions(env.getMasterServices().getZooKeeper());
                        }
                        return MetaTableAccessor.getTableRegions(env.getMasterServices().getConnection(),
                                tableName);
                    }
                });
    }

    protected static void waitRegionInTransition(final MasterProcedureEnv env, final List<HRegionInfo> regions)
            throws IOException, CoordinatedStateException {
        final AssignmentManager am = env.getMasterServices().getAssignmentManager();
        final RegionStates states = am.getRegionStates();
        for (final HRegionInfo region : regions) {
            ProcedureSyncWait.waitFor(env, "regions " + region.getRegionNameAsString() + " in transition",
                    new ProcedureSyncWait.Predicate<Boolean>() {
                        @Override
                        public Boolean evaluate() throws IOException {
                            if (states.isRegionInState(region, State.FAILED_OPEN)) {
                                am.regionOffline(region);
                            }
                            return !states.isRegionInTransition(region);
                        }
                    });
        }
    }

    protected static MasterQuotaManager getMasterQuotaManager(final MasterProcedureEnv env) throws IOException {
        return ProcedureSyncWait.waitFor(env, "quota manager to be available",
                new ProcedureSyncWait.Predicate<MasterQuotaManager>() {
                    @Override
                    public MasterQuotaManager evaluate() throws IOException {
                        return env.getMasterServices().getMasterQuotaManager();
                    }
                });
    }
}