Search in sources :

Example 1 with TSUIDQuery

use of net.opentsdb.meta.TSUIDQuery in project opentsdb by OpenTSDB.

the class QueryRpc method handleLastDataPointQuery.

/**
 * Processes a last data point query
 * @param tsdb The TSDB to which we belong
 * @param query The HTTP query to parse/respond
 */
private void handleLastDataPointQuery(final TSDB tsdb, final HttpQuery query) {
    final LastPointQuery data_query;
    if (query.method() == HttpMethod.POST) {
        switch(query.apiVersion()) {
            case 0:
            case 1:
                data_query = query.serializer().parseLastPointQueryV1();
                break;
            default:
                throw new BadRequestException(HttpResponseStatus.NOT_IMPLEMENTED, "Requested API version not implemented", "Version " + query.apiVersion() + " is not implemented");
        }
    } else {
        data_query = this.parseLastPointQuery(tsdb, query);
    }
    if (data_query.sub_queries == null || data_query.sub_queries.isEmpty()) {
        throw new BadRequestException(HttpResponseStatus.BAD_REQUEST, "Missing sub queries");
    }
    // a list of deferreds to wait on
    final ArrayList<Deferred<Object>> calls = new ArrayList<Deferred<Object>>();
    // final results for serialization
    final List<IncomingDataPoint> results = new ArrayList<IncomingDataPoint>();
    /**
     * Used to catch exceptions
     */
    final class ErrBack implements Callback<Object, Exception> {

        public Object call(final Exception e) throws Exception {
            Throwable ex = e;
            while (ex.getClass().equals(DeferredGroupException.class)) {
                if (ex.getCause() == null) {
                    LOG.warn("Unable to get to the root cause of the DGE");
                    break;
                }
                ex = ex.getCause();
            }
            if (ex instanceof RuntimeException) {
                throw new BadRequestException(ex);
            } else {
                throw e;
            }
        }

        @Override
        public String toString() {
            return "Error back";
        }
    }
    final class FetchCB implements Callback<Deferred<Object>, ArrayList<IncomingDataPoint>> {

        @Override
        public Deferred<Object> call(final ArrayList<IncomingDataPoint> dps) throws Exception {
            synchronized (results) {
                for (final IncomingDataPoint dp : dps) {
                    if (dp != null) {
                        results.add(dp);
                    }
                }
            }
            return Deferred.fromResult(null);
        }

        @Override
        public String toString() {
            return "Fetched data points CB";
        }
    }
    /**
     * Called after scanning the tsdb-meta table for TSUIDs that match the given
     * metric and/or tags. If matches were found, it fires off a number of
     * getLastPoint requests, adding the deferreds to the calls list
     */
    final class TSUIDQueryCB implements Callback<Deferred<Object>, ByteMap<Long>> {

        public Deferred<Object> call(final ByteMap<Long> tsuids) throws Exception {
            if (tsuids == null || tsuids.isEmpty()) {
                return null;
            }
            final ArrayList<Deferred<IncomingDataPoint>> deferreds = new ArrayList<Deferred<IncomingDataPoint>>(tsuids.size());
            for (Map.Entry<byte[], Long> entry : tsuids.entrySet()) {
                deferreds.add(TSUIDQuery.getLastPoint(tsdb, entry.getKey(), data_query.getResolveNames(), data_query.getBackScan(), entry.getValue()));
            }
            return Deferred.group(deferreds).addCallbackDeferring(new FetchCB());
        }

        @Override
        public String toString() {
            return "TSMeta scan CB";
        }
    }
    /**
     * Used to wait on the list of data point deferreds. Once they're all done
     * this will return the results to the call via the serializer
     */
    final class FinalCB implements Callback<Object, ArrayList<Object>> {

        public Object call(final ArrayList<Object> done) throws Exception {
            query.sendReply(query.serializer().formatLastPointQueryV1(results));
            return null;
        }

        @Override
        public String toString() {
            return "Final CB";
        }
    }
    try {
        // start executing the queries
        for (final LastPointSubQuery sub_query : data_query.getQueries()) {
            final ArrayList<Deferred<IncomingDataPoint>> deferreds = new ArrayList<Deferred<IncomingDataPoint>>();
            // process the TSUIDs and ignore the metric/tags
            if (sub_query.getTSUIDs() != null && !sub_query.getTSUIDs().isEmpty()) {
                for (final String tsuid : sub_query.getTSUIDs()) {
                    final TSUIDQuery tsuid_query = new TSUIDQuery(tsdb, UniqueId.stringToUid(tsuid));
                    deferreds.add(tsuid_query.getLastPoint(data_query.getResolveNames(), data_query.getBackScan()));
                }
            } else {
                @SuppressWarnings("unchecked") final TSUIDQuery tsuid_query = new TSUIDQuery(tsdb, sub_query.getMetric(), sub_query.getTags() != null ? sub_query.getTags() : Collections.EMPTY_MAP);
                if (data_query.getBackScan() > 0) {
                    deferreds.add(tsuid_query.getLastPoint(data_query.getResolveNames(), data_query.getBackScan()));
                } else {
                    calls.add(tsuid_query.getLastWriteTimes().addCallbackDeferring(new TSUIDQueryCB()));
                }
            }
            if (deferreds.size() > 0) {
                calls.add(Deferred.group(deferreds).addCallbackDeferring(new FetchCB()));
            }
        }
        Deferred.group(calls).addCallback(new FinalCB()).addErrback(new ErrBack()).joinUninterruptibly();
    } catch (Exception e) {
        Throwable ex = e;
        while (ex.getClass().equals(DeferredGroupException.class)) {
            if (ex.getCause() == null) {
                LOG.warn("Unable to get to the root cause of the DGE");
                break;
            }
            ex = ex.getCause();
        }
        if (ex instanceof RuntimeException) {
            throw new BadRequestException(ex);
        } else {
            throw new RuntimeException("Shouldn't be here", e);
        }
    }
}
Also used : Deferred(com.stumbleupon.async.Deferred) ArrayList(java.util.ArrayList) DeferredGroupException(com.stumbleupon.async.DeferredGroupException) TSUIDQuery(net.opentsdb.meta.TSUIDQuery) IncomingDataPoint(net.opentsdb.core.IncomingDataPoint) QueryException(net.opentsdb.core.QueryException) DeferredGroupException(com.stumbleupon.async.DeferredGroupException) IOException(java.io.IOException) RpcTimedOutException(org.hbase.async.RpcTimedOutException) HBaseException(org.hbase.async.HBaseException) Callback(com.stumbleupon.async.Callback) ByteMap(org.hbase.async.Bytes.ByteMap) AtomicLong(java.util.concurrent.atomic.AtomicLong) HashMap(java.util.HashMap) Map(java.util.Map) ByteMap(org.hbase.async.Bytes.ByteMap)

Example 2 with TSUIDQuery

use of net.opentsdb.meta.TSUIDQuery in project opentsdb by OpenTSDB.

the class UniqueIdRpc method handleTSMeta.

/**
 * Handles CRUD calls to individual TSMeta data entries
 * @param tsdb The TSDB from the RPC router
 * @param query The query for this request
 */
private void handleTSMeta(final TSDB tsdb, final HttpQuery query) {
    final HttpMethod method = query.getAPIMethod();
    // GET
    if (method == HttpMethod.GET) {
        String tsuid = null;
        if (query.hasQueryStringParam("tsuid")) {
            tsuid = query.getQueryStringParam("tsuid");
            try {
                final TSMeta meta = TSMeta.getTSMeta(tsdb, tsuid).joinUninterruptibly();
                if (meta != null) {
                    query.sendReply(query.serializer().formatTSMetaV1(meta));
                } else {
                    throw new BadRequestException(HttpResponseStatus.NOT_FOUND, "Could not find Timeseries meta data");
                }
            } catch (NoSuchUniqueName e) {
                // the timeseries meta data
                throw new BadRequestException(HttpResponseStatus.NOT_FOUND, "Unable to find one of the UIDs", e);
            } catch (BadRequestException e) {
                throw e;
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        } else {
            String mquery = query.getRequiredQueryStringParam("m");
            // m is of the following forms:
            // metric[{tag=value,...}]
            // where the parts in square brackets `[' .. `]' are optional.
            final HashMap<String, String> tags = new HashMap<String, String>();
            String metric = null;
            try {
                metric = Tags.parseWithMetric(mquery, tags);
            } catch (IllegalArgumentException e) {
                throw new BadRequestException(e);
            }
            final TSUIDQuery tsuid_query = new TSUIDQuery(tsdb, metric, tags);
            try {
                final List<TSMeta> tsmetas = tsuid_query.getTSMetas().joinUninterruptibly();
                query.sendReply(query.serializer().formatTSMetaListV1(tsmetas));
            } catch (NoSuchUniqueName e) {
                throw new BadRequestException(HttpResponseStatus.NOT_FOUND, "Unable to find one of the UIDs", e);
            } catch (BadRequestException e) {
                throw e;
            } catch (RuntimeException e) {
                throw new BadRequestException(e);
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        }
    // POST / PUT
    } else if (method == HttpMethod.POST || method == HttpMethod.PUT) {
        final TSMeta meta;
        if (query.hasContent()) {
            meta = query.serializer().parseTSMetaV1();
        } else {
            meta = this.parseTSMetaQS(query);
        }
        /**
         * Storage callback used to determine if the storage call was successful
         * or not. Also returns the updated object from storage.
         */
        class SyncCB implements Callback<Deferred<TSMeta>, Boolean> {

            @Override
            public Deferred<TSMeta> call(Boolean success) throws Exception {
                if (!success) {
                    throw new BadRequestException(HttpResponseStatus.INTERNAL_SERVER_ERROR, "Failed to save the TSMeta to storage", "This may be caused by another process modifying storage data");
                }
                return TSMeta.getTSMeta(tsdb, meta.getTSUID());
            }
        }
        if (meta.getTSUID() == null || meta.getTSUID().isEmpty()) {
            // we got a JSON object without TSUID. Try to find a timeseries spec of
            // the form "m": "metric{tagk=tagv,...}"
            final String metric = query.getRequiredQueryStringParam("m");
            final boolean create = query.getQueryStringParam("create") != null && query.getQueryStringParam("create").equals("true");
            final String tsuid = getTSUIDForMetric(metric, tsdb);
            class WriteCounterIfNotPresentCB implements Callback<Boolean, Boolean> {

                @Override
                public Boolean call(Boolean exists) throws Exception {
                    if (!exists && create) {
                        final PutRequest put = new PutRequest(tsdb.metaTable(), UniqueId.stringToUid(tsuid), TSMeta.FAMILY(), TSMeta.COUNTER_QUALIFIER(), Bytes.fromLong(0));
                        tsdb.getClient().put(put);
                    }
                    return exists;
                }
            }
            try {
                // Check whether we have a TSMeta stored already
                final boolean exists = TSMeta.metaExistsInStorage(tsdb, tsuid).joinUninterruptibly();
                // set TSUID
                meta.setTSUID(tsuid);
                if (!exists && create) {
                    // Write 0 to counter column if not present
                    TSMeta.counterExistsInStorage(tsdb, UniqueId.stringToUid(tsuid)).addCallback(new WriteCounterIfNotPresentCB()).joinUninterruptibly();
                    // set TSUID
                    final Deferred<TSMeta> process_meta = meta.storeNew(tsdb).addCallbackDeferring(new SyncCB());
                    final TSMeta updated_meta = process_meta.joinUninterruptibly();
                    tsdb.indexTSMeta(updated_meta);
                    tsdb.processTSMetaThroughTrees(updated_meta);
                    query.sendReply(query.serializer().formatTSMetaV1(updated_meta));
                } else if (exists) {
                    final Deferred<TSMeta> process_meta = meta.syncToStorage(tsdb, method == HttpMethod.PUT).addCallbackDeferring(new SyncCB());
                    final TSMeta updated_meta = process_meta.joinUninterruptibly();
                    tsdb.indexTSMeta(updated_meta);
                    query.sendReply(query.serializer().formatTSMetaV1(updated_meta));
                } else {
                    throw new BadRequestException("Could not find TSMeta, specify \"create=true\" to create a new one.");
                }
            } catch (IllegalStateException e) {
                query.sendStatusOnly(HttpResponseStatus.NOT_MODIFIED);
            } catch (IllegalArgumentException e) {
                throw new BadRequestException(e);
            } catch (BadRequestException e) {
                throw e;
            } catch (NoSuchUniqueName e) {
                // the timeseries meta data
                throw new BadRequestException(HttpResponseStatus.NOT_FOUND, "Unable to find one or more UIDs", e);
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        } else {
            try {
                final Deferred<TSMeta> process_meta = meta.syncToStorage(tsdb, method == HttpMethod.PUT).addCallbackDeferring(new SyncCB());
                final TSMeta updated_meta = process_meta.joinUninterruptibly();
                tsdb.indexTSMeta(updated_meta);
                query.sendReply(query.serializer().formatTSMetaV1(updated_meta));
            } catch (IllegalStateException e) {
                query.sendStatusOnly(HttpResponseStatus.NOT_MODIFIED);
            } catch (IllegalArgumentException e) {
                throw new BadRequestException(e);
            } catch (NoSuchUniqueName e) {
                // the timeseries meta data
                throw new BadRequestException(HttpResponseStatus.NOT_FOUND, "Unable to find one or more UIDs", e);
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        }
    // DELETE
    } else if (method == HttpMethod.DELETE) {
        final TSMeta meta;
        if (query.hasContent()) {
            meta = query.serializer().parseTSMetaV1();
        } else {
            meta = this.parseTSMetaQS(query);
        }
        try {
            meta.delete(tsdb);
            tsdb.deleteTSMeta(meta.getTSUID());
        } catch (IllegalArgumentException e) {
            throw new BadRequestException("Unable to delete TSMeta information", e);
        }
        query.sendStatusOnly(HttpResponseStatus.NO_CONTENT);
    } else {
        throw new BadRequestException(HttpResponseStatus.METHOD_NOT_ALLOWED, "Method not allowed", "The HTTP method [" + method.getName() + "] is not permitted for this endpoint");
    }
}
Also used : HashMap(java.util.HashMap) Deferred(com.stumbleupon.async.Deferred) TSMeta(net.opentsdb.meta.TSMeta) PutRequest(org.hbase.async.PutRequest) IOException(java.io.IOException) HttpMethod(org.jboss.netty.handler.codec.http.HttpMethod) TSUIDQuery(net.opentsdb.meta.TSUIDQuery) NoSuchUniqueName(net.opentsdb.uid.NoSuchUniqueName)

Aggregations

Deferred (com.stumbleupon.async.Deferred)2 IOException (java.io.IOException)2 HashMap (java.util.HashMap)2 TSUIDQuery (net.opentsdb.meta.TSUIDQuery)2 Callback (com.stumbleupon.async.Callback)1 DeferredGroupException (com.stumbleupon.async.DeferredGroupException)1 ArrayList (java.util.ArrayList)1 Map (java.util.Map)1 AtomicLong (java.util.concurrent.atomic.AtomicLong)1 IncomingDataPoint (net.opentsdb.core.IncomingDataPoint)1 QueryException (net.opentsdb.core.QueryException)1 TSMeta (net.opentsdb.meta.TSMeta)1 NoSuchUniqueName (net.opentsdb.uid.NoSuchUniqueName)1 ByteMap (org.hbase.async.Bytes.ByteMap)1 HBaseException (org.hbase.async.HBaseException)1 PutRequest (org.hbase.async.PutRequest)1 RpcTimedOutException (org.hbase.async.RpcTimedOutException)1 HttpMethod (org.jboss.netty.handler.codec.http.HttpMethod)1