use of com.stumbleupon.async.Callback in project opentsdb by OpenTSDB.
the class TSMeta method getFromStorage.
/**
* Attempts to fetch the timeseries meta data from storage.
* This method will fetch the {@code counter} and {@code meta} columns.
* <b>Note:</b> This method will not load the UIDMeta objects.
* @param tsdb The TSDB to use for storage access
* @param tsuid The UID of the meta to fetch
* @return A TSMeta object if found, null if not
* @throws HBaseException if there was an issue fetching
* @throws IllegalArgumentException if parsing failed
* @throws JSONException if the data was corrupted
*/
private static Deferred<TSMeta> getFromStorage(final TSDB tsdb, final byte[] tsuid) {
/**
* Called after executing the GetRequest to parse the meta data.
*/
final class GetCB implements Callback<Deferred<TSMeta>, ArrayList<KeyValue>> {
/**
* @return Null if the meta did not exist or a valid TSMeta object if it
* did.
*/
@Override
public Deferred<TSMeta> call(final ArrayList<KeyValue> row) throws Exception {
if (row == null || row.isEmpty()) {
return Deferred.fromResult(null);
}
long dps = 0;
long last_received = 0;
TSMeta meta = null;
for (KeyValue column : row) {
if (Arrays.equals(COUNTER_QUALIFIER, column.qualifier())) {
dps = Bytes.getLong(column.value());
last_received = column.timestamp() / 1000;
} else if (Arrays.equals(META_QUALIFIER, column.qualifier())) {
meta = JSON.parseToObject(column.value(), TSMeta.class);
}
}
if (meta == null) {
LOG.warn("Found a counter TSMeta column without a meta for TSUID: " + UniqueId.uidToString(row.get(0).key()));
return Deferred.fromResult(null);
}
meta.total_dps = dps;
meta.last_received = last_received;
return Deferred.fromResult(meta);
}
}
final GetRequest get = new GetRequest(tsdb.metaTable(), tsuid);
get.family(FAMILY);
get.qualifiers(new byte[][] { COUNTER_QUALIFIER, META_QUALIFIER });
return tsdb.getClient().get(get).addCallbackDeferring(new GetCB());
}
use of com.stumbleupon.async.Callback in project opentsdb by OpenTSDB.
the class TSMeta method metaExistsInStorage.
/**
* Determines if an entry exists in storage or not.
* 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> metaExistsInStorage(final TSDB tsdb, final String tsuid) {
final GetRequest get = new GetRequest(tsdb.metaTable(), UniqueId.stringToUid(tsuid));
get.family(FAMILY);
get.qualifier(META_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 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());
}
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());
}
use of com.stumbleupon.async.Callback in project opentsdb by OpenTSDB.
the class TSUIDQuery method getLastPoint.
/**
* Attempts to fetch the last data point for the given metric or TSUID.
* If back_scan == 0 and meta is enabled via
* "tsd.core.meta.enable_tsuid_tracking" or
* "tsd.core.meta.enable_tsuid_incrementing" then we will look up the metric
* or TSUID in the meta table first and use the counter there to get the
* last write time.
* <p>
* However if backscan is set, then we'll start with the current time and
* iterate back "back_scan" number of hours until we find a value.
* <p>
* @param resolve_names Whether or not to resolve the UIDs back to their
* names when we find a value.
* @param back_scan The number of hours back in time to scan
* @return A data point if found, null if not. Or an exception if something
* went pear shaped.
*/
public Deferred<IncomingDataPoint> getLastPoint(final boolean resolve_names, final int back_scan) {
if (back_scan < 0) {
throw new IllegalArgumentException("Backscan must be zero or a positive number");
}
this.resolve_names = resolve_names;
this.back_scan = back_scan;
final boolean meta_enabled = tsdb.getConfig().enable_tsuid_tracking() || tsdb.getConfig().enable_tsuid_incrementing();
class TSUIDCB implements Callback<Deferred<IncomingDataPoint>, byte[]> {
@Override
public Deferred<IncomingDataPoint> call(final byte[] incoming_tsuid) throws Exception {
if (tsuid == null && incoming_tsuid == null) {
return Deferred.fromError(new RuntimeException("Both incoming and " + "supplied TSUIDs were null for " + TSUIDQuery.this));
} else if (incoming_tsuid != null) {
setTSUID(incoming_tsuid);
}
if (back_scan < 1 && meta_enabled) {
final GetRequest get = new GetRequest(tsdb.metaTable(), tsuid);
get.family(TSMeta.FAMILY());
get.qualifier(TSMeta.COUNTER_QUALIFIER());
return tsdb.getClient().get(get).addCallbackDeferring(new MetaCB());
}
if (last_timestamp > 0) {
last_timestamp = Internal.baseTime(last_timestamp);
} else {
last_timestamp = Internal.baseTime(DateTime.currentTimeMillis());
}
final byte[] key = RowKey.rowKeyFromTSUID(tsdb, tsuid, last_timestamp);
final GetRequest get = new GetRequest(tsdb.dataTable(), key);
get.family(TSDB.FAMILY());
return tsdb.getClient().get(get).addCallbackDeferring(new LastPointCB());
}
@Override
public String toString() {
return "TSUID callback";
}
}
if (tsuid == null) {
return tsuidFromMetric(tsdb, metric, tags).addCallbackDeferring(new TSUIDCB());
}
try {
// damn typed exceptions....
return new TSUIDCB().call(null);
} catch (Exception e) {
return Deferred.fromError(e);
}
}
Aggregations