Search in sources :

Example 11 with HBaseException

use of org.hbase.async.HBaseException 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)

Example 12 with HBaseException

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

the class UidManager method assign.

/**
   * Implements the {@code assign} subcommand.
   * @param tsdb The TSDB to use.
   * @param table The name of the HBase table to use.
   * @param idwidth Number of bytes on which the UIDs should be.
   * @param args Command line arguments ({@code assign name [names]}).
   * @return The exit status of the command (0 means success).
   */
private static int assign(final TSDB tsdb, final byte[] table, final short idwidth, final String[] args) {
    boolean randomize = false;
    if (UniqueId.stringToUniqueIdType(args[1]) == UniqueIdType.METRIC) {
        randomize = tsdb.getConfig().getBoolean("tsd.core.uid.random_metrics");
    }
    final UniqueId uid = new UniqueId(tsdb.getClient(), table, args[1], (int) idwidth, randomize);
    for (int i = 2; i < args.length; i++) {
        try {
            uid.getOrCreateId(args[i]);
            // Lookup again the ID we've just created and print it.
            extactLookupName(tsdb.getClient(), table, idwidth, args[1], args[i]);
        } catch (HBaseException e) {
            LOG.error("error while processing " + args[i], e);
            return 3;
        }
    }
    return 0;
}
Also used : UniqueId(net.opentsdb.uid.UniqueId) NoSuchUniqueId(net.opentsdb.uid.NoSuchUniqueId) HBaseException(org.hbase.async.HBaseException)

Example 13 with HBaseException

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

the class UidManager method findAndPrintRow.

/**
   * Gets a given row in HBase and prints it on standard output.
   * @param client The HBase client to use.
   * @param table The name of the HBase table to use.
   * @param key The row key to attempt to get from HBase.
   * @param family The family in which we're interested.
   * @return 0 if at least one cell was found and printed, 1 otherwise.
   */
private static int findAndPrintRow(final HBaseClient client, final byte[] table, final byte[] key, final byte[] family, boolean formard) {
    final GetRequest get = new GetRequest(table, key);
    get.family(family);
    ArrayList<KeyValue> row;
    try {
        row = client.get(get).joinUninterruptibly();
    } catch (HBaseException e) {
        LOG.error("Get failed: " + get, e);
        return 1;
    } catch (Exception e) {
        LOG.error("WTF?  Unexpected exception type, get=" + get, e);
        return 42;
    }
    return printResult(row, family, formard) ? 0 : 1;
}
Also used : KeyValue(org.hbase.async.KeyValue) GetRequest(org.hbase.async.GetRequest) HBaseException(org.hbase.async.HBaseException) HBaseException(org.hbase.async.HBaseException)

Example 14 with HBaseException

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

the class UniqueId method rename.

/**
   * Reassigns the UID to a different name (non-atomic).
   * <p>
   * Whatever was the UID of {@code oldname} will be given to {@code newname}.
   * {@code oldname} will no longer be assigned a UID.
   * <p>
   * Beware that the assignment change is <b>not atommic</b>.  If two threads
   * or processes attempt to rename the same UID differently, the result is
   * unspecified and might even be inconsistent.  This API is only here for
   * administrative purposes, not for normal programmatic interactions.
   * @param oldname The old name to rename.
   * @param newname The new name.
   * @throws NoSuchUniqueName if {@code oldname} wasn't assigned.
   * @throws IllegalArgumentException if {@code newname} was already assigned.
   * @throws HBaseException if there was a problem with HBase while trying to
   * update the mapping.
   */
public void rename(final String oldname, final String newname) {
    final byte[] row = getId(oldname);
    final String row_string = fromBytes(row);
    {
        byte[] id = null;
        try {
            id = getId(newname);
        } catch (NoSuchUniqueName e) {
        // OK, we don't want the new name to be assigned.
        }
        if (id != null) {
            throw new IllegalArgumentException("When trying rename(\"" + oldname + "\", \"" + newname + "\") on " + this + ": new name already" + " assigned ID=" + Arrays.toString(id));
        }
    }
    if (renaming_id_names.contains(row_string) || renaming_id_names.contains(newname)) {
        throw new IllegalArgumentException("Ongoing rename on the same ID(\"" + Arrays.toString(row) + "\") or an identical new name(\"" + newname + "\")");
    }
    renaming_id_names.add(row_string);
    renaming_id_names.add(newname);
    final byte[] newnameb = toBytes(newname);
    // but the forward mapping without reverse mapping is bad.
    try {
        final PutRequest reverse_mapping = new PutRequest(table, row, NAME_FAMILY, kind, newnameb);
        hbasePutWithRetry(reverse_mapping, MAX_ATTEMPTS_PUT, INITIAL_EXP_BACKOFF_DELAY);
    } catch (HBaseException e) {
        LOG.error("When trying rename(\"" + oldname + "\", \"" + newname + "\") on " + this + ": Failed to update reverse" + " mapping for ID=" + Arrays.toString(row), e);
        renaming_id_names.remove(row_string);
        renaming_id_names.remove(newname);
        throw e;
    }
    // Now create the new forward mapping.
    try {
        final PutRequest forward_mapping = new PutRequest(table, newnameb, ID_FAMILY, kind, row);
        hbasePutWithRetry(forward_mapping, MAX_ATTEMPTS_PUT, INITIAL_EXP_BACKOFF_DELAY);
    } catch (HBaseException e) {
        LOG.error("When trying rename(\"" + oldname + "\", \"" + newname + "\") on " + this + ": Failed to create the" + " new forward mapping with ID=" + Arrays.toString(row), e);
        renaming_id_names.remove(row_string);
        renaming_id_names.remove(newname);
        throw e;
    }
    // Update cache.
    // add     new name -> ID
    addIdToCache(newname, row);
    // update  ID -> new name
    id_cache.put(fromBytes(row), newname);
    // remove  old name -> ID
    name_cache.remove(oldname);
    // Delete the old forward mapping.
    try {
        final DeleteRequest old_forward_mapping = new DeleteRequest(table, toBytes(oldname), ID_FAMILY, kind);
        client.delete(old_forward_mapping).joinUninterruptibly();
    } catch (HBaseException e) {
        LOG.error("When trying rename(\"" + oldname + "\", \"" + newname + "\") on " + this + ": Failed to remove the" + " old forward mapping for ID=" + Arrays.toString(row), e);
        throw e;
    } catch (Exception e) {
        final String msg = "Unexpected exception when trying rename(\"" + oldname + "\", \"" + newname + "\") on " + this + ": Failed to remove the" + " old forward mapping for ID=" + Arrays.toString(row);
        LOG.error("WTF?  " + msg, e);
        throw new RuntimeException(msg, e);
    } finally {
        renaming_id_names.remove(row_string);
        renaming_id_names.remove(newname);
    }
// Success!
}
Also used : PutRequest(org.hbase.async.PutRequest) HBaseException(org.hbase.async.HBaseException) DeleteRequest(org.hbase.async.DeleteRequest) HBaseException(org.hbase.async.HBaseException)

Example 15 with HBaseException

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

the class UniqueId method preloadUidCache.

/**
   * Pre-load UID caches, scanning up to "tsd.core.preload_uid_cache.max_entries"
   * rows from the UID table.
   * @param tsdb The TSDB to use 
   * @param uid_cache_map A map of {@link UniqueId} objects keyed on the kind.
   * @throws HBaseException Passes any HBaseException from HBase scanner.
   * @throws RuntimeException Wraps any non HBaseException from HBase scanner.
   * @2.1
   */
public static void preloadUidCache(final TSDB tsdb, final ByteMap<UniqueId> uid_cache_map) throws HBaseException {
    int max_results = tsdb.getConfig().getInt("tsd.core.preload_uid_cache.max_entries");
    LOG.info("Preloading uid cache with max_results=" + max_results);
    if (max_results <= 0) {
        return;
    }
    Scanner scanner = null;
    try {
        int num_rows = 0;
        scanner = getSuggestScanner(tsdb.getClient(), tsdb.uidTable(), "", null, max_results);
        for (ArrayList<ArrayList<KeyValue>> rows = scanner.nextRows().join(); rows != null; rows = scanner.nextRows().join()) {
            for (final ArrayList<KeyValue> row : rows) {
                for (KeyValue kv : row) {
                    final String name = fromBytes(kv.key());
                    final byte[] kind = kv.qualifier();
                    final byte[] id = kv.value();
                    LOG.debug("id='{}', name='{}', kind='{}'", Arrays.toString(id), name, fromBytes(kind));
                    UniqueId uid_cache = uid_cache_map.get(kind);
                    if (uid_cache != null) {
                        uid_cache.cacheMapping(name, id);
                    }
                }
                num_rows += row.size();
                // free()
                row.clear();
                if (num_rows >= max_results) {
                    break;
                }
            }
        }
        for (UniqueId unique_id_table : uid_cache_map.values()) {
            LOG.info("After preloading, uid cache '{}' has {} ids and {} names.", unique_id_table.kind(), unique_id_table.id_cache.size(), unique_id_table.name_cache.size());
        }
    } catch (Exception e) {
        if (e instanceof HBaseException) {
            throw (HBaseException) e;
        } else if (e instanceof RuntimeException) {
            throw (RuntimeException) e;
        } else {
            throw new RuntimeException("Error while preloading IDs", e);
        }
    } finally {
        if (scanner != null) {
            scanner.close();
        }
    }
}
Also used : Scanner(org.hbase.async.Scanner) KeyValue(org.hbase.async.KeyValue) ArrayList(java.util.ArrayList) HBaseException(org.hbase.async.HBaseException) HBaseException(org.hbase.async.HBaseException)

Aggregations

HBaseException (org.hbase.async.HBaseException)16 ArrayList (java.util.ArrayList)9 KeyValue (org.hbase.async.KeyValue)9 Callback (com.stumbleupon.async.Callback)5 Deferred (com.stumbleupon.async.Deferred)5 IOException (java.io.IOException)4 Map (java.util.Map)4 PutRequest (org.hbase.async.PutRequest)4 Scanner (org.hbase.async.Scanner)4 DeferredGroupException (com.stumbleupon.async.DeferredGroupException)3 HashMap (java.util.HashMap)3 DeleteRequest (org.hbase.async.DeleteRequest)3 Test (org.junit.Test)3 PrepareForTest (org.powermock.core.classloader.annotations.PrepareForTest)3 NoSuchUniqueId (net.opentsdb.uid.NoSuchUniqueId)2 NoSuchUniqueName (net.opentsdb.uid.NoSuchUniqueName)2 UniqueId (net.opentsdb.uid.UniqueId)2 JSONException (net.opentsdb.utils.JSONException)2 InvocationTargetException (java.lang.reflect.InvocationTargetException)1 HashSet (java.util.HashSet)1