Package org.apache.hadoop.hbase.index.coprocessor.regionserver

Source Code of org.apache.hadoop.hbase.index.coprocessor.regionserver.TTLStoreScanner

/**
* Copyright 2011 The Apache Software Foundation
*
* 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 org.apache.hadoop.hbase.index.coprocessor.regionserver;

import java.io.IOException;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.hadoop.hbase.KeyValue;
import org.apache.hadoop.hbase.client.Scan;
import org.apache.hadoop.hbase.index.IndexSpecification;
import org.apache.hadoop.hbase.index.manager.IndexManager;
import org.apache.hadoop.hbase.index.util.ByteArrayBuilder;
import org.apache.hadoop.hbase.index.util.IndexUtils;
import org.apache.hadoop.hbase.regionserver.HRegion;
import org.apache.hadoop.hbase.regionserver.HRegionServer;
import org.apache.hadoop.hbase.regionserver.InternalScanner;
import org.apache.hadoop.hbase.regionserver.KeyValueScanner;
import org.apache.hadoop.hbase.regionserver.ScanType;
import org.apache.hadoop.hbase.regionserver.Store;
import org.apache.hadoop.hbase.regionserver.StoreScanner;
import org.apache.hadoop.hbase.util.Bytes;

public class TTLStoreScanner implements InternalScanner {
  private InternalScanner delegate;
  private Store store;
  private long smallestReadPoint;
  private long earliestTS;
  private ScanType type; // (This should be scan type)
  private static final Log LOG = LogFactory.getLog(TTLStoreScanner.class);

  private TTLExpiryChecker ttlExpiryChecker;
  private String actualTableName;
  private HRegionServer rs;
  private Boolean userRegionAvailable = null;

  public TTLStoreScanner(Store store, long smallestReadPoint, long earliestTS, ScanType type,
      List<? extends KeyValueScanner> scanners, TTLExpiryChecker ttlExpiryChecker,
      String actualTableName, HRegionServer rs) throws IOException {
    this.store = store;
    this.smallestReadPoint = smallestReadPoint;
    this.earliestTS = earliestTS;
    this.type = type;
    Scan scan = new Scan();
    scan.setMaxVersions(store.getFamily().getMaxVersions());
    delegate =
        new StoreScanner(store, store.getScanInfo(), scan, scanners, type, this.smallestReadPoint,
            this.earliestTS);
    this.ttlExpiryChecker = ttlExpiryChecker;
    this.actualTableName = actualTableName;
    this.rs = rs;
  }

  @Override
  public boolean next(List<KeyValue> results) throws IOException {
    return this.next(results, 1);
  }

  @Override
  public boolean next(List<KeyValue> result, int limit) throws IOException {
    boolean next = this.delegate.next(result, limit);
    // Ideally here i should get only one result(i.e) only one kv
    for (Iterator<KeyValue> iterator = result.iterator(); iterator.hasNext();) {
      KeyValue kv = (KeyValue) iterator.next();
      byte[] indexNameInBytes = formIndexNameFromKV(kv);
      // From the indexname get the TTL
      IndexSpecification index =
          IndexManager.getInstance().getIndex(this.actualTableName, indexNameInBytes);
      HRegion hRegion = store.getHRegion();
      if (this.type == ScanType.MAJOR_COMPACT) {
        if (this.userRegionAvailable == null) {
          this.userRegionAvailable =
              isUserTableRegionAvailable(hRegion.getTableDesc().getNameAsString(), hRegion, this.rs);
        }
        // If index is null probably index is been dropped through drop index
        // If user region not available it may be due to the reason that the user region has not yet
        // opened but
        // the index region has opened.
        // Its better not to avoid the kv here, and write it during this current compaction.
        // Anyway later compaction will avoid it. May lead to false positives but better than
        // data loss
        if (null == index && userRegionAvailable) {
          // Remove the dropped index from the results
          LOG.info("The index has been removed for the kv " + kv);
          iterator.remove();
          continue;
        }
      }
      if (index != null) {
        boolean ttlExpired =
            this.ttlExpiryChecker.checkIfTTLExpired(index.getTTL(), kv.getTimestamp());
        if (ttlExpired) {
          result.clear();
          LOG.info("The ttl has expired for the kv " + kv);
          return false;
        }
      }
    }
    return next;
  }

  @Override
  public void close() throws IOException {
    this.delegate.close();
  }

  private byte[] formIndexNameFromKV(KeyValue kv) {
    byte[] rowKey = kv.getRow();
    // First two bytes are going to be the
    ByteArrayBuilder keyBuilder = ByteArrayBuilder.allocate(rowKey.length);
    // Start from 2nd offset because the first 2 bytes corresponds to the rowkeylength
    keyBuilder.put(rowKey, 0, rowKey.length);
    int indexOf = com.google.common.primitives.Bytes.indexOf(keyBuilder.array(), new byte[1]);
    return keyBuilder.array(indexOf + 1, IndexUtils.getMaxIndexNameLength());
  }

  private boolean isUserTableRegionAvailable(String indexTableName, HRegion indexRegion,
      HRegionServer rs) {
    Collection<HRegion> userRegions = rs.getOnlineRegions(Bytes.toBytes(this.actualTableName));
    for (HRegion userRegion : userRegions) {
      // TODO start key check is enough? May be we can check for the
      // possibility for N-1 Mapping?
      if (Bytes.equals(userRegion.getStartKey(), indexRegion.getStartKey())) {
        return true;
      }
    }
    return false;
  }

  @Override
  public boolean next(List<KeyValue> results, String metric) throws IOException {
    // TODO Implement InternalScanner.next
    return false;
  }

  @Override
  public boolean next(List<KeyValue> result, int limit, String metric) throws IOException {
    // TODO Implement InternalScanner.next
    return false;
  }
}
TOP

Related Classes of org.apache.hadoop.hbase.index.coprocessor.regionserver.TTLStoreScanner

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.