/** * Copyright 2010 The Apache Software Foundation * * 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.executor; import java.io.DataInput; import java.io.DataOutput; import java.io.IOException; import org.apache.hadoop.hbase.executor.EventHandler.EventType; import org.apache.hadoop.hbase.util.Bytes; import org.apache.hadoop.hbase.util.Writables; import org.apache.hadoop.io.Writable; /** * Data serialized into ZooKeeper for region transitions. */ public class RegionTransitionData implements Writable { /** * Type of transition event (offline, opening, opened, closing, closed). * Required. */ private EventType eventType; /** Region being transitioned. Required. */ private byte [] regionName; /** Server event originated from. Optional. */ private String serverName; /** Time the event was created. Required but automatically set. */ private long stamp; /** * Writable constructor. Do not use directly. */ public RegionTransitionData() {} /** * Construct data for a new region transition event with the specified event * type and region name. * * <p>Used when the server name is not known (the master is setting it). This * happens during cluster startup or during failure scenarios. When * processing a failed regionserver, the master assigns the regions from that * server to other servers though the region was never 'closed'. During * master failover, the new master may have regions stuck in transition * without a destination so may have to set regions offline and generate a new * assignment. * * <p>Since only the master uses this constructor, the type should always be * {@link EventType#M_ZK_REGION_OFFLINE}. * * @param eventType type of event * @param regionName name of region as per <code>HRegionInfo#getRegionName()</code> */ public RegionTransitionData(EventType eventType, byte [] regionName) { this(eventType, regionName, null); } /** * Construct data for a new region transition event with the specified event * type, region name, and server name. * * <p>Used when the server name is known (a regionserver is setting it). * * <p>Valid types for this constructor are {@link EventType#RS_ZK_REGION_CLOSING}, * {@link EventType#RS_ZK_REGION_CLOSED}, {@link EventType#RS_ZK_REGION_OPENING}, * and {@link EventType#RS_ZK_REGION_OPENED}. * * @param eventType type of event * @param regionName name of region as per <code>HRegionInfo#getRegionName()</code> * @param serverName name of server setting data */ public RegionTransitionData(EventType eventType, byte [] regionName, String serverName) { this.eventType = eventType; this.stamp = System.currentTimeMillis(); this.regionName = regionName; this.serverName = serverName; } /** * Gets the type of region transition event. * * <p>One of: * <ul> * <li>{@link EventType#M_ZK_REGION_OFFLINE} * <li>{@link EventType#RS_ZK_REGION_CLOSING} * <li>{@link EventType#RS_ZK_REGION_CLOSED} * <li>{@link EventType#RS_ZK_REGION_OPENING} * <li>{@link EventType#RS_ZK_REGION_OPENED} * </ul> * @return type of region transition event */ public EventType getEventType() { return eventType; } /** * Gets the name of the region being transitioned. * * <p>Region name is required so this never returns null. * @return region name, the result of a call to <code>HRegionInfo#getRegionName()</code> */ public byte [] getRegionName() { return regionName; } /** * Gets the server the event originated from. If null, this event originated * from the master. * * @return server name of originating regionserver, or null if from master */ public String getServerName() { return serverName; } /** * Gets the timestamp when this event was created. * * @return stamp event was created */ public long getStamp() { return stamp; } @Override public void readFields(DataInput in) throws IOException { // the event type byte eventType = EventType.values()[in.readShort()]; // the timestamp stamp = in.readLong(); // the encoded name of the region being transitioned regionName = Bytes.readByteArray(in); // remaining fields are optional so prefixed with boolean // the name of the regionserver sending the data if(in.readBoolean()) { serverName = in.readUTF(); } else { serverName = null; } } @Override public void write(DataOutput out) throws IOException { out.writeShort(eventType.ordinal()); out.writeLong(System.currentTimeMillis()); Bytes.writeByteArray(out, regionName); // remaining fields are optional so prefixed with boolean out.writeBoolean(serverName != null); if(serverName != null) { out.writeUTF(serverName); } } /** * Get the bytes for this instance. Throws a {@link RuntimeException} if * there is an error deserializing this instance because it represents a code * bug. * @return binary representation of this instance */ public byte [] getBytes() { try { return Writables.getBytes(this); } catch(IOException e) { throw new RuntimeException(e); } } /** * Get an instance from bytes. Throws a {@link RuntimeException} if * there is an error serializing this instance from bytes because it * represents a code bug. * @param bytes binary representation of this instance * @return instance of this class */ public static RegionTransitionData fromBytes(byte [] bytes) { try { RegionTransitionData data = new RegionTransitionData(); Writables.getWritable(bytes, data); return data; } catch(IOException e) { throw new RuntimeException(e); } } @Override public String toString() { return "region=" + Bytes.toString(regionName) + ", server=" + serverName + ", state=" + eventType; } }