1 /** 2 * Copyright 2010 The Apache Software Foundation 3 * 4 * Licensed to the Apache Software Foundation (ASF) under one 5 * or more contributor license agreements. See the NOTICE file 6 * distributed with this work for additional information 7 * regarding copyright ownership. The ASF licenses this file 8 * to you under the Apache License, Version 2.0 (the 9 * "License"); you may not use this file except in compliance 10 * with the License. You may obtain a copy of the License at 11 * 12 * http://www.apache.org/licenses/LICENSE-2.0 13 * 14 * Unless required by applicable law or agreed to in writing, software 15 * distributed under the License is distributed on an "AS IS" BASIS, 16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 * See the License for the specific language governing permissions and 18 * limitations under the License. 19 */ 20 package org.apache.hadoop.hbase.executor; 21 22 import java.io.DataInput; 23 import java.io.DataOutput; 24 import java.io.IOException; 25 26 import org.apache.hadoop.hbase.executor.EventHandler.EventType; 27 import org.apache.hadoop.hbase.util.Bytes; 28 import org.apache.hadoop.hbase.util.Writables; 29 import org.apache.hadoop.io.Writable; 30 31 /** 32 * Data serialized into ZooKeeper for region transitions. 33 */ 34 public class RegionTransitionData implements Writable { 35 /** 36 * Type of transition event (offline, opening, opened, closing, closed). 37 * Required. 38 */ 39 private EventType eventType; 40 41 /** Region being transitioned. Required. */ 42 private byte [] regionName; 43 44 /** Server event originated from. Optional. */ 45 private String serverName; 46 47 /** Time the event was created. Required but automatically set. */ 48 private long stamp; 49 50 /** 51 * Writable constructor. Do not use directly. 52 */ 53 public RegionTransitionData() {} 54 55 /** 56 * Construct data for a new region transition event with the specified event 57 * type and region name. 58 * 59 * <p>Used when the server name is not known (the master is setting it). This 60 * happens during cluster startup or during failure scenarios. When 61 * processing a failed regionserver, the master assigns the regions from that 62 * server to other servers though the region was never 'closed'. During 63 * master failover, the new master may have regions stuck in transition 64 * without a destination so may have to set regions offline and generate a new 65 * assignment. 66 * 67 * <p>Since only the master uses this constructor, the type should always be 68 * {@link EventType#M_ZK_REGION_OFFLINE}. 69 * 70 * @param eventType type of event 71 * @param regionName name of region as per <code>HRegionInfo#getRegionName()</code> 72 */ 73 public RegionTransitionData(EventType eventType, byte [] regionName) { 74 this(eventType, regionName, null); 75 } 76 77 /** 78 * Construct data for a new region transition event with the specified event 79 * type, region name, and server name. 80 * 81 * <p>Used when the server name is known (a regionserver is setting it). 82 * 83 * <p>Valid types for this constructor are {@link EventType#RS_ZK_REGION_CLOSING}, 84 * {@link EventType#RS_ZK_REGION_CLOSED}, {@link EventType#RS_ZK_REGION_OPENING}, 85 * and {@link EventType#RS_ZK_REGION_OPENED}. 86 * 87 * @param eventType type of event 88 * @param regionName name of region as per <code>HRegionInfo#getRegionName()</code> 89 * @param serverName name of server setting data 90 */ 91 public RegionTransitionData(EventType eventType, byte [] regionName, 92 String serverName) { 93 this.eventType = eventType; 94 this.stamp = System.currentTimeMillis(); 95 this.regionName = regionName; 96 this.serverName = serverName; 97 } 98 99 /** 100 * Gets the type of region transition event. 101 * 102 * <p>One of: 103 * <ul> 104 * <li>{@link EventType#M_ZK_REGION_OFFLINE} 105 * <li>{@link EventType#RS_ZK_REGION_CLOSING} 106 * <li>{@link EventType#RS_ZK_REGION_CLOSED} 107 * <li>{@link EventType#RS_ZK_REGION_OPENING} 108 * <li>{@link EventType#RS_ZK_REGION_OPENED} 109 * </ul> 110 * @return type of region transition event 111 */ 112 public EventType getEventType() { 113 return eventType; 114 } 115 116 /** 117 * Gets the name of the region being transitioned. 118 * 119 * <p>Region name is required so this never returns null. 120 * @return region name, the result of a call to <code>HRegionInfo#getRegionName()</code> 121 */ 122 public byte [] getRegionName() { 123 return regionName; 124 } 125 126 /** 127 * Gets the server the event originated from. If null, this event originated 128 * from the master. 129 * 130 * @return server name of originating regionserver, or null if from master 131 */ 132 public String getServerName() { 133 return serverName; 134 } 135 136 /** 137 * Gets the timestamp when this event was created. 138 * 139 * @return stamp event was created 140 */ 141 public long getStamp() { 142 return stamp; 143 } 144 145 @Override 146 public void readFields(DataInput in) throws IOException { 147 // the event type byte 148 eventType = EventType.values()[in.readShort()]; 149 // the timestamp 150 stamp = in.readLong(); 151 // the encoded name of the region being transitioned 152 regionName = Bytes.readByteArray(in); 153 // remaining fields are optional so prefixed with boolean 154 // the name of the regionserver sending the data 155 if(in.readBoolean()) { 156 serverName = in.readUTF(); 157 } else { 158 serverName = null; 159 } 160 } 161 162 @Override 163 public void write(DataOutput out) throws IOException { 164 out.writeShort(eventType.ordinal()); 165 out.writeLong(System.currentTimeMillis()); 166 Bytes.writeByteArray(out, regionName); 167 // remaining fields are optional so prefixed with boolean 168 out.writeBoolean(serverName != null); 169 if(serverName != null) { 170 out.writeUTF(serverName); 171 } 172 } 173 174 /** 175 * Get the bytes for this instance. Throws a {@link RuntimeException} if 176 * there is an error deserializing this instance because it represents a code 177 * bug. 178 * @return binary representation of this instance 179 */ 180 public byte [] getBytes() { 181 try { 182 return Writables.getBytes(this); 183 } catch(IOException e) { 184 throw new RuntimeException(e); 185 } 186 } 187 188 /** 189 * Get an instance from bytes. Throws a {@link RuntimeException} if 190 * there is an error serializing this instance from bytes because it 191 * represents a code bug. 192 * @param bytes binary representation of this instance 193 * @return instance of this class 194 */ 195 public static RegionTransitionData fromBytes(byte [] bytes) { 196 try { 197 RegionTransitionData data = new RegionTransitionData(); 198 Writables.getWritable(bytes, data); 199 return data; 200 } catch(IOException e) { 201 throw new RuntimeException(e); 202 } 203 } 204 205 @Override 206 public String toString() { 207 return "region=" + Bytes.toStringBinary(regionName) + 208 ", server=" + serverName + ", state=" + eventType; 209 } 210 }