Search in sources :

Example 46 with KeyValue

use of org.hbase.async.KeyValue in project opentsdb by OpenTSDB.

the class Annotation method getAnnotation.

/**
   * Attempts to fetch a global or local annotation from storage
   * @param tsdb The TSDB to use for storage access
   * @param tsuid The TSUID as a byte array. May be null if retrieving a global
   * annotation
   * @param start_time The start time as a Unix epoch timestamp
   * @return A valid annotation object if found, null if not
   */
public static Deferred<Annotation> getAnnotation(final TSDB tsdb, final byte[] tsuid, final long start_time) {
    /**
     * Called after executing the GetRequest to parse the meta data.
     */
    final class GetCB implements Callback<Deferred<Annotation>, ArrayList<KeyValue>> {

        /**
       * @return Null if the meta did not exist or a valid Annotation object if 
       * it did.
       */
        @Override
        public Deferred<Annotation> call(final ArrayList<KeyValue> row) throws Exception {
            if (row == null || row.isEmpty()) {
                return Deferred.fromResult(null);
            }
            Annotation note = JSON.parseToObject(row.get(0).value(), Annotation.class);
            return Deferred.fromResult(note);
        }
    }
    final GetRequest get = new GetRequest(tsdb.dataTable(), getRowKey(start_time, tsuid));
    get.family(FAMILY);
    get.qualifier(getQualifier(start_time));
    return tsdb.getClient().get(get).addCallbackDeferring(new GetCB());
}
Also used : Callback(com.stumbleupon.async.Callback) KeyValue(org.hbase.async.KeyValue) GetRequest(org.hbase.async.GetRequest) ArrayList(java.util.ArrayList)

Example 47 with KeyValue

use of org.hbase.async.KeyValue in project opentsdb by OpenTSDB.

the class TSMeta method counterExistsInStorage.

/**
   * Determines if the counter column exists for the TSUID. 
   * This is used by the UID Manager tool to determine if we need to write a 
   * new TSUID entry or not. It will not attempt to verify if the stored data is 
   * valid, just checks to see if something is stored in the proper column.
   * @param tsdb The TSDB to use for storage access
   * @param tsuid The UID of the meta to verify
   * @return True if data was found, false if not
   * @throws HBaseException if there was an issue fetching
   */
public static Deferred<Boolean> counterExistsInStorage(final TSDB tsdb, final byte[] tsuid) {
    final GetRequest get = new GetRequest(tsdb.metaTable(), tsuid);
    get.family(FAMILY);
    get.qualifier(COUNTER_QUALIFIER);
    /**
     * Callback from the GetRequest that simply determines if the row is empty
     * or not
     */
    final class ExistsCB implements Callback<Boolean, ArrayList<KeyValue>> {

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

Example 48 with KeyValue

use of org.hbase.async.KeyValue in project opentsdb by OpenTSDB.

the class TSUIDQuery method getTSMetas.

/**
   * Returns all TSMeta objects stored for timeseries defined by this query. The 
   * query is similar to TsdbQuery without any aggregations. Returns an empty 
   * list, when no TSMetas are found. Only returns stored TSMetas.
   * <p>
   * NOTE: If you called {@link #setQuery(String, Map)} successfully this will
   * immediately scan the meta table. But if you used the CTOR to set the
   * metric and tags it will attempt to resolve those and may return an exception.
   * @return A list of existing TSMetas for the timeseries covered by the query.
   * @throws IllegalArgumentException When either no metric was specified or the
   * tag map was null (Empty map is OK).
   */
public Deferred<List<TSMeta>> getTSMetas() {
    class ResolutionCB implements Callback<Deferred<List<TSMeta>>, Object> {

        @Override
        public Deferred<List<TSMeta>> call(final Object done) throws Exception {
            final Scanner scanner = getScanner();
            scanner.setQualifier(TSMeta.META_QUALIFIER());
            final Deferred<List<TSMeta>> results = new Deferred<List<TSMeta>>();
            final List<TSMeta> tsmetas = new ArrayList<TSMeta>();
            final List<Deferred<TSMeta>> tsmeta_group = new ArrayList<Deferred<TSMeta>>();
            final class TSMetaGroupCB implements Callback<Object, ArrayList<TSMeta>> {

                @Override
                public List<TSMeta> call(ArrayList<TSMeta> ts) throws Exception {
                    for (TSMeta tsm : ts) {
                        if (tsm != null) {
                            tsmetas.add(tsm);
                        }
                    }
                    results.callback(tsmetas);
                    return null;
                }

                @Override
                public String toString() {
                    return "TSMeta callback";
                }
            }
            final class ErrBack implements Callback<Object, Exception> {

                @Override
                public Object call(final Exception e) throws Exception {
                    results.callback(e);
                    return null;
                }

                @Override
                public String toString() {
                    return "Error callback";
                }
            }
            /**
         * Scanner callback that will call itself while iterating through the 
         * tsdb-meta table.
         * 
         * Keeps track of a Set of Deferred TSMeta calls. When all rows are scanned,
         * will wait for all TSMeta calls to be completed and then create the result 
         * list.
         */
            final class ScannerCB implements Callback<Object, ArrayList<ArrayList<KeyValue>>> {

                /**
           * Starts the scanner and is called recursively to fetch the next set of
           * rows from the scanner.
           * @return The map of spans if loaded successfully, null if no data was
           * found
           */
                public Object scan() {
                    return scanner.nextRows().addCallback(this).addErrback(new ErrBack());
                }

                /**
           * Loops through each row of the scanner results and parses out data
           * points and optional meta data
           * @return null if no rows were found, otherwise the TreeMap with spans
           */
                @Override
                public Object call(final ArrayList<ArrayList<KeyValue>> rows) throws Exception {
                    try {
                        if (rows == null) {
                            Deferred.group(tsmeta_group).addCallback(new TSMetaGroupCB()).addErrback(new ErrBack());
                            return null;
                        }
                        for (final ArrayList<KeyValue> row : rows) {
                            tsmeta_group.add(TSMeta.parseFromColumn(tsdb, row.get(0), true));
                        }
                        return scan();
                    } catch (Exception e) {
                        results.callback(e);
                        return null;
                    }
                }
            }
            new ScannerCB().scan();
            return results;
        }

        @Override
        public String toString() {
            return "TSMeta scan callback";
        }
    }
    if (metric_uid == null) {
        return resolveMetric().addCallbackDeferring(new ResolutionCB());
    }
    try {
        return new ResolutionCB().call(null);
    } catch (Exception e) {
        return Deferred.fromError(e);
    }
}
Also used : Scanner(org.hbase.async.Scanner) KeyValue(org.hbase.async.KeyValue) Deferred(com.stumbleupon.async.Deferred) ArrayList(java.util.ArrayList) Callback(com.stumbleupon.async.Callback) ArrayList(java.util.ArrayList) List(java.util.List)

Example 49 with KeyValue

use of org.hbase.async.KeyValue in project opentsdb by OpenTSDB.

the class UIDMeta method syncToStorage.

/**
   * Attempts a CompareAndSet storage call, loading the object from storage, 
   * synchronizing changes, and attempting a put.
   * <b>Note:</b> If the local object didn't have any fields set by the caller
   * then the data will not be written.
   * @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 fetching
   * @throws IllegalArgumentException if parsing failed
   * @throws NoSuchUniqueId If the UID does 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 (uid == null || uid.isEmpty()) {
        throw new IllegalArgumentException("Missing UID");
    }
    if (type == null) {
        throw new IllegalArgumentException("Missing type");
    }
    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 UID meta data");
    }
    /**
     * Callback used to verify that the UID to name mapping exists. Uses the TSD
     * for verification so the name may be cached. If the name does not exist
     * it will throw a NoSuchUniqueId and the meta data will not be saved to
     * storage
     */
    final class NameCB implements Callback<Deferred<Boolean>, String> {

        private final UIDMeta local_meta;

        public NameCB(final UIDMeta meta) {
            local_meta = meta;
        }

        /**
       *  Nested callback used to merge and store the meta data after verifying
       *  that the UID mapping exists. It has to access the {@code local_meta} 
       *  object so that's why it's nested within the NameCB class
       */
        final class StoreUIDMeta implements Callback<Deferred<Boolean>, ArrayList<KeyValue>> {

            /**
         * Executes the CompareAndSet after merging changes
         * @return True if the CAS was successful, false if the stored data
         * was modified during flight.
         */
            @Override
            public Deferred<Boolean> call(final ArrayList<KeyValue> row) throws Exception {
                final UIDMeta stored_meta;
                if (row == null || row.isEmpty()) {
                    stored_meta = null;
                } else {
                    stored_meta = JSON.parseToObject(row.get(0).value(), UIDMeta.class);
                    stored_meta.initializeChangedMap();
                }
                final byte[] original_meta = row == null || row.isEmpty() ? new byte[0] : row.get(0).value();
                if (stored_meta != null) {
                    local_meta.syncMeta(stored_meta, overwrite);
                }
                // verify the name is set locally just to be safe
                if (name == null || name.isEmpty()) {
                    local_meta.name = name;
                }
                final PutRequest put = new PutRequest(tsdb.uidTable(), UniqueId.stringToUid(uid), FAMILY, (type.toString().toLowerCase() + "_meta").getBytes(CHARSET), local_meta.getStorageJSON());
                return tsdb.getClient().compareAndSet(put, original_meta);
            }
        }

        /**
       * NameCB method that fetches the object from storage for merging and
       * use in the CAS call
       * @return The results of the {@link #StoreUIDMeta} callback
       */
        @Override
        public Deferred<Boolean> call(final String name) throws Exception {
            final GetRequest get = new GetRequest(tsdb.uidTable(), UniqueId.stringToUid(uid));
            get.family(FAMILY);
            get.qualifier((type.toString().toLowerCase() + "_meta").getBytes(CHARSET));
            // #2 deferred
            return tsdb.getClient().get(get).addCallbackDeferring(new StoreUIDMeta());
        }
    }
    // start the callback chain by veryfing that the UID name mapping exists
    return tsdb.getUidName(type, UniqueId.stringToUid(uid)).addCallbackDeferring(new NameCB(this));
}
Also used : KeyValue(org.hbase.async.KeyValue) 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) GetRequest(org.hbase.async.GetRequest) HashMap(java.util.HashMap) Map(java.util.Map)

Example 50 with KeyValue

use of org.hbase.async.KeyValue in project opentsdb by OpenTSDB.

the class UIDMeta method getUIDMeta.

/**
   * Verifies the UID object exists, then attempts to fetch the meta from 
   * storage and if not found, returns a default object.
   * <p>
   * The reason for returning a default object (with the type, uid and name set)
   * is due to users who may have just enabled meta data or have upgraded; we 
   * want to return valid data. If they modify the entry, it will write to 
   * storage. You can tell it's a default if the {@code created} value is 0. If
   * the meta was generated at UID assignment or updated by the meta sync CLI
   * command, it will have a valid created timestamp.
   * @param tsdb The TSDB to use for storage access
   * @param type The type of UID to fetch
   * @param uid The ID of the meta to fetch
   * @return A UIDMeta from storage or a default
   * @throws HBaseException if there was an issue fetching
   * @throws NoSuchUniqueId If the UID does not exist
   */
public static Deferred<UIDMeta> getUIDMeta(final TSDB tsdb, final UniqueIdType type, final byte[] uid) {
    /**
     * Callback used to verify that the UID to name mapping exists. Uses the TSD
     * for verification so the name may be cached. If the name does not exist
     * it will throw a NoSuchUniqueId and the meta data will not be returned. 
     * This helps in case the user deletes a UID but the meta data is still 
     * stored. The fsck utility can be used later to cleanup orphaned objects.
     */
    class NameCB implements Callback<Deferred<UIDMeta>, String> {

        /**
       * Called after verifying that the name mapping exists
       * @return The results of {@link #FetchMetaCB}
       */
        @Override
        public Deferred<UIDMeta> call(final String name) throws Exception {
            /**
         * Inner class called to retrieve the meta data after verifying that the
         * name mapping exists. It requires the name to set the default, hence
         * the reason it's nested.
         */
            class FetchMetaCB implements Callback<Deferred<UIDMeta>, ArrayList<KeyValue>> {

                /**
           * Called to parse the response of our storage GET call after 
           * verification
           * @return The stored UIDMeta or a default object if the meta data
           * did not exist 
           */
                @Override
                public Deferred<UIDMeta> call(ArrayList<KeyValue> row) throws Exception {
                    if (row == null || row.isEmpty()) {
                        // return the default
                        final UIDMeta meta = new UIDMeta();
                        meta.uid = UniqueId.uidToString(uid);
                        meta.type = type;
                        meta.name = name;
                        return Deferred.fromResult(meta);
                    }
                    final UIDMeta meta = JSON.parseToObject(row.get(0).value(), UIDMeta.class);
                    // overwrite the name and UID
                    meta.name = name;
                    meta.uid = UniqueId.uidToString(uid);
                    // fix missing types
                    if (meta.type == null) {
                        final String qualifier = new String(row.get(0).qualifier(), CHARSET);
                        meta.type = UniqueId.stringToUniqueIdType(qualifier.substring(0, qualifier.indexOf("_meta")));
                    }
                    meta.initializeChangedMap();
                    return Deferred.fromResult(meta);
                }
            }
            final GetRequest get = new GetRequest(tsdb.uidTable(), uid);
            get.family(FAMILY);
            get.qualifier((type.toString().toLowerCase() + "_meta").getBytes(CHARSET));
            return tsdb.getClient().get(get).addCallbackDeferring(new FetchMetaCB());
        }
    }
    // verify that the UID is still in the map before fetching from storage
    return tsdb.getUidName(type, uid).addCallbackDeferring(new NameCB());
}
Also used : Callback(com.stumbleupon.async.Callback) KeyValue(org.hbase.async.KeyValue) GetRequest(org.hbase.async.GetRequest) ArrayList(java.util.ArrayList)

Aggregations

KeyValue (org.hbase.async.KeyValue)171 Test (org.junit.Test)127 PrepareForTest (org.powermock.core.classloader.annotations.PrepareForTest)121 ArrayList (java.util.ArrayList)101 Annotation (net.opentsdb.meta.Annotation)50 Callback (com.stumbleupon.async.Callback)30 GetRequest (org.hbase.async.GetRequest)21 Scanner (org.hbase.async.Scanner)19 Deferred (com.stumbleupon.async.Deferred)14 HBaseException (org.hbase.async.HBaseException)13 TSDB (net.opentsdb.core.TSDB)12 Matchers.anyString (org.mockito.Matchers.anyString)11 Config (net.opentsdb.utils.Config)10 UniqueIdType (net.opentsdb.uid.UniqueId.UniqueIdType)9 DeleteRequest (org.hbase.async.DeleteRequest)8 DeferredGroupException (com.stumbleupon.async.DeferredGroupException)7 Map (java.util.Map)7 HashMap (java.util.HashMap)6 PutRequest (org.hbase.async.PutRequest)6 List (java.util.List)5