sleet.generators.reservedinstance.ZooKeeperReservedInstanceIdGenerator.java Source code

Java tutorial

Introduction

Here is the source code for sleet.generators.reservedinstance.ZooKeeperReservedInstanceIdGenerator.java

Source

/**
 * 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 sleet.generators.reservedinstance;

import java.io.IOException;
import java.util.List;
import java.util.Properties;

import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.Watcher;
import org.apache.zookeeper.ZooKeeper;

import sleet.SleetException;
import sleet.generators.GeneratorConfigException;
import sleet.generators.GeneratorSessionException;
import sleet.generators.IdGenerator;
import sleet.id.LongId;
import sleet.id.LongIdType;
import sleet.state.IdState;
import sleet.utils.zookeeper.InstanceIdManagerRaceZooKeeper;
import sleet.utils.zookeeper.ZooKeeperClient;

public class ZooKeeperReservedInstanceIdGenerator implements IdGenerator<LongIdType> {

    public static final String ZK_SERVER_KEY = "zk.reserved.instance.zk.server";
    public static final String ZK_PATH_KEY = "zk.reserved.instance.zk.path";
    public static final String ZK_TIMEOUT_KEY = "zk.reserved.instance.zk.timeout";
    public static final String BITS_IN_INSTANCE_ID_KEY = "zk.reserved.instance.bits.in.instance.value";
    public static final String MILLISECONDS_TO_WAIT_FOR_ID = "zk.reserved.instance.milliseconds.to.wait.for.startup";

    private int bitsInInstanceValue = -1;
    private int maxInstanceValue = -1;
    private ZooKeeper zk = null;
    private String path = null;
    private InstanceIdManagerRaceZooKeeper instMgr = null;
    private LongId id = null;

    public ZooKeeperReservedInstanceIdGenerator() {
    }

    @Override
    public void beginIdSession(Properties config) throws SleetException {
        if (this.zk != null) {
            throw new GeneratorSessionException(
                    "Session was already started.  Stop session by calling endIdSession() then start session by calling beginIdSession()");
        }

        String zkStr = config.getProperty(ZK_SERVER_KEY);
        if (zkStr == null) {
            throw new GeneratorConfigException(
                    "Missing ZooKeeper server string, must be specified in configuration properties key \""
                            + ZK_SERVER_KEY + "\".");
        }

        String zkPathStr = config.getProperty(ZK_PATH_KEY);
        if (zkPathStr == null) {
            throw new GeneratorConfigException(
                    "Missing ZooKeeper path string, must be specified in configuration properties key \""
                            + ZK_PATH_KEY + "\".");
        }

        this.path = zkPathStr;

        String zkTimeoutStr = config.getProperty(ZK_TIMEOUT_KEY);
        if (zkTimeoutStr == null) {
            throw new GeneratorConfigException(
                    "Missing ZooKeeper timeout, must be specified in configuration properties key \""
                            + ZK_TIMEOUT_KEY + "\".");
        }
        int zkTimeout = -1;
        try {
            zkTimeout = Integer.valueOf(zkTimeoutStr);
        } catch (NumberFormatException e) {
            throw new GeneratorConfigException("Failed to parse ZooKeeper timeout from value \"" + zkTimeoutStr
                    + "\".  The value must be an integer.");
        }

        try {
            this.zk = new ZooKeeperClient(zkStr, zkTimeout, new Watcher() {
                @Override
                public void process(WatchedEvent event) {

                }
            });
        } catch (IOException e) {
            throw new SleetException(e);
        }

        String bitsStr = config.getProperty(BITS_IN_INSTANCE_ID_KEY);
        if (bitsStr == null) {
            throw new GeneratorConfigException(
                    "Missing number of bits, must be specified in configuration properties key \""
                            + BITS_IN_INSTANCE_ID_KEY + "\".");
        }
        int bits = -1;
        try {
            bits = Integer.valueOf(bitsStr);
        } catch (NumberFormatException e) {
            throw new GeneratorConfigException("Failed to parse number of bits from value \"" + bitsStr
                    + "\".  The value must be an integer.");
        }
        this.bitsInInstanceValue = bits;
        this.maxInstanceValue = (1 << this.bitsInInstanceValue) - 1;

        String msTimeoutStr = config.getProperty(MILLISECONDS_TO_WAIT_FOR_ID);
        if (msTimeoutStr == null) {
            throw new GeneratorConfigException(
                    "Missing number of milliseconds to wait on startup, must be specified in configuration properties key \""
                            + MILLISECONDS_TO_WAIT_FOR_ID + "\".");
        }
        int msTimeout = -1;
        try {
            msTimeout = Integer.valueOf(msTimeoutStr);
        } catch (NumberFormatException e) {
            throw new GeneratorConfigException(
                    "Failed to parse number of milliseconds to wait on startup from value \"" + msTimeoutStr
                            + "\".  The value must be an integer.");
        }

        try {
            this.instMgr = new InstanceIdManagerRaceZooKeeper(this.zk, this.path, this.maxInstanceValue + 1);
            long underlyingid = this.instMgr.tryToGetId(msTimeout);
            if (underlyingid == -1) {
                throw new ReservedInstanceTimeoutException(
                        "Unable to allocate an id instance within the timeout allotted (" + msTimeout + ")");
            } else {
                this.id = new LongId(underlyingid, null, this.bitsInInstanceValue);
            }
        } catch (IOException e) {
            throw new SleetException(e);
        }
    }

    @Override
    public void checkSessionValidity() throws SleetException {
        checkSessionValidity(true);
    }

    public void checkSessionValidity(boolean allowValidityStateCaching) throws SleetException {
        validateSessionStarted();
        try {
            if (!this.instMgr.sessionValid(allowValidityStateCaching)) {
                throw new GeneratorSessionException("Underlying " + this.instMgr.getClass().getName()
                        + " implementation lost session validity.");
            }
        } catch (IOException e) {
            throw new SleetException(e);
        }
    }

    @Override
    public void endIdSession() throws SleetException {
        checkSessionValidity(false);
        try {
            this.instMgr.releaseId(this.id.getId().intValue());
        } catch (IOException e) {
            throw new SleetException(e);
        }
        try {
            this.zk.close();
        } catch (InterruptedException e) {
            throw new SleetException(e);
        }
        this.bitsInInstanceValue = -1;
        this.maxInstanceValue = -1;
        this.zk = null;
        this.path = null;
        this.instMgr = null;
        this.id = null;
    }

    @Override
    public LongIdType getId(List<IdState<?, ?>> states) throws SleetException {
        checkSessionValidity(true);
        return this.id;
    }

    private void validateSessionStarted() throws GeneratorSessionException {
        if (this.id == null) {
            throw new GeneratorSessionException(
                    "Session was not started.  Start session by calling beginIdSession()");
        }
    }

}