Search in sources :

Example 31 with Callback

use of com.stumbleupon.async.Callback in project opentsdb by OpenTSDB.

the class Annotation method getGlobalAnnotations.

/**
   * Scans through the global annotation storage rows and returns a list of 
   * parsed annotation objects. If no annotations were found for the given
   * timespan, the resulting list will be empty.
   * @param tsdb The TSDB to use for storage access
   * @param start_time Start time to scan from. May be 0
   * @param end_time End time to scan to. Must be greater than 0
   * @return A list with detected annotations. May be empty.
   * @throws IllegalArgumentException if the end timestamp has not been set or 
   * the end time is less than the start time
   */
public static Deferred<List<Annotation>> getGlobalAnnotations(final TSDB tsdb, final long start_time, final long end_time) {
    if (end_time < 1) {
        throw new IllegalArgumentException("The end timestamp has not been set");
    }
    if (end_time < start_time) {
        throw new IllegalArgumentException("The end timestamp cannot be less than the start timestamp");
    }
    /**
     * Scanner that loops through the [0, 0, 0, timestamp] rows looking for
     * global annotations. Returns a list of parsed annotation objects.
     * The list may be empty.
     */
    final class ScannerCB implements Callback<Deferred<List<Annotation>>, ArrayList<ArrayList<KeyValue>>> {

        final Scanner scanner;

        final ArrayList<Annotation> annotations = new ArrayList<Annotation>();

        /**
       * Initializes the scanner
       */
        public ScannerCB() {
            final byte[] start = new byte[Const.SALT_WIDTH() + TSDB.metrics_width() + Const.TIMESTAMP_BYTES];
            final byte[] end = new byte[Const.SALT_WIDTH() + TSDB.metrics_width() + Const.TIMESTAMP_BYTES];
            final long normalized_start = (start_time - (start_time % Const.MAX_TIMESPAN));
            final long normalized_end = (end_time - (end_time % Const.MAX_TIMESPAN) + Const.MAX_TIMESPAN);
            Bytes.setInt(start, (int) normalized_start, Const.SALT_WIDTH() + TSDB.metrics_width());
            Bytes.setInt(end, (int) normalized_end, Const.SALT_WIDTH() + TSDB.metrics_width());
            scanner = tsdb.getClient().newScanner(tsdb.dataTable());
            scanner.setStartKey(start);
            scanner.setStopKey(end);
            scanner.setFamily(FAMILY);
        }

        public Deferred<List<Annotation>> scan() {
            return scanner.nextRows().addCallbackDeferring(this);
        }

        @Override
        public Deferred<List<Annotation>> call(final ArrayList<ArrayList<KeyValue>> rows) throws Exception {
            if (rows == null || rows.isEmpty()) {
                return Deferred.fromResult((List<Annotation>) annotations);
            }
            for (final ArrayList<KeyValue> row : rows) {
                for (KeyValue column : row) {
                    if ((column.qualifier().length == 3 || column.qualifier().length == 5) && column.qualifier()[0] == PREFIX()) {
                        Annotation note = JSON.parseToObject(column.value(), Annotation.class);
                        if (note.start_time < start_time || note.end_time > end_time) {
                            continue;
                        }
                        annotations.add(note);
                    }
                }
            }
            return scan();
        }
    }
    return new ScannerCB().scan();
}
Also used : Scanner(org.hbase.async.Scanner) KeyValue(org.hbase.async.KeyValue) Callback(com.stumbleupon.async.Callback) ArrayList(java.util.ArrayList) ArrayList(java.util.ArrayList) List(java.util.List)

Example 32 with Callback

use of com.stumbleupon.async.Callback in project opentsdb by OpenTSDB.

the class EDPtoDPS method getAggregatedTagsAsync.

@Override
public Deferred<List<String>> getAggregatedTagsAsync() {
    final ByteSet tagks = edps[index].aggregatedTags();
    final List<String> aggregated_tags = new ArrayList<String>(tagks.size());
    final List<Deferred<String>> names = new ArrayList<Deferred<String>>(tagks.size());
    for (final byte[] tagk : tagks) {
        names.add(tsdb.getUidName(UniqueIdType.TAGK, tagk));
    }
    /** Adds the names to the aggregated_tags list */
    final class ResolveCB implements Callback<List<String>, ArrayList<String>> {

        @Override
        public List<String> call(final ArrayList<String> names) throws Exception {
            for (final String name : names) {
                aggregated_tags.add(name);
            }
            return aggregated_tags;
        }
    }
    return Deferred.group(names).addCallback(new ResolveCB());
}
Also used : Callback(com.stumbleupon.async.Callback) Deferred(com.stumbleupon.async.Deferred) ArrayList(java.util.ArrayList) ByteSet(net.opentsdb.utils.ByteSet)

Example 33 with Callback

use of com.stumbleupon.async.Callback in project opentsdb by OpenTSDB.

the class TSMeta method incrementAndGetCounter.

/**
   * Increments the tsuid datapoint counter or creates a new counter. Also
   * creates a new meta data entry if the counter did not exist.
   * <b>Note:</b> This method also:
   * <ul><li>Passes the new TSMeta object to the Search plugin after loading 
   * UIDMeta objects</li>
   * <li>Passes the new TSMeta through all configured trees if enabled</li></ul>
   * @param tsdb The TSDB to use for storage access
   * @param tsuid The TSUID to increment or create
   * @return 0 if the put failed, a positive LONG if the put was successful
   * @throws HBaseException if there was a storage issue
   * @throws JSONException if the data was corrupted
   * @throws NoSuchUniqueName if one of the UIDMeta objects does not exist
   */
public static Deferred<Long> incrementAndGetCounter(final TSDB tsdb, final byte[] tsuid) {
    /**
     * Callback that will create a new TSMeta if the increment result is 1 or
     * will simply return the new value.
     */
    final class TSMetaCB implements Callback<Deferred<Long>, Long> {

        /**
       * Called after incrementing the counter and will create a new TSMeta if
       * the returned value was 1 as well as pass the new meta through trees
       * and the search indexer if configured.
       * @return 0 if the put failed, a positive LONG if the put was successful
       */
        @Override
        public Deferred<Long> call(final Long incremented_value) throws Exception {
            LOG.debug("Value: " + incremented_value);
            if (incremented_value > 1) {
                // whenever the user runs the full sync CLI
                return Deferred.fromResult(incremented_value);
            }
            // create a new meta object with the current system timestamp. Ideally
            // we would want the data point's timestamp, but that's much more data
            // to keep track of and may not be accurate.
            final TSMeta meta = new TSMeta(tsuid, System.currentTimeMillis() / 1000);
            /**
         * Called after the meta has been passed through tree processing. The 
         * result of the processing doesn't matter and the user may not even
         * have it enabled, so we'll just return the counter.
         */
            final class TreeCB implements Callback<Deferred<Long>, Boolean> {

                @Override
                public Deferred<Long> call(Boolean success) throws Exception {
                    return Deferred.fromResult(incremented_value);
                }
            }
            /**
         * Called after retrieving the newly stored TSMeta and loading
         * associated UIDMeta objects. This class will also pass the meta to the
         * search plugin and run it through any configured trees
         */
            final class FetchNewCB implements Callback<Deferred<Long>, TSMeta> {

                @Override
                public Deferred<Long> call(TSMeta stored_meta) throws Exception {
                    // pass to the search plugin
                    tsdb.indexTSMeta(stored_meta);
                    // pass through the trees
                    return tsdb.processTSMetaThroughTrees(stored_meta).addCallbackDeferring(new TreeCB());
                }
            }
            /**
         * Called after the CAS to store the new TSMeta object. If the CAS
         * failed then we return immediately with a 0 for the counter value.
         * Otherwise we keep processing to load the meta and pass it on.
         */
            final class StoreNewCB implements Callback<Deferred<Long>, Boolean> {

                @Override
                public Deferred<Long> call(Boolean success) throws Exception {
                    if (!success) {
                        LOG.warn("Unable to save metadata: " + meta);
                        return Deferred.fromResult(0L);
                    }
                    LOG.info("Successfullly created new TSUID entry for: " + meta);
                    return new LoadUIDs(tsdb, UniqueId.uidToString(tsuid)).call(meta).addCallbackDeferring(new FetchNewCB());
                }
            }
            // store the new TSMeta object and setup the callback chain
            return meta.storeNew(tsdb).addCallbackDeferring(new StoreNewCB());
        }
    }
    // setup the increment request and execute
    final AtomicIncrementRequest inc = new AtomicIncrementRequest(tsdb.metaTable(), tsuid, FAMILY, COUNTER_QUALIFIER);
    // then we only want to increment the data point count.
    if (!tsdb.getConfig().enable_realtime_ts()) {
        return tsdb.getClient().atomicIncrement(inc);
    }
    return tsdb.getClient().atomicIncrement(inc).addCallbackDeferring(new TSMetaCB());
}
Also used : Callback(com.stumbleupon.async.Callback) AtomicIncrementRequest(org.hbase.async.AtomicIncrementRequest)

Example 34 with Callback

use of com.stumbleupon.async.Callback in project opentsdb by OpenTSDB.

the class TSMeta method storeIfNecessary.

/**
   * Attempts to fetch the meta column and if null, attempts to write a new 
   * column using {@link #storeNew}.
   * @param tsdb The TSDB instance to use for access.
   * @param tsuid The TSUID of the time series.
   * @return A deferred with a true if the meta exists or was created, false
   * if the meta did not exist and writing failed.
   */
public static Deferred<Boolean> storeIfNecessary(final TSDB tsdb, final byte[] tsuid) {
    final GetRequest get = new GetRequest(tsdb.metaTable(), tsuid);
    get.family(FAMILY);
    get.qualifier(META_QUALIFIER);
    final class CreateNewCB implements Callback<Deferred<Boolean>, Object> {

        @Override
        public Deferred<Boolean> call(Object arg0) throws Exception {
            final TSMeta meta = new TSMeta(tsuid, System.currentTimeMillis() / 1000);
            final class FetchNewCB implements Callback<Deferred<Boolean>, TSMeta> {

                @Override
                public Deferred<Boolean> call(TSMeta stored_meta) throws Exception {
                    // pass to the search plugin
                    tsdb.indexTSMeta(stored_meta);
                    // pass through the trees
                    tsdb.processTSMetaThroughTrees(stored_meta);
                    return Deferred.fromResult(true);
                }
            }
            final class StoreNewCB implements Callback<Deferred<Boolean>, Boolean> {

                @Override
                public Deferred<Boolean> call(Boolean success) throws Exception {
                    if (!success) {
                        LOG.warn("Unable to save metadata: " + meta);
                        return Deferred.fromResult(false);
                    }
                    LOG.info("Successfullly created new TSUID entry for: " + meta);
                    return new LoadUIDs(tsdb, UniqueId.uidToString(tsuid)).call(meta).addCallbackDeferring(new FetchNewCB());
                }
            }
            return meta.storeNew(tsdb).addCallbackDeferring(new StoreNewCB());
        }
    }
    final class ExistsCB implements Callback<Deferred<Boolean>, ArrayList<KeyValue>> {

        @Override
        public Deferred<Boolean> call(ArrayList<KeyValue> row) throws Exception {
            if (row == null || row.isEmpty() || row.get(0).value() == null) {
                return new CreateNewCB().call(null);
            }
            return Deferred.fromResult(true);
        }
    }
    return tsdb.getClient().get(get).addCallbackDeferring(new ExistsCB());
}
Also used : Callback(com.stumbleupon.async.Callback) KeyValue(org.hbase.async.KeyValue) GetRequest(org.hbase.async.GetRequest) ArrayList(java.util.ArrayList)

Example 35 with Callback

use of com.stumbleupon.async.Callback in project opentsdb by OpenTSDB.

the class TSMeta method syncToStorage.

/**
   * Attempts a CompareAndSet storage call, loading the object from storage, 
   * synchronizing changes, and attempting a put. Also verifies that associated 
   * UID name mappings exist before merging.
   * <b>Note:</b> If the local object didn't have any fields set by the caller
   * or there weren't any changes, then the data will not be written and an 
   * exception will be thrown.
   * <b>Note:</b> We do not store the UIDMeta information with TSMeta's since
   * users may change a single UIDMeta object and we don't want to update every
   * TSUID that includes that object with the new data. Instead, UIDMetas are
   * merged into the TSMeta on retrieval so we always have canonical data. This
   * also saves space in storage. 
   * @param tsdb The TSDB to use for storage access
   * @param overwrite When the RPC method is PUT, will overwrite all user
   * accessible fields
   * @return True if the storage call was successful, false if the object was
   * modified in storage during the CAS call. If false, retry the call. Other 
   * failures will result in an exception being thrown.
   * @throws HBaseException if there was an issue
   * @throws IllegalArgumentException if parsing failed
   * @throws NoSuchUniqueId If any of the UID name mappings do not exist
   * @throws IllegalStateException if the data hasn't changed. This is OK!
   * @throws JSONException if the object could not be serialized
   */
public Deferred<Boolean> syncToStorage(final TSDB tsdb, final boolean overwrite) {
    if (tsuid == null || tsuid.isEmpty()) {
        throw new IllegalArgumentException("Missing TSUID");
    }
    boolean has_changes = false;
    for (Map.Entry<String, Boolean> entry : changed.entrySet()) {
        if (entry.getValue()) {
            has_changes = true;
            break;
        }
    }
    if (!has_changes) {
        LOG.debug(this + " does not have changes, skipping sync to storage");
        throw new IllegalStateException("No changes detected in TSUID meta data");
    }
    /**
     * Callback used to verify that the UID name mappings exist. We don't need
     * to process the actual name, we just want it to throw an error if any
     * of the UIDs don't exist.
     */
    class UidCB implements Callback<Object, String> {

        @Override
        public Object call(String name) throws Exception {
            // nothing to do as missing mappings will throw a NoSuchUniqueId
            return null;
        }
    }
    // parse out the tags from the tsuid
    final List<byte[]> parsed_tags = UniqueId.getTagsFromTSUID(tsuid);
    // Deferred group used to accumulate UidCB callbacks so the next call
    // can wait until all of the UIDs have been verified
    ArrayList<Deferred<Object>> uid_group = new ArrayList<Deferred<Object>>(parsed_tags.size() + 1);
    // calculate the metric UID and fetch it's name mapping
    final byte[] metric_uid = UniqueId.stringToUid(tsuid.substring(0, TSDB.metrics_width() * 2));
    uid_group.add(tsdb.getUidName(UniqueIdType.METRIC, metric_uid).addCallback(new UidCB()));
    int idx = 0;
    for (byte[] tag : parsed_tags) {
        if (idx % 2 == 0) {
            uid_group.add(tsdb.getUidName(UniqueIdType.TAGK, tag).addCallback(new UidCB()));
        } else {
            uid_group.add(tsdb.getUidName(UniqueIdType.TAGV, tag).addCallback(new UidCB()));
        }
        idx++;
    }
    /**
     * Callback executed after all of the UID mappings have been verified. This
     * will then proceed with the CAS call.
     */
    final class ValidateCB implements Callback<Deferred<Boolean>, ArrayList<Object>> {

        private final TSMeta local_meta;

        public ValidateCB(final TSMeta local_meta) {
            this.local_meta = local_meta;
        }

        /**
       * Nested class that executes the CAS after retrieving existing TSMeta
       * from storage.
       */
        final class StoreCB implements Callback<Deferred<Boolean>, TSMeta> {

            /**
         * Executes the CAS if the TSMeta was successfully retrieved
         * @return True if the CAS was successful, false if the stored data
         * was modified in flight
         * @throws IllegalArgumentException if the TSMeta did not exist in
         * storage. Only the TSD should be able to create TSMeta objects.
         */
            @Override
            public Deferred<Boolean> call(TSMeta stored_meta) throws Exception {
                if (stored_meta == null) {
                    throw new IllegalArgumentException("Requested TSMeta did not exist");
                }
                final byte[] original_meta = stored_meta.getStorageJSON();
                local_meta.syncMeta(stored_meta, overwrite);
                final PutRequest put = new PutRequest(tsdb.metaTable(), UniqueId.stringToUid(local_meta.tsuid), FAMILY, META_QUALIFIER, local_meta.getStorageJSON());
                return tsdb.getClient().compareAndSet(put, original_meta);
            }
        }

        /**
       * Called on UID mapping verification and continues executing the CAS 
       * procedure.
       * @return Results from the {@link #StoreCB} callback
       */
        @Override
        public Deferred<Boolean> call(ArrayList<Object> validated) throws Exception {
            return getFromStorage(tsdb, UniqueId.stringToUid(tsuid)).addCallbackDeferring(new StoreCB());
        }
    }
    // Begins the callback chain by validating that the UID mappings exist
    return Deferred.group(uid_group).addCallbackDeferring(new ValidateCB(this));
}
Also used : Deferred(com.stumbleupon.async.Deferred) ArrayList(java.util.ArrayList) PutRequest(org.hbase.async.PutRequest) IOException(java.io.IOException) HBaseException(org.hbase.async.HBaseException) JSONException(net.opentsdb.utils.JSONException) Callback(com.stumbleupon.async.Callback) HashMap(java.util.HashMap) Map(java.util.Map)

Aggregations

Callback (com.stumbleupon.async.Callback)59 ArrayList (java.util.ArrayList)47 KeyValue (org.hbase.async.KeyValue)30 Deferred (com.stumbleupon.async.Deferred)29 GetRequest (org.hbase.async.GetRequest)17 HashMap (java.util.HashMap)15 Map (java.util.Map)15 IOException (java.io.IOException)13 Scanner (org.hbase.async.Scanner)12 PutRequest (org.hbase.async.PutRequest)11 DeferredGroupException (com.stumbleupon.async.DeferredGroupException)9 List (java.util.List)9 HBaseException (org.hbase.async.HBaseException)9 TreeMap (java.util.TreeMap)8 DeleteRequest (org.hbase.async.DeleteRequest)7 IncomingDataPoint (net.opentsdb.core.IncomingDataPoint)6 DataPoints (net.opentsdb.core.DataPoints)5 TSSubQuery (net.opentsdb.core.TSSubQuery)5 TSQuery (net.opentsdb.core.TSQuery)4 Annotation (net.opentsdb.meta.Annotation)4