All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.tikv.common.region.TiRegion Maven / Gradle / Ivy

The newest version!
/*
 *
 * Copyright 2017 PingCAP, Inc.
 *
 * Licensed 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,
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

package org.tikv.common.region;

import com.google.protobuf.ByteString;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import org.tikv.common.TiConfiguration.KVMode;
import org.tikv.common.codec.Codec.BytesCodec;
import org.tikv.common.codec.CodecDataInput;
import org.tikv.common.codec.KeyUtils;
import org.tikv.common.exception.TiClientInternalException;
import org.tikv.common.key.Key;
import org.tikv.common.util.FastByteComparisons;
import org.tikv.common.util.KeyRangeUtils;
import org.tikv.kvproto.Kvrpcpb;
import org.tikv.kvproto.Kvrpcpb.IsolationLevel;
import org.tikv.kvproto.Metapb;
import org.tikv.kvproto.Metapb.Peer;
import org.tikv.kvproto.Metapb.Region;

public class TiRegion implements Serializable {
  private final Region meta;
  private final IsolationLevel isolationLevel;
  private final Kvrpcpb.CommandPri commandPri;
  private Peer peer;

  public TiRegion(
      Region meta,
      Peer peer,
      IsolationLevel isolationLevel,
      Kvrpcpb.CommandPri commandPri,
      KVMode kvMode) {
    Objects.requireNonNull(meta, "meta is null");
    this.meta = decodeRegion(meta, kvMode == KVMode.RAW);
    if (peer == null || peer.getId() == 0) {
      if (meta.getPeersCount() == 0) {
        throw new TiClientInternalException("Empty peer list for region " + meta.getId());
      }
      // region's first peer is leader.
      this.peer = meta.getPeers(0);
    } else {
      this.peer = peer;
    }
    this.isolationLevel = isolationLevel;
    this.commandPri = commandPri;
  }

  private Region decodeRegion(Region region, boolean isRawRegion) {
    Region.Builder builder =
        Region.newBuilder()
            .setId(region.getId())
            .setRegionEpoch(region.getRegionEpoch())
            .addAllPeers(region.getPeersList());

    if (region.getStartKey().isEmpty() || isRawRegion) {
      builder.setStartKey(region.getStartKey());
    } else {
      byte[] decodedStartKey = BytesCodec.readBytes(new CodecDataInput(region.getStartKey()));
      builder.setStartKey(ByteString.copyFrom(decodedStartKey));
    }

    if (region.getEndKey().isEmpty() || isRawRegion) {
      builder.setEndKey(region.getEndKey());
    } else {
      byte[] decodedEndKey = BytesCodec.readBytes(new CodecDataInput(region.getEndKey()));
      builder.setEndKey(ByteString.copyFrom(decodedEndKey));
    }

    return builder.build();
  }

  public Peer getLeader() {
    return peer;
  }

  public List getLearnerList() {
    List peers = new ArrayList<>();
    for (Peer peer : getMeta().getPeersList()) {
      if (peer.getIsLearner()) {
        peers.add(peer);
      }
    }
    return peers;
  }

  public long getId() {
    return this.meta.getId();
  }

  public ByteString getStartKey() {
    return meta.getStartKey();
  }

  public boolean contains(Key key) {
    return KeyRangeUtils.makeRange(this.getStartKey(), this.getEndKey()).contains(key);
  }

  public ByteString getEndKey() {
    return meta.getEndKey();
  }

  public Key getRowEndKey() {
    return Key.toRawKey(getEndKey());
  }

  public Kvrpcpb.Context getContext() {
    return getContext(java.util.Collections.emptySet());
  }

  public Kvrpcpb.Context getContext(Set resolvedLocks) {
    Kvrpcpb.Context.Builder builder = Kvrpcpb.Context.newBuilder();
    builder.setIsolationLevel(this.isolationLevel);
    builder.setPriority(this.commandPri);
    builder.setRegionId(meta.getId()).setPeer(this.peer).setRegionEpoch(this.meta.getRegionEpoch());
    builder.addAllResolvedLocks(resolvedLocks);
    return builder.build();
  }

  // getVerID returns the Region's RegionVerID.
  public RegionVerID getVerID() {
    return new RegionVerID(
        meta.getId(), meta.getRegionEpoch().getConfVer(), meta.getRegionEpoch().getVersion());
  }

  /**
   * switches current peer to the one on specific store. It return false if no peer matches the
   * storeID.
   *
   * @param leaderStoreID is leader peer id.
   * @return false if no peers matches the store id.
   */
  boolean switchPeer(long leaderStoreID) {
    List peers = meta.getPeersList();
    for (Peer p : peers) {
      if (p.getStoreId() == leaderStoreID) {
        this.peer = p;
        return true;
      }
    }
    return false;
  }

  public boolean isMoreThan(ByteString key) {
    return FastByteComparisons.compareTo(
            meta.getStartKey().toByteArray(),
            0,
            meta.getStartKey().size(),
            key.toByteArray(),
            0,
            key.size())
        > 0;
  }

  public boolean isLessThan(ByteString key) {
    return FastByteComparisons.compareTo(
            meta.getEndKey().toByteArray(),
            0,
            meta.getEndKey().size(),
            key.toByteArray(),
            0,
            key.size())
        <= 0;
  }

  public boolean contains(ByteString key) {
    return !isMoreThan(key) && !isLessThan(key);
  }

  public boolean isValid() {
    return peer != null && meta != null;
  }

  public Metapb.RegionEpoch getRegionEpoch() {
    return this.meta.getRegionEpoch();
  }

  public Region getMeta() {
    return meta;
  }

  @Override
  public boolean equals(final Object another) {
    if (!(another instanceof TiRegion)) {
      return false;
    }
    TiRegion anotherRegion = ((TiRegion) another);
    return anotherRegion.meta.equals(this.meta)
        && anotherRegion.peer.equals(this.peer)
        && anotherRegion.commandPri.equals(this.commandPri)
        && anotherRegion.isolationLevel.equals(this.isolationLevel);
  }

  @Override
  public int hashCode() {
    return Objects.hash(meta, peer, isolationLevel, commandPri);
  }

  @Override
  public String toString() {
    return String.format(
        "{Region[%d] ConfVer[%d] Version[%d] Store[%d] KeyRange[%s]:[%s]}",
        getId(),
        getRegionEpoch().getConfVer(),
        getRegionEpoch().getVersion(),
        getLeader().getStoreId(),
        KeyUtils.formatBytesUTF8(getStartKey()),
        KeyUtils.formatBytesUTF8(getEndKey()));
  }

  public class RegionVerID {
    final long id;
    final long confVer;
    final long ver;

    RegionVerID(long id, long confVer, long ver) {
      this.id = id;
      this.confVer = confVer;
      this.ver = ver;
    }

    @Override
    public boolean equals(Object other) {
      if (this == other) {
        return true;
      }
      if (!(other instanceof RegionVerID)) {
        return false;
      }

      RegionVerID that = (RegionVerID) other;
      return id == that.id && confVer == that.confVer && ver == that.ver;
    }

    @Override
    public int hashCode() {
      int hash = Long.hashCode(id);
      hash = hash * 31 + Long.hashCode(confVer);
      hash = hash * 31 + Long.hashCode(ver);
      return hash;
    }
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy