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());
}
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());
}
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);
}
}
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));
}
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());
}
Aggregations