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.ServerName; 27 import org.apache.hadoop.hbase.executor.EventHandler.EventType; 28 import org.apache.hadoop.hbase.util.Bytes; 29 import org.apache.hadoop.hbase.util.Writables; 30 import org.apache.hadoop.io.Writable; 31 32 /** 33 * Data serialized into ZooKeeper for region transitions. 34 */ 35 public class RegionTransitionData implements Writable { 36 /** 37 * Type of transition event (offline, opening, opened, closing, closed). 38 * Required. 39 */ 40 private EventType eventType; 41 42 /** Region being transitioned. Required. */ 43 private byte [] regionName; 44 45 /** Server event originated from. Optional. */ 46 private ServerName origin; 47 48 /** Time the event was created. Required but automatically set. */ 49 private long stamp; 50 51 private byte [] payload; 52 53 /** 54 * Writable constructor. Do not use directly. 55 */ 56 public RegionTransitionData() {} 57 58 /** 59 * Construct data for a new region transition event with the specified event 60 * type and region name. 61 * 62 * <p>Used when the server name is not known (the master is setting it). This 63 * happens during cluster startup or during failure scenarios. When 64 * processing a failed regionserver, the master assigns the regions from that 65 * server to other servers though the region was never 'closed'. During 66 * master failover, the new master may have regions stuck in transition 67 * without a destination so may have to set regions offline and generate a new 68 * assignment. 69 * 70 * <p>Since only the master uses this constructor, the type should always be 71 * {@link EventType#M_ZK_REGION_OFFLINE}. 72 * 73 * @param eventType type of event 74 * @param regionName name of region as per <code>HRegionInfo#getRegionName()</code> 75 */ 76 public RegionTransitionData(EventType eventType, byte [] regionName) { 77 this(eventType, regionName, null); 78 } 79 80 /** 81 * Construct data for a new region transition event with the specified event 82 * type, region name, and server name. 83 * 84 * <p>Used when the server name is known (a regionserver is setting it). 85 * 86 * <p>Valid types for this constructor are {@link EventType#M_ZK_REGION_CLOSING}, 87 * {@link EventType#RS_ZK_REGION_CLOSED}, {@link EventType#RS_ZK_REGION_OPENING}, 88 * {@link EventType#RS_ZK_REGION_SPLITTING}, 89 * and {@link EventType#RS_ZK_REGION_OPENED}. 90 * 91 * @param eventType type of event 92 * @param regionName name of region as per <code>HRegionInfo#getRegionName()</code> 93 * @param origin Originating {@link ServerName} 94 */ 95 public RegionTransitionData(EventType eventType, byte [] regionName, 96 final ServerName origin) { 97 this(eventType, regionName, origin, null); 98 } 99 100 /** 101 * Construct data for a new region transition event with the specified event 102 * type, region name, and server name. 103 * 104 * <p>Used when the server name is known (a regionserver is setting it). 105 * 106 * <p>Valid types for this constructor are {@link EventType#RS_ZK_REGION_SPLIT} 107 * since SPLIT is only type that currently carries a payload. 108 * 109 * @param eventType type of event 110 * @param regionName name of region as per <code>HRegionInfo#getRegionName()</code> 111 * @param serverName Originating {@link ServerName} 112 * @param payload Payload examples include the daughters involved in a 113 * {@link EventType#RS_ZK_REGION_SPLIT}. Can be null 114 */ 115 public RegionTransitionData(EventType eventType, byte [] regionName, 116 final ServerName serverName, final byte [] payload) { 117 this.eventType = eventType; 118 this.stamp = System.currentTimeMillis(); 119 this.regionName = regionName; 120 this.origin = serverName; 121 this.payload = payload; 122 } 123 124 /** 125 * Gets the type of region transition event. 126 * 127 * <p>One of: 128 * <ul> 129 * <li>{@link EventType#M_ZK_REGION_OFFLINE} 130 * <li>{@link EventType#M_ZK_REGION_CLOSING} 131 * <li>{@link EventType#RS_ZK_REGION_CLOSED} 132 * <li>{@link EventType#RS_ZK_REGION_OPENING} 133 * <li>{@link EventType#RS_ZK_REGION_OPENED} 134 * <li>{@link EventType#RS_ZK_REGION_SPLITTING} 135 * <li>{@link EventType#RS_ZK_REGION_SPLIT} 136 * </ul> 137 * @return type of region transition event 138 */ 139 public EventType getEventType() { 140 return eventType; 141 } 142 143 /** 144 * Gets the name of the region being transitioned. 145 * 146 * <p>Region name is required so this never returns null. 147 * @return region name, the result of a call to <code>HRegionInfo#getRegionName()</code> 148 */ 149 public byte [] getRegionName() { 150 return regionName; 151 } 152 153 /** 154 * Gets the server the event originated from. If null, this event originated 155 * from the master. 156 * 157 * @return server name of originating regionserver, or null if from master 158 */ 159 public ServerName getOrigin() { 160 return origin; 161 } 162 163 /** 164 * Gets the timestamp when this event was created. 165 * 166 * @return stamp event was created 167 */ 168 public long getStamp() { 169 return stamp; 170 } 171 172 /** 173 * @return Payload if any. 174 */ 175 public byte [] getPayload() { 176 return this.payload; 177 } 178 179 @Override 180 public void readFields(DataInput in) throws IOException { 181 // the event type byte 182 eventType = EventType.values()[in.readShort()]; 183 // the timestamp 184 stamp = in.readLong(); 185 // the encoded name of the region being transitioned 186 regionName = Bytes.readByteArray(in); 187 // remaining fields are optional so prefixed with boolean 188 // the name of the regionserver sending the data 189 if (in.readBoolean()) { 190 byte [] versionedBytes = Bytes.readByteArray(in); 191 this.origin = ServerName.parseVersionedServerName(versionedBytes); 192 } 193 if (in.readBoolean()) { 194 this.payload = Bytes.readByteArray(in); 195 } 196 } 197 198 @Override 199 public void write(DataOutput out) throws IOException { 200 out.writeShort(eventType.ordinal()); 201 out.writeLong(System.currentTimeMillis()); 202 Bytes.writeByteArray(out, regionName); 203 // remaining fields are optional so prefixed with boolean 204 out.writeBoolean(this.origin != null); 205 if (this.origin != null) { 206 Bytes.writeByteArray(out, this.origin.getVersionedBytes()); 207 } 208 out.writeBoolean(this.payload != null); 209 if (this.payload != null) { 210 Bytes.writeByteArray(out, this.payload); 211 } 212 } 213 214 /** 215 * Get the bytes for this instance. Throws a {@link RuntimeException} if 216 * there is an error deserializing this instance because it represents a code 217 * bug. 218 * @return binary representation of this instance 219 */ 220 public byte [] getBytes() { 221 try { 222 return Writables.getBytes(this); 223 } catch(IOException e) { 224 throw new RuntimeException(e); 225 } 226 } 227 228 /** 229 * Get an instance from bytes. Throws a {@link RuntimeException} if 230 * there is an error serializing this instance from bytes because it 231 * represents a code bug. 232 * @param bytes binary representation of this instance 233 * @return instance of this class 234 */ 235 public static RegionTransitionData fromBytes(byte [] bytes) { 236 try { 237 RegionTransitionData data = new RegionTransitionData(); 238 Writables.getWritable(bytes, data); 239 return data; 240 } catch(IOException e) { 241 throw new RuntimeException(e); 242 } 243 } 244 245 @Override 246 public String toString() { 247 return "region=" + Bytes.toStringBinary(regionName) + ", origin=" + this.origin + 248 ", state=" + eventType; 249 } 250 }