use of net.opentsdb.meta.TSUIDQuery in project opentsdb by OpenTSDB.
the class QueryRpc method handleLastDataPointQuery.
/**
* Processes a last data point query
* @param tsdb The TSDB to which we belong
* @param query The HTTP query to parse/respond
*/
private void handleLastDataPointQuery(final TSDB tsdb, final HttpQuery query) {
final LastPointQuery data_query;
if (query.method() == HttpMethod.POST) {
switch(query.apiVersion()) {
case 0:
case 1:
data_query = query.serializer().parseLastPointQueryV1();
break;
default:
throw new BadRequestException(HttpResponseStatus.NOT_IMPLEMENTED, "Requested API version not implemented", "Version " + query.apiVersion() + " is not implemented");
}
} else {
data_query = this.parseLastPointQuery(tsdb, query);
}
if (data_query.sub_queries == null || data_query.sub_queries.isEmpty()) {
throw new BadRequestException(HttpResponseStatus.BAD_REQUEST, "Missing sub queries");
}
// a list of deferreds to wait on
final ArrayList<Deferred<Object>> calls = new ArrayList<Deferred<Object>>();
// final results for serialization
final List<IncomingDataPoint> results = new ArrayList<IncomingDataPoint>();
/**
* Used to catch exceptions
*/
final class ErrBack implements Callback<Object, Exception> {
public Object call(final Exception e) throws Exception {
Throwable ex = e;
while (ex.getClass().equals(DeferredGroupException.class)) {
if (ex.getCause() == null) {
LOG.warn("Unable to get to the root cause of the DGE");
break;
}
ex = ex.getCause();
}
if (ex instanceof RuntimeException) {
throw new BadRequestException(ex);
} else {
throw e;
}
}
@Override
public String toString() {
return "Error back";
}
}
final class FetchCB implements Callback<Deferred<Object>, ArrayList<IncomingDataPoint>> {
@Override
public Deferred<Object> call(final ArrayList<IncomingDataPoint> dps) throws Exception {
synchronized (results) {
for (final IncomingDataPoint dp : dps) {
if (dp != null) {
results.add(dp);
}
}
}
return Deferred.fromResult(null);
}
@Override
public String toString() {
return "Fetched data points CB";
}
}
/**
* Called after scanning the tsdb-meta table for TSUIDs that match the given
* metric and/or tags. If matches were found, it fires off a number of
* getLastPoint requests, adding the deferreds to the calls list
*/
final class TSUIDQueryCB implements Callback<Deferred<Object>, ByteMap<Long>> {
public Deferred<Object> call(final ByteMap<Long> tsuids) throws Exception {
if (tsuids == null || tsuids.isEmpty()) {
return null;
}
final ArrayList<Deferred<IncomingDataPoint>> deferreds = new ArrayList<Deferred<IncomingDataPoint>>(tsuids.size());
for (Map.Entry<byte[], Long> entry : tsuids.entrySet()) {
deferreds.add(TSUIDQuery.getLastPoint(tsdb, entry.getKey(), data_query.getResolveNames(), data_query.getBackScan(), entry.getValue()));
}
return Deferred.group(deferreds).addCallbackDeferring(new FetchCB());
}
@Override
public String toString() {
return "TSMeta scan CB";
}
}
/**
* Used to wait on the list of data point deferreds. Once they're all done
* this will return the results to the call via the serializer
*/
final class FinalCB implements Callback<Object, ArrayList<Object>> {
public Object call(final ArrayList<Object> done) throws Exception {
query.sendReply(query.serializer().formatLastPointQueryV1(results));
return null;
}
@Override
public String toString() {
return "Final CB";
}
}
try {
// start executing the queries
for (final LastPointSubQuery sub_query : data_query.getQueries()) {
final ArrayList<Deferred<IncomingDataPoint>> deferreds = new ArrayList<Deferred<IncomingDataPoint>>();
// process the TSUIDs and ignore the metric/tags
if (sub_query.getTSUIDs() != null && !sub_query.getTSUIDs().isEmpty()) {
for (final String tsuid : sub_query.getTSUIDs()) {
final TSUIDQuery tsuid_query = new TSUIDQuery(tsdb, UniqueId.stringToUid(tsuid));
deferreds.add(tsuid_query.getLastPoint(data_query.getResolveNames(), data_query.getBackScan()));
}
} else {
@SuppressWarnings("unchecked") final TSUIDQuery tsuid_query = new TSUIDQuery(tsdb, sub_query.getMetric(), sub_query.getTags() != null ? sub_query.getTags() : Collections.EMPTY_MAP);
if (data_query.getBackScan() > 0) {
deferreds.add(tsuid_query.getLastPoint(data_query.getResolveNames(), data_query.getBackScan()));
} else {
calls.add(tsuid_query.getLastWriteTimes().addCallbackDeferring(new TSUIDQueryCB()));
}
}
if (deferreds.size() > 0) {
calls.add(Deferred.group(deferreds).addCallbackDeferring(new FetchCB()));
}
}
Deferred.group(calls).addCallback(new FinalCB()).addErrback(new ErrBack()).joinUninterruptibly();
} catch (Exception e) {
Throwable ex = e;
while (ex.getClass().equals(DeferredGroupException.class)) {
if (ex.getCause() == null) {
LOG.warn("Unable to get to the root cause of the DGE");
break;
}
ex = ex.getCause();
}
if (ex instanceof RuntimeException) {
throw new BadRequestException(ex);
} else {
throw new RuntimeException("Shouldn't be here", e);
}
}
}
use of net.opentsdb.meta.TSUIDQuery in project opentsdb by OpenTSDB.
the class UniqueIdRpc method handleTSMeta.
/**
* Handles CRUD calls to individual TSMeta data entries
* @param tsdb The TSDB from the RPC router
* @param query The query for this request
*/
private void handleTSMeta(final TSDB tsdb, final HttpQuery query) {
final HttpMethod method = query.getAPIMethod();
// GET
if (method == HttpMethod.GET) {
String tsuid = null;
if (query.hasQueryStringParam("tsuid")) {
tsuid = query.getQueryStringParam("tsuid");
try {
final TSMeta meta = TSMeta.getTSMeta(tsdb, tsuid).joinUninterruptibly();
if (meta != null) {
query.sendReply(query.serializer().formatTSMetaV1(meta));
} else {
throw new BadRequestException(HttpResponseStatus.NOT_FOUND, "Could not find Timeseries meta data");
}
} catch (NoSuchUniqueName e) {
// the timeseries meta data
throw new BadRequestException(HttpResponseStatus.NOT_FOUND, "Unable to find one of the UIDs", e);
} catch (BadRequestException e) {
throw e;
} catch (Exception e) {
throw new RuntimeException(e);
}
} else {
String mquery = query.getRequiredQueryStringParam("m");
// m is of the following forms:
// metric[{tag=value,...}]
// where the parts in square brackets `[' .. `]' are optional.
final HashMap<String, String> tags = new HashMap<String, String>();
String metric = null;
try {
metric = Tags.parseWithMetric(mquery, tags);
} catch (IllegalArgumentException e) {
throw new BadRequestException(e);
}
final TSUIDQuery tsuid_query = new TSUIDQuery(tsdb, metric, tags);
try {
final List<TSMeta> tsmetas = tsuid_query.getTSMetas().joinUninterruptibly();
query.sendReply(query.serializer().formatTSMetaListV1(tsmetas));
} catch (NoSuchUniqueName e) {
throw new BadRequestException(HttpResponseStatus.NOT_FOUND, "Unable to find one of the UIDs", e);
} catch (BadRequestException e) {
throw e;
} catch (RuntimeException e) {
throw new BadRequestException(e);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
// POST / PUT
} else if (method == HttpMethod.POST || method == HttpMethod.PUT) {
final TSMeta meta;
if (query.hasContent()) {
meta = query.serializer().parseTSMetaV1();
} else {
meta = this.parseTSMetaQS(query);
}
/**
* Storage callback used to determine if the storage call was successful
* or not. Also returns the updated object from storage.
*/
class SyncCB implements Callback<Deferred<TSMeta>, Boolean> {
@Override
public Deferred<TSMeta> call(Boolean success) throws Exception {
if (!success) {
throw new BadRequestException(HttpResponseStatus.INTERNAL_SERVER_ERROR, "Failed to save the TSMeta to storage", "This may be caused by another process modifying storage data");
}
return TSMeta.getTSMeta(tsdb, meta.getTSUID());
}
}
if (meta.getTSUID() == null || meta.getTSUID().isEmpty()) {
// we got a JSON object without TSUID. Try to find a timeseries spec of
// the form "m": "metric{tagk=tagv,...}"
final String metric = query.getRequiredQueryStringParam("m");
final boolean create = query.getQueryStringParam("create") != null && query.getQueryStringParam("create").equals("true");
final String tsuid = getTSUIDForMetric(metric, tsdb);
class WriteCounterIfNotPresentCB implements Callback<Boolean, Boolean> {
@Override
public Boolean call(Boolean exists) throws Exception {
if (!exists && create) {
final PutRequest put = new PutRequest(tsdb.metaTable(), UniqueId.stringToUid(tsuid), TSMeta.FAMILY(), TSMeta.COUNTER_QUALIFIER(), Bytes.fromLong(0));
tsdb.getClient().put(put);
}
return exists;
}
}
try {
// Check whether we have a TSMeta stored already
final boolean exists = TSMeta.metaExistsInStorage(tsdb, tsuid).joinUninterruptibly();
// set TSUID
meta.setTSUID(tsuid);
if (!exists && create) {
// Write 0 to counter column if not present
TSMeta.counterExistsInStorage(tsdb, UniqueId.stringToUid(tsuid)).addCallback(new WriteCounterIfNotPresentCB()).joinUninterruptibly();
// set TSUID
final Deferred<TSMeta> process_meta = meta.storeNew(tsdb).addCallbackDeferring(new SyncCB());
final TSMeta updated_meta = process_meta.joinUninterruptibly();
tsdb.indexTSMeta(updated_meta);
tsdb.processTSMetaThroughTrees(updated_meta);
query.sendReply(query.serializer().formatTSMetaV1(updated_meta));
} else if (exists) {
final Deferred<TSMeta> process_meta = meta.syncToStorage(tsdb, method == HttpMethod.PUT).addCallbackDeferring(new SyncCB());
final TSMeta updated_meta = process_meta.joinUninterruptibly();
tsdb.indexTSMeta(updated_meta);
query.sendReply(query.serializer().formatTSMetaV1(updated_meta));
} else {
throw new BadRequestException("Could not find TSMeta, specify \"create=true\" to create a new one.");
}
} catch (IllegalStateException e) {
query.sendStatusOnly(HttpResponseStatus.NOT_MODIFIED);
} catch (IllegalArgumentException e) {
throw new BadRequestException(e);
} catch (BadRequestException e) {
throw e;
} catch (NoSuchUniqueName e) {
// the timeseries meta data
throw new BadRequestException(HttpResponseStatus.NOT_FOUND, "Unable to find one or more UIDs", e);
} catch (Exception e) {
throw new RuntimeException(e);
}
} else {
try {
final Deferred<TSMeta> process_meta = meta.syncToStorage(tsdb, method == HttpMethod.PUT).addCallbackDeferring(new SyncCB());
final TSMeta updated_meta = process_meta.joinUninterruptibly();
tsdb.indexTSMeta(updated_meta);
query.sendReply(query.serializer().formatTSMetaV1(updated_meta));
} catch (IllegalStateException e) {
query.sendStatusOnly(HttpResponseStatus.NOT_MODIFIED);
} catch (IllegalArgumentException e) {
throw new BadRequestException(e);
} catch (NoSuchUniqueName e) {
// the timeseries meta data
throw new BadRequestException(HttpResponseStatus.NOT_FOUND, "Unable to find one or more UIDs", e);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
// DELETE
} else if (method == HttpMethod.DELETE) {
final TSMeta meta;
if (query.hasContent()) {
meta = query.serializer().parseTSMetaV1();
} else {
meta = this.parseTSMetaQS(query);
}
try {
meta.delete(tsdb);
tsdb.deleteTSMeta(meta.getTSUID());
} catch (IllegalArgumentException e) {
throw new BadRequestException("Unable to delete TSMeta information", e);
}
query.sendStatusOnly(HttpResponseStatus.NO_CONTENT);
} else {
throw new BadRequestException(HttpResponseStatus.METHOD_NOT_ALLOWED, "Method not allowed", "The HTTP method [" + method.getName() + "] is not permitted for this endpoint");
}
}
Aggregations