use of io.prestosql.statestore.SharedQueryState in project hetu-core by openlookeng.
the class SqlQueryManager method killExpiredQuery.
/**
* Kill query when expired, state has already been updated in StateFetcher.
*/
private void killExpiredQuery() {
if (!isMultiCoordinatorEnabled()) {
return;
}
List<QueryExecution> localRunningQueries = queryTracker.getAllQueries().stream().filter(query -> query.getState() == RUNNING).collect(toImmutableList());
Map<String, SharedQueryState> queries = StateCacheStore.get().getCachedStates(StateStoreConstants.FINISHED_QUERY_STATE_COLLECTION_NAME);
if (queries != null) {
Set<String> expiredQueryIds = queries.entrySet().stream().filter(entry -> isQueryExpired(entry.getValue())).map(entry -> entry.getKey()).collect(Collectors.toSet());
if (!expiredQueryIds.isEmpty()) {
for (QueryExecution localQuery : localRunningQueries) {
if (expiredQueryIds.contains(localQuery.getQueryId().getId())) {
localQuery.fail(new PrestoException(QUERY_EXPIRE, "Query killed because the query has expired. Please try again in a few minutes."));
}
}
}
}
}
use of io.prestosql.statestore.SharedQueryState in project hetu-core by openlookeng.
the class DistributedResourceGroup method internalRefreshStats.
/**
* Update internal stats for all the children groups
* Stats are calculated based on cached resource group states from state store
* Stats include: running queries, queued queries, memory usage, cpu usage
*/
@Override
protected void internalRefreshStats() {
checkState(Thread.holdsLock(root), "Must hold lock to refresh stats");
synchronized (root) {
if (subGroups.isEmpty()) {
descendantRunningQueries = 0;
descendantQueuedQueries = 0;
cachedMemoryUsageBytes = 0;
Optional<SharedResourceGroupState> resourceGroupState = getSharedResourceGroupState();
if (!resourceGroupState.isPresent()) {
return;
}
resourceGroupState.ifPresent(state -> this.lastExecutionTime = state.getLastExecutionTime());
Set<SharedQueryState> sharedQueryStates = resourceGroupState.get().getRunningQueries();
for (SharedQueryState state : sharedQueryStates) {
cachedMemoryUsageBytes += state.getTotalMemoryReservation().toBytes();
}
// get cpuUsageMillis from resourceGroupState
cpuUsageMillis = resourceGroupState.get().getCpuUsageMillis();
} else {
int tempDescendantRunningQueries = 0;
int tempDescendantQueuedQueries = 0;
long tempCachedMemoryUsageBytes = 0L;
long tempCpuUsageMillis = 0L;
for (BaseResourceGroup group : subGroups()) {
group.internalRefreshStats();
tempCpuUsageMillis += ((DistributedResourceGroup) group).cpuUsageMillis;
}
// Sub-groups are created on demand, so need to also check stats in sub-groups created on other coordinators
for (SharedResourceGroupState state : getSharedSubGroups()) {
tempDescendantRunningQueries += state.getRunningQueries().size();
tempDescendantQueuedQueries += state.getQueuedQueries().size();
tempCachedMemoryUsageBytes += state.getRunningQueries().stream().mapToLong(query -> query.getTotalMemoryReservation().toBytes()).reduce(0, (memoryUsage1, memoryUsage2) -> memoryUsage1 + memoryUsage2);
}
descendantRunningQueries = tempDescendantRunningQueries;
descendantQueuedQueries = tempDescendantQueuedQueries;
cachedMemoryUsageBytes = tempCachedMemoryUsageBytes;
cpuUsageMillis = tempCpuUsageMillis;
}
lastUpdateTime = new DateTime();
}
}
use of io.prestosql.statestore.SharedQueryState in project hetu-core by openlookeng.
the class DistributedResourceGroup method internalCancelQuery.
public void internalCancelQuery() {
checkState(Thread.holdsLock(root), "Must hold lock to check cancel query");
synchronized (root) {
if (!subGroups.isEmpty()) {
for (BaseResourceGroup group : subGroups()) {
((DistributedResourceGroup) group).internalCancelQuery();
}
return;
}
if (cachedMemoryUsageBytes <= softMemoryLimitBytes) {
return;
}
Optional<SharedResourceGroupState> resourceGroupState = getSharedResourceGroupState();
if (!resourceGroupState.isPresent()) {
return;
}
Set<SharedQueryState> globalRunningQueries = resourceGroupState.get().getRunningQueries();
List<SharedQueryState> sortedQueryList;
Lock lock = stateStore.getLock(id.toString());
boolean locked = false;
try {
// If lock is not free, then we return immediately, so no need to refresh after taking lock.
// Before next call of this function, refresh will already happen.
locked = lock.tryLock();
if (locked) {
switch(killPolicy) {
case HIGH_MEMORY_QUERIES:
double absMemoryMargin = 1 - (double) memoryMarginPercent / 100;
double absQueryProgressMargin = 1 - (double) queryProgressMarginPercent / 100;
sortedQueryList = globalRunningQueries.stream().sorted((o1, o2) -> {
if (o1.getTotalMemoryReservation().toBytes() < o2.getTotalMemoryReservation().toBytes() * absMemoryMargin || o2.getTotalMemoryReservation().toBytes() < o1.getTotalMemoryReservation().toBytes() * absMemoryMargin) {
return ((Long) o2.getTotalMemoryReservation().toBytes()).compareTo(o1.getTotalMemoryReservation().toBytes());
}
// if query progress difference is within 5%, then order will be decided based on memory itself.
if (o1.getQueryProgress().orElse(0) < o2.getQueryProgress().orElse(0) * absQueryProgressMargin || o2.getQueryProgress().orElse(0) < o1.getQueryProgress().orElse(0) * absQueryProgressMargin) {
return ((Double) o1.getQueryProgress().orElse(0)).compareTo((o2.getQueryProgress().orElse(0)));
}
return ((Long) o2.getTotalMemoryReservation().toBytes()).compareTo(o1.getTotalMemoryReservation().toBytes());
}).collect(Collectors.toList());
break;
case OLDEST_QUERIES:
sortedQueryList = globalRunningQueries.stream().sorted(Comparator.comparing(o -> (o.getExecutionStartTime().get()))).collect(Collectors.toList());
break;
case RECENT_QUERIES:
sortedQueryList = globalRunningQueries.stream().sorted(Comparator.comparing(o -> (o.getExecutionStartTime().get()), Comparator.reverseOrder())).collect(Collectors.toList());
break;
case FINISH_PERCENTAGE_QUERIES:
sortedQueryList = globalRunningQueries.stream().sorted(Comparator.comparing(o -> (o.getQueryProgress().orElse(0)))).collect(Collectors.toList());
break;
case NO_KILL:
// fall through
default:
sortedQueryList = new ArrayList<>();
}
long tempGlobalCachedMemoryUsage = cachedMemoryUsageBytes;
long tempLocalCachedMemoryUsage = cachedMemoryUsageBytes;
// So in this case only Q1 will be killed from local coordinator.
for (SharedQueryState query : sortedQueryList) {
for (ManagedQueryExecution localQuery : runningQueries) {
if (query.getBasicQueryInfo().getQueryId().equals(localQuery.getBasicQueryInfo().getQueryId())) {
LOG.info("Query " + localQuery.getBasicQueryInfo().getQueryId() + " is getting killed for resource group " + this + " query will be killed with policy " + killPolicy);
localQuery.fail(new PrestoException(GENERIC_INSUFFICIENT_RESOURCES, "Memory consumption " + tempLocalCachedMemoryUsage + " exceed the limit " + softMemoryLimitBytes + "for resource group " + this));
queryFinished(localQuery);
tempLocalCachedMemoryUsage -= query.getTotalMemoryReservation().toBytes();
break;
}
}
tempGlobalCachedMemoryUsage -= query.getTotalMemoryReservation().toBytes();
if (tempGlobalCachedMemoryUsage <= softMemoryLimitBytes) {
break;
}
}
}
} catch (RuntimeException e) {
return;
} finally {
if (locked) {
lock.unlock();
}
}
}
}
use of io.prestosql.statestore.SharedQueryState in project hetu-core by openlookeng.
the class DistributedResourceGroupTemp method internalCancelQuery.
public void internalCancelQuery() {
checkState(Thread.holdsLock(root), "Must hold lock to check cancel query");
synchronized (root) {
if (!subGroups.isEmpty()) {
for (BaseResourceGroup group : subGroups()) {
((DistributedResourceGroupTemp) group).internalCancelQuery();
}
return;
}
long cachedMemoryUsageBytes = getGlobalCachedMemoryUsageBytes();
if (cachedMemoryUsageBytes <= softMemoryLimitBytes) {
return;
}
Optional<SharedResourceGroupState> resourceGroupState = getSharedResourceGroupState();
if (!resourceGroupState.isPresent()) {
return;
}
Set<SharedQueryState> globalRunningQueries = resourceGroupState.get().getRunningQueries();
List<SharedQueryState> sortedQueryList;
Lock lock = stateStore.getLock(id.toString());
boolean locked = false;
try {
// If lock is not free, then we return immediately, so no need to refresh after taking lock.
// Before next call of this function, refresh will already happen.
locked = lock.tryLock();
if (locked) {
switch(killPolicy) {
case HIGH_MEMORY_QUERIES:
double absMemoryMargin = 1 - (double) memoryMarginPercent / 100;
double absQueryProgressMargin = 1 - (double) queryProgressMarginPercent / 100;
sortedQueryList = globalRunningQueries.stream().sorted((o1, o2) -> {
if (o1.getTotalMemoryReservation().toBytes() < o2.getTotalMemoryReservation().toBytes() * absMemoryMargin || o2.getTotalMemoryReservation().toBytes() < o1.getTotalMemoryReservation().toBytes() * absMemoryMargin) {
return ((Long) o2.getTotalMemoryReservation().toBytes()).compareTo(o1.getTotalMemoryReservation().toBytes());
}
// if query progress difference is within 5%, then order will be decided based on memory itself.
if (o1.getQueryProgress().orElse(0) < o2.getQueryProgress().orElse(0) * absQueryProgressMargin || o2.getQueryProgress().orElse(0) < o1.getQueryProgress().orElse(0) * absQueryProgressMargin) {
return ((Double) o1.getQueryProgress().orElse(0)).compareTo((o2.getQueryProgress().orElse(0)));
}
return ((Long) o2.getTotalMemoryReservation().toBytes()).compareTo(o1.getTotalMemoryReservation().toBytes());
}).collect(Collectors.toList());
break;
case OLDEST_QUERIES:
sortedQueryList = globalRunningQueries.stream().sorted(Comparator.comparing(o -> (o.getExecutionStartTime().get()))).collect(Collectors.toList());
break;
case RECENT_QUERIES:
sortedQueryList = globalRunningQueries.stream().sorted(Comparator.comparing(o -> (o.getExecutionStartTime().get()), Comparator.reverseOrder())).collect(Collectors.toList());
break;
case FINISH_PERCENTAGE_QUERIES:
sortedQueryList = globalRunningQueries.stream().sorted(Comparator.comparing(o -> (o.getQueryProgress().orElse(0)))).collect(Collectors.toList());
break;
case NO_KILL:
// fall through
default:
sortedQueryList = new ArrayList<>();
}
long tempGlobalCachedMemoryUsage = cachedMemoryUsageBytes;
long tempLocalCachedMemoryUsage = localCachedMemoryUsageBytes;
// So in this case only Q1 will be killed from local coordinator.
for (SharedQueryState query : sortedQueryList) {
for (ManagedQueryExecution localQuery : localRunningQueries) {
if (query.getBasicQueryInfo().getQueryId().equals(localQuery.getBasicQueryInfo().getQueryId())) {
LOG.info("Query " + localQuery.getBasicQueryInfo().getQueryId() + " is getting killed for resource group " + this + " query will be killed with policy " + killPolicy);
localQuery.fail(new PrestoException(GENERIC_INSUFFICIENT_RESOURCES, "Memory consumption " + tempLocalCachedMemoryUsage + " exceed the limit " + softMemoryLimitBytes + "for resource group " + this));
queryFinished(localQuery);
tempLocalCachedMemoryUsage -= query.getTotalMemoryReservation().toBytes();
break;
}
}
tempGlobalCachedMemoryUsage -= query.getTotalMemoryReservation().toBytes();
if (tempGlobalCachedMemoryUsage <= softMemoryLimitBytes) {
break;
}
}
}
} catch (RuntimeException e) {
return;
} finally {
if (locked) {
lock.unlock();
}
}
}
}
use of io.prestosql.statestore.SharedQueryState in project hetu-core by openlookeng.
the class DistributedResourceGroupTemp method internalStartNext.
/**
* Check if there is any queued query in any eligible sub-group that can be started
*
* @return if any query has been started in sub-groups
*/
protected boolean internalStartNext() {
checkState(Thread.holdsLock(root), "Must hold lock to find next query");
synchronized (root) {
if (!canRunMore()) {
return false;
}
// Only start the query if it exists locally
Optional<SharedResourceGroupState> resourceGroupState = getSharedResourceGroupState();
PriorityQueue<SharedQueryState> globalQueuedQueries = resourceGroupState.isPresent() ? resourceGroupState.get().getQueuedQueries() : new PriorityQueue<>();
if (!globalQueuedQueries.isEmpty() && !localQueuedQueries.isEmpty()) {
// Get queued query with longest queued time from state cache store.
// Remove it if local queued queries contains it.
SharedQueryState nextQuery = globalQueuedQueries.peek();
for (ManagedQueryExecution localQuery : localQueuedQueries) {
if (nextQuery.getBasicQueryInfo().getQueryId().equals(localQuery.getBasicQueryInfo().getQueryId())) {
Lock lock = stateStore.getLock(id.toString());
boolean locked = false;
try {
locked = lock.tryLock(MILLISECONDS_PER_SECOND, TimeUnit.MILLISECONDS);
if (locked) {
// Get the most recent cached state store status and check canRunMore again
// Avoid the race condition that state store is updated by other process
// Make sure queued query start is synchronized
DistributedResourceGroupUtils.mapCachedStates();
if (canRunMore()) {
startInBackground(localQuery);
return true;
}
}
return false;
} catch (InterruptedException | RuntimeException e) {
return false;
} finally {
if (locked) {
lock.unlock();
}
}
}
}
}
// Try to find least recently used eligible group
DistributedResourceGroupTemp chosenGroup = findLeastRecentlyExecutedSubgroup();
if (chosenGroup == null) {
return false;
}
// Try to start queued query in the group
boolean started = chosenGroup.internalStartNext();
long currentTime = System.currentTimeMillis();
if (lastStartMillis != 0) {
timeBetweenStartsSec.update(Math.max(0, (currentTime - lastStartMillis) / MILLISECONDS_PER_SECOND));
}
lastStartMillis = currentTime;
return started;
}
}
Aggregations