Package net.opentsdb.tools

Source Code of net.opentsdb.tools.ContinueCB

// This file is part of OpenTSDB.
// Copyright (C) 2013  The OpenTSDB Authors.
//
// This program is free software: you can redistribute it and/or modify it
// under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 2.1 of the License, or (at your
// option) any later version.  This program is distributed in the hope that it
// will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser
// General Public License for more details.  You should have received a copy
// of the GNU Lesser General Public License along with this program.  If not,
// see <http://www.gnu.org/licenses/>.
package net.opentsdb.tools;

import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.Arrays;

import net.opentsdb.core.TSDB;
import net.opentsdb.meta.TSMeta;

import org.hbase.async.Bytes;
import org.hbase.async.DeleteRequest;
import org.hbase.async.HBaseException;
import org.hbase.async.KeyValue;
import org.hbase.async.Scanner;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.stumbleupon.async.Callback;
import com.stumbleupon.async.Deferred;

/**
* Tool helper class used to delete all TSMeta and UIDMeta entries from the
* UID table.
* <b>Note:</b> After you execute this, you may want to perform a "flush" on
* the UID table in HBase so that the data doesn't mysteriously come back.
*/
final class MetaPurge extends Thread {
  private static final Logger LOG = LoggerFactory.getLogger(MetaPurge.class);
 
  /** Charset used to convert Strings to byte arrays and back. */
  private static final Charset CHARSET = Charset.forName("ISO-8859-1");
  /** Name of the CF where trees and branches are stored */
  private static final byte[] NAME_FAMILY = "name".getBytes(CHARSET);
 
  /** TSDB to use for storage access */
  private final TSDB tsdb;

  /** Number of columns deleted */
  private long columns;
 
  /** The ID to start the sync with for this thread */
  final long start_id;
 
  /** The end of the ID block to work on */
  final long end_id;
 
  /** Diagnostic ID for this thread */
  final int thread_id;
 
  /**
   * Constructor that sets local variables
   * @param tsdb The TSDB to process with
   * @param start_id The starting ID of the block we'll work on
   * @param quotient The total number of IDs in our block
   * @param thread_id The ID of this thread (starts at 0)
   */
  public MetaPurge(final TSDB tsdb, final long start_id, final double quotient,
      final int thread_id) {
    this.tsdb = tsdb;
    this.start_id = start_id;
    this.end_id = start_id + (long) quotient + 1; // teensy bit of overlap
    this.thread_id = thread_id;
  }
 
  /**
   * Loops through the entire tsdb-uid table, then the meta data table and exits
   * when complete.
   */
  public void run() {
    long purged_columns;
    try {
      purged_columns = purgeUIDMeta().joinUninterruptibly();
      LOG.info("Thread [" + thread_id + "] finished. Purged [" +
          purged_columns + "] UIDMeta columns from storage");
     
      purged_columns = purgeTSMeta().joinUninterruptibly();
      LOG.info("Thread [" + thread_id + "] finished. Purged [" +
          purged_columns + "] TSMeta columns from storage");
    } catch (Exception e) {
      LOG.error("Unexpected exception", e);
    }
   
  }
 
  /**
   * Scans the entire UID table and removes any UIDMeta objects found.
   * @return The total number of columns deleted
   */
  public Deferred<Long> purgeUIDMeta() {
   
    // a list to store all pending deletes so we don't exit before they've
    // completed
    final ArrayList<Deferred<Object>> delete_calls =
      new ArrayList<Deferred<Object>>();
    final Deferred<Long> result = new Deferred<Long>();
   
    /**
     * Scanner callback that will recursively call itself and loop through the
     * rows of the UID table, issuing delete requests for all of the columns in
     * a row that match a meta qualifier.
     */
    final class MetaScanner implements Callback<Deferred<Long>,
      ArrayList<ArrayList<KeyValue>>> {

      final Scanner scanner;
     
      public MetaScanner() {
        scanner = getScanner(tsdb.uidTable());
      }
     
      /**
       * Fetches the next group of rows from the scanner and sets this class as
       * a callback
       * @return The total number of columns deleted after completion
       */
      public Deferred<Long> scan() {
        return scanner.nextRows().addCallbackDeferring(this);
      }
     
      @Override
      public Deferred<Long> call(ArrayList<ArrayList<KeyValue>> rows)
          throws Exception {
        if (rows == null) {
          result.callback(columns);
          return null;
        }
       
        for (final ArrayList<KeyValue> row : rows) {
          // one delete request per row. We'll almost always delete the whole
          // row, so preallocate some ram.
          ArrayList<byte[]> qualifiers = new ArrayList<byte[]>(row.size());
         
          for (KeyValue column : row) {
            if (Bytes.equals(TSMeta.META_QUALIFIER(), column.qualifier())) {
              qualifiers.add(column.qualifier());
            } else if (Bytes.equals("metric_meta".getBytes(CHARSET),
                column.qualifier())) {
              qualifiers.add(column.qualifier());
            } else if (Bytes.equals("tagk_meta".getBytes(CHARSET),
                column.qualifier())) {
              qualifiers.add(column.qualifier());
            } else if (Bytes.equals("tagv_meta".getBytes(CHARSET),
                column.qualifier())) {
              qualifiers.add(column.qualifier());
            }
          }
         
          if (qualifiers.size() > 0) {
            columns += qualifiers.size();
            final DeleteRequest delete = new DeleteRequest(tsdb.uidTable(),
                row.get(0).key(), NAME_FAMILY,
                qualifiers.toArray(new byte[qualifiers.size()][]));
            delete_calls.add(tsdb.getClient().delete(delete));
          }
        }
       
        /**
         * Buffer callback used to wait on all of the delete calls for the
         * last set of rows returned from the scanner so we don't fill up the
         * deferreds array and OOM out.
         */
        final class ContinueCB implements Callback<Deferred<Long>,
          ArrayList<Object>> {

          @Override
          public Deferred<Long> call(ArrayList<Object> deletes)
              throws Exception {
            LOG.debug("[" + thread_id + "] Processed [" + deletes.size()
                + "] delete calls");
            delete_calls.clear();
            return scan();
          }
         
        }
       
        // fetch the next set of rows after waiting for current set of delete
        // requests to complete
        Deferred.group(delete_calls).addCallbackDeferring(new ContinueCB());
        return null;
      }
     
    }
   
    // start the scan
    new MetaScanner().scan();
    return result;
  }
 
  /**
   * Scans the entire UID table and removes any UIDMeta objects found.
   * @return The total number of columns deleted
   */
  public Deferred<Long> purgeTSMeta() {
   
    // a list to store all pending deletes so we don't exit before they've
    // completed
    final ArrayList<Deferred<Object>> delete_calls =
      new ArrayList<Deferred<Object>>();
    final Deferred<Long> result = new Deferred<Long>();
   
    /**
     * Scanner callback that will recursively call itself and loop through the
     * rows of the UID table, issuing delete requests for all of the columns in
     * a row that match a meta qualifier.
     */
    final class MetaScanner implements Callback<Deferred<Long>,
      ArrayList<ArrayList<KeyValue>>> {

      final Scanner scanner;
     
      public MetaScanner() {
        scanner = getScanner(tsdb.metaTable());
      }
     
      /**
       * Fetches the next group of rows from the scanner and sets this class as
       * a callback
       * @return The total number of columns deleted after completion
       */
      public Deferred<Long> scan() {
        return scanner.nextRows().addCallbackDeferring(this);
      }
     
      @Override
      public Deferred<Long> call(ArrayList<ArrayList<KeyValue>> rows)
          throws Exception {
        if (rows == null) {
          result.callback(columns);
          return null;
        }
       
        for (final ArrayList<KeyValue> row : rows) {
          // one delete request per row. We'll almost always delete the whole
          // row, so preallocate some ram.
          ArrayList<byte[]> qualifiers = new ArrayList<byte[]>(row.size());
         
          for (KeyValue column : row) {
            if (Bytes.equals(TSMeta.META_QUALIFIER(), column.qualifier())) {
              qualifiers.add(column.qualifier());
            } else if (Bytes.equals(TSMeta.COUNTER_QUALIFIER(),
                column.qualifier())) {
              qualifiers.add(column.qualifier());
            }
          }
         
          if (qualifiers.size() > 0) {
            columns += qualifiers.size();
            final DeleteRequest delete = new DeleteRequest(tsdb.metaTable(),
                row.get(0).key(), NAME_FAMILY,
                qualifiers.toArray(new byte[qualifiers.size()][]));
            delete_calls.add(tsdb.getClient().delete(delete));
          }
        }
       
        /**
         * Buffer callback used to wait on all of the delete calls for the
         * last set of rows returned from the scanner so we don't fill up the
         * deferreds array and OOM out.
         */
        final class ContinueCB implements Callback<Deferred<Long>,
          ArrayList<Object>> {

          @Override
          public Deferred<Long> call(ArrayList<Object> deletes)
              throws Exception {
            LOG.debug("[" + thread_id + "] Processed [" + deletes.size()
                + "] delete calls");
            delete_calls.clear();
            return scan();
          }
         
        }
       
        // fetch the next set of rows after waiting for current set of delete
        // requests to complete
        Deferred.group(delete_calls).addCallbackDeferring(new ContinueCB());
        return null;
      }
     
    }
   
    // start the scan
    new MetaScanner().scan();
    return result;
  }
 
  /**
   * Returns a scanner to run over the UID table starting at the given row
   * @return A scanner configured for the entire table
   * @throws HBaseException if something goes boom
   */
  private Scanner getScanner(final byte[] table) throws HBaseException {
    short metric_width = TSDB.metrics_width();
    final byte[] start_row =
      Arrays.copyOfRange(Bytes.fromLong(start_id), 8 - metric_width, 8);
    final byte[] end_row =
      Arrays.copyOfRange(Bytes.fromLong(end_id), 8 - metric_width, 8);
    final Scanner scanner = tsdb.getClient().newScanner(table);
    scanner.setStartKey(start_row);
    scanner.setStopKey(end_row);
    scanner.setFamily(NAME_FAMILY);
    return scanner;
  }
}
TOP

Related Classes of net.opentsdb.tools.ContinueCB

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.