Search in sources :

Example 1 with TreeBuilder

use of net.opentsdb.tree.TreeBuilder in project opentsdb by OpenTSDB.

the class TreeRpc method handleTest.

/**
   * Runs the specified TSMeta object through a tree's rule set to determine
   * what the results would be or debug a meta that wasn't added to a tree
   * successfully
   * @param tsdb The TSDB to which we belong
   * @param query The HTTP query to work with
   * @throws BadRequestException if the request was invalid.
   */
private void handleTest(TSDB tsdb, HttpQuery query) {
    final Map<String, Object> map;
    if (query.hasContent()) {
        map = query.serializer().parseTreeTSUIDsListV1();
    } else {
        map = parseTSUIDsList(query);
    }
    final Integer tree_id = (Integer) map.get("treeId");
    if (tree_id == null) {
        throw new BadRequestException("Missing or invalid Tree ID");
    }
    // make sure the tree exists
    Tree tree = null;
    try {
        tree = Tree.fetchTree(tsdb, tree_id).joinUninterruptibly();
        if (tree == null) {
            throw new BadRequestException(HttpResponseStatus.NOT_FOUND, "Unable to locate tree: " + tree_id);
        }
        // ugly, but keeps from having to create a dedicated class just to 
        // convert one field.
        @SuppressWarnings("unchecked") final List<String> tsuids = (List<String>) map.get("tsuids");
        if (tsuids == null || tsuids.isEmpty()) {
            throw new BadRequestException("Missing or empty TSUID list");
        }
        if (query.getAPIMethod() == HttpMethod.GET || query.getAPIMethod() == HttpMethod.POST || query.getAPIMethod() == HttpMethod.PUT) {
            final HashMap<String, HashMap<String, Object>> results = new HashMap<String, HashMap<String, Object>>(tsuids.size());
            final TreeBuilder builder = new TreeBuilder(tsdb, tree);
            for (String tsuid : tsuids) {
                final HashMap<String, Object> tsuid_results = new HashMap<String, Object>();
                try {
                    final TSMeta meta = TSMeta.getTSMeta(tsdb, tsuid).joinUninterruptibly();
                    // message to the results and move on to the next TSUID
                    if (meta == null) {
                        tsuid_results.put("branch", null);
                        tsuid_results.put("meta", null);
                        final ArrayList<String> messages = new ArrayList<String>(1);
                        messages.add("Unable to locate TSUID meta data");
                        tsuid_results.put("messages", messages);
                        results.put(tsuid, tsuid_results);
                        continue;
                    }
                    builder.processTimeseriesMeta(meta, true).joinUninterruptibly();
                    tsuid_results.put("branch", builder.getRootBranch());
                    tsuid_results.put("meta", meta);
                    tsuid_results.put("messages", builder.getTestMessage());
                    results.put(tsuid, tsuid_results);
                } catch (DeferredGroupException e) {
                    // we want to catch NSU errors and handle them gracefully for
                    // TSUIDs where they may have been deleted
                    Throwable ex = e;
                    while (ex.getClass().equals(DeferredGroupException.class)) {
                        ex = ex.getCause();
                    }
                    if (ex.getClass().equals(NoSuchUniqueId.class)) {
                        tsuid_results.put("branch", null);
                        tsuid_results.put("meta", null);
                        final ArrayList<String> messages = new ArrayList<String>(1);
                        messages.add("TSUID was missing a UID name: " + ex.getMessage());
                        tsuid_results.put("messages", messages);
                        results.put(tsuid, tsuid_results);
                    }
                }
            }
            query.sendReply(query.serializer().formatTreeTestV1(results));
        } else {
            throw new BadRequestException(HttpResponseStatus.BAD_REQUEST, "Unsupported HTTP request method");
        }
    } catch (BadRequestException e) {
        throw e;
    } catch (IllegalArgumentException e) {
        throw new BadRequestException(e);
    } catch (Exception e) {
        throw new RuntimeException(e);
    }
}
Also used : HashMap(java.util.HashMap) ArrayList(java.util.ArrayList) TSMeta(net.opentsdb.meta.TSMeta) PatternSyntaxException(java.util.regex.PatternSyntaxException) IOException(java.io.IOException) DeferredGroupException(com.stumbleupon.async.DeferredGroupException) TreeBuilder(net.opentsdb.tree.TreeBuilder) DeferredGroupException(com.stumbleupon.async.DeferredGroupException) NoSuchUniqueId(net.opentsdb.uid.NoSuchUniqueId) Tree(net.opentsdb.tree.Tree) ArrayList(java.util.ArrayList) List(java.util.List)

Example 2 with TreeBuilder

use of net.opentsdb.tree.TreeBuilder in project opentsdb by OpenTSDB.

the class TreeSync method run.

/**
   * Performs a tree synchronization using a table scanner across the UID table
   * @return 0 if completed successfully, something else if an error occurred
   */
public void run() {
    final Scanner scanner = getScanner();
    // start the process by loading all of the trees in the system
    final List<Tree> trees;
    try {
        trees = Tree.fetchAllTrees(tsdb).joinUninterruptibly();
        LOG.info("[" + thread_id + "] Complete");
    } catch (Exception e) {
        LOG.error("[" + thread_id + "] Unexpected Exception", e);
        throw new RuntimeException("[" + thread_id + "] Unexpected exception", e);
    }
    if (trees == null) {
        LOG.warn("No tree definitions were found");
        return;
    } else {
        boolean has_enabled_tree = false;
        for (Tree tree : trees) {
            if (tree.getEnabled()) {
                has_enabled_tree = true;
                break;
            }
        }
        if (!has_enabled_tree) {
            LOG.warn("No enabled trees were found");
            return;
        }
        LOG.info("Found [" + trees.size() + "] trees");
    }
    // setup an array for storing the tree processing calls so we can block 
    // until each call has completed
    final ArrayList<Deferred<Boolean>> tree_calls = new ArrayList<Deferred<Boolean>>();
    final Deferred<Boolean> completed = new Deferred<Boolean>();
    /**
     * Scanner callback that loops through the UID table recursively until 
     * the scanner returns a null row set.
     */
    final class TsuidScanner implements Callback<Deferred<Boolean>, ArrayList<ArrayList<KeyValue>>> {

        /**
       * Fetches the next set of rows from the scanner, adding this class as a 
       * callback
       * @return A meaningless deferred used to wait on until processing has
       * completed
       */
        public Deferred<Boolean> scan() {
            return scanner.nextRows().addCallbackDeferring(this);
        }

        @Override
        public Deferred<Boolean> call(ArrayList<ArrayList<KeyValue>> rows) throws Exception {
            if (rows == null) {
                completed.callback(true);
                return null;
            }
            for (final ArrayList<KeyValue> row : rows) {
                // convert to a string one time
                final String tsuid = UniqueId.uidToString(row.get(0).key());
                /**
           * A throttling callback used to wait for the current TSMeta to 
           * complete processing through the trees before continuing on with 
           * the next set.
           */
                final class TreeBuilderBufferCB implements Callback<Boolean, ArrayList<ArrayList<Boolean>>> {

                    @Override
                    public Boolean call(ArrayList<ArrayList<Boolean>> builder_calls) throws Exception {
                        //LOG.debug("Processed [" + builder_calls.size() + "] tree_calls");
                        return true;
                    }
                }
                /**
           * Executed after parsing a TSMeta object and loading all of the
           * associated UIDMetas. Once the meta has been loaded, this callback
           * runs it through each of the configured TreeBuilder objects and
           * stores the resulting deferred in an array. Once processing of all
           * of the rules has completed, we group the deferreds and call
           * BufferCB() to wait for their completion.
           */
                final class ParseCB implements Callback<Deferred<Boolean>, TSMeta> {

                    final ArrayList<Deferred<ArrayList<Boolean>>> builder_calls = new ArrayList<Deferred<ArrayList<Boolean>>>();

                    @Override
                    public Deferred<Boolean> call(TSMeta meta) throws Exception {
                        if (meta != null) {
                            LOG.debug("Processing TSMeta: " + meta + " w value: " + JSON.serializeToString(meta));
                            // copy the trees into a tree builder object and iterate through
                            // each builder. We need to do this as a builder is not thread
                            // safe and cannot be used asynchronously.
                            final ArrayList<TreeBuilder> tree_builders = new ArrayList<TreeBuilder>(trees.size());
                            for (Tree tree : trees) {
                                if (!tree.getEnabled()) {
                                    continue;
                                }
                                final TreeBuilder builder = new TreeBuilder(tsdb, tree);
                                tree_builders.add(builder);
                            }
                            for (TreeBuilder builder : tree_builders) {
                                builder_calls.add(builder.processTimeseriesMeta(meta));
                            }
                            return Deferred.group(builder_calls).addCallback(new TreeBuilderBufferCB());
                        } else {
                            return Deferred.fromResult(false);
                        }
                    }
                }
                /**
           * An error handler used to catch issues when loading the TSMeta such
           * as a missing UID name. In these situations we want to log that the 
           * TSMeta had an issue and continue on.
           */
                final class ErrBack implements Callback<Deferred<Boolean>, Exception> {

                    @Override
                    public Deferred<Boolean> call(Exception e) throws Exception {
                        if (e.getClass().equals(IllegalStateException.class)) {
                            LOG.error("Invalid data when processing TSUID [" + tsuid + "]", e);
                        } else if (e.getClass().equals(IllegalArgumentException.class)) {
                            LOG.error("Invalid data when processing TSUID [" + tsuid + "]", e);
                        } else if (e.getClass().equals(NoSuchUniqueId.class)) {
                            LOG.warn("Timeseries [" + tsuid + "] includes a non-existant UID: " + e.getMessage());
                        } else {
                            LOG.error("[" + thread_id + "] Exception while processing TSUID [" + tsuid + "]", e);
                        }
                        return Deferred.fromResult(false);
                    }
                }
                // matched a TSMeta column, so request a parsing and loading of
                // associated UIDMeta objects, then pass it off to callbacks for 
                // parsing through the trees.
                final Deferred<Boolean> process_tsmeta = TSMeta.parseFromColumn(tsdb, row.get(0), true).addCallbackDeferring(new ParseCB());
                process_tsmeta.addErrback(new ErrBack());
                tree_calls.add(process_tsmeta);
            }
            /**
         * Another buffer callback that waits for the current set of TSMetas to
         * complete their tree calls before we fetch another set of rows from
         * the scanner. This necessary to avoid OOM issues.
         */
            final class ContinueCB implements Callback<Deferred<Boolean>, ArrayList<Boolean>> {

                @Override
                public Deferred<Boolean> call(ArrayList<Boolean> tsuids) throws Exception {
                    LOG.debug("Processed [" + tsuids.size() + "] tree_calls, continuing");
                    tree_calls.clear();
                    return scan();
                }
            }
            // request the next set of rows from the scanner, but wait until the
            // current set of TSMetas has been processed so we don't slaughter our
            // host
            Deferred.group(tree_calls).addCallback(new ContinueCB());
            return Deferred.fromResult(null);
        }
    }
    /**
     * Used to capture unhandled exceptions from the scanner callbacks and 
     * exit the thread properly
     */
    final class ErrBack implements Callback<Deferred<Boolean>, Exception> {

        @Override
        public Deferred<Boolean> call(Exception e) throws Exception {
            LOG.error("Unexpected exception", e);
            completed.callback(false);
            return Deferred.fromResult(false);
        }
    }
    final TsuidScanner tree_scanner = new TsuidScanner();
    tree_scanner.scan().addErrback(new ErrBack());
    try {
        completed.joinUninterruptibly();
        LOG.info("[" + thread_id + "] Complete");
    } catch (Exception e) {
        LOG.error("[" + thread_id + "] Scanner Exception", e);
        throw new RuntimeException("[" + thread_id + "] Scanner exception", e);
    }
    return;
}
Also used : Scanner(org.hbase.async.Scanner) KeyValue(org.hbase.async.KeyValue) Deferred(com.stumbleupon.async.Deferred) ArrayList(java.util.ArrayList) Tree(net.opentsdb.tree.Tree) TSMeta(net.opentsdb.meta.TSMeta) HBaseException(org.hbase.async.HBaseException) TreeBuilder(net.opentsdb.tree.TreeBuilder) Callback(com.stumbleupon.async.Callback)

Aggregations

ArrayList (java.util.ArrayList)2 TSMeta (net.opentsdb.meta.TSMeta)2 Tree (net.opentsdb.tree.Tree)2 TreeBuilder (net.opentsdb.tree.TreeBuilder)2 Callback (com.stumbleupon.async.Callback)1 Deferred (com.stumbleupon.async.Deferred)1 DeferredGroupException (com.stumbleupon.async.DeferredGroupException)1 IOException (java.io.IOException)1 HashMap (java.util.HashMap)1 List (java.util.List)1 PatternSyntaxException (java.util.regex.PatternSyntaxException)1 NoSuchUniqueId (net.opentsdb.uid.NoSuchUniqueId)1 HBaseException (org.hbase.async.HBaseException)1 KeyValue (org.hbase.async.KeyValue)1 Scanner (org.hbase.async.Scanner)1