c5db.tablet.tabletCreationBehaviors.RootTabletLeaderBehavior.java Source code

Java tutorial

Introduction

Here is the source code for c5db.tablet.tabletCreationBehaviors.RootTabletLeaderBehavior.java

Source

/*
 * Copyright 2014 WANdisco
 *
 *  WANdisco 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 c5db.tablet.tabletCreationBehaviors;

import c5db.C5ServerConstants;
import c5db.client.ProtobufUtil;
import c5db.client.generated.Condition;
import c5db.client.generated.MutationProto;
import c5db.client.generated.RegionInfo;
import c5db.client.generated.Scan;
import c5db.client.generated.TableName;
import c5db.interfaces.ModuleInformationProvider;
import c5db.interfaces.server.CommandRpcRequest;
import c5db.interfaces.tablet.Tablet;
import c5db.messages.generated.ModuleSubCommand;
import c5db.messages.generated.ModuleType;
import c5db.tablet.Region;
import c5db.tablet.SystemTableNames;
import c5db.util.FiberOnly;
import c5db.util.TabletNameHelpers;
import io.protostuff.LinkedBuffer;
import io.protostuff.ProtobufIOUtil;
import org.apache.commons.lang.StringUtils;
import org.apache.hadoop.hbase.Cell;
import org.apache.hadoop.hbase.HConstants;
import org.apache.hadoop.hbase.client.Put;
import org.apache.hadoop.hbase.regionserver.RegionScanner;
import org.apache.hadoop.hbase.util.Bytes;

import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.ExecutionException;

public class RootTabletLeaderBehavior implements TabletLeaderBehavior {
    private final long numberOfMetaPeers;
    private final Tablet tablet;
    private final ModuleInformationProvider moduleInformationProvider;

    public RootTabletLeaderBehavior(final Tablet tablet, final ModuleInformationProvider moduleInformationProvider,
            final long numberOfMetaPeers) {
        this.numberOfMetaPeers = numberOfMetaPeers;
        this.moduleInformationProvider = moduleInformationProvider;
        this.tablet = tablet;
    }

    public void start() throws IOException, ExecutionException, InterruptedException {
        Region region = tablet.getRegion();
        if (!metaExists(region)) {
            List<Long> pickedPeers = shuffleListAndReturnMetaRegionPeers(tablet.getPeers());
            createLeaderLessMetaEntryInRoot(region, pickedPeers);
            requestMetaCommandCreated(pickedPeers);
        } else {
            // TODO Check to see if you can take root
        }
    }

    boolean metaExists(Region region) throws IOException {
        // TODO We should make sure the meta is well formed
        RegionScanner scanner = region.getScanner(new Scan());
        List<Cell> results = new ArrayList<>();
        scanner.next(results, 1);
        return results.size() > 0;
    }

    private List<Long> shuffleListAndReturnMetaRegionPeers(final List<Long> peers) {
        Collections.shuffle(new ArrayList<>(peers));
        return peers.subList(0, (int) numberOfMetaPeers);
    }

    @FiberOnly
    private void requestMetaCommandCreated(List<Long> peers) throws ExecutionException, InterruptedException {
        String pickedPeersString = StringUtils.join(peers, ',');
        ModuleSubCommand moduleSubCommand = new ModuleSubCommand(ModuleType.Tablet,
                C5ServerConstants.START_META + ":" + pickedPeersString);

        for (long peer : peers) {
            CommandRpcRequest<ModuleSubCommand> commandRpcRequest = new CommandRpcRequest<>(peer, moduleSubCommand);
            TabletLeaderBehaviorHelper.sendRequest(commandRpcRequest, moduleInformationProvider);
        }
    }

    private void createLeaderLessMetaEntryInRoot(Region region, List<Long> pickedPeers) throws IOException {
        org.apache.hadoop.hbase.TableName hbaseDatabaseName = SystemTableNames.metaTableName();
        ByteBuffer hbaseNameSpace = ByteBuffer.wrap(hbaseDatabaseName.getNamespace());
        ByteBuffer hbaseTableName = ByteBuffer.wrap(hbaseDatabaseName.getQualifier());
        TableName tableName = new TableName(hbaseNameSpace, hbaseTableName);

        byte[] initialMetaRockeyInRoot = Bytes.add(TabletNameHelpers.toBytes(tableName), SystemTableNames.sep,
                new byte[0]);
        Put put = new Put(initialMetaRockeyInRoot);

        RegionInfo regionInfo = new RegionInfo(1, tableName, pickedPeers, 0l, // This signifies that we haven't picked the leader
                ByteBuffer.wrap(new byte[0]), ByteBuffer.wrap(new byte[0]), true, false);

        put.add(HConstants.CATALOG_FAMILY, HConstants.REGIONINFO_QUALIFIER,
                ProtobufIOUtil.toByteArray(regionInfo, RegionInfo.getSchema(), LinkedBuffer.allocate(512)));

        boolean processed = region.mutate(ProtobufUtil.toMutation(MutationProto.MutationType.PUT, put),
                new Condition());
        if (!processed) {
            throw new IOException(
                    "Unable to mutate root and thus we can't properly run root tablet leader behavior");
        }
    }
}