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.hbase.zookeeper; 020 021import java.io.IOException; 022import org.apache.hadoop.hbase.Abortable; 023import org.apache.hadoop.hbase.exceptions.DeserializationException; 024import org.apache.hadoop.hbase.util.Bytes; 025import org.apache.yetus.audience.InterfaceAudience; 026import org.apache.zookeeper.KeeperException; 027import org.slf4j.Logger; 028import org.slf4j.LoggerFactory; 029 030import org.apache.hadoop.hbase.shaded.protobuf.ProtobufUtil; 031import org.apache.hadoop.hbase.shaded.protobuf.generated.RegionNormalizerProtos; 032 033/** 034 * Tracks region normalizer state up in ZK 035 */ 036@InterfaceAudience.Private 037public class RegionNormalizerTracker extends ZKNodeTracker { 038 private static final Logger LOG = LoggerFactory.getLogger(RegionNormalizerTracker.class); 039 040 public RegionNormalizerTracker(ZKWatcher watcher, Abortable abortable) { 041 super(watcher, watcher.getZNodePaths().regionNormalizerZNode, abortable); 042 } 043 044 /** 045 * Return true if region normalizer is on, false otherwise 046 */ 047 public boolean isNormalizerOn() { 048 byte [] upData = super.getData(false); 049 try { 050 // if data in ZK is null, use default of on. 051 return upData == null || parseFrom(upData).getNormalizerOn(); 052 } catch (DeserializationException dex) { 053 LOG.error("ZK state for RegionNormalizer could not be parsed " 054 + Bytes.toStringBinary(upData)); 055 // return false to be safe. 056 return false; 057 } 058 } 059 060 /** 061 * Set region normalizer on/off 062 * @param normalizerOn whether normalizer should be on or off 063 * @throws KeeperException if a ZooKeeper operation fails 064 */ 065 public void setNormalizerOn(boolean normalizerOn) throws KeeperException { 066 byte [] upData = toByteArray(normalizerOn); 067 try { 068 ZKUtil.setData(watcher, watcher.getZNodePaths().regionNormalizerZNode, upData); 069 } catch(KeeperException.NoNodeException nne) { 070 ZKUtil.createAndWatch(watcher, watcher.getZNodePaths().regionNormalizerZNode, upData); 071 } 072 super.nodeDataChanged(watcher.getZNodePaths().regionNormalizerZNode); 073 } 074 075 private byte [] toByteArray(boolean isNormalizerOn) { 076 RegionNormalizerProtos.RegionNormalizerState.Builder builder = 077 RegionNormalizerProtos.RegionNormalizerState.newBuilder(); 078 builder.setNormalizerOn(isNormalizerOn); 079 return ProtobufUtil.prependPBMagic(builder.build().toByteArray()); 080 } 081 082 private RegionNormalizerProtos.RegionNormalizerState parseFrom(byte [] pbBytes) 083 throws DeserializationException { 084 ProtobufUtil.expectPBMagicPrefix(pbBytes); 085 RegionNormalizerProtos.RegionNormalizerState.Builder builder = 086 RegionNormalizerProtos.RegionNormalizerState.newBuilder(); 087 try { 088 int magicLen = ProtobufUtil.lengthOfPBMagic(); 089 ProtobufUtil.mergeFrom(builder, pbBytes, magicLen, pbBytes.length - magicLen); 090 } catch (IOException e) { 091 throw new DeserializationException(e); 092 } 093 return builder.build(); 094 } 095}