View Javadoc

1   /**
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *     http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing, software
13   * distributed under the License is distributed on an "AS IS" BASIS,
14   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15   * See the License for the specific language governing permissions and
16   * limitations under the License.
17   */
18  package org.apache.hadoop.hbase.zookeeper;
19  
20  import org.apache.commons.logging.Log;
21  import org.apache.commons.logging.LogFactory;
22  import org.apache.hadoop.classification.InterfaceAudience;
23  import org.apache.hadoop.hbase.Abortable;
24  import org.apache.hadoop.hbase.exceptions.DeserializationException;
25  import org.apache.hadoop.hbase.protobuf.ProtobufUtil;
26  import org.apache.hadoop.hbase.protobuf.generated.LoadBalancerProtos;
27  import org.apache.hadoop.hbase.util.Bytes;
28  import org.apache.zookeeper.KeeperException;
29  
30  import com.google.protobuf.InvalidProtocolBufferException;
31  
32  /**
33   * Tracks the load balancer state up in ZK
34   */
35  @InterfaceAudience.Private
36  public class LoadBalancerTracker extends ZooKeeperNodeTracker {
37    private static final Log LOG = LogFactory.getLog(LoadBalancerTracker.class);
38  
39    public LoadBalancerTracker(ZooKeeperWatcher watcher,
40        Abortable abortable) {
41      super(watcher, watcher.balancerZNode, abortable);
42    }
43  
44    /**
45     * Return true if the balance switch is on, false otherwise
46     */
47    public boolean isBalancerOn() {
48      byte [] upData = super.getData(false);
49      try {
50        // if data in ZK is null, use default of on.
51        return upData == null || parseFrom(upData).getBalancerOn();
52      } catch (DeserializationException dex) {
53        LOG.error("ZK state for LoadBalancer could not be parsed " + Bytes.toStringBinary(upData));
54        // return false to be safe.
55        return false;
56      }
57    }
58  
59    /**
60     * Set the balancer on/off
61     * @param balancerOn
62     * @throws KeeperException
63     */
64    public void setBalancerOn(boolean balancerOn) throws KeeperException {
65    byte [] upData = toByteArray(balancerOn);
66      try {
67        ZKUtil.setData(watcher, watcher.balancerZNode, upData);
68      } catch(KeeperException.NoNodeException nne) {
69        ZKUtil.createAndWatch(watcher, watcher.balancerZNode, upData);
70      }
71      super.nodeDataChanged(watcher.balancerZNode);
72    }
73  
74    private byte [] toByteArray(boolean isBalancerOn) {
75      LoadBalancerProtos.LoadBalancerState.Builder builder =
76        LoadBalancerProtos.LoadBalancerState.newBuilder();
77      builder.setBalancerOn(isBalancerOn);
78      return ProtobufUtil.prependPBMagic(builder.build().toByteArray());
79    }
80  
81    private LoadBalancerProtos.LoadBalancerState parseFrom(byte [] pbBytes)
82    throws DeserializationException {
83      ProtobufUtil.expectPBMagicPrefix(pbBytes);
84      LoadBalancerProtos.LoadBalancerState.Builder builder =
85        LoadBalancerProtos.LoadBalancerState.newBuilder();
86      try {
87        int magicLen = ProtobufUtil.lengthOfPBMagic();
88        builder.mergeFrom(pbBytes, magicLen, pbBytes.length - magicLen);
89      } catch (InvalidProtocolBufferException e) {
90        throw new DeserializationException(e);
91      }
92      return builder.build();
93    }
94  }