From 1ee64c771343c957d28cabe98be4f92b2c997cff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Osipiuk?= Date: Wed, 16 Feb 2022 12:47:17 +0100 Subject: [PATCH 1/2] Remove support for reserved memory pool --- .../execution/MemoryRevokingScheduler.java | 1 - .../io/trino/execution/SqlTaskManager.java | 40 ------- .../java/io/trino/execution/TaskManager.java | 3 - .../io/trino/memory/ClusterMemoryManager.java | 105 ++---------------- .../io/trino/memory/LocalMemoryManager.java | 11 -- .../io/trino/memory/MemoryPoolAssignment.java | 56 ---------- .../memory/MemoryPoolAssignmentsRequest.java | 65 ----------- .../java/io/trino/memory/MemoryResource.java | 18 +-- .../io/trino/memory/NodeMemoryConfig.java | 25 +---- .../io/trino/memory/RemoteNodeMemory.java | 23 +--- .../io/trino/server/ServerMainModule.java | 2 - .../src/main/resources/webapp/dist/worker.js | 2 +- .../webapp/src/components/WorkerStatus.jsx | 4 - .../memory/LowMemoryKillerTestingUtils.java | 33 +----- .../trino/memory/TestLocalMemoryManager.java | 18 +-- .../io/trino/memory/TestNodeMemoryConfig.java | 7 +- .../io/trino/memory/TestQueryContext.java | 85 +------------- .../TestTotalReservationLowMemoryKiller.java | 12 +- ...ervationOnBlockedNodesLowMemoryKiller.java | 18 +-- .../io/trino/memory/TestMemoryManager.java | 99 +++-------------- 20 files changed, 54 insertions(+), 573 deletions(-) delete mode 100644 core/trino-main/src/main/java/io/trino/memory/MemoryPoolAssignment.java delete mode 100644 core/trino-main/src/main/java/io/trino/memory/MemoryPoolAssignmentsRequest.java diff --git a/core/trino-main/src/main/java/io/trino/execution/MemoryRevokingScheduler.java b/core/trino-main/src/main/java/io/trino/execution/MemoryRevokingScheduler.java index 532483371f7f..f29aee70e962 100644 --- a/core/trino-main/src/main/java/io/trino/execution/MemoryRevokingScheduler.java +++ b/core/trino-main/src/main/java/io/trino/execution/MemoryRevokingScheduler.java @@ -111,7 +111,6 @@ private static List getMemoryPools(LocalMemoryManager localMemoryMan requireNonNull(localMemoryManager, "localMemoryManager cannot be null"); ImmutableList.Builder builder = new ImmutableList.Builder<>(); builder.add(localMemoryManager.getGeneralPool()); - localMemoryManager.getReservedPool().ifPresent(builder::add); return builder.build(); } diff --git a/core/trino-main/src/main/java/io/trino/execution/SqlTaskManager.java b/core/trino-main/src/main/java/io/trino/execution/SqlTaskManager.java index 4865e60e72c7..c864b3f24b30 100644 --- a/core/trino-main/src/main/java/io/trino/execution/SqlTaskManager.java +++ b/core/trino-main/src/main/java/io/trino/execution/SqlTaskManager.java @@ -36,9 +36,6 @@ import io.trino.execution.buffer.OutputBuffers.OutputBufferId; import io.trino.execution.executor.TaskExecutor; import io.trino.memory.LocalMemoryManager; -import io.trino.memory.MemoryPool; -import io.trino.memory.MemoryPoolAssignment; -import io.trino.memory.MemoryPoolAssignmentsRequest; import io.trino.memory.NodeMemoryConfig; import io.trino.memory.QueryContext; import io.trino.spi.QueryId; @@ -57,7 +54,6 @@ import javax.annotation.PostConstruct; import javax.annotation.PreDestroy; -import javax.annotation.concurrent.GuardedBy; import javax.inject.Inject; import java.io.Closeable; @@ -79,8 +75,6 @@ import static io.trino.SystemSessionProperties.resourceOvercommit; import static io.trino.collect.cache.SafeCaches.buildNonEvictableCache; import static io.trino.execution.SqlTask.createSqlTask; -import static io.trino.memory.LocalMemoryManager.GENERAL_POOL; -import static io.trino.memory.LocalMemoryManager.RESERVED_POOL; import static io.trino.spi.StandardErrorCode.ABANDONED_TASK; import static io.trino.spi.StandardErrorCode.SERVER_SHUTTING_DOWN; import static java.lang.Math.min; @@ -104,7 +98,6 @@ public class SqlTaskManager private final Duration infoCacheTime; private final Duration clientTimeout; - private final LocalMemoryManager localMemoryManager; private final NonEvictableLoadingCache queryContexts; private final NonEvictableLoadingCache tasks; @@ -114,11 +107,6 @@ public class SqlTaskManager private final long queryMaxMemoryPerNode; private final Optional queryMaxMemoryPerTask; - @GuardedBy("this") - private long currentMemoryPoolAssignmentVersion; - @GuardedBy("this") - private String coordinatorId; - private final CounterStat failedTasks = new CounterStat(); @Inject @@ -155,7 +143,6 @@ public SqlTaskManager( SqlTaskExecutionFactory sqlTaskExecutionFactory = new SqlTaskExecutionFactory(taskNotificationExecutor, taskExecutor, planner, splitMonitor, config); - this.localMemoryManager = requireNonNull(localMemoryManager, "localMemoryManager is null"); DataSize maxQueryMemoryPerNode = nodeMemoryConfig.getMaxQueryMemoryPerNode(); queryMaxMemoryPerTask = nodeMemoryConfig.getMaxQueryMemoryPerTask(); DataSize maxQuerySpillPerNode = nodeSpillConfig.getQueryMaxSpillPerNode(); @@ -201,33 +188,6 @@ private QueryContext createQueryContext( localSpillManager.getSpillSpaceTracker()); } - @Override - public synchronized void updateMemoryPoolAssignments(MemoryPoolAssignmentsRequest assignments) - { - if (coordinatorId != null && coordinatorId.equals(assignments.getCoordinatorId()) && assignments.getVersion() <= currentMemoryPoolAssignmentVersion) { - return; - } - currentMemoryPoolAssignmentVersion = assignments.getVersion(); - if (coordinatorId != null && !coordinatorId.equals(assignments.getCoordinatorId())) { - log.warn("Switching coordinator affinity from %s to %s", coordinatorId, assignments.getCoordinatorId()); - } - coordinatorId = assignments.getCoordinatorId(); - - for (MemoryPoolAssignment assignment : assignments.getAssignments()) { - if (assignment.getPoolId().equals(GENERAL_POOL)) { - queryContexts.getUnchecked(assignment.getQueryId()).setMemoryPool(localMemoryManager.getGeneralPool()); - } - else if (assignment.getPoolId().equals(RESERVED_POOL)) { - MemoryPool reservedPool = localMemoryManager.getReservedPool() - .orElseThrow(() -> new IllegalArgumentException(format("Cannot move %s to the reserved pool as the reserved pool is not enabled", assignment.getQueryId()))); - queryContexts.getUnchecked(assignment.getQueryId()).setMemoryPool(reservedPool); - } - else { - throw new IllegalArgumentException(format("Cannot move %s to %s as the target memory pool id is invalid", assignment.getQueryId(), assignment.getPoolId())); - } - } - } - @PostConstruct public void start() { diff --git a/core/trino-main/src/main/java/io/trino/execution/TaskManager.java b/core/trino-main/src/main/java/io/trino/execution/TaskManager.java index d45928526179..6502ac93b500 100644 --- a/core/trino-main/src/main/java/io/trino/execution/TaskManager.java +++ b/core/trino-main/src/main/java/io/trino/execution/TaskManager.java @@ -21,7 +21,6 @@ import io.trino.execution.buffer.BufferResult; import io.trino.execution.buffer.OutputBuffers; import io.trino.execution.buffer.OutputBuffers.OutputBufferId; -import io.trino.memory.MemoryPoolAssignmentsRequest; import io.trino.spi.predicate.Domain; import io.trino.sql.planner.PlanFragment; import io.trino.sql.planner.plan.DynamicFilterId; @@ -82,8 +81,6 @@ public interface TaskManager VersionedDynamicFilterDomains acknowledgeAndGetNewDynamicFilterDomains(TaskId taskId, long currentDynamicFiltersVersion); - void updateMemoryPoolAssignments(MemoryPoolAssignmentsRequest assignments); - /** * Updates the task plan, splitAssignments and output buffers. If the task does not * already exist, it is created and then updated. diff --git a/core/trino-main/src/main/java/io/trino/memory/ClusterMemoryManager.java b/core/trino-main/src/main/java/io/trino/memory/ClusterMemoryManager.java index 586c4a268982..11f416a7ad8a 100644 --- a/core/trino-main/src/main/java/io/trino/memory/ClusterMemoryManager.java +++ b/core/trino-main/src/main/java/io/trino/memory/ClusterMemoryManager.java @@ -15,7 +15,6 @@ import com.google.common.annotations.VisibleForTesting; import com.google.common.base.Joiner; -import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSet; import com.google.common.collect.Streams; @@ -64,7 +63,6 @@ import static com.google.common.base.Preconditions.checkState; import static com.google.common.base.Verify.verify; -import static com.google.common.base.Verify.verifyNotNull; import static com.google.common.collect.ImmutableList.toImmutableList; import static com.google.common.collect.ImmutableSet.toImmutableSet; import static com.google.common.collect.MoreCollectors.toOptional; @@ -78,7 +76,6 @@ import static io.trino.SystemSessionProperties.getQueryMaxTotalMemory; import static io.trino.SystemSessionProperties.resourceOvercommit; import static io.trino.memory.LocalMemoryManager.GENERAL_POOL; -import static io.trino.memory.LocalMemoryManager.RESERVED_POOL; import static io.trino.metadata.NodeState.ACTIVE; import static io.trino.metadata.NodeState.SHUTTING_DOWN; import static io.trino.spi.StandardErrorCode.CLUSTER_OUT_OF_MEMORY; @@ -98,14 +95,11 @@ public class ClusterMemoryManager private final HttpClient httpClient; private final MBeanExporter exporter; private final JsonCodec memoryInfoCodec; - private final JsonCodec assignmentsRequestJsonCodec; private final DataSize maxQueryMemory; private final DataSize maxQueryTotalMemory; private final LowMemoryKiller lowMemoryKiller; private final Duration killOnOutOfMemoryDelay; - private final String coordinatorId; private final AtomicLong totalAvailableProcessors = new AtomicLong(); - private final AtomicLong memoryPoolAssignmentsVersion = new AtomicLong(); private final AtomicLong clusterUserMemoryReservation = new AtomicLong(); private final AtomicLong clusterTotalMemoryReservation = new AtomicLong(); private final AtomicLong clusterMemoryBytes = new AtomicLong(); @@ -134,7 +128,6 @@ public ClusterMemoryManager( LocationFactory locationFactory, MBeanExporter exporter, JsonCodec memoryInfoCodec, - JsonCodec assignmentsRequestJsonCodec, QueryIdGenerator queryIdGenerator, LowMemoryKiller lowMemoryKiller, ServerConfig serverConfig, @@ -153,27 +146,22 @@ public ClusterMemoryManager( this.httpClient = requireNonNull(httpClient, "httpClient is null"); this.exporter = requireNonNull(exporter, "exporter is null"); this.memoryInfoCodec = requireNonNull(memoryInfoCodec, "memoryInfoCodec is null"); - this.assignmentsRequestJsonCodec = requireNonNull(assignmentsRequestJsonCodec, "assignmentsRequestJsonCodec is null"); this.lowMemoryKiller = requireNonNull(lowMemoryKiller, "lowMemoryKiller is null"); this.maxQueryMemory = config.getMaxQueryMemory(); this.maxQueryTotalMemory = config.getMaxQueryTotalMemory(); - this.coordinatorId = queryIdGenerator.getCoordinatorId(); this.killOnOutOfMemoryDelay = config.getKillOnOutOfMemoryDelay(); this.isWorkScheduledOnCoordinator = schedulerConfig.isIncludeCoordinator(); verify(maxQueryMemory.toBytes() <= maxQueryTotalMemory.toBytes(), "maxQueryMemory cannot be greater than maxQueryTotalMemory"); - this.pools = createClusterMemoryPools(!nodeMemoryConfig.isReservedPoolDisabled()); + this.pools = createClusterMemoryPools(); } - private Map createClusterMemoryPools(boolean reservedPoolEnabled) + private Map createClusterMemoryPools() { Set memoryPools = new HashSet<>(); memoryPools.add(GENERAL_POOL); - if (reservedPoolEnabled) { - memoryPools.add(RESERVED_POOL); - } ImmutableMap.Builder builder = ImmutableMap.builder(); for (MemoryPoolId poolId : memoryPools) { @@ -268,19 +256,7 @@ public synchronized void process(Iterable runningQueries, Suppli } updatePools(countByPool); - - MemoryPoolAssignmentsRequest assignmentsRequest; - if (pools.containsKey(RESERVED_POOL)) { - assignmentsRequest = updateAssignments(runningQueries); - } - else { - // If reserved pool is not enabled, we don't create a MemoryPoolAssignmentsRequest that puts all the queries - // in the general pool (as they already are). In this case we create an effectively NOOP MemoryPoolAssignmentsRequest. - // Once the reserved pool is removed we should get rid of the logic of putting queries into reserved pool including - // this piece of code. - assignmentsRequest = new MemoryPoolAssignmentsRequest(coordinatorId, Long.MIN_VALUE, ImmutableList.of()); - } - updateNodes(assignmentsRequest); + updateNodes(); } private synchronized void callOomKiller(Iterable runningQueries) @@ -369,52 +345,7 @@ public synchronized Map getMemoryPoolInfo() private synchronized boolean isClusterOutOfMemory() { - ClusterMemoryPool reservedPool = pools.get(RESERVED_POOL); - ClusterMemoryPool generalPool = pools.get(GENERAL_POOL); - if (reservedPool == null) { - return generalPool.getBlockedNodes() > 0; - } - return reservedPool.getAssignedQueries() > 0 && generalPool.getBlockedNodes() > 0; - } - - // TODO once the reserved pool is removed we can remove this method. We can also update - // RemoteNodeMemory as we don't need to POST anything. - private synchronized MemoryPoolAssignmentsRequest updateAssignments(Iterable queries) - { - ClusterMemoryPool reservedPool = verifyNotNull(pools.get(RESERVED_POOL), "reservedPool is null"); - ClusterMemoryPool generalPool = verifyNotNull(pools.get(GENERAL_POOL), "generalPool is null"); - long version = memoryPoolAssignmentsVersion.incrementAndGet(); - // Check that all previous assignments have propagated to the visible nodes. This doesn't account for temporary network issues, - // and is more of a safety check than a guarantee - if (allAssignmentsHavePropagated(queries)) { - if (reservedPool.getAssignedQueries() == 0 && generalPool.getBlockedNodes() > 0) { - QueryExecution biggestQuery = null; - long maxMemory = -1; - for (QueryExecution queryExecution : queries) { - if (resourceOvercommit(queryExecution.getSession())) { - // Don't promote queries that requested resource overcommit to the reserved pool, - // since their memory usage is unbounded. - continue; - } - - long bytesUsed = getQueryMemoryReservation(queryExecution); - if (bytesUsed > maxMemory) { - biggestQuery = queryExecution; - maxMemory = bytesUsed; - } - } - if (biggestQuery != null) { - log.info("Moving query %s to the reserved pool", biggestQuery.getQueryId()); - biggestQuery.setMemoryPool(new VersionedMemoryPoolId(RESERVED_POOL, version)); - } - } - } - - ImmutableList.Builder assignments = ImmutableList.builder(); - for (QueryExecution queryExecution : queries) { - assignments.add(new MemoryPoolAssignment(queryExecution.getQueryId(), queryExecution.getMemoryPool().getId())); - } - return new MemoryPoolAssignmentsRequest(coordinatorId, version, assignments.build()); + return pools.get(GENERAL_POOL).getBlockedNodes() > 0; } private QueryMemoryInfo createQueryMemoryInfo(QueryExecution query) @@ -427,27 +358,7 @@ private long getQueryMemoryReservation(QueryExecution query) return query.getTotalMemoryReservation().toBytes(); } - private synchronized boolean allAssignmentsHavePropagated(Iterable queries) - { - if (nodes.isEmpty()) { - // Assignments can't have propagated, if there are no visible nodes. - return false; - } - long newestAssignment = ImmutableList.copyOf(queries).stream() - .map(QueryExecution::getMemoryPool) - .mapToLong(VersionedMemoryPoolId::getVersion) - .min() - .orElse(-1); - - long mostOutOfDateNode = nodes.values().stream() - .mapToLong(RemoteNodeMemory::getCurrentAssignmentVersion) - .min() - .orElse(Long.MAX_VALUE); - - return newestAssignment <= mostOutOfDateNode; - } - - private synchronized void updateNodes(MemoryPoolAssignmentsRequest assignments) + private synchronized void updateNodes() { ImmutableSet.Builder builder = ImmutableSet.builder(); Set aliveNodes = builder @@ -467,19 +378,19 @@ private synchronized void updateNodes(MemoryPoolAssignmentsRequest assignments) // Add new nodes for (InternalNode node : aliveNodes) { if (!nodes.containsKey(node.getNodeIdentifier())) { - nodes.put(node.getNodeIdentifier(), new RemoteNodeMemory(node, httpClient, memoryInfoCodec, assignmentsRequestJsonCodec, locationFactory.createMemoryInfoLocation(node))); + nodes.put(node.getNodeIdentifier(), new RemoteNodeMemory(node, httpClient, memoryInfoCodec, locationFactory.createMemoryInfoLocation(node))); } } // If work isn't scheduled on the coordinator (the current node) there is no point - // in polling or updating (when moving queries to the reserved pool) its memory pools + // in polling or updating its memory pools if (!isWorkScheduledOnCoordinator) { nodes.remove(nodeManager.getCurrentNode().getNodeIdentifier()); } // Schedule refresh for (RemoteNodeMemory node : nodes.values()) { - node.asyncRefresh(assignments); + node.asyncRefresh(); } } diff --git a/core/trino-main/src/main/java/io/trino/memory/LocalMemoryManager.java b/core/trino-main/src/main/java/io/trino/memory/LocalMemoryManager.java index 782830202155..d50bf26ecb8a 100644 --- a/core/trino-main/src/main/java/io/trino/memory/LocalMemoryManager.java +++ b/core/trino-main/src/main/java/io/trino/memory/LocalMemoryManager.java @@ -26,7 +26,6 @@ import java.lang.management.OperatingSystemMXBean; import java.util.List; import java.util.Map; -import java.util.Optional; import static com.google.common.base.Verify.verify; import static java.lang.String.format; @@ -35,7 +34,6 @@ public final class LocalMemoryManager { public static final MemoryPoolId GENERAL_POOL = new MemoryPoolId("general"); - public static final MemoryPoolId RESERVED_POOL = new MemoryPoolId("reserved"); private static final OperatingSystemMXBean OPERATING_SYSTEM_MX_BEAN = ManagementFactory.getOperatingSystemMXBean(); private DataSize maxMemory; @@ -60,10 +58,6 @@ private void configureMemoryPools(NodeMemoryConfig config, long availableMemory) maxMemory = DataSize.ofBytes(availableMemory - config.getHeapHeadroom().toBytes()); ImmutableMap.Builder builder = ImmutableMap.builder(); long generalPoolSize = maxMemory.toBytes(); - if (!config.isReservedPoolDisabled()) { - builder.put(RESERVED_POOL, new MemoryPool(RESERVED_POOL, config.getMaxQueryMemoryPerNode())); - generalPoolSize -= config.getMaxQueryMemoryPerNode().toBytes(); - } verify(generalPoolSize > 0, "general memory pool size is 0"); builder.put(GENERAL_POOL, new MemoryPool(GENERAL_POOL, DataSize.ofBytes(generalPoolSize))); this.pools = builder.buildOrThrow(); @@ -102,9 +96,4 @@ public MemoryPool getGeneralPool() { return pools.get(GENERAL_POOL); } - - public Optional getReservedPool() - { - return Optional.ofNullable(pools.get(RESERVED_POOL)); - } } diff --git a/core/trino-main/src/main/java/io/trino/memory/MemoryPoolAssignment.java b/core/trino-main/src/main/java/io/trino/memory/MemoryPoolAssignment.java deleted file mode 100644 index fa399c643c6a..000000000000 --- a/core/trino-main/src/main/java/io/trino/memory/MemoryPoolAssignment.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.trino.memory; - -import com.fasterxml.jackson.annotation.JsonCreator; -import com.fasterxml.jackson.annotation.JsonProperty; -import io.trino.spi.QueryId; -import io.trino.spi.memory.MemoryPoolId; - -import static com.google.common.base.MoreObjects.toStringHelper; -import static java.util.Objects.requireNonNull; - -public class MemoryPoolAssignment -{ - private final QueryId queryId; - private final MemoryPoolId poolId; - - @JsonCreator - public MemoryPoolAssignment(@JsonProperty("queryId") QueryId queryId, @JsonProperty("poolId") MemoryPoolId poolId) - { - this.queryId = requireNonNull(queryId, "queryId is null"); - this.poolId = requireNonNull(poolId, "poolId is null"); - } - - @JsonProperty - public QueryId getQueryId() - { - return queryId; - } - - @JsonProperty - public MemoryPoolId getPoolId() - { - return poolId; - } - - @Override - public String toString() - { - return toStringHelper(this) - .add("queryId", queryId) - .add("poolId", poolId) - .toString(); - } -} diff --git a/core/trino-main/src/main/java/io/trino/memory/MemoryPoolAssignmentsRequest.java b/core/trino-main/src/main/java/io/trino/memory/MemoryPoolAssignmentsRequest.java deleted file mode 100644 index 028cc965dee1..000000000000 --- a/core/trino-main/src/main/java/io/trino/memory/MemoryPoolAssignmentsRequest.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.trino.memory; - -import com.fasterxml.jackson.annotation.JsonCreator; -import com.fasterxml.jackson.annotation.JsonProperty; -import com.google.common.collect.ImmutableList; - -import java.util.List; - -import static com.google.common.base.MoreObjects.toStringHelper; -import static java.util.Objects.requireNonNull; - -public class MemoryPoolAssignmentsRequest -{ - private final String coordinatorId; - private final long version; - private final List assignments; - - @JsonCreator - public MemoryPoolAssignmentsRequest(@JsonProperty("coordinatorId") String coordinatorId, @JsonProperty("version") long version, @JsonProperty("assignments") List assignments) - { - this.coordinatorId = requireNonNull(coordinatorId, "coordinatorId is null"); - this.version = version; - this.assignments = ImmutableList.copyOf(requireNonNull(assignments, "assignments is null")); - } - - @JsonProperty - public String getCoordinatorId() - { - return coordinatorId; - } - - @JsonProperty - public long getVersion() - { - return version; - } - - @JsonProperty - public List getAssignments() - { - return assignments; - } - - @Override - public String toString() - { - return toStringHelper(this) - .add("version", version) - .add("assignments", assignments) - .toString(); - } -} diff --git a/core/trino-main/src/main/java/io/trino/memory/MemoryResource.java b/core/trino-main/src/main/java/io/trino/memory/MemoryResource.java index 448f6660ff0b..1eb05afbc444 100644 --- a/core/trino-main/src/main/java/io/trino/memory/MemoryResource.java +++ b/core/trino-main/src/main/java/io/trino/memory/MemoryResource.java @@ -13,14 +13,11 @@ */ package io.trino.memory; -import io.trino.execution.TaskManager; import io.trino.server.security.ResourceSecurity; import io.trino.spi.memory.MemoryPoolInfo; import javax.inject.Inject; -import javax.ws.rs.Consumes; import javax.ws.rs.GET; -import javax.ws.rs.POST; import javax.ws.rs.Path; import javax.ws.rs.PathParam; import javax.ws.rs.Produces; @@ -28,7 +25,6 @@ import javax.ws.rs.core.Response; import static io.trino.memory.LocalMemoryManager.GENERAL_POOL; -import static io.trino.memory.LocalMemoryManager.RESERVED_POOL; import static io.trino.server.security.ResourceSecurity.AccessType.INTERNAL_ONLY; import static io.trino.server.security.ResourceSecurity.AccessType.MANAGEMENT_READ; import static java.util.Objects.requireNonNull; @@ -41,22 +37,18 @@ public class MemoryResource { private final LocalMemoryManager memoryManager; - private final TaskManager taskManager; @Inject - public MemoryResource(LocalMemoryManager memoryManager, TaskManager taskManager) + public MemoryResource(LocalMemoryManager memoryManager) { this.memoryManager = requireNonNull(memoryManager, "memoryManager is null"); - this.taskManager = requireNonNull(taskManager, "taskManager is null"); } @ResourceSecurity(INTERNAL_ONLY) - @POST + @GET @Produces(MediaType.APPLICATION_JSON) - @Consumes(MediaType.APPLICATION_JSON) - public MemoryInfo getMemoryInfo(MemoryPoolAssignmentsRequest request) + public MemoryInfo getMemoryInfo() { - taskManager.updateMemoryPoolAssignments(request); return memoryManager.getInfo(); } @@ -69,10 +61,6 @@ public Response getMemoryInfo(@PathParam("poolId") String poolId) return toSuccessfulResponse(memoryManager.getGeneralPool().getInfo()); } - if (RESERVED_POOL.getId().equals(poolId) && memoryManager.getReservedPool().isPresent()) { - return toSuccessfulResponse(memoryManager.getReservedPool().get().getInfo()); - } - return Response.status(NOT_FOUND).build(); } diff --git a/core/trino-main/src/main/java/io/trino/memory/NodeMemoryConfig.java b/core/trino-main/src/main/java/io/trino/memory/NodeMemoryConfig.java index d58054de0660..7e0ef24df113 100644 --- a/core/trino-main/src/main/java/io/trino/memory/NodeMemoryConfig.java +++ b/core/trino-main/src/main/java/io/trino/memory/NodeMemoryConfig.java @@ -26,6 +26,8 @@ // This is separate from MemoryManagerConfig because it's difficult to test the default value of maxQueryMemoryPerNode @DefunctConfig({ "deprecated.legacy-system-pool-enabled", + "experimental.reserved-pool-disabled", + "experimental.reserved-pool-enabled", "query.max-total-memory-per-node", }) public class NodeMemoryConfig @@ -34,8 +36,6 @@ public class NodeMemoryConfig public static final String QUERY_MAX_MEMORY_PER_NODE_CONFIG = "query.max-memory-per-node"; public static final String QUERY_MAX_MEMORY_PER_TASK_CONFIG = "query.max-memory-per-task"; - private boolean isReservedPoolDisabled = true; - private DataSize maxQueryMemoryPerNode = DataSize.ofBytes(Math.round(AVAILABLE_HEAP_MEMORY * 0.3)); private Optional maxQueryMemoryPerTask = Optional.empty(); @@ -70,27 +70,6 @@ public NodeMemoryConfig setMaxQueryMemoryPerTask(DataSize maxQueryMemoryPerTask) return this; } - @Deprecated - @LegacyConfig(value = "experimental.reserved-pool-enabled", replacedBy = "experimental.reserved-pool-disabled") - public void setReservedPoolEnabled(boolean reservedPoolEnabled) - { - isReservedPoolDisabled = !reservedPoolEnabled; - } - - @Deprecated - public boolean isReservedPoolDisabled() - { - return isReservedPoolDisabled; - } - - @Deprecated - @Config("experimental.reserved-pool-disabled") - public NodeMemoryConfig setReservedPoolDisabled(boolean reservedPoolDisabled) - { - this.isReservedPoolDisabled = reservedPoolDisabled; - return this; - } - @NotNull public DataSize getHeapHeadroom() { diff --git a/core/trino-main/src/main/java/io/trino/memory/RemoteNodeMemory.java b/core/trino-main/src/main/java/io/trino/memory/RemoteNodeMemory.java index 3d65c100057c..f71081fa4e92 100644 --- a/core/trino-main/src/main/java/io/trino/memory/RemoteNodeMemory.java +++ b/core/trino-main/src/main/java/io/trino/memory/RemoteNodeMemory.java @@ -33,16 +33,13 @@ import java.util.concurrent.atomic.AtomicLong; import java.util.concurrent.atomic.AtomicReference; -import static com.google.common.net.MediaType.JSON_UTF_8; import static com.google.common.util.concurrent.MoreExecutors.directExecutor; import static io.airlift.http.client.FullJsonResponseHandler.createFullJsonResponseHandler; import static io.airlift.http.client.HttpStatus.OK; -import static io.airlift.http.client.JsonBodyGenerator.jsonBodyGenerator; -import static io.airlift.http.client.Request.Builder.preparePost; +import static io.airlift.http.client.Request.Builder.prepareGet; import static io.airlift.units.Duration.nanosSince; import static java.util.Objects.requireNonNull; import static java.util.concurrent.TimeUnit.SECONDS; -import static javax.ws.rs.core.HttpHeaders.CONTENT_TYPE; @ThreadSafe public class RemoteNodeMemory @@ -53,30 +50,21 @@ public class RemoteNodeMemory private final HttpClient httpClient; private final URI memoryInfoUri; private final JsonCodec memoryInfoCodec; - private final JsonCodec assignmentsRequestJsonCodec; private final AtomicReference> memoryInfo = new AtomicReference<>(Optional.empty()); private final AtomicReference> future = new AtomicReference<>(); private final AtomicLong lastUpdateNanos = new AtomicLong(); private final AtomicLong lastWarningLogged = new AtomicLong(); - private final AtomicLong currentAssignmentVersion = new AtomicLong(-1); public RemoteNodeMemory( InternalNode node, HttpClient httpClient, JsonCodec memoryInfoCodec, - JsonCodec assignmentsRequestJsonCodec, URI memoryInfoUri) { this.node = requireNonNull(node, "node is null"); this.httpClient = requireNonNull(httpClient, "httpClient is null"); this.memoryInfoUri = requireNonNull(memoryInfoUri, "memoryInfoUri is null"); this.memoryInfoCodec = requireNonNull(memoryInfoCodec, "memoryInfoCodec is null"); - this.assignmentsRequestJsonCodec = requireNonNull(assignmentsRequestJsonCodec, "assignmentsRequestJsonCodec is null"); - } - - public long getCurrentAssignmentVersion() - { - return currentAssignmentVersion.get(); } public Optional getInfo() @@ -89,7 +77,7 @@ public InternalNode getNode() return node; } - public void asyncRefresh(MemoryPoolAssignmentsRequest assignments) + public void asyncRefresh() { Duration sinceUpdate = nanosSince(lastUpdateNanos.get()); if (nanosSince(lastWarningLogged.get()).toMillis() > 1_000 && @@ -99,10 +87,8 @@ public void asyncRefresh(MemoryPoolAssignmentsRequest assignments) lastWarningLogged.set(System.nanoTime()); } if (sinceUpdate.toMillis() > 1_000 && future.get() == null) { - Request request = preparePost() + Request request = prepareGet() .setUri(memoryInfoUri) - .setHeader(CONTENT_TYPE, JSON_UTF_8.toString()) - .setBodyGenerator(jsonBodyGenerator(assignmentsRequestJsonCodec, assignments)) .build(); HttpResponseFuture> responseFuture = httpClient.executeAsync(request, createFullJsonResponseHandler(memoryInfoCodec)); future.compareAndSet(null, responseFuture); @@ -114,17 +100,14 @@ public void onSuccess(@Nullable JsonResponse result) { lastUpdateNanos.set(System.nanoTime()); future.compareAndSet(responseFuture, null); - long version = currentAssignmentVersion.get(); if (result != null) { if (result.hasValue()) { memoryInfo.set(Optional.ofNullable(result.getValue())); } if (result.getStatusCode() != OK.code()) { log.warn("Error fetching memory info from %s returned status %d", memoryInfoUri, result.getStatusCode()); - return; } } - currentAssignmentVersion.compareAndSet(version, assignments.getVersion()); } @Override diff --git a/core/trino-main/src/main/java/io/trino/server/ServerMainModule.java b/core/trino-main/src/main/java/io/trino/server/ServerMainModule.java index 3b3aa2587a8a..0a3a38bb48ce 100644 --- a/core/trino-main/src/main/java/io/trino/server/ServerMainModule.java +++ b/core/trino-main/src/main/java/io/trino/server/ServerMainModule.java @@ -60,7 +60,6 @@ import io.trino.memory.LocalMemoryManagerExporter; import io.trino.memory.MemoryInfo; import io.trino.memory.MemoryManagerConfig; -import io.trino.memory.MemoryPoolAssignmentsRequest; import io.trino.memory.MemoryResource; import io.trino.memory.NodeMemoryConfig; import io.trino.metadata.AnalyzePropertyManager; @@ -355,7 +354,6 @@ protected void setup(Binder binder) // memory manager jaxrsBinder(binder).bind(MemoryResource.class); jsonCodecBinder(binder).bindJsonCodec(MemoryInfo.class); - jsonCodecBinder(binder).bindJsonCodec(MemoryPoolAssignmentsRequest.class); // transaction manager configBinder(binder).bindConfig(TransactionManagerConfig.class); diff --git a/core/trino-main/src/main/resources/webapp/dist/worker.js b/core/trino-main/src/main/resources/webapp/dist/worker.js index 01234bc6d29c..fce55f271937 100644 --- a/core/trino-main/src/main/resources/webapp/dist/worker.js +++ b/core/trino-main/src/main/resources/webapp/dist/worker.js @@ -106,7 +106,7 @@ eval("\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n}); /***/ (function(module, exports, __webpack_require__) { "use strict"; -eval("\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\nexports.WorkerStatus = undefined;\n\nvar _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if (\"value\" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();\n\nvar _react = __webpack_require__(/*! react */ \"./node_modules/react/index.js\");\n\nvar _react2 = _interopRequireDefault(_react);\n\nvar _utils = __webpack_require__(/*! ../utils */ \"./utils.js\");\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\nfunction _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError(\"Cannot call a class as a function\"); } }\n\nfunction _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); } return call && (typeof call === \"object\" || typeof call === \"function\") ? call : self; }\n\nfunction _inherits(subClass, superClass) { if (typeof superClass !== \"function\" && superClass !== null) { throw new TypeError(\"Super expression must either be null or a function, not \" + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } /*\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nvar SMALL_SPARKLINE_PROPERTIES = {\n width: '100%',\n height: '57px',\n fillColor: '#3F4552',\n lineColor: '#747F96',\n spotColor: '#1EDCFF',\n tooltipClassname: 'sparkline-tooltip',\n disableHiddenCheck: true\n};\n\nvar WorkerStatus = exports.WorkerStatus = function (_React$Component) {\n _inherits(WorkerStatus, _React$Component);\n\n function WorkerStatus(props) {\n _classCallCheck(this, WorkerStatus);\n\n var _this = _possibleConstructorReturn(this, (WorkerStatus.__proto__ || Object.getPrototypeOf(WorkerStatus)).call(this, props));\n\n _this.state = {\n serverInfo: null,\n initialized: false,\n ended: false,\n\n processCpuLoad: [],\n systemCpuLoad: [],\n heapPercentUsed: [],\n nonHeapUsed: []\n };\n\n _this.refreshLoop = _this.refreshLoop.bind(_this);\n return _this;\n }\n\n _createClass(WorkerStatus, [{\n key: \"resetTimer\",\n value: function resetTimer() {\n clearTimeout(this.timeoutId);\n // stop refreshing when query finishes or fails\n if (this.state.query === null || !this.state.ended) {\n this.timeoutId = setTimeout(this.refreshLoop, 1000);\n }\n }\n }, {\n key: \"refreshLoop\",\n value: function refreshLoop() {\n clearTimeout(this.timeoutId); // to stop multiple series of refreshLoop from going on simultaneously\n var nodeId = (0, _utils.getFirstParameter)(window.location.search);\n $.get('/ui/api/worker/' + nodeId + '/status', function (serverInfo) {\n this.setState({\n serverInfo: serverInfo,\n initialized: true,\n\n processCpuLoad: (0, _utils.addToHistory)(serverInfo.processCpuLoad * 100.0, this.state.processCpuLoad),\n systemCpuLoad: (0, _utils.addToHistory)(serverInfo.systemCpuLoad * 100.0, this.state.systemCpuLoad),\n heapPercentUsed: (0, _utils.addToHistory)(serverInfo.heapUsed * 100.0 / serverInfo.heapAvailable, this.state.heapPercentUsed),\n nonHeapUsed: (0, _utils.addToHistory)(serverInfo.nonHeapUsed, this.state.nonHeapUsed)\n });\n\n this.resetTimer();\n }.bind(this)).fail(function () {\n this.setState({\n initialized: true\n });\n this.resetTimer();\n }.bind(this));\n }\n }, {\n key: \"componentDidMount\",\n value: function componentDidMount() {\n this.refreshLoop();\n }\n }, {\n key: \"componentDidUpdate\",\n value: function componentDidUpdate() {\n $('#process-cpu-load-sparkline').sparkline(this.state.processCpuLoad, $.extend({}, SMALL_SPARKLINE_PROPERTIES, { chartRangeMin: 0, numberFormatter: _utils.precisionRound }));\n $('#system-cpu-load-sparkline').sparkline(this.state.systemCpuLoad, $.extend({}, SMALL_SPARKLINE_PROPERTIES, { chartRangeMin: 0, numberFormatter: _utils.precisionRound }));\n $('#heap-percent-used-sparkline').sparkline(this.state.heapPercentUsed, $.extend({}, SMALL_SPARKLINE_PROPERTIES, { chartRangeMin: 0, numberFormatter: _utils.precisionRound }));\n $('#nonheap-used-sparkline').sparkline(this.state.nonHeapUsed, $.extend({}, SMALL_SPARKLINE_PROPERTIES, { chartRangeMin: 0, numberFormatter: _utils.formatDataSize }));\n\n $('[data-toggle=\"tooltip\"]').tooltip();\n new window.ClipboardJS('.copy-button');\n }\n }, {\n key: \"renderPoolQueries\",\n value: function renderPoolQueries(pool) {\n if (!pool) {\n return;\n }\n\n var queries = {};\n var reservations = pool.queryMemoryReservations;\n var revocableReservations = pool.queryMemoryRevocableReservations;\n\n for (var query in reservations) {\n queries[query] = [reservations[query], 0];\n }\n\n for (var _query in revocableReservations) {\n if (queries.hasOwnProperty(_query)) {\n queries[_query][1] = revocableReservations[_query];\n } else {\n queries[_query] = [0, revocableReservations[_query]];\n }\n }\n\n var size = pool.maxBytes;\n\n if (Object.keys(queries).length === 0) {\n return _react2.default.createElement(\n \"div\",\n null,\n _react2.default.createElement(\n \"table\",\n { className: \"table table-condensed\" },\n _react2.default.createElement(\n \"tbody\",\n null,\n _react2.default.createElement(\n \"tr\",\n null,\n _react2.default.createElement(\n \"td\",\n null,\n \"No queries using pool\"\n )\n )\n )\n )\n );\n }\n\n return _react2.default.createElement(\n \"div\",\n null,\n _react2.default.createElement(\n \"table\",\n { className: \"table\" },\n _react2.default.createElement(\n \"tbody\",\n null,\n Object.keys(queries).map(function (key) {\n return WorkerStatus.renderPoolQuery(key, queries[key][0], queries[key][1], size);\n })\n )\n )\n );\n }\n }, {\n key: \"render\",\n value: function render() {\n var serverInfo = this.state.serverInfo;\n\n if (serverInfo === null) {\n if (this.state.initialized === false) {\n return _react2.default.createElement(\n \"div\",\n { className: \"loader\" },\n \"Loading...\"\n );\n } else {\n return _react2.default.createElement(\n \"div\",\n { className: \"row error-message\" },\n _react2.default.createElement(\n \"div\",\n { className: \"col-xs-12\" },\n _react2.default.createElement(\n \"h4\",\n null,\n \"Node information could not be loaded\"\n )\n )\n );\n }\n }\n\n return _react2.default.createElement(\n \"div\",\n null,\n _react2.default.createElement(\n \"div\",\n { className: \"row\" },\n _react2.default.createElement(\n \"div\",\n { className: \"col-xs-12\" },\n _react2.default.createElement(\n \"h3\",\n null,\n \"Overview\"\n ),\n _react2.default.createElement(\"hr\", { className: \"h3-hr\" }),\n _react2.default.createElement(\n \"div\",\n { className: \"row\" },\n _react2.default.createElement(\n \"div\",\n { className: \"col-xs-6\" },\n _react2.default.createElement(\n \"table\",\n { className: \"table\" },\n _react2.default.createElement(\n \"tbody\",\n null,\n _react2.default.createElement(\n \"tr\",\n null,\n _react2.default.createElement(\n \"td\",\n { className: \"info-title\" },\n \"Node ID\"\n ),\n _react2.default.createElement(\n \"td\",\n { className: \"info-text wrap-text\" },\n _react2.default.createElement(\n \"span\",\n { id: \"node-id\" },\n serverInfo.nodeId\n ),\n \"\\xA0\\xA0\",\n _react2.default.createElement(\n \"a\",\n { href: \"#\", className: \"copy-button\", \"data-clipboard-target\": \"#node-id\", \"data-toggle\": \"tooltip\", \"data-placement\": \"right\",\n title: \"Copy to clipboard\" },\n _react2.default.createElement(\"span\", { className: \"glyphicon glyphicon-copy\", alt: \"Copy to clipboard\" })\n )\n )\n ),\n _react2.default.createElement(\n \"tr\",\n null,\n _react2.default.createElement(\n \"td\",\n { className: \"info-title\" },\n \"Heap Memory\"\n ),\n _react2.default.createElement(\n \"td\",\n { className: \"info-text wrap-text\" },\n _react2.default.createElement(\n \"span\",\n { id: \"node-heap-available\" },\n (0, _utils.formatDataSize)(serverInfo.heapAvailable)\n )\n )\n ),\n _react2.default.createElement(\n \"tr\",\n null,\n _react2.default.createElement(\n \"td\",\n { className: \"info-title\" },\n \"Processors\"\n ),\n _react2.default.createElement(\n \"td\",\n { className: \"info-text wrap-text\" },\n _react2.default.createElement(\n \"span\",\n { id: \"node-processors\" },\n serverInfo.processors\n )\n )\n )\n )\n )\n ),\n _react2.default.createElement(\n \"div\",\n { className: \"col-xs-6\" },\n _react2.default.createElement(\n \"table\",\n { className: \"table\" },\n _react2.default.createElement(\n \"tbody\",\n null,\n _react2.default.createElement(\n \"tr\",\n null,\n _react2.default.createElement(\n \"td\",\n { className: \"info-title\" },\n \"Uptime\"\n ),\n _react2.default.createElement(\n \"td\",\n { className: \"info-text wrap-text\" },\n serverInfo.uptime\n )\n ),\n _react2.default.createElement(\n \"tr\",\n null,\n _react2.default.createElement(\n \"td\",\n { className: \"info-title\" },\n \"External Address\"\n ),\n _react2.default.createElement(\n \"td\",\n { className: \"info-text wrap-text\" },\n _react2.default.createElement(\n \"span\",\n { id: \"external-address\" },\n serverInfo.externalAddress\n ),\n \"\\xA0\\xA0\",\n _react2.default.createElement(\n \"a\",\n { href: \"#\", className: \"copy-button\", \"data-clipboard-target\": \"#external-address\", \"data-toggle\": \"tooltip\", \"data-placement\": \"right\",\n title: \"Copy to clipboard\" },\n _react2.default.createElement(\"span\", { className: \"glyphicon glyphicon-copy\", alt: \"Copy to clipboard\" })\n )\n )\n ),\n _react2.default.createElement(\n \"tr\",\n null,\n _react2.default.createElement(\n \"td\",\n { className: \"info-title\" },\n \"Internal Address\"\n ),\n _react2.default.createElement(\n \"td\",\n { className: \"info-text wrap-text\" },\n _react2.default.createElement(\n \"span\",\n { id: \"internal-address\" },\n serverInfo.internalAddress\n ),\n \"\\xA0\\xA0\",\n _react2.default.createElement(\n \"a\",\n { href: \"#\", className: \"copy-button\", \"data-clipboard-target\": \"#internal-address\", \"data-toggle\": \"tooltip\", \"data-placement\": \"right\",\n title: \"Copy to clipboard\" },\n _react2.default.createElement(\"span\", { className: \"glyphicon glyphicon-copy\", alt: \"Copy to clipboard\" })\n )\n )\n )\n )\n )\n )\n ),\n _react2.default.createElement(\n \"div\",\n { className: \"row\" },\n _react2.default.createElement(\n \"div\",\n { className: \"col-xs-12\" },\n _react2.default.createElement(\n \"h3\",\n null,\n \"Resource Utilization\"\n ),\n _react2.default.createElement(\"hr\", { className: \"h3-hr\" }),\n _react2.default.createElement(\n \"div\",\n { className: \"row\" },\n _react2.default.createElement(\n \"div\",\n { className: \"col-xs-6\" },\n _react2.default.createElement(\n \"table\",\n { className: \"table\" },\n _react2.default.createElement(\n \"tbody\",\n null,\n _react2.default.createElement(\n \"tr\",\n null,\n _react2.default.createElement(\n \"td\",\n { className: \"info-title\" },\n \"Process CPU Utilization\"\n ),\n _react2.default.createElement(\n \"td\",\n { rowSpan: \"2\" },\n _react2.default.createElement(\n \"div\",\n { className: \"query-stats-sparkline-container\" },\n _react2.default.createElement(\n \"span\",\n { className: \"sparkline\", id: \"process-cpu-load-sparkline\" },\n _react2.default.createElement(\n \"div\",\n { className: \"loader\" },\n \"Loading ...\"\n )\n )\n )\n )\n ),\n _react2.default.createElement(\n \"tr\",\n { className: \"tr-noborder\" },\n _react2.default.createElement(\n \"td\",\n { className: \"info-sparkline-text\" },\n (0, _utils.formatCount)(this.state.processCpuLoad[this.state.processCpuLoad.length - 1]),\n \"%\"\n )\n ),\n _react2.default.createElement(\n \"tr\",\n null,\n _react2.default.createElement(\n \"td\",\n { className: \"info-title\" },\n \"System CPU Utilization\"\n ),\n _react2.default.createElement(\n \"td\",\n { rowSpan: \"2\" },\n _react2.default.createElement(\n \"div\",\n { className: \"query-stats-sparkline-container\" },\n _react2.default.createElement(\n \"span\",\n { className: \"sparkline\", id: \"system-cpu-load-sparkline\" },\n _react2.default.createElement(\n \"div\",\n { className: \"loader\" },\n \"Loading ...\"\n )\n )\n )\n )\n ),\n _react2.default.createElement(\n \"tr\",\n { className: \"tr-noborder\" },\n _react2.default.createElement(\n \"td\",\n { className: \"info-sparkline-text\" },\n (0, _utils.formatCount)(this.state.systemCpuLoad[this.state.systemCpuLoad.length - 1]),\n \"%\"\n )\n )\n )\n )\n ),\n _react2.default.createElement(\n \"div\",\n { className: \"col-xs-6\" },\n _react2.default.createElement(\n \"table\",\n { className: \"table\" },\n _react2.default.createElement(\n \"tbody\",\n null,\n _react2.default.createElement(\n \"tr\",\n null,\n _react2.default.createElement(\n \"td\",\n { className: \"info-title\" },\n \"Heap Utilization\"\n ),\n _react2.default.createElement(\n \"td\",\n { rowSpan: \"2\" },\n _react2.default.createElement(\n \"div\",\n { className: \"query-stats-sparkline-container\" },\n _react2.default.createElement(\n \"span\",\n { className: \"sparkline\", id: \"heap-percent-used-sparkline\" },\n _react2.default.createElement(\n \"div\",\n { className: \"loader\" },\n \"Loading ...\"\n )\n )\n )\n )\n ),\n _react2.default.createElement(\n \"tr\",\n { className: \"tr-noborder\" },\n _react2.default.createElement(\n \"td\",\n { className: \"info-sparkline-text\" },\n (0, _utils.formatCount)(this.state.heapPercentUsed[this.state.heapPercentUsed.length - 1]),\n \"%\"\n )\n ),\n _react2.default.createElement(\n \"tr\",\n null,\n _react2.default.createElement(\n \"td\",\n { className: \"info-title\" },\n \"Non-Heap Memory Used\"\n ),\n _react2.default.createElement(\n \"td\",\n { rowSpan: \"2\" },\n _react2.default.createElement(\n \"div\",\n { className: \"query-stats-sparkline-container\" },\n _react2.default.createElement(\n \"span\",\n { className: \"sparkline\", id: \"nonheap-used-sparkline\" },\n _react2.default.createElement(\n \"div\",\n { className: \"loader\" },\n \"Loading ...\"\n )\n )\n )\n )\n ),\n _react2.default.createElement(\n \"tr\",\n { className: \"tr-noborder\" },\n _react2.default.createElement(\n \"td\",\n { className: \"info-sparkline-text\" },\n (0, _utils.formatDataSize)(this.state.nonHeapUsed[this.state.nonHeapUsed.length - 1])\n )\n )\n )\n )\n )\n )\n )\n )\n )\n ),\n _react2.default.createElement(\n \"div\",\n { className: \"row\" },\n _react2.default.createElement(\n \"div\",\n { className: \"col-xs-12\" },\n _react2.default.createElement(\n \"h3\",\n null,\n \"Memory Pools\"\n ),\n _react2.default.createElement(\"hr\", { className: \"h3-hr\" }),\n _react2.default.createElement(\n \"div\",\n { className: \"row\" },\n _react2.default.createElement(\n \"div\",\n { className: \"col-xs-6\" },\n WorkerStatus.renderPoolBar(\"General\", serverInfo.memoryInfo.pools.general),\n this.renderPoolQueries(serverInfo.memoryInfo.pools.general)\n ),\n _react2.default.createElement(\n \"div\",\n { className: \"col-xs-6\" },\n WorkerStatus.renderPoolBar(\"Reserved\", serverInfo.memoryInfo.pools.reserved),\n this.renderPoolQueries(serverInfo.memoryInfo.pools.reserved)\n )\n )\n )\n )\n );\n }\n }], [{\n key: \"renderPoolBar\",\n value: function renderPoolBar(name, pool) {\n if (!pool) {\n return;\n }\n\n var size = pool.maxBytes;\n var reserved = pool.reservedBytes;\n var revocable = pool.reservedRevocableBytes;\n\n var percentageReservedNonRevocable = reserved === 0 ? 0 : Math.max(Math.round(reserved * 100.0 / size), 15);\n var percentageRevocable = revocable === 0 ? 0 : Math.max(Math.round(revocable * 100.0 / size), 15);\n var percentageFree = 100 - (percentageRevocable + percentageReservedNonRevocable);\n\n return _react2.default.createElement(\n \"div\",\n { className: \"row\" },\n _react2.default.createElement(\n \"div\",\n { className: \"col-xs-12\" },\n _react2.default.createElement(\n \"div\",\n { className: \"row\" },\n _react2.default.createElement(\n \"div\",\n { className: \"col-xs-8\" },\n _react2.default.createElement(\n \"h4\",\n null,\n name,\n \" Pool\"\n )\n ),\n _react2.default.createElement(\n \"div\",\n { className: \"col-xs-4\" },\n _react2.default.createElement(\n \"div\",\n { className: \"progress\", style: { marginTop: \"6px\" } },\n _react2.default.createElement(\n \"div\",\n { className: \"progress-bar memory-progress-bar memory-progress-bar-info\", role: \"progressbar\", style: { width: \"100%\" } },\n (0, _utils.formatDataSize)(size),\n \" total\"\n )\n )\n )\n ),\n _react2.default.createElement(\n \"div\",\n { className: \"row\" },\n _react2.default.createElement(\n \"div\",\n { className: \"col-xs-12\" },\n _react2.default.createElement(\"hr\", { className: \"h4-hr\" }),\n _react2.default.createElement(\n \"div\",\n { className: \"progress\" },\n _react2.default.createElement(\n \"div\",\n { className: \"progress-bar memory-progress-bar progress-bar-warning progress-bar-striped active\", role: \"progressbar\",\n style: { width: percentageReservedNonRevocable + \"%\" } },\n (0, _utils.formatDataSize)(reserved)\n ),\n _react2.default.createElement(\n \"div\",\n { className: \"progress-bar memory-progress-bar progress-bar-danger progress-bar-striped active\", role: \"progressbar\",\n style: { width: percentageRevocable + \"%\" } },\n (0, _utils.formatDataSize)(revocable)\n ),\n _react2.default.createElement(\n \"div\",\n { className: \"progress-bar memory-progress-bar progress-bar-success\", role: \"progressbar\", style: { width: percentageFree + \"%\" } },\n (0, _utils.formatDataSize)(size - reserved - revocable)\n )\n )\n )\n )\n )\n );\n }\n }, {\n key: \"renderPoolQuery\",\n value: function renderPoolQuery(query, reserved, revocable, total) {\n return _react2.default.createElement(\n \"tr\",\n null,\n _react2.default.createElement(\n \"td\",\n null,\n _react2.default.createElement(\n \"div\",\n { className: \"row query-memory-list-header\" },\n _react2.default.createElement(\n \"div\",\n { className: \"col-xs-7\" },\n _react2.default.createElement(\n \"a\",\n { href: \"query.html?\" + query, target: \"_blank\" },\n query\n )\n ),\n _react2.default.createElement(\n \"div\",\n { className: \"col-xs-5\" },\n _react2.default.createElement(\n \"div\",\n { className: \"row text-right\" },\n _react2.default.createElement(\n \"div\",\n { className: \"col-xs-6\" },\n _react2.default.createElement(\n \"span\",\n { \"data-toggle\": \"tooltip\", \"data-placement\": \"top\", title: \"% of pool memory reserved\" },\n Math.round(reserved * 100.0 / total),\n \"%\"\n )\n ),\n _react2.default.createElement(\n \"div\",\n { className: \"col-xs-6\" },\n _react2.default.createElement(\n \"span\",\n { \"data-toggle\": \"tooltip\", \"data-placement\": \"top\",\n title: \"Reserved: \" + (0, _utils.formatDataSize)(reserved) + \". Revocable: \" + (0, _utils.formatDataSize)(revocable) },\n (0, _utils.formatDataSize)(reserved)\n )\n )\n )\n )\n )\n )\n );\n }\n }]);\n\n return WorkerStatus;\n}(_react2.default.Component);\n\n//# sourceURL=webpack:///./components/WorkerStatus.jsx?"); +eval("\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\nexports.WorkerStatus = undefined;\n\nvar _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if (\"value\" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();\n\nvar _react = __webpack_require__(/*! react */ \"./node_modules/react/index.js\");\n\nvar _react2 = _interopRequireDefault(_react);\n\nvar _utils = __webpack_require__(/*! ../utils */ \"./utils.js\");\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\nfunction _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError(\"Cannot call a class as a function\"); } }\n\nfunction _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); } return call && (typeof call === \"object\" || typeof call === \"function\") ? call : self; }\n\nfunction _inherits(subClass, superClass) { if (typeof superClass !== \"function\" && superClass !== null) { throw new TypeError(\"Super expression must either be null or a function, not \" + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } /*\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nvar SMALL_SPARKLINE_PROPERTIES = {\n width: '100%',\n height: '57px',\n fillColor: '#3F4552',\n lineColor: '#747F96',\n spotColor: '#1EDCFF',\n tooltipClassname: 'sparkline-tooltip',\n disableHiddenCheck: true\n};\n\nvar WorkerStatus = exports.WorkerStatus = function (_React$Component) {\n _inherits(WorkerStatus, _React$Component);\n\n function WorkerStatus(props) {\n _classCallCheck(this, WorkerStatus);\n\n var _this = _possibleConstructorReturn(this, (WorkerStatus.__proto__ || Object.getPrototypeOf(WorkerStatus)).call(this, props));\n\n _this.state = {\n serverInfo: null,\n initialized: false,\n ended: false,\n\n processCpuLoad: [],\n systemCpuLoad: [],\n heapPercentUsed: [],\n nonHeapUsed: []\n };\n\n _this.refreshLoop = _this.refreshLoop.bind(_this);\n return _this;\n }\n\n _createClass(WorkerStatus, [{\n key: \"resetTimer\",\n value: function resetTimer() {\n clearTimeout(this.timeoutId);\n // stop refreshing when query finishes or fails\n if (this.state.query === null || !this.state.ended) {\n this.timeoutId = setTimeout(this.refreshLoop, 1000);\n }\n }\n }, {\n key: \"refreshLoop\",\n value: function refreshLoop() {\n clearTimeout(this.timeoutId); // to stop multiple series of refreshLoop from going on simultaneously\n var nodeId = (0, _utils.getFirstParameter)(window.location.search);\n $.get('/ui/api/worker/' + nodeId + '/status', function (serverInfo) {\n this.setState({\n serverInfo: serverInfo,\n initialized: true,\n\n processCpuLoad: (0, _utils.addToHistory)(serverInfo.processCpuLoad * 100.0, this.state.processCpuLoad),\n systemCpuLoad: (0, _utils.addToHistory)(serverInfo.systemCpuLoad * 100.0, this.state.systemCpuLoad),\n heapPercentUsed: (0, _utils.addToHistory)(serverInfo.heapUsed * 100.0 / serverInfo.heapAvailable, this.state.heapPercentUsed),\n nonHeapUsed: (0, _utils.addToHistory)(serverInfo.nonHeapUsed, this.state.nonHeapUsed)\n });\n\n this.resetTimer();\n }.bind(this)).fail(function () {\n this.setState({\n initialized: true\n });\n this.resetTimer();\n }.bind(this));\n }\n }, {\n key: \"componentDidMount\",\n value: function componentDidMount() {\n this.refreshLoop();\n }\n }, {\n key: \"componentDidUpdate\",\n value: function componentDidUpdate() {\n $('#process-cpu-load-sparkline').sparkline(this.state.processCpuLoad, $.extend({}, SMALL_SPARKLINE_PROPERTIES, { chartRangeMin: 0, numberFormatter: _utils.precisionRound }));\n $('#system-cpu-load-sparkline').sparkline(this.state.systemCpuLoad, $.extend({}, SMALL_SPARKLINE_PROPERTIES, { chartRangeMin: 0, numberFormatter: _utils.precisionRound }));\n $('#heap-percent-used-sparkline').sparkline(this.state.heapPercentUsed, $.extend({}, SMALL_SPARKLINE_PROPERTIES, { chartRangeMin: 0, numberFormatter: _utils.precisionRound }));\n $('#nonheap-used-sparkline').sparkline(this.state.nonHeapUsed, $.extend({}, SMALL_SPARKLINE_PROPERTIES, { chartRangeMin: 0, numberFormatter: _utils.formatDataSize }));\n\n $('[data-toggle=\"tooltip\"]').tooltip();\n new window.ClipboardJS('.copy-button');\n }\n }, {\n key: \"renderPoolQueries\",\n value: function renderPoolQueries(pool) {\n if (!pool) {\n return;\n }\n\n var queries = {};\n var reservations = pool.queryMemoryReservations;\n var revocableReservations = pool.queryMemoryRevocableReservations;\n\n for (var query in reservations) {\n queries[query] = [reservations[query], 0];\n }\n\n for (var _query in revocableReservations) {\n if (queries.hasOwnProperty(_query)) {\n queries[_query][1] = revocableReservations[_query];\n } else {\n queries[_query] = [0, revocableReservations[_query]];\n }\n }\n\n var size = pool.maxBytes;\n\n if (Object.keys(queries).length === 0) {\n return _react2.default.createElement(\n \"div\",\n null,\n _react2.default.createElement(\n \"table\",\n { className: \"table table-condensed\" },\n _react2.default.createElement(\n \"tbody\",\n null,\n _react2.default.createElement(\n \"tr\",\n null,\n _react2.default.createElement(\n \"td\",\n null,\n \"No queries using pool\"\n )\n )\n )\n )\n );\n }\n\n return _react2.default.createElement(\n \"div\",\n null,\n _react2.default.createElement(\n \"table\",\n { className: \"table\" },\n _react2.default.createElement(\n \"tbody\",\n null,\n Object.keys(queries).map(function (key) {\n return WorkerStatus.renderPoolQuery(key, queries[key][0], queries[key][1], size);\n })\n )\n )\n );\n }\n }, {\n key: \"render\",\n value: function render() {\n var serverInfo = this.state.serverInfo;\n\n if (serverInfo === null) {\n if (this.state.initialized === false) {\n return _react2.default.createElement(\n \"div\",\n { className: \"loader\" },\n \"Loading...\"\n );\n } else {\n return _react2.default.createElement(\n \"div\",\n { className: \"row error-message\" },\n _react2.default.createElement(\n \"div\",\n { className: \"col-xs-12\" },\n _react2.default.createElement(\n \"h4\",\n null,\n \"Node information could not be loaded\"\n )\n )\n );\n }\n }\n\n return _react2.default.createElement(\n \"div\",\n null,\n _react2.default.createElement(\n \"div\",\n { className: \"row\" },\n _react2.default.createElement(\n \"div\",\n { className: \"col-xs-12\" },\n _react2.default.createElement(\n \"h3\",\n null,\n \"Overview\"\n ),\n _react2.default.createElement(\"hr\", { className: \"h3-hr\" }),\n _react2.default.createElement(\n \"div\",\n { className: \"row\" },\n _react2.default.createElement(\n \"div\",\n { className: \"col-xs-6\" },\n _react2.default.createElement(\n \"table\",\n { className: \"table\" },\n _react2.default.createElement(\n \"tbody\",\n null,\n _react2.default.createElement(\n \"tr\",\n null,\n _react2.default.createElement(\n \"td\",\n { className: \"info-title\" },\n \"Node ID\"\n ),\n _react2.default.createElement(\n \"td\",\n { className: \"info-text wrap-text\" },\n _react2.default.createElement(\n \"span\",\n { id: \"node-id\" },\n serverInfo.nodeId\n ),\n \"\\xA0\\xA0\",\n _react2.default.createElement(\n \"a\",\n { href: \"#\", className: \"copy-button\", \"data-clipboard-target\": \"#node-id\", \"data-toggle\": \"tooltip\", \"data-placement\": \"right\",\n title: \"Copy to clipboard\" },\n _react2.default.createElement(\"span\", { className: \"glyphicon glyphicon-copy\", alt: \"Copy to clipboard\" })\n )\n )\n ),\n _react2.default.createElement(\n \"tr\",\n null,\n _react2.default.createElement(\n \"td\",\n { className: \"info-title\" },\n \"Heap Memory\"\n ),\n _react2.default.createElement(\n \"td\",\n { className: \"info-text wrap-text\" },\n _react2.default.createElement(\n \"span\",\n { id: \"node-heap-available\" },\n (0, _utils.formatDataSize)(serverInfo.heapAvailable)\n )\n )\n ),\n _react2.default.createElement(\n \"tr\",\n null,\n _react2.default.createElement(\n \"td\",\n { className: \"info-title\" },\n \"Processors\"\n ),\n _react2.default.createElement(\n \"td\",\n { className: \"info-text wrap-text\" },\n _react2.default.createElement(\n \"span\",\n { id: \"node-processors\" },\n serverInfo.processors\n )\n )\n )\n )\n )\n ),\n _react2.default.createElement(\n \"div\",\n { className: \"col-xs-6\" },\n _react2.default.createElement(\n \"table\",\n { className: \"table\" },\n _react2.default.createElement(\n \"tbody\",\n null,\n _react2.default.createElement(\n \"tr\",\n null,\n _react2.default.createElement(\n \"td\",\n { className: \"info-title\" },\n \"Uptime\"\n ),\n _react2.default.createElement(\n \"td\",\n { className: \"info-text wrap-text\" },\n serverInfo.uptime\n )\n ),\n _react2.default.createElement(\n \"tr\",\n null,\n _react2.default.createElement(\n \"td\",\n { className: \"info-title\" },\n \"External Address\"\n ),\n _react2.default.createElement(\n \"td\",\n { className: \"info-text wrap-text\" },\n _react2.default.createElement(\n \"span\",\n { id: \"external-address\" },\n serverInfo.externalAddress\n ),\n \"\\xA0\\xA0\",\n _react2.default.createElement(\n \"a\",\n { href: \"#\", className: \"copy-button\", \"data-clipboard-target\": \"#external-address\", \"data-toggle\": \"tooltip\", \"data-placement\": \"right\",\n title: \"Copy to clipboard\" },\n _react2.default.createElement(\"span\", { className: \"glyphicon glyphicon-copy\", alt: \"Copy to clipboard\" })\n )\n )\n ),\n _react2.default.createElement(\n \"tr\",\n null,\n _react2.default.createElement(\n \"td\",\n { className: \"info-title\" },\n \"Internal Address\"\n ),\n _react2.default.createElement(\n \"td\",\n { className: \"info-text wrap-text\" },\n _react2.default.createElement(\n \"span\",\n { id: \"internal-address\" },\n serverInfo.internalAddress\n ),\n \"\\xA0\\xA0\",\n _react2.default.createElement(\n \"a\",\n { href: \"#\", className: \"copy-button\", \"data-clipboard-target\": \"#internal-address\", \"data-toggle\": \"tooltip\", \"data-placement\": \"right\",\n title: \"Copy to clipboard\" },\n _react2.default.createElement(\"span\", { className: \"glyphicon glyphicon-copy\", alt: \"Copy to clipboard\" })\n )\n )\n )\n )\n )\n )\n ),\n _react2.default.createElement(\n \"div\",\n { className: \"row\" },\n _react2.default.createElement(\n \"div\",\n { className: \"col-xs-12\" },\n _react2.default.createElement(\n \"h3\",\n null,\n \"Resource Utilization\"\n ),\n _react2.default.createElement(\"hr\", { className: \"h3-hr\" }),\n _react2.default.createElement(\n \"div\",\n { className: \"row\" },\n _react2.default.createElement(\n \"div\",\n { className: \"col-xs-6\" },\n _react2.default.createElement(\n \"table\",\n { className: \"table\" },\n _react2.default.createElement(\n \"tbody\",\n null,\n _react2.default.createElement(\n \"tr\",\n null,\n _react2.default.createElement(\n \"td\",\n { className: \"info-title\" },\n \"Process CPU Utilization\"\n ),\n _react2.default.createElement(\n \"td\",\n { rowSpan: \"2\" },\n _react2.default.createElement(\n \"div\",\n { className: \"query-stats-sparkline-container\" },\n _react2.default.createElement(\n \"span\",\n { className: \"sparkline\", id: \"process-cpu-load-sparkline\" },\n _react2.default.createElement(\n \"div\",\n { className: \"loader\" },\n \"Loading ...\"\n )\n )\n )\n )\n ),\n _react2.default.createElement(\n \"tr\",\n { className: \"tr-noborder\" },\n _react2.default.createElement(\n \"td\",\n { className: \"info-sparkline-text\" },\n (0, _utils.formatCount)(this.state.processCpuLoad[this.state.processCpuLoad.length - 1]),\n \"%\"\n )\n ),\n _react2.default.createElement(\n \"tr\",\n null,\n _react2.default.createElement(\n \"td\",\n { className: \"info-title\" },\n \"System CPU Utilization\"\n ),\n _react2.default.createElement(\n \"td\",\n { rowSpan: \"2\" },\n _react2.default.createElement(\n \"div\",\n { className: \"query-stats-sparkline-container\" },\n _react2.default.createElement(\n \"span\",\n { className: \"sparkline\", id: \"system-cpu-load-sparkline\" },\n _react2.default.createElement(\n \"div\",\n { className: \"loader\" },\n \"Loading ...\"\n )\n )\n )\n )\n ),\n _react2.default.createElement(\n \"tr\",\n { className: \"tr-noborder\" },\n _react2.default.createElement(\n \"td\",\n { className: \"info-sparkline-text\" },\n (0, _utils.formatCount)(this.state.systemCpuLoad[this.state.systemCpuLoad.length - 1]),\n \"%\"\n )\n )\n )\n )\n ),\n _react2.default.createElement(\n \"div\",\n { className: \"col-xs-6\" },\n _react2.default.createElement(\n \"table\",\n { className: \"table\" },\n _react2.default.createElement(\n \"tbody\",\n null,\n _react2.default.createElement(\n \"tr\",\n null,\n _react2.default.createElement(\n \"td\",\n { className: \"info-title\" },\n \"Heap Utilization\"\n ),\n _react2.default.createElement(\n \"td\",\n { rowSpan: \"2\" },\n _react2.default.createElement(\n \"div\",\n { className: \"query-stats-sparkline-container\" },\n _react2.default.createElement(\n \"span\",\n { className: \"sparkline\", id: \"heap-percent-used-sparkline\" },\n _react2.default.createElement(\n \"div\",\n { className: \"loader\" },\n \"Loading ...\"\n )\n )\n )\n )\n ),\n _react2.default.createElement(\n \"tr\",\n { className: \"tr-noborder\" },\n _react2.default.createElement(\n \"td\",\n { className: \"info-sparkline-text\" },\n (0, _utils.formatCount)(this.state.heapPercentUsed[this.state.heapPercentUsed.length - 1]),\n \"%\"\n )\n ),\n _react2.default.createElement(\n \"tr\",\n null,\n _react2.default.createElement(\n \"td\",\n { className: \"info-title\" },\n \"Non-Heap Memory Used\"\n ),\n _react2.default.createElement(\n \"td\",\n { rowSpan: \"2\" },\n _react2.default.createElement(\n \"div\",\n { className: \"query-stats-sparkline-container\" },\n _react2.default.createElement(\n \"span\",\n { className: \"sparkline\", id: \"nonheap-used-sparkline\" },\n _react2.default.createElement(\n \"div\",\n { className: \"loader\" },\n \"Loading ...\"\n )\n )\n )\n )\n ),\n _react2.default.createElement(\n \"tr\",\n { className: \"tr-noborder\" },\n _react2.default.createElement(\n \"td\",\n { className: \"info-sparkline-text\" },\n (0, _utils.formatDataSize)(this.state.nonHeapUsed[this.state.nonHeapUsed.length - 1])\n )\n )\n )\n )\n )\n )\n )\n )\n )\n ),\n _react2.default.createElement(\n \"div\",\n { className: \"row\" },\n _react2.default.createElement(\n \"div\",\n { className: \"col-xs-12\" },\n _react2.default.createElement(\n \"h3\",\n null,\n \"Memory Pools\"\n ),\n _react2.default.createElement(\"hr\", { className: \"h3-hr\" }),\n _react2.default.createElement(\n \"div\",\n { className: \"row\" },\n _react2.default.createElement(\n \"div\",\n { className: \"col-xs-6\" },\n WorkerStatus.renderPoolBar(\"General\", serverInfo.memoryInfo.pools.general),\n this.renderPoolQueries(serverInfo.memoryInfo.pools.general)\n )\n )\n )\n )\n );\n }\n }], [{\n key: \"renderPoolBar\",\n value: function renderPoolBar(name, pool) {\n if (!pool) {\n return;\n }\n\n var size = pool.maxBytes;\n var reserved = pool.reservedBytes;\n var revocable = pool.reservedRevocableBytes;\n\n var percentageReservedNonRevocable = reserved === 0 ? 0 : Math.max(Math.round(reserved * 100.0 / size), 15);\n var percentageRevocable = revocable === 0 ? 0 : Math.max(Math.round(revocable * 100.0 / size), 15);\n var percentageFree = 100 - (percentageRevocable + percentageReservedNonRevocable);\n\n return _react2.default.createElement(\n \"div\",\n { className: \"row\" },\n _react2.default.createElement(\n \"div\",\n { className: \"col-xs-12\" },\n _react2.default.createElement(\n \"div\",\n { className: \"row\" },\n _react2.default.createElement(\n \"div\",\n { className: \"col-xs-8\" },\n _react2.default.createElement(\n \"h4\",\n null,\n name,\n \" Pool\"\n )\n ),\n _react2.default.createElement(\n \"div\",\n { className: \"col-xs-4\" },\n _react2.default.createElement(\n \"div\",\n { className: \"progress\", style: { marginTop: \"6px\" } },\n _react2.default.createElement(\n \"div\",\n { className: \"progress-bar memory-progress-bar memory-progress-bar-info\", role: \"progressbar\", style: { width: \"100%\" } },\n (0, _utils.formatDataSize)(size),\n \" total\"\n )\n )\n )\n ),\n _react2.default.createElement(\n \"div\",\n { className: \"row\" },\n _react2.default.createElement(\n \"div\",\n { className: \"col-xs-12\" },\n _react2.default.createElement(\"hr\", { className: \"h4-hr\" }),\n _react2.default.createElement(\n \"div\",\n { className: \"progress\" },\n _react2.default.createElement(\n \"div\",\n { className: \"progress-bar memory-progress-bar progress-bar-warning progress-bar-striped active\", role: \"progressbar\",\n style: { width: percentageReservedNonRevocable + \"%\" } },\n (0, _utils.formatDataSize)(reserved)\n ),\n _react2.default.createElement(\n \"div\",\n { className: \"progress-bar memory-progress-bar progress-bar-danger progress-bar-striped active\", role: \"progressbar\",\n style: { width: percentageRevocable + \"%\" } },\n (0, _utils.formatDataSize)(revocable)\n ),\n _react2.default.createElement(\n \"div\",\n { className: \"progress-bar memory-progress-bar progress-bar-success\", role: \"progressbar\", style: { width: percentageFree + \"%\" } },\n (0, _utils.formatDataSize)(size - reserved - revocable)\n )\n )\n )\n )\n )\n );\n }\n }, {\n key: \"renderPoolQuery\",\n value: function renderPoolQuery(query, reserved, revocable, total) {\n return _react2.default.createElement(\n \"tr\",\n null,\n _react2.default.createElement(\n \"td\",\n null,\n _react2.default.createElement(\n \"div\",\n { className: \"row query-memory-list-header\" },\n _react2.default.createElement(\n \"div\",\n { className: \"col-xs-7\" },\n _react2.default.createElement(\n \"a\",\n { href: \"query.html?\" + query, target: \"_blank\" },\n query\n )\n ),\n _react2.default.createElement(\n \"div\",\n { className: \"col-xs-5\" },\n _react2.default.createElement(\n \"div\",\n { className: \"row text-right\" },\n _react2.default.createElement(\n \"div\",\n { className: \"col-xs-6\" },\n _react2.default.createElement(\n \"span\",\n { \"data-toggle\": \"tooltip\", \"data-placement\": \"top\", title: \"% of pool memory reserved\" },\n Math.round(reserved * 100.0 / total),\n \"%\"\n )\n ),\n _react2.default.createElement(\n \"div\",\n { className: \"col-xs-6\" },\n _react2.default.createElement(\n \"span\",\n { \"data-toggle\": \"tooltip\", \"data-placement\": \"top\",\n title: \"Reserved: \" + (0, _utils.formatDataSize)(reserved) + \". Revocable: \" + (0, _utils.formatDataSize)(revocable) },\n (0, _utils.formatDataSize)(reserved)\n )\n )\n )\n )\n )\n )\n );\n }\n }]);\n\n return WorkerStatus;\n}(_react2.default.Component);\n\n//# sourceURL=webpack:///./components/WorkerStatus.jsx?"); /***/ }), diff --git a/core/trino-main/src/main/resources/webapp/src/components/WorkerStatus.jsx b/core/trino-main/src/main/resources/webapp/src/components/WorkerStatus.jsx index b08e2e211f74..9c47cce5ce63 100644 --- a/core/trino-main/src/main/resources/webapp/src/components/WorkerStatus.jsx +++ b/core/trino-main/src/main/resources/webapp/src/components/WorkerStatus.jsx @@ -421,10 +421,6 @@ export class WorkerStatus extends React.Component { {WorkerStatus.renderPoolBar("General", serverInfo.memoryInfo.pools.general)} {this.renderPoolQueries(serverInfo.memoryInfo.pools.general)} -
- {WorkerStatus.renderPoolBar("Reserved", serverInfo.memoryInfo.pools.reserved)} - {this.renderPoolQueries(serverInfo.memoryInfo.pools.reserved)} -
diff --git a/core/trino-main/src/test/java/io/trino/memory/LowMemoryKillerTestingUtils.java b/core/trino-main/src/test/java/io/trino/memory/LowMemoryKillerTestingUtils.java index 4ce99c04431a..87c278a7ba07 100644 --- a/core/trino-main/src/test/java/io/trino/memory/LowMemoryKillerTestingUtils.java +++ b/core/trino-main/src/test/java/io/trino/memory/LowMemoryKillerTestingUtils.java @@ -29,13 +29,12 @@ import java.util.Map; import static io.trino.memory.LocalMemoryManager.GENERAL_POOL; -import static io.trino.memory.LocalMemoryManager.RESERVED_POOL; public final class LowMemoryKillerTestingUtils { private LowMemoryKillerTestingUtils() {} - static List toNodeMemoryInfoList(long maxReservedPoolBytes, long maxGeneralPoolBytes, String reservedQuery, Map> queries) + static List toNodeMemoryInfoList(long maxGeneralPoolBytes, Map> queries) { Map nodeReservations = new HashMap<>(); @@ -49,12 +48,7 @@ static List toNodeMemoryInfoList(long maxReservedPoolBytes, long max if (bytes == 0) { continue; } - if (reservedQuery.equals(entry.getKey())) { - nodeReservations.computeIfAbsent(node, ignored -> new NodeReservation()).getReserved().add(queryId, bytes); - } - else { - nodeReservations.computeIfAbsent(node, ignored -> new NodeReservation()).getGeneral().add(queryId, bytes); - } + nodeReservations.computeIfAbsent(node, ignored -> new NodeReservation()).getGeneral().add(queryId, bytes); } } @@ -73,23 +67,12 @@ static List toNodeMemoryInfoList(long maxReservedPoolBytes, long max ImmutableMap.of(), ImmutableMap.of())); } - if (nodeReservation.getReserved().getTotalReservedBytes() > 0) { - pools.put( - RESERVED_POOL, - new MemoryPoolInfo( - maxReservedPoolBytes, - nodeReservation.getReserved().getTotalReservedBytes(), - 0, - nodeReservation.getReserved().getReservationByQuery(), - ImmutableMap.of(), - ImmutableMap.of())); - } - result.add(new MemoryInfo(7, DataSize.ofBytes(maxReservedPoolBytes + maxGeneralPoolBytes), pools.buildOrThrow())); + result.add(new MemoryInfo(7, DataSize.ofBytes(maxGeneralPoolBytes), pools.buildOrThrow())); } return result.build(); } - static List toQueryMemoryInfoList(String reservedQuery, Map> queries) + static List toQueryMemoryInfoList(Map> queries) { ImmutableList.Builder result = ImmutableList.builder(); for (Map.Entry> entry : queries.entrySet()) { @@ -97,7 +80,7 @@ static List toQueryMemoryInfoList(String reserv long totalReservation = entry.getValue().values().stream() .mapToLong(x -> x) .sum(); - result.add(new LowMemoryKiller.QueryMemoryInfo(new QueryId(queryId), queryId.equals(reservedQuery) ? RESERVED_POOL : GENERAL_POOL, totalReservation)); + result.add(new LowMemoryKiller.QueryMemoryInfo(new QueryId(queryId), GENERAL_POOL, totalReservation)); } return result.build(); } @@ -105,17 +88,11 @@ static List toQueryMemoryInfoList(String reserv private static class NodeReservation { private final PoolReservation general = new PoolReservation(); - private final PoolReservation reserved = new PoolReservation(); public PoolReservation getGeneral() { return general; } - - public PoolReservation getReserved() - { - return reserved; - } } private static class PoolReservation diff --git a/core/trino-main/src/test/java/io/trino/memory/TestLocalMemoryManager.java b/core/trino-main/src/test/java/io/trino/memory/TestLocalMemoryManager.java index 06db73e0edb5..f1ded908186b 100644 --- a/core/trino-main/src/test/java/io/trino/memory/TestLocalMemoryManager.java +++ b/core/trino-main/src/test/java/io/trino/memory/TestLocalMemoryManager.java @@ -19,36 +19,20 @@ import static io.airlift.units.DataSize.Unit.GIGABYTE; import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.testng.Assert.assertEquals; -import static org.testng.Assert.assertFalse; -import static org.testng.Assert.assertTrue; public class TestLocalMemoryManager { @Test - public void testReservedMemoryPoolDisabled() + public void testLocalMemoryManger() { NodeMemoryConfig config = new NodeMemoryConfig() .setHeapHeadroom(DataSize.of(10, GIGABYTE)) .setMaxQueryMemoryPerNode(DataSize.of(20, GIGABYTE)); LocalMemoryManager localMemoryManager = new LocalMemoryManager(config, DataSize.of(60, GIGABYTE).toBytes()); - assertFalse(localMemoryManager.getReservedPool().isPresent()); assertEquals(localMemoryManager.getPools().size(), 1); } - @Test - public void testReservedMemoryPoolEnabled() - { - NodeMemoryConfig config = new NodeMemoryConfig() - .setReservedPoolDisabled(false) - .setHeapHeadroom(DataSize.of(10, GIGABYTE)) - .setMaxQueryMemoryPerNode(DataSize.of(20, GIGABYTE)); - - LocalMemoryManager localMemoryManager = new LocalMemoryManager(config, DataSize.of(60, GIGABYTE).toBytes()); - assertTrue(localMemoryManager.getReservedPool().isPresent()); - assertEquals(localMemoryManager.getPools().size(), 2); - } - @Test public void testNotEnoughAvailableMemory() { diff --git a/core/trino-main/src/test/java/io/trino/memory/TestNodeMemoryConfig.java b/core/trino-main/src/test/java/io/trino/memory/TestNodeMemoryConfig.java index cfec17ebaae0..f02280c69f77 100644 --- a/core/trino-main/src/test/java/io/trino/memory/TestNodeMemoryConfig.java +++ b/core/trino-main/src/test/java/io/trino/memory/TestNodeMemoryConfig.java @@ -34,8 +34,7 @@ public void testDefaults() assertRecordedDefaults(recordDefaults(NodeMemoryConfig.class) .setMaxQueryMemoryPerNode(DataSize.ofBytes(Math.round(AVAILABLE_HEAP_MEMORY * 0.3))) .setMaxQueryMemoryPerTask(null) - .setHeapHeadroom(DataSize.ofBytes(Math.round(AVAILABLE_HEAP_MEMORY * 0.3))) - .setReservedPoolDisabled(true)); + .setHeapHeadroom(DataSize.ofBytes(Math.round(AVAILABLE_HEAP_MEMORY * 0.3)))); } @Test @@ -45,14 +44,12 @@ public void testExplicitPropertyMappings() .put("query.max-memory-per-node", "1GB") .put("query.max-memory-per-task", "200MB") .put("memory.heap-headroom-per-node", "1GB") - .put("experimental.reserved-pool-disabled", "false") .buildOrThrow(); NodeMemoryConfig expected = new NodeMemoryConfig() .setMaxQueryMemoryPerNode(DataSize.of(1, GIGABYTE)) .setMaxQueryMemoryPerTask(DataSize.of(200, MEGABYTE)) - .setHeapHeadroom(DataSize.of(1, GIGABYTE)) - .setReservedPoolDisabled(false); + .setHeapHeadroom(DataSize.of(1, GIGABYTE)); assertFullMapping(properties, expected); } diff --git a/core/trino-main/src/test/java/io/trino/memory/TestQueryContext.java b/core/trino-main/src/test/java/io/trino/memory/TestQueryContext.java index 5acdbc084e02..982cdd916d81 100644 --- a/core/trino-main/src/test/java/io/trino/memory/TestQueryContext.java +++ b/core/trino-main/src/test/java/io/trino/memory/TestQueryContext.java @@ -13,34 +13,22 @@ */ package io.trino.memory; -import com.google.common.collect.ImmutableMap; import io.airlift.stats.TestingGcMonitor; import io.airlift.units.DataSize; -import io.trino.execution.TaskId; -import io.trino.execution.TaskStateMachine; import io.trino.memory.context.LocalMemoryContext; -import io.trino.operator.DriverContext; -import io.trino.operator.OperatorContext; -import io.trino.operator.TaskContext; import io.trino.spi.QueryId; import io.trino.spiller.SpillSpaceTracker; -import io.trino.sql.planner.plan.PlanNodeId; import io.trino.testing.LocalQueryRunner; import org.testng.annotations.AfterClass; -import org.testng.annotations.DataProvider; import org.testng.annotations.Test; -import java.util.Map; import java.util.Optional; import java.util.concurrent.ScheduledExecutorService; import static io.airlift.concurrent.Threads.threadsNamed; import static io.trino.SessionTestUtils.TEST_SESSION; import static io.trino.memory.LocalMemoryManager.GENERAL_POOL; -import static io.trino.memory.LocalMemoryManager.RESERVED_POOL; import static java.util.concurrent.Executors.newScheduledThreadPool; -import static org.testng.Assert.assertEquals; -import static org.testng.Assert.assertNull; import static org.testng.Assert.assertTrue; public class TestQueryContext @@ -53,25 +41,9 @@ public void tearDown() TEST_EXECUTOR.shutdownNow(); } - @DataProvider - public Object[][] testSetMemoryPoolOptions() - { - return new Object[][] { - {false}, - {true}, - }; - } - - @Test(dataProvider = "testSetMemoryPoolOptions") - public void testSetMemoryPool(boolean useReservedPool) + @Test + public void testSetMemoryPool() { - QueryId secondQuery = new QueryId("second"); - MemoryPool reservedPool = new MemoryPool(RESERVED_POOL, DataSize.ofBytes(10)); - long secondQueryMemory = reservedPool.getMaxBytes() - 1; - if (useReservedPool) { - assertTrue(reservedPool.reserve(secondQuery, "test", secondQueryMemory).isDone()); - } - try (LocalQueryRunner localQueryRunner = LocalQueryRunner.create(TEST_SESSION)) { QueryContext queryContext = new QueryContext( new QueryId("query"), @@ -91,62 +63,9 @@ public void testSetMemoryPool(boolean useReservedPool) assertTrue(userMemoryContext.setBytes(3).isDone()); assertTrue(revocableMemoryContext.setBytes(5).isDone()); - queryContext.setMemoryPool(reservedPool); - - if (useReservedPool) { - reservedPool.free(secondQuery, "test", secondQueryMemory); - } - // Free memory userMemoryContext.close(); revocableMemoryContext.close(); } } - - @Test - public void testMoveTaggedAllocations() - { - MemoryPool generalPool = new MemoryPool(GENERAL_POOL, DataSize.ofBytes(10_000)); - MemoryPool reservedPool = new MemoryPool(RESERVED_POOL, DataSize.ofBytes(10_000)); - QueryId queryId = new QueryId("query"); - QueryContext queryContext = createQueryContext(queryId, generalPool); - TaskStateMachine taskStateMachine = new TaskStateMachine(TaskId.valueOf("task-id"), TEST_EXECUTOR); - TaskContext taskContext = queryContext.addTaskContext(taskStateMachine, TEST_SESSION, () -> {}, false, false); - DriverContext driverContext = taskContext.addPipelineContext(0, false, false, false).addDriverContext(); - OperatorContext operatorContext = driverContext.addOperatorContext(0, new PlanNodeId("test"), "test"); - - // allocate some memory in the general pool - LocalMemoryContext memoryContext = operatorContext.aggregateUserMemoryContext().newLocalMemoryContext("test_context"); - memoryContext.setBytes(1_000); - - Map allocations = generalPool.getTaggedMemoryAllocations().get(queryId); - assertEquals(allocations, ImmutableMap.of("test_context", 1_000L)); - - queryContext.setMemoryPool(reservedPool); - - assertNull(generalPool.getTaggedMemoryAllocations().get(queryId)); - allocations = reservedPool.getTaggedMemoryAllocations().get(queryId); - assertEquals(allocations, ImmutableMap.of("test_context", 1_000L)); - - assertEquals(generalPool.getFreeBytes(), 10_000); - assertEquals(reservedPool.getFreeBytes(), 9_000); - - memoryContext.close(); - - assertEquals(generalPool.getFreeBytes(), 10_000); - assertEquals(reservedPool.getFreeBytes(), 10_000); - } - - private static QueryContext createQueryContext(QueryId queryId, MemoryPool generalPool) - { - return new QueryContext(queryId, - DataSize.ofBytes(10_000), - Optional.empty(), - generalPool, - new TestingGcMonitor(), - TEST_EXECUTOR, - TEST_EXECUTOR, - DataSize.ofBytes(0), - new SpillSpaceTracker(DataSize.ofBytes(0))); - } } diff --git a/core/trino-main/src/test/java/io/trino/memory/TestTotalReservationLowMemoryKiller.java b/core/trino-main/src/test/java/io/trino/memory/TestTotalReservationLowMemoryKiller.java index 06dc15de5df7..eb2895341c4d 100644 --- a/core/trino-main/src/test/java/io/trino/memory/TestTotalReservationLowMemoryKiller.java +++ b/core/trino-main/src/test/java/io/trino/memory/TestTotalReservationLowMemoryKiller.java @@ -32,23 +32,20 @@ public class TestTotalReservationLowMemoryKiller @Test public void testGeneralPoolHasNoReservation() { - int reservePool = 10; int generalPool = 12; Map> queries = ImmutableMap.>builder() .put("q_1", ImmutableMap.of("n1", 0L, "n2", 0L, "n3", 0L, "n4", 0L, "n5", 0L)) - .put("q_r", ImmutableMap.of("n1", 6L, "n2", 6L, "n3", 6L, "n4", 6L, "n5", 6L)) .buildOrThrow(); assertEquals( lowMemoryKiller.chooseQueryToKill( - toQueryMemoryInfoList("q_r", queries), - toNodeMemoryInfoList(reservePool, generalPool, "q_r", queries)), + toQueryMemoryInfoList(queries), + toNodeMemoryInfoList(generalPool, queries)), Optional.empty()); } @Test public void testSkewedQuery() { - int reservePool = 10; int generalPool = 12; // q2 is the query with the most total memory reservation, but not the query with the max memory reservation. // This also tests the corner case where a node doesn't have a general pool. @@ -56,12 +53,11 @@ public void testSkewedQuery() .put("q_1", ImmutableMap.of("n1", 0L, "n2", 8L, "n3", 0L, "n4", 0L, "n5", 0L)) .put("q_2", ImmutableMap.of("n1", 3L, "n2", 5L, "n3", 2L, "n4", 4L, "n5", 0L)) .put("q_3", ImmutableMap.of("n1", 0L, "n2", 0L, "n3", 9L, "n4", 0L, "n5", 0L)) - .put("q_r", ImmutableMap.of("n1", 6L, "n2", 6L, "n3", 6L, "n4", 6L, "n5", 6L)) .buildOrThrow(); assertEquals( lowMemoryKiller.chooseQueryToKill( - toQueryMemoryInfoList("q_r", queries), - toNodeMemoryInfoList(reservePool, generalPool, "q_r", queries)), + toQueryMemoryInfoList(queries), + toNodeMemoryInfoList(generalPool, queries)), Optional.of(new QueryId("q_2"))); } } diff --git a/core/trino-main/src/test/java/io/trino/memory/TestTotalReservationOnBlockedNodesLowMemoryKiller.java b/core/trino-main/src/test/java/io/trino/memory/TestTotalReservationOnBlockedNodesLowMemoryKiller.java index f3d08164edfd..15b917d477a0 100644 --- a/core/trino-main/src/test/java/io/trino/memory/TestTotalReservationOnBlockedNodesLowMemoryKiller.java +++ b/core/trino-main/src/test/java/io/trino/memory/TestTotalReservationOnBlockedNodesLowMemoryKiller.java @@ -32,40 +32,35 @@ public class TestTotalReservationOnBlockedNodesLowMemoryKiller @Test public void testGeneralPoolHasNoReservation() { - int reservePool = 10; int generalPool = 12; Map> queries = ImmutableMap.>builder() .put("q_1", ImmutableMap.of("n1", 0L, "n2", 0L, "n3", 0L, "n4", 0L, "n5", 0L)) - .put("q_r", ImmutableMap.of("n1", 6L, "n2", 6L, "n3", 6L, "n4", 6L, "n5", 6L)) .buildOrThrow(); assertEquals( lowMemoryKiller.chooseQueryToKill( - toQueryMemoryInfoList("q_r", queries), - toNodeMemoryInfoList(reservePool, generalPool, "q_r", queries)), + toQueryMemoryInfoList(queries), + toNodeMemoryInfoList(generalPool, queries)), Optional.empty()); } @Test public void testGeneralPoolNotBlocked() { - int reservePool = 10; int generalPool = 12; Map> queries = ImmutableMap.>builder() .put("q_1", ImmutableMap.of("n1", 0L, "n2", 6L, "n3", 0L, "n4", 0L, "n5", 0L)) .put("q_2", ImmutableMap.of("n1", 3L, "n2", 5L, "n3", 2L, "n4", 4L, "n5", 0L)) - .put("q_r", ImmutableMap.of("n1", 6L, "n2", 6L, "n3", 6L, "n4", 6L, "n5", 6L)) .buildOrThrow(); assertEquals( lowMemoryKiller.chooseQueryToKill( - toQueryMemoryInfoList("q_r", queries), - toNodeMemoryInfoList(reservePool, generalPool, "q_r", queries)), + toQueryMemoryInfoList(queries), + toNodeMemoryInfoList(generalPool, queries)), Optional.empty()); } @Test public void testSkewedQuery() { - int reservePool = 10; int generalPool = 12; // q1 is neither the query with the most total memory reservation, nor the query with the max memory reservation. // This also tests the corner case where a node doesn't have a general pool. @@ -73,12 +68,11 @@ public void testSkewedQuery() .put("q_1", ImmutableMap.of("n1", 0L, "n2", 8L, "n3", 0L, "n4", 0L, "n5", 0L)) .put("q_2", ImmutableMap.of("n1", 3L, "n2", 5L, "n3", 2L, "n4", 4L, "n5", 0L)) .put("q_3", ImmutableMap.of("n1", 0L, "n2", 0L, "n3", 9L, "n4", 0L, "n5", 0L)) - .put("q_r", ImmutableMap.of("n1", 6L, "n2", 6L, "n3", 6L, "n4", 6L, "n5", 6L)) .buildOrThrow(); assertEquals( lowMemoryKiller.chooseQueryToKill( - toQueryMemoryInfoList("q_r", queries), - toNodeMemoryInfoList(reservePool, generalPool, "q_r", queries)), + toQueryMemoryInfoList(queries), + toNodeMemoryInfoList(generalPool, queries)), Optional.of(new QueryId("q_1"))); } } diff --git a/testing/trino-tests/src/test/java/io/trino/memory/TestMemoryManager.java b/testing/trino-tests/src/test/java/io/trino/memory/TestMemoryManager.java index 6ab0a2161450..7b163c6e0838 100644 --- a/testing/trino-tests/src/test/java/io/trino/memory/TestMemoryManager.java +++ b/testing/trino-tests/src/test/java/io/trino/memory/TestMemoryManager.java @@ -31,7 +31,6 @@ import java.util.ArrayList; import java.util.List; import java.util.Map; -import java.util.Optional; import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; import java.util.concurrent.Future; @@ -39,7 +38,6 @@ import static io.trino.SystemSessionProperties.RESOURCE_OVERCOMMIT; import static io.trino.execution.QueryState.FINISHED; import static io.trino.memory.LocalMemoryManager.GENERAL_POOL; -import static io.trino.memory.LocalMemoryManager.RESERVED_POOL; import static io.trino.operator.BlockedReason.WAITING_FOR_MEMORY; import static io.trino.spi.StandardErrorCode.CLUSTER_OUT_OF_MEMORY; import static io.trino.testing.TestingSession.testSessionBuilder; @@ -109,8 +107,6 @@ public void testOutOfMemoryKiller() throws Exception { Map properties = ImmutableMap.builder() - .put("experimental.reserved-pool-disabled", "false") - .put("task.verbose-stats", "true") .put("query.low-memory-killer.delay", "5s") .put("query.low-memory-killer.policy", "total-reservation") .buildOrThrow(); @@ -119,9 +115,9 @@ public void testOutOfMemoryKiller() // Reserve all the memory QueryId fakeQueryId = new QueryId("fake"); for (TestingTrinoServer server : queryRunner.getServers()) { - for (MemoryPool pool : server.getLocalMemoryManager().getPools()) { - assertTrue(pool.tryReserve(fakeQueryId, "test", pool.getMaxBytes())); - } + List memoryPools = server.getLocalMemoryManager().getPools(); + assertEquals(memoryPools.size(), 1, "Only general pool should exist"); + assertTrue(memoryPools.get(0).tryReserve(fakeQueryId, "test", memoryPools.get(0).getMaxBytes())); } List> queryFutures = new ArrayList<>(); @@ -132,13 +128,12 @@ public void testOutOfMemoryKiller() // Wait for one of the queries to die waitForQueryToBeKilled(queryRunner); - // Release the memory in the reserved pool for (TestingTrinoServer server : queryRunner.getServers()) { - Optional reserved = server.getLocalMemoryManager().getReservedPool(); - assertTrue(reserved.isPresent()); + MemoryPool general = server.getLocalMemoryManager().getGeneralPool(); + assertTrue(general.getReservedBytes() > 0); // Free up the entire pool - reserved.get().free(fakeQueryId, "test", reserved.get().getMaxBytes()); - assertTrue(reserved.get().getFreeBytes() > 0); + general.free(fakeQueryId, "test", general.getMaxBytes()); + assertTrue(general.getFreeBytes() > 0); } for (Future query : queryFutures) { @@ -162,50 +157,6 @@ private void waitForQueryToBeKilled(DistributedQueryRunner queryRunner) } } - @Test(timeOut = 240_000, expectedExceptions = ExecutionException.class, expectedExceptionsMessageRegExp = ".*Query killed because the cluster is out of memory. Please try again in a few minutes.") - public void testReservedPoolDisabled() - throws Exception - { - Map properties = ImmutableMap.builder() - .put("experimental.reserved-pool-disabled", "true") - .put("query.low-memory-killer.delay", "5s") - .put("query.low-memory-killer.policy", "total-reservation") - .buildOrThrow(); - - try (DistributedQueryRunner queryRunner = createQueryRunner(TINY_SESSION, properties)) { - // Reserve all the memory - QueryId fakeQueryId = new QueryId("fake"); - for (TestingTrinoServer server : queryRunner.getServers()) { - List memoryPools = server.getLocalMemoryManager().getPools(); - assertEquals(memoryPools.size(), 1, "Only general pool should exist"); - assertTrue(memoryPools.get(0).tryReserve(fakeQueryId, "test", memoryPools.get(0).getMaxBytes())); - } - - List> queryFutures = new ArrayList<>(); - for (int i = 0; i < 2; i++) { - queryFutures.add(executor.submit(() -> queryRunner.execute("SELECT COUNT(*), clerk FROM orders GROUP BY clerk"))); - } - - // Wait for one of the queries to die - waitForQueryToBeKilled(queryRunner); - - // Reserved pool shouldn't exist on the workers and allocation should have been done in the general pool - for (TestingTrinoServer server : queryRunner.getServers()) { - Optional reserved = server.getLocalMemoryManager().getReservedPool(); - MemoryPool general = server.getLocalMemoryManager().getGeneralPool(); - assertFalse(reserved.isPresent()); - assertTrue(general.getReservedBytes() > 0); - // Free up the entire pool - general.free(fakeQueryId, "test", general.getMaxBytes()); - assertTrue(general.getFreeBytes() > 0); - } - - for (Future query : queryFutures) { - query.get(); - } - } - } - @Test(timeOut = 240_000) public void testNoLeak() throws Exception @@ -218,7 +169,6 @@ private void testNoLeak(@Language("SQL") String query) throws Exception { Map properties = ImmutableMap.builder() - .put("experimental.reserved-pool-disabled", "false") .put("task.verbose-stats", "true") .buildOrThrow(); @@ -231,9 +181,6 @@ private void testNoLeak(@Language("SQL") String query) // Make sure we didn't leak any memory on the workers for (TestingTrinoServer worker : queryRunner.getServers()) { - Optional reserved = worker.getLocalMemoryManager().getReservedPool(); - assertTrue(reserved.isPresent()); - assertEquals(reserved.get().getMaxBytes(), reserved.get().getFreeBytes()); MemoryPool general = worker.getLocalMemoryManager().getGeneralPool(); assertEquals(general.getMaxBytes(), general.getFreeBytes()); } @@ -245,7 +192,6 @@ public void testClusterPools() throws Exception { Map properties = ImmutableMap.builder() - .put("experimental.reserved-pool-disabled", "false") .put("task.verbose-stats", "true") .buildOrThrow(); @@ -264,22 +210,18 @@ public void testClusterPools() } ClusterMemoryManager memoryManager = queryRunner.getCoordinator().getClusterMemoryManager(); - ClusterMemoryPool reservedPool; - while ((reservedPool = memoryManager.getPools().get(RESERVED_POOL)) == null) { - MILLISECONDS.sleep(10); - } ClusterMemoryPool generalPool = memoryManager.getPools().get(GENERAL_POOL); assertNotNull(generalPool); // Wait for the pools to become blocked - while (generalPool.getBlockedNodes() != 2 || reservedPool.getBlockedNodes() != 2) { + while (generalPool.getBlockedNodes() != 2) { MILLISECONDS.sleep(10); } - // Make sure the queries are assigned to different memory pools + // Ger query infos for both queries List currentQueryInfos = queryRunner.getCoordinator().getQueryManager().getQueries(); - while (currentQueryInfos.size() != 2 || currentQueryInfos.get(0).getMemoryPool().equals(currentQueryInfos.get(1).getMemoryPool())) { + while (currentQueryInfos.size() != 2) { MILLISECONDS.sleep(10); currentQueryInfos = queryRunner.getCoordinator().getQueryManager().getQueries(); } @@ -290,8 +232,8 @@ public void testClusterPools() } // Check that queries are assigned to expected pools - assertThat(currentQueryInfos.get(0).getMemoryPool()).isIn(GENERAL_POOL, RESERVED_POOL); - assertThat(currentQueryInfos.get(1).getMemoryPool()).isIn(GENERAL_POOL, RESERVED_POOL); + assertThat(currentQueryInfos.get(0).getMemoryPool()).isIn(GENERAL_POOL); + assertThat(currentQueryInfos.get(1).getMemoryPool()).isIn(GENERAL_POOL); while (!currentQueryInfos.stream().allMatch(TestMemoryManager::isBlockedWaitingForMemory)) { MILLISECONDS.sleep(10); @@ -301,17 +243,15 @@ public void testClusterPools() } } - // Release the memory in the reserved pool + // Release the memory in the general pool for (TestingTrinoServer server : queryRunner.getServers()) { - Optional reserved = server.getLocalMemoryManager().getReservedPool(); - assertTrue(reserved.isPresent()); + MemoryPool general = server.getLocalMemoryManager().getGeneralPool(); // Free up the entire pool - reserved.get().free(fakeQueryId, "test", reserved.get().getMaxBytes()); - assertTrue(reserved.get().getFreeBytes() > 0); + general.free(fakeQueryId, "test", general.getMaxBytes()); + assertTrue(general.getFreeBytes() > 0); } - // Make sure both queries finish now that there's memory free in the reserved pool. - // This also checks that the query in the general pool is successfully moved to the reserved pool. + // Make sure both queries finish now that there's memory free in the general pool. for (Future query : queryFutures) { query.get(); } @@ -322,12 +262,7 @@ public void testClusterPools() // Make sure we didn't leak any memory on the workers for (TestingTrinoServer worker : queryRunner.getServers()) { - Optional reserved = worker.getLocalMemoryManager().getReservedPool(); - assertTrue(reserved.isPresent()); - assertEquals(reserved.get().getMaxBytes(), reserved.get().getFreeBytes()); MemoryPool general = worker.getLocalMemoryManager().getGeneralPool(); - // Free up the memory we reserved earlier - general.free(fakeQueryId, "test", general.getMaxBytes()); assertEquals(general.getMaxBytes(), general.getFreeBytes()); } } From cd2cdda1ee4edd79f1f68832f1c7e9989d0a4024 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Osipiuk?= Date: Wed, 16 Feb 2022 15:12:59 +0100 Subject: [PATCH 2/2] Remove mechanism for supporting multiple memory pools --- .../trino/dispatcher/FailedDispatchQuery.java | 2 - .../execution/DataDefinitionExecution.java | 13 --- .../execution/MemoryRevokingScheduler.java | 42 ++----- .../io/trino/execution/QueryExecution.java | 5 - .../java/io/trino/execution/QueryInfo.java | 10 -- .../io/trino/execution/QueryStateMachine.java | 17 --- .../io/trino/execution/SqlQueryExecution.java | 13 --- .../io/trino/execution/SqlTaskManager.java | 2 +- .../memory/ClusterMemoryLeakDetector.java | 2 +- .../io/trino/memory/ClusterMemoryManager.java | 106 ++++++------------ .../io/trino/memory/ClusterMemoryPool.java | 68 +++-------- .../io/trino/memory/LocalMemoryManager.java | 41 ++----- .../memory/LocalMemoryManagerExporter.java | 42 +++---- .../java/io/trino/memory/LowMemoryKiller.java | 11 +- .../main/java/io/trino/memory/MemoryInfo.java | 27 +---- .../main/java/io/trino/memory/MemoryPool.java | 36 +----- .../java/io/trino/memory/MemoryResource.java | 16 --- .../java/io/trino/memory/QueryContext.java | 54 +-------- .../TotalReservationLowMemoryKiller.java | 4 +- ...ervationOnBlockedNodesLowMemoryKiller.java | 9 +- .../trino/memory/VersionedMemoryPoolId.java | 50 --------- .../java/io/trino/server/BasicQueryInfo.java | 11 -- .../server/ui/TrimmedBasicQueryInfo.java | 9 -- .../io/trino/testing/TestingTaskContext.java | 3 +- .../src/main/resources/webapp/dist/query.js | 2 +- .../src/main/resources/webapp/dist/worker.js | 2 +- .../webapp/src/components/QueryDetail.jsx | 8 -- .../webapp/src/components/WorkerStatus.jsx | 6 +- .../execution/MockManagedQueryExecution.java | 3 - .../execution/MockRemoteTaskFactory.java | 3 +- .../TestMemoryRevokingScheduler.java | 45 +------- .../execution/TestQueryStateMachine.java | 7 -- .../java/io/trino/execution/TestSqlTask.java | 3 +- .../trino/execution/TestSqlTaskExecution.java | 3 +- .../memory/LowMemoryKillerTestingUtils.java | 41 ++----- .../trino/memory/TestLocalMemoryManager.java | 12 -- .../java/io/trino/memory/TestMemoryPools.java | 43 +------ .../io/trino/memory/TestMemoryTracking.java | 3 +- .../io/trino/memory/TestQueryContext.java | 3 +- .../TestTotalReservationLowMemoryKiller.java | 12 +- ...ervationOnBlockedNodesLowMemoryKiller.java | 18 +-- .../operator/GroupByHashYieldAssertion.java | 3 +- .../io/trino/server/TestBasicQueryInfo.java | 3 - .../io/trino/server/TestQueryStateInfo.java | 2 - .../spi/connector/ConnectorPageSink.java | 2 +- .../spi/connector/ConnectorPageSource.java | 2 +- .../io/trino/spi/exchange/ExchangeSink.java | 2 +- .../io/trino/spi/exchange/ExchangeSource.java | 2 +- .../spi/memory/ClusterMemoryPoolManager.java | 2 +- .../io/trino/spi/memory/MemoryPoolId.java | 68 ----------- .../AbstractResourceConfigurationManager.java | 25 ++--- ...FileResourceGroupConfigurationManager.java | 19 ++-- ...stDbResourceGroupConfigurationManager.java | 24 ++-- .../benchmark/AbstractOperatorBenchmark.java | 3 +- .../benchmark/MemoryLocalQueryRunner.java | 3 +- .../memory/TestClusterMemoryLeakDetector.java | 2 - .../io/trino/memory/TestMemoryManager.java | 48 ++++---- 57 files changed, 206 insertions(+), 811 deletions(-) delete mode 100644 core/trino-main/src/main/java/io/trino/memory/VersionedMemoryPoolId.java delete mode 100644 core/trino-spi/src/main/java/io/trino/spi/memory/MemoryPoolId.java diff --git a/core/trino-main/src/main/java/io/trino/dispatcher/FailedDispatchQuery.java b/core/trino-main/src/main/java/io/trino/dispatcher/FailedDispatchQuery.java index 4848390a4cea..66e3dcbfa957 100644 --- a/core/trino-main/src/main/java/io/trino/dispatcher/FailedDispatchQuery.java +++ b/core/trino-main/src/main/java/io/trino/dispatcher/FailedDispatchQuery.java @@ -36,7 +36,6 @@ import java.util.concurrent.Executor; import static com.google.common.util.concurrent.Futures.immediateVoidFuture; -import static io.trino.memory.LocalMemoryManager.GENERAL_POOL; import static io.trino.server.DynamicFilterService.DynamicFiltersStats; import static io.trino.util.Failures.toFailure; import static java.util.Objects.requireNonNull; @@ -214,7 +213,6 @@ private static QueryInfo immediateFailureQueryInfo( session.getQueryId(), session.toSessionRepresentation(), QueryState.FAILED, - GENERAL_POOL, false, self, ImmutableList.of(), diff --git a/core/trino-main/src/main/java/io/trino/execution/DataDefinitionExecution.java b/core/trino-main/src/main/java/io/trino/execution/DataDefinitionExecution.java index 4532be10f996..dd12a8913050 100644 --- a/core/trino-main/src/main/java/io/trino/execution/DataDefinitionExecution.java +++ b/core/trino-main/src/main/java/io/trino/execution/DataDefinitionExecution.java @@ -22,7 +22,6 @@ import io.trino.execution.QueryPreparer.PreparedQuery; import io.trino.execution.StateMachine.StateChangeListener; import io.trino.execution.warnings.WarningCollector; -import io.trino.memory.VersionedMemoryPoolId; import io.trino.server.BasicQueryInfo; import io.trino.server.protocol.Slug; import io.trino.spi.QueryId; @@ -77,18 +76,6 @@ public Slug getSlug() return slug; } - @Override - public VersionedMemoryPoolId getMemoryPool() - { - return stateMachine.getMemoryPool(); - } - - @Override - public void setMemoryPool(VersionedMemoryPoolId poolId) - { - stateMachine.setMemoryPool(poolId); - } - @Override public Session getSession() { diff --git a/core/trino-main/src/main/java/io/trino/execution/MemoryRevokingScheduler.java b/core/trino-main/src/main/java/io/trino/execution/MemoryRevokingScheduler.java index f29aee70e962..071eaffe8998 100644 --- a/core/trino-main/src/main/java/io/trino/execution/MemoryRevokingScheduler.java +++ b/core/trino-main/src/main/java/io/trino/execution/MemoryRevokingScheduler.java @@ -14,7 +14,6 @@ package io.trino.execution; import com.google.common.annotations.VisibleForTesting; -import com.google.common.collect.ImmutableList; import com.google.common.collect.Ordering; import io.airlift.log.Logger; import io.trino.FeaturesConfig; @@ -26,7 +25,6 @@ import io.trino.operator.OperatorContext; import io.trino.operator.PipelineContext; import io.trino.operator.TaskContext; -import io.trino.spi.memory.MemoryPoolId; import javax.annotation.Nullable; import javax.annotation.PostConstruct; @@ -52,7 +50,7 @@ public class MemoryRevokingScheduler private static final Logger log = Logger.get(MemoryRevokingScheduler.class); private static final Ordering ORDER_BY_CREATE_TIME = Ordering.natural().onResultOf(SqlTask::getTaskCreatedTime); - private final List memoryPools; + private final MemoryPool memoryPool; private final Supplier> currentTasksSupplier; private final ScheduledExecutorService taskManagementExecutor; private final double memoryRevokingThreshold; @@ -73,7 +71,7 @@ public MemoryRevokingScheduler( FeaturesConfig config) { this( - ImmutableList.copyOf(getMemoryPools(localMemoryManager)), + localMemoryManager.getMemoryPool(), requireNonNull(sqlTaskManager, "sqlTaskManager cannot be null")::getAllTasks, requireNonNull(taskManagementExecutor, "taskManagementExecutor cannot be null").getExecutor(), config.getMemoryRevokingThreshold(), @@ -82,13 +80,13 @@ public MemoryRevokingScheduler( @VisibleForTesting MemoryRevokingScheduler( - List memoryPools, + MemoryPool memoryPool, Supplier> currentTasksSupplier, ScheduledExecutorService taskManagementExecutor, double memoryRevokingThreshold, double memoryRevokingTarget) { - this.memoryPools = ImmutableList.copyOf(requireNonNull(memoryPools, "memoryPools is null")); + this.memoryPool = requireNonNull(memoryPool, "memoryPool is null"); this.currentTasksSupplier = requireNonNull(currentTasksSupplier, "currentTasksSupplier is null"); this.taskManagementExecutor = requireNonNull(taskManagementExecutor, "taskManagementExecutor is null"); this.memoryRevokingThreshold = checkFraction(memoryRevokingThreshold, "memoryRevokingThreshold"); @@ -106,14 +104,6 @@ private static double checkFraction(double value, String valueName) return value; } - private static List getMemoryPools(LocalMemoryManager localMemoryManager) - { - requireNonNull(localMemoryManager, "localMemoryManager cannot be null"); - ImmutableList.Builder builder = new ImmutableList.Builder<>(); - builder.add(localMemoryManager.getGeneralPool()); - return builder.build(); - } - @PostConstruct public void start() { @@ -141,13 +131,13 @@ public void stop() scheduledFuture = null; } - memoryPools.forEach(memoryPool -> memoryPool.removeListener(memoryPoolListener)); + memoryPool.removeListener(memoryPoolListener); } @VisibleForTesting void registerPoolListeners() { - memoryPools.forEach(memoryPool -> memoryPool.addListener(memoryPoolListener)); + memoryPool.addListener(memoryPoolListener); } private void onMemoryReserved(MemoryPool memoryPool) @@ -190,18 +180,10 @@ private void scheduleRevoking() private synchronized void runMemoryRevoking() { if (checkPending.getAndSet(false)) { - Collection allTasks = null; - for (MemoryPool memoryPool : memoryPools) { - if (!memoryRevokingNeeded(memoryPool)) { - continue; - } - - if (allTasks == null) { - allTasks = requireNonNull(currentTasksSupplier.get()); - } - - requestMemoryRevoking(memoryPool, allTasks); + if (!memoryRevokingNeeded(memoryPool)) { + return; } + requestMemoryRevoking(memoryPool, requireNonNull(currentTasksSupplier.get())); } } @@ -211,7 +193,7 @@ private void requestMemoryRevoking(MemoryPool memoryPool, Collection al List runningTasksInPool = findRunningTasksInMemoryPool(allTasks, memoryPool); remainingBytesToRevoke -= getMemoryAlreadyBeingRevoked(runningTasksInPool, remainingBytesToRevoke); if (remainingBytesToRevoke > 0) { - requestRevoking(memoryPool.getId(), runningTasksInPool, remainingBytesToRevoke); + requestRevoking(runningTasksInPool, remainingBytesToRevoke); } } @@ -256,7 +238,7 @@ public Long mergeResults(List childrenResults) return currentRevoking; } - private void requestRevoking(MemoryPoolId memoryPoolId, List sqlTasks, long remainingBytesToRevoke) + private void requestRevoking(List sqlTasks, long remainingBytesToRevoke) { VoidTraversingQueryContextVisitor visitor = new VoidTraversingQueryContextVisitor<>() { @@ -277,7 +259,7 @@ public Void visitOperatorContext(OperatorContext operatorContext, AtomicLong rem long revokedBytes = operatorContext.requestMemoryRevoking(); if (revokedBytes > 0) { remainingBytesToRevoke.addAndGet(-revokedBytes); - log.debug("memoryPool=%s: requested revoking %s; remaining %s", memoryPoolId, revokedBytes, remainingBytesToRevoke.get()); + log.debug("requested revoking %s; remaining %s", revokedBytes, remainingBytesToRevoke.get()); } } return null; diff --git a/core/trino-main/src/main/java/io/trino/execution/QueryExecution.java b/core/trino-main/src/main/java/io/trino/execution/QueryExecution.java index aa52e399bf1d..a1875cc1ac25 100644 --- a/core/trino-main/src/main/java/io/trino/execution/QueryExecution.java +++ b/core/trino-main/src/main/java/io/trino/execution/QueryExecution.java @@ -22,7 +22,6 @@ import io.trino.execution.QueryTracker.TrackedQuery; import io.trino.execution.StateMachine.StateChangeListener; import io.trino.execution.warnings.WarningCollector; -import io.trino.memory.VersionedMemoryPoolId; import io.trino.server.BasicQueryInfo; import io.trino.server.protocol.Slug; import io.trino.spi.type.Type; @@ -62,10 +61,6 @@ public interface QueryExecution DataSize getTotalMemoryReservation(); - VersionedMemoryPoolId getMemoryPool(); - - void setMemoryPool(VersionedMemoryPoolId poolId); - void start(); void cancelQuery(); diff --git a/core/trino-main/src/main/java/io/trino/execution/QueryInfo.java b/core/trino-main/src/main/java/io/trino/execution/QueryInfo.java index 6e550cb74835..91e37e95fc65 100644 --- a/core/trino-main/src/main/java/io/trino/execution/QueryInfo.java +++ b/core/trino-main/src/main/java/io/trino/execution/QueryInfo.java @@ -25,7 +25,6 @@ import io.trino.spi.TrinoWarning; import io.trino.spi.eventlistener.RoutineInfo; import io.trino.spi.eventlistener.TableInfo; -import io.trino.spi.memory.MemoryPoolId; import io.trino.spi.resourcegroups.QueryType; import io.trino.spi.resourcegroups.ResourceGroupId; import io.trino.spi.security.SelectedRole; @@ -51,7 +50,6 @@ public class QueryInfo private final QueryId queryId; private final SessionRepresentation session; private final QueryState state; - private final MemoryPoolId memoryPool; private final boolean scheduled; private final URI self; private final List fieldNames; @@ -87,7 +85,6 @@ public QueryInfo( @JsonProperty("queryId") QueryId queryId, @JsonProperty("session") SessionRepresentation session, @JsonProperty("state") QueryState state, - @JsonProperty("memoryPool") MemoryPoolId memoryPool, @JsonProperty("scheduled") boolean scheduled, @JsonProperty("self") URI self, @JsonProperty("fieldNames") List fieldNames, @@ -145,7 +142,6 @@ public QueryInfo( this.queryId = queryId; this.session = session; this.state = state; - this.memoryPool = requireNonNull(memoryPool, "memoryPool is null"); this.scheduled = scheduled; this.self = self; this.fieldNames = ImmutableList.copyOf(fieldNames); @@ -195,12 +191,6 @@ public QueryState getState() return state; } - @JsonProperty - public MemoryPoolId getMemoryPool() - { - return memoryPool; - } - @JsonProperty public boolean isScheduled() { diff --git a/core/trino-main/src/main/java/io/trino/execution/QueryStateMachine.java b/core/trino-main/src/main/java/io/trino/execution/QueryStateMachine.java index 9b7a01b93d8f..12edc2096b2c 100644 --- a/core/trino-main/src/main/java/io/trino/execution/QueryStateMachine.java +++ b/core/trino-main/src/main/java/io/trino/execution/QueryStateMachine.java @@ -28,7 +28,6 @@ import io.trino.execution.QueryExecution.QueryOutputInfo; import io.trino.execution.StateMachine.StateChangeListener; import io.trino.execution.warnings.WarningCollector; -import io.trino.memory.VersionedMemoryPoolId; import io.trino.metadata.Metadata; import io.trino.operator.BlockedReason; import io.trino.operator.OperatorStats; @@ -89,7 +88,6 @@ import static io.trino.execution.QueryState.TERMINAL_QUERY_STATES; import static io.trino.execution.QueryState.WAITING_FOR_RESOURCES; import static io.trino.execution.StageInfo.getAllStages; -import static io.trino.memory.LocalMemoryManager.GENERAL_POOL; import static io.trino.server.DynamicFilterService.DynamicFiltersStats; import static io.trino.spi.StandardErrorCode.NOT_FOUND; import static io.trino.spi.StandardErrorCode.USER_CANCELED; @@ -112,8 +110,6 @@ public class QueryStateMachine private final Metadata metadata; private final QueryOutputManager outputManager; - private final AtomicReference memoryPool = new AtomicReference<>(new VersionedMemoryPoolId(GENERAL_POOL, 0)); - private final AtomicLong currentUserMemory = new AtomicLong(); private final AtomicLong peakUserMemory = new AtomicLong(); @@ -403,7 +399,6 @@ public BasicQueryInfo getBasicQueryInfo(Optional rootStage) session.toSessionRepresentation(), Optional.of(resourceGroup), state, - memoryPool.get().getId(), stageStats.isScheduled(), self, query, @@ -440,7 +435,6 @@ QueryInfo getQueryInfo(Optional rootStage) queryId, session.toSessionRepresentation(), state, - memoryPool.get().getId(), isScheduled, self, outputManager.getQueryOutputInfo().map(QueryOutputInfo::getColumnNames).orElse(ImmutableList.of()), @@ -638,16 +632,6 @@ private QueryStats getQueryStats(Optional rootStage) operatorStatsSummary.build()); } - public VersionedMemoryPoolId getMemoryPool() - { - return memoryPool.get(); - } - - public void setMemoryPool(VersionedMemoryPoolId memoryPool) - { - this.memoryPool.set(requireNonNull(memoryPool, "memoryPool is null")); - } - public void addOutputInfoListener(Consumer listener) { outputManager.addOutputInfoListener(listener); @@ -1105,7 +1089,6 @@ public void pruneQueryInfo() queryInfo.getQueryId(), queryInfo.getSession(), queryInfo.getState(), - getMemoryPool().getId(), queryInfo.isScheduled(), queryInfo.getSelf(), queryInfo.getFieldNames(), diff --git a/core/trino-main/src/main/java/io/trino/execution/SqlQueryExecution.java b/core/trino-main/src/main/java/io/trino/execution/SqlQueryExecution.java index 9e4e9ceafee7..2e51b7cd00ea 100644 --- a/core/trino-main/src/main/java/io/trino/execution/SqlQueryExecution.java +++ b/core/trino-main/src/main/java/io/trino/execution/SqlQueryExecution.java @@ -33,7 +33,6 @@ import io.trino.execution.scheduler.policy.ExecutionPolicy; import io.trino.execution.warnings.WarningCollector; import io.trino.failuredetector.FailureDetector; -import io.trino.memory.VersionedMemoryPoolId; import io.trino.metadata.TableHandle; import io.trino.operator.ForScheduler; import io.trino.server.BasicQueryInfo; @@ -276,18 +275,6 @@ public Slug getSlug() return slug; } - @Override - public VersionedMemoryPoolId getMemoryPool() - { - return stateMachine.getMemoryPool(); - } - - @Override - public void setMemoryPool(VersionedMemoryPoolId poolId) - { - stateMachine.setMemoryPool(poolId); - } - @Override public DataSize getUserMemoryReservation() { diff --git a/core/trino-main/src/main/java/io/trino/execution/SqlTaskManager.java b/core/trino-main/src/main/java/io/trino/execution/SqlTaskManager.java index c864b3f24b30..a53eb2ee3899 100644 --- a/core/trino-main/src/main/java/io/trino/execution/SqlTaskManager.java +++ b/core/trino-main/src/main/java/io/trino/execution/SqlTaskManager.java @@ -180,7 +180,7 @@ private QueryContext createQueryContext( queryId, maxQueryUserMemoryPerNode, maxQueryMemoryPerTask, - localMemoryManager.getGeneralPool(), + localMemoryManager.getMemoryPool(), gcMonitor, taskNotificationExecutor, driverYieldExecutor, diff --git a/core/trino-main/src/main/java/io/trino/memory/ClusterMemoryLeakDetector.java b/core/trino-main/src/main/java/io/trino/memory/ClusterMemoryLeakDetector.java index d0d19abed1fa..5ca46639a185 100644 --- a/core/trino-main/src/main/java/io/trino/memory/ClusterMemoryLeakDetector.java +++ b/core/trino-main/src/main/java/io/trino/memory/ClusterMemoryLeakDetector.java @@ -49,7 +49,7 @@ public class ClusterMemoryLeakDetector /** * @param queryInfoSupplier All queries that the coordinator knows about. - * @param queryMemoryReservations The memory reservations of queries in the GENERAL cluster memory pool. + * @param queryMemoryReservations The memory reservations of queries in the cluster memory pool. */ void checkForMemoryLeaks(Supplier> queryInfoSupplier, Map queryMemoryReservations) { diff --git a/core/trino-main/src/main/java/io/trino/memory/ClusterMemoryManager.java b/core/trino-main/src/main/java/io/trino/memory/ClusterMemoryManager.java index 11f416a7ad8a..ff3345e05399 100644 --- a/core/trino-main/src/main/java/io/trino/memory/ClusterMemoryManager.java +++ b/core/trino-main/src/main/java/io/trino/memory/ClusterMemoryManager.java @@ -15,8 +15,8 @@ import com.google.common.annotations.VisibleForTesting; import com.google.common.base.Joiner; -import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSet; +import com.google.common.collect.Iterables; import com.google.common.collect.Streams; import com.google.common.io.Closer; import io.airlift.http.client.HttpClient; @@ -36,7 +36,6 @@ import io.trino.spi.QueryId; import io.trino.spi.TrinoException; import io.trino.spi.memory.ClusterMemoryPoolManager; -import io.trino.spi.memory.MemoryPoolId; import io.trino.spi.memory.MemoryPoolInfo; import org.weakref.jmx.JmxException; import org.weakref.jmx.MBeanExporter; @@ -49,7 +48,6 @@ import java.io.IOException; import java.util.ArrayList; import java.util.HashMap; -import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Map.Entry; @@ -75,7 +73,6 @@ import static io.trino.SystemSessionProperties.getQueryMaxMemory; import static io.trino.SystemSessionProperties.getQueryMaxTotalMemory; import static io.trino.SystemSessionProperties.resourceOvercommit; -import static io.trino.memory.LocalMemoryManager.GENERAL_POOL; import static io.trino.metadata.NodeState.ACTIVE; import static io.trino.metadata.NodeState.SHUTTING_DOWN; import static io.trino.spi.StandardErrorCode.CLUSTER_OUT_OF_MEMORY; @@ -87,6 +84,7 @@ public class ClusterMemoryManager implements ClusterMemoryPoolManager { private static final Logger log = Logger.get(ClusterMemoryManager.class); + private static final String EXPORTED_POOL_NAME = "general"; private final ExecutorService listenerExecutor = Executors.newSingleThreadExecutor(); private final ClusterMemoryLeakDetector memoryLeakDetector = new ClusterMemoryLeakDetector(); @@ -110,10 +108,9 @@ public class ClusterMemoryManager private final Map nodes = new HashMap<>(); @GuardedBy("this") - private final Map>> changeListeners = new HashMap<>(); + private final List> changeListeners = new ArrayList<>(); - @GuardedBy("this") - private final Map pools; + private final ClusterMemoryPool pool; @GuardedBy("this") private long lastTimeNotOutOfMemory = System.nanoTime(); @@ -155,45 +152,31 @@ public ClusterMemoryManager( verify(maxQueryMemory.toBytes() <= maxQueryTotalMemory.toBytes(), "maxQueryMemory cannot be greater than maxQueryTotalMemory"); - this.pools = createClusterMemoryPools(); + this.pool = new ClusterMemoryPool(); + exportMemoryPool(); } - private Map createClusterMemoryPools() + private void exportMemoryPool() { - Set memoryPools = new HashSet<>(); - memoryPools.add(GENERAL_POOL); - - ImmutableMap.Builder builder = ImmutableMap.builder(); - for (MemoryPoolId poolId : memoryPools) { - ClusterMemoryPool pool = new ClusterMemoryPool(poolId); - builder.put(poolId, pool); - try { - exporter.exportWithGeneratedName(pool, ClusterMemoryPool.class, poolId.toString()); - } - catch (JmxException e) { - log.error(e, "Error exporting memory pool %s", poolId); - } + try { + exporter.exportWithGeneratedName(pool, ClusterMemoryPool.class, EXPORTED_POOL_NAME); + } + catch (JmxException e) { + log.error(e, "Error exporting memory pool"); } - return builder.buildOrThrow(); } @Override - public synchronized void addChangeListener(MemoryPoolId poolId, Consumer listener) + public synchronized void addChangeListener(Consumer listener) { - verify(memoryPoolExists(poolId), "Memory pool does not exist: %s", poolId); - changeListeners.computeIfAbsent(poolId, id -> new ArrayList<>()).add(listener); - } - - public synchronized boolean memoryPoolExists(MemoryPoolId poolId) - { - return pools.containsKey(poolId); + changeListeners.add(listener); } public synchronized void process(Iterable runningQueries, Supplier> allQueryInfoSupplier) { // TODO revocable memory reservations can also leak and may need to be detected in the future - // We are only concerned about the leaks in general pool. - memoryLeakDetector.checkForMemoryLeaks(allQueryInfoSupplier, pools.get(GENERAL_POOL).getQueryMemoryReservations()); + // We are only concerned about the leaks in the memory pool. + memoryLeakDetector.checkForMemoryLeaks(allQueryInfoSupplier, pool.getQueryMemoryReservations()); boolean outOfMemory = isClusterOutOfMemory(); if (!outOfMemory) { @@ -249,13 +232,7 @@ public synchronized void process(Iterable runningQueries, Suppli } } - Map countByPool = new HashMap<>(); - for (QueryExecution query : runningQueries) { - MemoryPoolId id = query.getMemoryPool().getId(); - countByPool.put(id, countByPool.getOrDefault(id, 0) + 1); - } - - updatePools(countByPool); + updateMemoryPool(Iterables.size(runningQueries)); updateNodes(); } @@ -299,11 +276,11 @@ private boolean isLastKilledQueryGone() return true; } - // pools fields is updated based on nodes field. - // Therefore, if the query is gone from pools field, it should also be gone from nodes field. + // pool fields is updated based on nodes field. + // Therefore, if the query is gone from pool field, it should also be gone from nodes field. // However, since nodes can updated asynchronously, it has the potential of coming back after being gone. // Therefore, even if the query appears to be gone here, it might be back when one inspects nodes later. - return !pools.get(GENERAL_POOL) + return !pool .getQueryMemoryReservations() .containsKey(lastKilledQuery); } @@ -316,10 +293,7 @@ private void logQueryKill(QueryId killedQueryId, List nodes) StringBuilder nodeDescription = new StringBuilder(); nodeDescription.append("Query Kill Decision: Killed ").append(killedQueryId).append("\n"); for (MemoryInfo node : nodes) { - MemoryPoolInfo memoryPoolInfo = node.getPools().get(GENERAL_POOL); - if (memoryPoolInfo == null) { - continue; - } + MemoryPoolInfo memoryPoolInfo = node.getPool(); nodeDescription.append("Query Kill Scenario: "); nodeDescription.append("MaxBytes ").append(memoryPoolInfo.getMaxBytes()).append(' '); nodeDescription.append("FreeBytes ").append(memoryPoolInfo.getFreeBytes() + memoryPoolInfo.getReservedRevocableBytes()).append(' '); @@ -331,26 +305,19 @@ private void logQueryKill(QueryId killedQueryId, List nodes) } @VisibleForTesting - synchronized Map getPools() - { - return ImmutableMap.copyOf(pools); - } - - public synchronized Map getMemoryPoolInfo() + ClusterMemoryPool getPool() { - ImmutableMap.Builder builder = new ImmutableMap.Builder<>(); - pools.forEach((poolId, memoryPool) -> builder.put(poolId, memoryPool.getInfo())); - return builder.buildOrThrow(); + return pool; } - private synchronized boolean isClusterOutOfMemory() + private boolean isClusterOutOfMemory() { - return pools.get(GENERAL_POOL).getBlockedNodes() > 0; + return pool.getBlockedNodes() > 0; } private QueryMemoryInfo createQueryMemoryInfo(QueryExecution query) { - return new QueryMemoryInfo(query.getQueryId(), query.getMemoryPool().getId(), query.getTotalMemoryReservation().toBytes()); + return new QueryMemoryInfo(query.getQueryId(), query.getTotalMemoryReservation().toBytes()); } private long getQueryMemoryReservation(QueryExecution query) @@ -394,7 +361,7 @@ private synchronized void updateNodes() } } - private synchronized void updatePools(Map queryCounts) + private synchronized void updateMemoryPool(int queryCount) { // Update view of cluster memory and pools List nodeMemoryInfos = nodes.values().stream() @@ -409,18 +376,15 @@ private synchronized void updatePools(Map queryCounts) totalAvailableProcessors.set(totalProcessors); long totalClusterMemory = nodeMemoryInfos.stream() - .map(MemoryInfo::getTotalNodeMemory) - .mapToLong(DataSize::toBytes) + .mapToLong(memoryInfo -> memoryInfo.getPool().getMaxBytes()) .sum(); clusterMemoryBytes.set(totalClusterMemory); - for (ClusterMemoryPool pool : pools.values()) { - pool.update(nodeMemoryInfos, queryCounts.getOrDefault(pool.getId(), 0)); - if (changeListeners.containsKey(pool.getId())) { - MemoryPoolInfo info = pool.getInfo(); - for (Consumer listener : changeListeners.get(pool.getId())) { - listenerExecutor.execute(() -> listener.accept(info)); - } + pool.update(nodeMemoryInfos, queryCount); + if (!changeListeners.isEmpty()) { + MemoryPoolInfo info = pool.getInfo(); + for (Consumer listener : changeListeners) { + listenerExecutor.execute(() -> listener.accept(info)); } } } @@ -441,9 +405,7 @@ public synchronized void destroy() throws IOException { try (Closer closer = Closer.create()) { - for (ClusterMemoryPool pool : pools.values()) { - closer.register(() -> exporter.unexportWithGeneratedName(ClusterMemoryPool.class, pool.getId().toString())); - } + closer.register(() -> exporter.unexportWithGeneratedName(ClusterMemoryPool.class, EXPORTED_POOL_NAME)); closer.register(listenerExecutor::shutdownNow); } } diff --git a/core/trino-main/src/main/java/io/trino/memory/ClusterMemoryPool.java b/core/trino-main/src/main/java/io/trino/memory/ClusterMemoryPool.java index 37f50b8c727f..75b4d836c47d 100644 --- a/core/trino-main/src/main/java/io/trino/memory/ClusterMemoryPool.java +++ b/core/trino-main/src/main/java/io/trino/memory/ClusterMemoryPool.java @@ -16,7 +16,6 @@ import com.google.common.collect.ImmutableMap; import io.trino.spi.QueryId; import io.trino.spi.memory.MemoryAllocation; -import io.trino.spi.memory.MemoryPoolId; import io.trino.spi.memory.MemoryPoolInfo; import org.weakref.jmx.Managed; @@ -27,7 +26,6 @@ import java.util.HashMap; import java.util.List; import java.util.Map; -import java.util.Objects; import static com.google.common.base.MoreObjects.toStringHelper; import static java.util.Objects.requireNonNull; @@ -35,8 +33,6 @@ @ThreadSafe public class ClusterMemoryPool { - private final MemoryPoolId id; - @GuardedBy("this") private long totalDistributedBytes; @@ -65,11 +61,6 @@ public class ClusterMemoryPool @GuardedBy("this") private final Map queryMemoryRevocableReservations = new HashMap<>(); - public ClusterMemoryPool(MemoryPoolId id) - { - this.id = requireNonNull(id, "id is null"); - } - public synchronized MemoryPoolInfo getInfo() { return new MemoryPoolInfo( @@ -81,11 +72,6 @@ public synchronized MemoryPoolInfo getInfo() ImmutableMap.copyOf(queryMemoryRevocableReservations)); } - public MemoryPoolId getId() - { - return id; - } - @Managed public synchronized long getTotalDistributedBytes() { @@ -151,24 +137,22 @@ public synchronized void update(List memoryInfos, int assignedQuerie this.queryMemoryRevocableReservations.clear(); for (MemoryInfo info : memoryInfos) { - MemoryPoolInfo poolInfo = info.getPools().get(id); - if (poolInfo != null) { - nodes++; - if (poolInfo.getFreeBytes() + poolInfo.getReservedRevocableBytes() <= 0) { - blockedNodes++; - } - totalDistributedBytes += poolInfo.getMaxBytes(); - reservedDistributedBytes += poolInfo.getReservedBytes(); - reservedRevocableDistributedBytes += poolInfo.getReservedRevocableBytes(); - for (Map.Entry entry : poolInfo.getQueryMemoryReservations().entrySet()) { - queryMemoryReservations.merge(entry.getKey(), entry.getValue(), Long::sum); - } - for (Map.Entry> entry : poolInfo.getQueryMemoryAllocations().entrySet()) { - queryMemoryAllocations.merge(entry.getKey(), entry.getValue(), this::mergeQueryAllocations); - } - for (Map.Entry entry : poolInfo.getQueryMemoryRevocableReservations().entrySet()) { - queryMemoryRevocableReservations.merge(entry.getKey(), entry.getValue(), Long::sum); - } + MemoryPoolInfo poolInfo = info.getPool(); + nodes++; + if (poolInfo.getFreeBytes() + poolInfo.getReservedRevocableBytes() <= 0) { + blockedNodes++; + } + totalDistributedBytes += poolInfo.getMaxBytes(); + reservedDistributedBytes += poolInfo.getReservedBytes(); + reservedRevocableDistributedBytes += poolInfo.getReservedRevocableBytes(); + for (Map.Entry entry : poolInfo.getQueryMemoryReservations().entrySet()) { + queryMemoryReservations.merge(entry.getKey(), entry.getValue(), Long::sum); + } + for (Map.Entry> entry : poolInfo.getQueryMemoryAllocations().entrySet()) { + queryMemoryAllocations.merge(entry.getKey(), entry.getValue(), this::mergeQueryAllocations); + } + for (Map.Entry entry : poolInfo.getQueryMemoryRevocableReservations().entrySet()) { + queryMemoryRevocableReservations.merge(entry.getKey(), entry.getValue(), Long::sum); } } } @@ -194,30 +178,10 @@ private List mergeQueryAllocations(List left return new ArrayList<>(mergedAllocations.values()); } - @Override - public boolean equals(Object o) - { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - ClusterMemoryPool that = (ClusterMemoryPool) o; - return Objects.equals(id, that.id); - } - - @Override - public int hashCode() - { - return Objects.hash(id); - } - @Override public synchronized String toString() { return toStringHelper(this) - .add("id", id) .add("totalDistributedBytes", totalDistributedBytes) .add("freeDistributedBytes", getFreeDistributedBytes()) .add("reservedDistributedBytes", reservedDistributedBytes) diff --git a/core/trino-main/src/main/java/io/trino/memory/LocalMemoryManager.java b/core/trino-main/src/main/java/io/trino/memory/LocalMemoryManager.java index d50bf26ecb8a..c93caee240f1 100644 --- a/core/trino-main/src/main/java/io/trino/memory/LocalMemoryManager.java +++ b/core/trino-main/src/main/java/io/trino/memory/LocalMemoryManager.java @@ -14,18 +14,12 @@ package io.trino.memory; import com.google.common.annotations.VisibleForTesting; -import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableMap; import io.airlift.units.DataSize; -import io.trino.spi.memory.MemoryPoolId; -import io.trino.spi.memory.MemoryPoolInfo; import javax.inject.Inject; import java.lang.management.ManagementFactory; import java.lang.management.OperatingSystemMXBean; -import java.util.List; -import java.util.Map; import static com.google.common.base.Verify.verify; import static java.lang.String.format; @@ -33,11 +27,9 @@ public final class LocalMemoryManager { - public static final MemoryPoolId GENERAL_POOL = new MemoryPoolId("general"); private static final OperatingSystemMXBean OPERATING_SYSTEM_MX_BEAN = ManagementFactory.getOperatingSystemMXBean(); - private DataSize maxMemory; - private Map pools; + private final MemoryPool memoryPool; @Inject public LocalMemoryManager(NodeMemoryConfig config) @@ -49,25 +41,17 @@ public LocalMemoryManager(NodeMemoryConfig config) LocalMemoryManager(NodeMemoryConfig config, long availableMemory) { requireNonNull(config, "config is null"); - configureMemoryPools(config, availableMemory); - } - - private void configureMemoryPools(NodeMemoryConfig config, long availableMemory) - { validateHeapHeadroom(config, availableMemory); - maxMemory = DataSize.ofBytes(availableMemory - config.getHeapHeadroom().toBytes()); - ImmutableMap.Builder builder = ImmutableMap.builder(); - long generalPoolSize = maxMemory.toBytes(); - verify(generalPoolSize > 0, "general memory pool size is 0"); - builder.put(GENERAL_POOL, new MemoryPool(GENERAL_POOL, DataSize.ofBytes(generalPoolSize))); - this.pools = builder.buildOrThrow(); + DataSize memoryPoolSize = DataSize.ofBytes(availableMemory - config.getHeapHeadroom().toBytes()); + verify(memoryPoolSize.toBytes() > 0, "memory pool size is 0"); + memoryPool = new MemoryPool(memoryPoolSize); } private void validateHeapHeadroom(NodeMemoryConfig config, long availableMemory) { long maxQueryTotalMemoryPerNode = config.getMaxQueryMemoryPerNode().toBytes(); long heapHeadroom = config.getHeapHeadroom().toBytes(); - // (availableMemory - maxQueryTotalMemoryPerNode) bytes will be available for the general pool and the + // (availableMemory - maxQueryTotalMemoryPerNode) bytes will be available for the memory pool and the // headroom/untracked allocations, so the heapHeadroom cannot be larger than that space. if (heapHeadroom < 0 || heapHeadroom + maxQueryTotalMemoryPerNode > availableMemory) { throw new IllegalArgumentException( @@ -80,20 +64,11 @@ private void validateHeapHeadroom(NodeMemoryConfig config, long availableMemory) public MemoryInfo getInfo() { - ImmutableMap.Builder builder = ImmutableMap.builder(); - for (Map.Entry entry : pools.entrySet()) { - builder.put(entry.getKey(), entry.getValue().getInfo()); - } - return new MemoryInfo(OPERATING_SYSTEM_MX_BEAN.getAvailableProcessors(), maxMemory, builder.buildOrThrow()); - } - - public List getPools() - { - return ImmutableList.copyOf(pools.values()); + return new MemoryInfo(OPERATING_SYSTEM_MX_BEAN.getAvailableProcessors(), memoryPool.getInfo()); } - public MemoryPool getGeneralPool() + public MemoryPool getMemoryPool() { - return pools.get(GENERAL_POOL); + return memoryPool; } } diff --git a/core/trino-main/src/main/java/io/trino/memory/LocalMemoryManagerExporter.java b/core/trino-main/src/main/java/io/trino/memory/LocalMemoryManagerExporter.java index b4ed48060094..bae97eec5063 100644 --- a/core/trino-main/src/main/java/io/trino/memory/LocalMemoryManagerExporter.java +++ b/core/trino-main/src/main/java/io/trino/memory/LocalMemoryManagerExporter.java @@ -18,52 +18,44 @@ import org.weakref.jmx.ObjectNames; import javax.annotation.PreDestroy; -import javax.annotation.concurrent.GuardedBy; import javax.inject.Inject; -import java.util.ArrayList; -import java.util.List; - import static java.util.Objects.requireNonNull; public final class LocalMemoryManagerExporter { + public static final String EXPORTED_POOL_NAME = "general"; private final MBeanExporter exporter; - @GuardedBy("this") - private final List pools = new ArrayList<>(); + private final boolean poolExported; @Inject public LocalMemoryManagerExporter(LocalMemoryManager memoryManager, MBeanExporter exporter) { this.exporter = requireNonNull(exporter, "exporter is null"); - for (MemoryPool pool : memoryManager.getPools()) { - addPool(pool); - } - } - - private synchronized void addPool(MemoryPool pool) - { + boolean poolExportedLocal = false; try { - exporter.exportWithGeneratedName(pool, MemoryPool.class, pool.getId().toString()); - pools.add(pool); + this.exporter.exportWithGeneratedName(memoryManager.getMemoryPool(), MemoryPool.class, EXPORTED_POOL_NAME); + poolExportedLocal = true; } catch (JmxException e) { // ignored } + this.poolExported = poolExportedLocal; } @PreDestroy - public synchronized void destroy() + public void destroy() { - for (MemoryPool pool : pools) { - String objectName = ObjectNames.builder(MemoryPool.class, pool.getId().toString()).build(); - try { - exporter.unexport(objectName); - } - catch (JmxException e) { - // ignored - } + if (!poolExported) { + return; + } + + String objectName = ObjectNames.builder(MemoryPool.class, EXPORTED_POOL_NAME).build(); + try { + exporter.unexport(objectName); + } + catch (JmxException e) { + // ignored } - pools.clear(); } } diff --git a/core/trino-main/src/main/java/io/trino/memory/LowMemoryKiller.java b/core/trino-main/src/main/java/io/trino/memory/LowMemoryKiller.java index 94b0ef5e3dca..12fbde93dd66 100644 --- a/core/trino-main/src/main/java/io/trino/memory/LowMemoryKiller.java +++ b/core/trino-main/src/main/java/io/trino/memory/LowMemoryKiller.java @@ -15,7 +15,6 @@ package io.trino.memory; import io.trino.spi.QueryId; -import io.trino.spi.memory.MemoryPoolId; import java.util.List; import java.util.Optional; @@ -30,13 +29,11 @@ public interface LowMemoryKiller class QueryMemoryInfo { private final QueryId queryId; - private final MemoryPoolId memoryPoolId; private final long memoryReservation; - public QueryMemoryInfo(QueryId queryId, MemoryPoolId memoryPoolId, long memoryReservation) + public QueryMemoryInfo(QueryId queryId, long memoryReservation) { this.queryId = requireNonNull(queryId, "queryId is null"); - this.memoryPoolId = requireNonNull(memoryPoolId, "memoryPoolId is null"); this.memoryReservation = memoryReservation; } @@ -45,11 +42,6 @@ public QueryId getQueryId() return queryId; } - public MemoryPoolId getMemoryPoolId() - { - return memoryPoolId; - } - public long getMemoryReservation() { return memoryReservation; @@ -60,7 +52,6 @@ public String toString() { return toStringHelper(this) .add("queryId", queryId) - .add("memoryPoolId", memoryPoolId) .add("memoryReservation", memoryReservation) .toString(); } diff --git a/core/trino-main/src/main/java/io/trino/memory/MemoryInfo.java b/core/trino-main/src/main/java/io/trino/memory/MemoryInfo.java index 06ac76a8ecef..86d58ce69ef1 100644 --- a/core/trino-main/src/main/java/io/trino/memory/MemoryInfo.java +++ b/core/trino-main/src/main/java/io/trino/memory/MemoryInfo.java @@ -15,31 +15,23 @@ import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; -import com.google.common.collect.ImmutableMap; -import io.airlift.units.DataSize; -import io.trino.spi.memory.MemoryPoolId; import io.trino.spi.memory.MemoryPoolInfo; -import java.util.Map; - import static com.google.common.base.MoreObjects.toStringHelper; import static java.util.Objects.requireNonNull; public class MemoryInfo { private final int availableProcessors; - private final DataSize totalNodeMemory; - private final Map pools; + private final MemoryPoolInfo pool; @JsonCreator public MemoryInfo( @JsonProperty("availableProcessors") int availableProcessors, - @JsonProperty("totalNodeMemory") DataSize totalNodeMemory, - @JsonProperty("pools") Map pools) + @JsonProperty("pool") MemoryPoolInfo pool) { - this.totalNodeMemory = requireNonNull(totalNodeMemory, "totalNodeMemory is null"); - this.pools = ImmutableMap.copyOf(requireNonNull(pools, "pools is null")); this.availableProcessors = availableProcessors; + this.pool = requireNonNull(pool, "pool is null"); } @JsonProperty @@ -49,15 +41,9 @@ public int getAvailableProcessors() } @JsonProperty - public DataSize getTotalNodeMemory() - { - return totalNodeMemory; - } - - @JsonProperty - public Map getPools() + public MemoryPoolInfo getPool() { - return pools; + return pool; } @Override @@ -65,8 +51,7 @@ public String toString() { return toStringHelper(this) .add("availableProcessors", availableProcessors) - .add("totalNodeMemory", totalNodeMemory) - .add("pools", pools) + .add("pool", pool) .toString(); } } diff --git a/core/trino-main/src/main/java/io/trino/memory/MemoryPool.java b/core/trino-main/src/main/java/io/trino/memory/MemoryPool.java index 7d722e057b46..43e05af9e7a2 100644 --- a/core/trino-main/src/main/java/io/trino/memory/MemoryPool.java +++ b/core/trino-main/src/main/java/io/trino/memory/MemoryPool.java @@ -20,7 +20,6 @@ import io.airlift.units.DataSize; import io.trino.spi.QueryId; import io.trino.spi.memory.MemoryAllocation; -import io.trino.spi.memory.MemoryPoolId; import io.trino.spi.memory.MemoryPoolInfo; import org.weakref.jmx.Managed; @@ -37,15 +36,11 @@ import static com.google.common.base.MoreObjects.toStringHelper; import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Preconditions.checkState; -import static com.google.common.util.concurrent.Futures.immediateVoidFuture; import static io.trino.operator.Operator.NOT_BLOCKED; import static java.util.Objects.requireNonNull; public class MemoryPool { - private static final String MOVE_QUERY_TAG = "MOVE_QUERY_OPERATION"; - - private final MemoryPoolId id; private final long maxBytes; @GuardedBy("this") @@ -70,18 +65,12 @@ public class MemoryPool private final List listeners = new CopyOnWriteArrayList<>(); - public MemoryPool(MemoryPoolId id, DataSize size) + public MemoryPool(DataSize size) { - this.id = requireNonNull(id, "id is null"); requireNonNull(size, "size is null"); maxBytes = size.toBytes(); } - public MemoryPoolId getId() - { - return id; - } - public synchronized MemoryPoolInfo getInfo() { Map> memoryAllocations = new HashMap<>(); @@ -241,28 +230,6 @@ public synchronized void freeRevocable(QueryId queryId, long bytes) } } - // When this method returns the MOVE_QUERY_TAG won't be visible in the tagged memory allocations map. - // Because, we remove the tagged allocations from this MemoryPool for queryId, and then we reserve - // N bytes with MOVE_QUERY_TAG in the targetMemoryPool, and then immediately overwrite it - // with a put() call. - synchronized ListenableFuture moveQuery(QueryId queryId, MemoryPool targetMemoryPool) - { - long originalReserved = getQueryMemoryReservation(queryId); - long originalRevocableReserved = getQueryRevocableMemoryReservation(queryId); - // Get the tags before we call free() as that would remove the tags and we will lose the tags. - Map taggedAllocations = taggedMemoryAllocations.remove(queryId); - if (taggedAllocations == null) { - // query is not registered (likely a race with query completion) - return immediateVoidFuture(); - } - ListenableFuture future = targetMemoryPool.reserve(queryId, MOVE_QUERY_TAG, originalReserved); - free(queryId, MOVE_QUERY_TAG, originalReserved); - targetMemoryPool.reserveRevocable(queryId, originalRevocableReserved); - freeRevocable(queryId, originalRevocableReserved); - targetMemoryPool.taggedMemoryAllocations.put(queryId, taggedAllocations); - return future; - } - /** * Returns the number of free bytes. This value may be negative, which indicates that the pool is over-committed. */ @@ -304,7 +271,6 @@ synchronized long getQueryRevocableMemoryReservation(QueryId queryId) public synchronized String toString() { return toStringHelper(this) - .add("id", id) .add("maxBytes", maxBytes) .add("freeBytes", getFreeBytes()) .add("reservedBytes", reservedBytes) diff --git a/core/trino-main/src/main/java/io/trino/memory/MemoryResource.java b/core/trino-main/src/main/java/io/trino/memory/MemoryResource.java index 1eb05afbc444..007287c760df 100644 --- a/core/trino-main/src/main/java/io/trino/memory/MemoryResource.java +++ b/core/trino-main/src/main/java/io/trino/memory/MemoryResource.java @@ -19,16 +19,12 @@ import javax.inject.Inject; import javax.ws.rs.GET; import javax.ws.rs.Path; -import javax.ws.rs.PathParam; import javax.ws.rs.Produces; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; -import static io.trino.memory.LocalMemoryManager.GENERAL_POOL; import static io.trino.server.security.ResourceSecurity.AccessType.INTERNAL_ONLY; -import static io.trino.server.security.ResourceSecurity.AccessType.MANAGEMENT_READ; import static java.util.Objects.requireNonNull; -import static javax.ws.rs.core.Response.Status.NOT_FOUND; /** * Manages memory pools on this worker node @@ -52,18 +48,6 @@ public MemoryInfo getMemoryInfo() return memoryManager.getInfo(); } - @ResourceSecurity(MANAGEMENT_READ) - @GET - @Path("{poolId}") - public Response getMemoryInfo(@PathParam("poolId") String poolId) - { - if (GENERAL_POOL.getId().equals(poolId)) { - return toSuccessfulResponse(memoryManager.getGeneralPool().getInfo()); - } - - return Response.status(NOT_FOUND).build(); - } - private Response toSuccessfulResponse(MemoryPoolInfo memoryInfo) { return Response.ok() diff --git a/core/trino-main/src/main/java/io/trino/memory/QueryContext.java b/core/trino-main/src/main/java/io/trino/memory/QueryContext.java index 8f5f468c4973..3f374de27b57 100644 --- a/core/trino-main/src/main/java/io/trino/memory/QueryContext.java +++ b/core/trino-main/src/main/java/io/trino/memory/QueryContext.java @@ -14,9 +14,7 @@ package io.trino.memory; import com.google.common.annotations.VisibleForTesting; -import com.google.common.collect.ImmutableList; import com.google.common.util.concurrent.ListenableFuture; -import com.google.common.util.concurrent.SettableFuture; import io.airlift.stats.GcMonitor; import io.airlift.units.DataSize; import io.trino.Session; @@ -46,8 +44,6 @@ import static com.google.common.base.Verify.verify; import static com.google.common.base.Verify.verifyNotNull; import static com.google.common.collect.ImmutableMap.toImmutableMap; -import static com.google.common.util.concurrent.MoreExecutors.directExecutor; -import static io.airlift.concurrent.MoreFutures.whenAnyComplete; import static io.airlift.units.DataSize.Unit.MEGABYTE; import static io.airlift.units.DataSize.succinctBytes; import static io.trino.ExceededMemoryLimitException.exceededLocalUserMemoryLimit; @@ -73,8 +69,6 @@ public class QueryContext private final SpillSpaceTracker spillSpaceTracker; private final Map taskContexts = new ConcurrentHashMap<>(); - @GuardedBy("this") - private boolean resourceOverCommit; private volatile boolean memoryLimitsInitialized; // TODO: This field should be final. However, due to the way QueryContext is constructed the memory limit is not known in advance @@ -84,12 +78,7 @@ public class QueryContext private Optional maxTaskMemory; private final MemoryTrackingContext queryMemoryContext; - - @GuardedBy("this") - private MemoryPool memoryPool; - // TODO: remove after https://github.com/trinodb/trino/issues/6677 is done - @GuardedBy("this") - private SettableFuture memoryPoolMoveFuture = SettableFuture.create(); + private final MemoryPool memoryPool; @GuardedBy("this") private long spillUsed; @@ -153,7 +142,6 @@ public boolean isMemoryLimitsInitialized() public synchronized void initializeMemoryLimits(boolean resourceOverCommit, long maxUserMemory, Optional maxTaskMemory) { checkArgument(maxUserMemory >= 0, "maxUserMemory must be >= 0, found: %s", maxUserMemory); - this.resourceOverCommit = resourceOverCommit; if (resourceOverCommit) { // Allow the query to use the entire pool. This way the worker will kill the query, if it uses the entire local memory pool. // The coordinator will kill the query if the cluster runs out of memory. @@ -193,7 +181,7 @@ private synchronized ListenableFuture updateUserMemory(String allocationTa return NOT_BLOCKED; } - return whenAnyComplete(ImmutableList.of(future, memoryPoolMoveFuture)); + return future; } memoryPool.free(queryId, allocationTag, -delta); return NOT_BLOCKED; @@ -208,7 +196,7 @@ private synchronized ListenableFuture updateRevocableMemory(String allocat return NOT_BLOCKED; } - return whenAnyComplete(ImmutableList.of(future, memoryPoolMoveFuture)); + return future; } memoryPool.freeRevocable(queryId, -delta); return NOT_BLOCKED; @@ -250,42 +238,6 @@ public synchronized void freeSpill(long bytes) spillSpaceTracker.free(bytes); } - public synchronized void setMemoryPool(MemoryPool newMemoryPool) - { - // This method first acquires the monitor of this instance. - // After that in this method if we acquire the monitors of the - // user/revocable memory contexts in the queryMemoryContext instance - // (say, by calling queryMemoryContext.getUserMemory()) it's possible - // to have a deadlock. Because, the driver threads running the operators - // will allocate memory concurrently through the child memory context -> ... -> - // root memory context -> this.updateUserMemory() calls, and will acquire - // the monitors of the user/revocable memory contexts in the queryMemoryContext instance - // first, and then the monitor of this, which may cause deadlocks. - // That's why instead of calling methods on queryMemoryContext to get the - // user/revocable memory reservations, we call the MemoryPool to get the same - // information. - requireNonNull(newMemoryPool, "newMemoryPool is null"); - if (memoryPool == newMemoryPool) { - // Don't unblock our tasks and thrash the pools, if this is a no-op - return; - } - ListenableFuture future = memoryPool.moveQuery(queryId, newMemoryPool); - memoryPool = newMemoryPool; - if (resourceOverCommit) { - // Reset the memory limits based on the new pool assignment - maxUserMemory = memoryPool.getMaxBytes(); - } - - // Create a new move future for allocations in new memory pool - SettableFuture oldPoolMoveFuture = this.memoryPoolMoveFuture; - this.memoryPoolMoveFuture = SettableFuture.create(); - - future.addListener(() -> { - // Unblock allocations in old memory pool as all memory is now accounted for in new pool - oldPoolMoveFuture.set(null); - }, directExecutor()); - } - public synchronized MemoryPool getMemoryPool() { return memoryPool; diff --git a/core/trino-main/src/main/java/io/trino/memory/TotalReservationLowMemoryKiller.java b/core/trino-main/src/main/java/io/trino/memory/TotalReservationLowMemoryKiller.java index 9f4535459d18..895e3342b3be 100644 --- a/core/trino-main/src/main/java/io/trino/memory/TotalReservationLowMemoryKiller.java +++ b/core/trino-main/src/main/java/io/trino/memory/TotalReservationLowMemoryKiller.java @@ -19,8 +19,6 @@ import java.util.List; import java.util.Optional; -import static io.trino.memory.LocalMemoryManager.GENERAL_POOL; - public class TotalReservationLowMemoryKiller implements LowMemoryKiller { @@ -31,7 +29,7 @@ public Optional chooseQueryToKill(List runningQueries, long maxMemory = 0; for (QueryMemoryInfo query : runningQueries) { long bytesUsed = query.getMemoryReservation(); - if (bytesUsed > maxMemory && GENERAL_POOL.equals(query.getMemoryPoolId())) { + if (bytesUsed > maxMemory) { biggestQuery = query.getQueryId(); maxMemory = bytesUsed; } diff --git a/core/trino-main/src/main/java/io/trino/memory/TotalReservationOnBlockedNodesLowMemoryKiller.java b/core/trino-main/src/main/java/io/trino/memory/TotalReservationOnBlockedNodesLowMemoryKiller.java index 9f1edc19b0b4..d5eb81fa5d9e 100644 --- a/core/trino-main/src/main/java/io/trino/memory/TotalReservationOnBlockedNodesLowMemoryKiller.java +++ b/core/trino-main/src/main/java/io/trino/memory/TotalReservationOnBlockedNodesLowMemoryKiller.java @@ -22,7 +22,6 @@ import java.util.Map; import java.util.Optional; -import static io.trino.memory.LocalMemoryManager.GENERAL_POOL; import static java.util.Comparator.comparingLong; public class TotalReservationOnBlockedNodesLowMemoryKiller @@ -33,14 +32,14 @@ public Optional chooseQueryToKill(List runningQueries, { Map memoryReservationOnBlockedNodes = new HashMap<>(); for (MemoryInfo node : nodes) { - MemoryPoolInfo generalPool = node.getPools().get(GENERAL_POOL); - if (generalPool == null) { + MemoryPoolInfo memoryPool = node.getPool(); + if (memoryPool == null) { continue; } - if (generalPool.getFreeBytes() + generalPool.getReservedRevocableBytes() > 0) { + if (memoryPool.getFreeBytes() + memoryPool.getReservedRevocableBytes() > 0) { continue; } - Map queryMemoryReservations = generalPool.getQueryMemoryReservations(); + Map queryMemoryReservations = memoryPool.getQueryMemoryReservations(); queryMemoryReservations.forEach((queryId, memoryReservation) -> { memoryReservationOnBlockedNodes.compute(queryId, (id, oldValue) -> oldValue == null ? memoryReservation : oldValue + memoryReservation); }); diff --git a/core/trino-main/src/main/java/io/trino/memory/VersionedMemoryPoolId.java b/core/trino-main/src/main/java/io/trino/memory/VersionedMemoryPoolId.java deleted file mode 100644 index 4d2e62f0ee07..000000000000 --- a/core/trino-main/src/main/java/io/trino/memory/VersionedMemoryPoolId.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.trino.memory; - -import io.trino.spi.memory.MemoryPoolId; - -import static com.google.common.base.MoreObjects.toStringHelper; -import static java.util.Objects.requireNonNull; - -public class VersionedMemoryPoolId -{ - private final MemoryPoolId id; - private final long version; - - public VersionedMemoryPoolId(MemoryPoolId id, long version) - { - this.id = requireNonNull(id, "id is null"); - this.version = version; - } - - public MemoryPoolId getId() - { - return id; - } - - public long getVersion() - { - return version; - } - - @Override - public String toString() - { - return toStringHelper(this) - .add("id", id) - .add("version", version) - .toString(); - } -} diff --git a/core/trino-main/src/main/java/io/trino/server/BasicQueryInfo.java b/core/trino-main/src/main/java/io/trino/server/BasicQueryInfo.java index e3f3725e5c0e..1bd034e26a97 100644 --- a/core/trino-main/src/main/java/io/trino/server/BasicQueryInfo.java +++ b/core/trino-main/src/main/java/io/trino/server/BasicQueryInfo.java @@ -21,7 +21,6 @@ import io.trino.spi.ErrorCode; import io.trino.spi.ErrorType; import io.trino.spi.QueryId; -import io.trino.spi.memory.MemoryPoolId; import io.trino.spi.resourcegroups.QueryType; import io.trino.spi.resourcegroups.ResourceGroupId; @@ -45,7 +44,6 @@ public class BasicQueryInfo private final SessionRepresentation session; private final Optional resourceGroupId; private final QueryState state; - private final MemoryPoolId memoryPool; private final boolean scheduled; private final URI self; private final String query; @@ -62,7 +60,6 @@ public BasicQueryInfo( @JsonProperty("session") SessionRepresentation session, @JsonProperty("resourceGroupId") Optional resourceGroupId, @JsonProperty("state") QueryState state, - @JsonProperty("memoryPool") MemoryPoolId memoryPool, @JsonProperty("scheduled") boolean scheduled, @JsonProperty("self") URI self, @JsonProperty("query") String query, @@ -77,7 +74,6 @@ public BasicQueryInfo( this.session = requireNonNull(session, "session is null"); this.resourceGroupId = requireNonNull(resourceGroupId, "resourceGroupId is null"); this.state = requireNonNull(state, "state is null"); - this.memoryPool = memoryPool; this.errorType = errorType; this.errorCode = errorCode; this.scheduled = scheduled; @@ -95,7 +91,6 @@ public BasicQueryInfo(QueryInfo queryInfo) queryInfo.getSession(), queryInfo.getResourceGroupId(), queryInfo.getState(), - queryInfo.getMemoryPool(), queryInfo.isScheduled(), queryInfo.getSelf(), queryInfo.getQuery(), @@ -131,12 +126,6 @@ public QueryState getState() return state; } - @JsonProperty - public MemoryPoolId getMemoryPool() - { - return memoryPool; - } - @JsonProperty public boolean isScheduled() { diff --git a/core/trino-main/src/main/java/io/trino/server/ui/TrimmedBasicQueryInfo.java b/core/trino-main/src/main/java/io/trino/server/ui/TrimmedBasicQueryInfo.java index 27ede974aa81..ec0b2dae6d93 100644 --- a/core/trino-main/src/main/java/io/trino/server/ui/TrimmedBasicQueryInfo.java +++ b/core/trino-main/src/main/java/io/trino/server/ui/TrimmedBasicQueryInfo.java @@ -20,7 +20,6 @@ import io.trino.spi.ErrorCode; import io.trino.spi.ErrorType; import io.trino.spi.QueryId; -import io.trino.spi.memory.MemoryPoolId; import io.trino.spi.resourcegroups.QueryType; import io.trino.spi.resourcegroups.ResourceGroupId; @@ -43,7 +42,6 @@ public class TrimmedBasicQueryInfo private final Optional sessionSource; private final Optional resourceGroupId; private final QueryState state; - private final MemoryPoolId memoryPool; private final boolean scheduled; private final URI self; private final String queryTextPreview; @@ -62,7 +60,6 @@ public TrimmedBasicQueryInfo(BasicQueryInfo queryInfo) this.sessionSource = requireNonNull(queryInfo.getSession().getSource(), "source is null"); this.resourceGroupId = requireNonNull(queryInfo.getResourceGroupId(), "resourceGroupId is null"); this.state = requireNonNull(queryInfo.getState(), "state is null"); - this.memoryPool = requireNonNull(queryInfo.getMemoryPool(), "memoryPool is null"); this.errorType = Optional.ofNullable(queryInfo.getErrorType()); this.errorCode = Optional.ofNullable(queryInfo.getErrorCode()); this.scheduled = queryInfo.isScheduled(); @@ -116,12 +113,6 @@ public QueryState getState() return state; } - @JsonProperty - public MemoryPoolId getMemoryPool() - { - return memoryPool; - } - @JsonProperty public boolean isScheduled() { diff --git a/core/trino-main/src/main/java/io/trino/testing/TestingTaskContext.java b/core/trino-main/src/main/java/io/trino/testing/TestingTaskContext.java index 2fb813563961..6d3b33162a9e 100644 --- a/core/trino-main/src/main/java/io/trino/testing/TestingTaskContext.java +++ b/core/trino-main/src/main/java/io/trino/testing/TestingTaskContext.java @@ -24,7 +24,6 @@ import io.trino.memory.QueryContext; import io.trino.operator.TaskContext; import io.trino.spi.QueryId; -import io.trino.spi.memory.MemoryPoolId; import io.trino.spiller.SpillSpaceTracker; import java.util.Optional; @@ -138,7 +137,7 @@ public Builder setQueryId(QueryId queryId) public TaskContext build() { - MemoryPool memoryPool = new MemoryPool(new MemoryPoolId("test"), memoryPoolSize); + MemoryPool memoryPool = new MemoryPool(memoryPoolSize); SpillSpaceTracker spillSpaceTracker = new SpillSpaceTracker(maxSpillSize); QueryContext queryContext = new QueryContext( queryId, diff --git a/core/trino-main/src/main/resources/webapp/dist/query.js b/core/trino-main/src/main/resources/webapp/dist/query.js index b7ba760701b0..046421e4f171 100644 --- a/core/trino-main/src/main/resources/webapp/dist/query.js +++ b/core/trino-main/src/main/resources/webapp/dist/query.js @@ -106,7 +106,7 @@ eval("\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n}); /***/ (function(module, exports, __webpack_require__) { "use strict"; -eval("\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\nexports.QueryDetail = undefined;\n\nvar _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if (\"value\" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();\n\nvar _react = __webpack_require__(/*! react */ \"./node_modules/react/index.js\");\n\nvar _react2 = _interopRequireDefault(_react);\n\nvar _reactable = __webpack_require__(/*! reactable */ \"./node_modules/reactable/lib/reactable.js\");\n\nvar _reactable2 = _interopRequireDefault(_reactable);\n\nvar _utils = __webpack_require__(/*! ../utils */ \"./utils.js\");\n\nvar _QueryHeader = __webpack_require__(/*! ./QueryHeader */ \"./components/QueryHeader.jsx\");\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\nfunction _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError(\"Cannot call a class as a function\"); } }\n\nfunction _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); } return call && (typeof call === \"object\" || typeof call === \"function\") ? call : self; }\n\nfunction _inherits(subClass, superClass) { if (typeof superClass !== \"function\" && superClass !== null) { throw new TypeError(\"Super expression must either be null or a function, not \" + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } /*\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nvar Table = _reactable2.default.Table,\n Thead = _reactable2.default.Thead,\n Th = _reactable2.default.Th,\n Tr = _reactable2.default.Tr,\n Td = _reactable2.default.Td;\n\nvar TaskList = function (_React$Component) {\n _inherits(TaskList, _React$Component);\n\n function TaskList() {\n _classCallCheck(this, TaskList);\n\n return _possibleConstructorReturn(this, (TaskList.__proto__ || Object.getPrototypeOf(TaskList)).apply(this, arguments));\n }\n\n _createClass(TaskList, [{\n key: \"render\",\n value: function render() {\n var tasks = this.props.tasks;\n\n if (tasks === undefined || tasks.length === 0) {\n return _react2.default.createElement(\n \"div\",\n { className: \"row error-message\" },\n _react2.default.createElement(\n \"div\",\n { className: \"col-xs-12\" },\n _react2.default.createElement(\n \"h4\",\n null,\n \"No threads in the selected group\"\n )\n )\n );\n }\n\n var showPortNumbers = TaskList.showPortNumbers(tasks);\n\n var renderedTasks = tasks.map(function (task) {\n var elapsedTime = (0, _utils.parseDuration)(task.stats.elapsedTime);\n if (elapsedTime === 0) {\n elapsedTime = Date.now() - Date.parse(task.stats.createTime);\n }\n\n return _react2.default.createElement(\n Tr,\n { key: task.taskStatus.taskId },\n _react2.default.createElement(\n Td,\n { column: \"id\", value: task.taskStatus.taskId },\n _react2.default.createElement(\n \"a\",\n { href: \"/ui/api/worker/\" + task.taskStatus.nodeId + \"/task/\" + task.taskStatus.taskId + \"?pretty\" },\n (0, _utils.getTaskIdSuffix)(task.taskStatus.taskId)\n )\n ),\n _react2.default.createElement(\n Td,\n { column: \"host\", value: (0, _utils.getHostname)(task.taskStatus.self) },\n _react2.default.createElement(\n \"a\",\n { href: \"worker.html?\" + task.taskStatus.nodeId, className: \"font-light\", target: \"_blank\" },\n showPortNumbers ? (0, _utils.getHostAndPort)(task.taskStatus.self) : (0, _utils.getHostname)(task.taskStatus.self)\n )\n ),\n _react2.default.createElement(\n Td,\n { column: \"state\", value: TaskList.formatState(task.taskStatus.state, task.stats.fullyBlocked) },\n TaskList.formatState(task.taskStatus.state, task.stats.fullyBlocked)\n ),\n _react2.default.createElement(\n Td,\n { column: \"rows\", value: task.stats.rawInputPositions },\n (0, _utils.formatCount)(task.stats.rawInputPositions)\n ),\n _react2.default.createElement(\n Td,\n { column: \"rowsSec\", value: (0, _utils.computeRate)(task.stats.rawInputPositions, elapsedTime) },\n (0, _utils.formatCount)((0, _utils.computeRate)(task.stats.rawInputPositions, elapsedTime))\n ),\n _react2.default.createElement(\n Td,\n { column: \"bytes\", value: (0, _utils.parseDataSize)(task.stats.rawInputDataSize) },\n (0, _utils.formatDataSizeBytes)((0, _utils.parseDataSize)(task.stats.rawInputDataSize))\n ),\n _react2.default.createElement(\n Td,\n { column: \"bytesSec\", value: (0, _utils.computeRate)((0, _utils.parseDataSize)(task.stats.rawInputDataSize), elapsedTime) },\n (0, _utils.formatDataSizeBytes)((0, _utils.computeRate)((0, _utils.parseDataSize)(task.stats.rawInputDataSize), elapsedTime))\n ),\n _react2.default.createElement(\n Td,\n { column: \"splitsPending\", value: task.stats.queuedDrivers },\n task.stats.queuedDrivers\n ),\n _react2.default.createElement(\n Td,\n { column: \"splitsRunning\", value: task.stats.runningDrivers },\n task.stats.runningDrivers\n ),\n _react2.default.createElement(\n Td,\n { column: \"splitsBlocked\", value: task.stats.blockedDrivers },\n task.stats.blockedDrivers\n ),\n _react2.default.createElement(\n Td,\n { column: \"splitsDone\", value: task.stats.completedDrivers },\n task.stats.completedDrivers\n ),\n _react2.default.createElement(\n Td,\n { column: \"elapsedTime\", value: (0, _utils.parseDuration)(task.stats.elapsedTime) },\n task.stats.elapsedTime\n ),\n _react2.default.createElement(\n Td,\n { column: \"cpuTime\", value: (0, _utils.parseDuration)(task.stats.totalCpuTime) },\n task.stats.totalCpuTime\n ),\n _react2.default.createElement(\n Td,\n { column: \"bufferedBytes\", value: task.outputBuffers.totalBufferedBytes },\n (0, _utils.formatDataSizeBytes)(task.outputBuffers.totalBufferedBytes)\n )\n );\n });\n\n return _react2.default.createElement(\n Table,\n { id: \"tasks\", className: \"table table-striped sortable\", sortable: [{\n column: 'id',\n sortFunction: TaskList.compareTaskId\n }, 'host', 'state', 'splitsPending', 'splitsRunning', 'splitsBlocked', 'splitsDone', 'rows', 'rowsSec', 'bytes', 'bytesSec', 'elapsedTime', 'cpuTime', 'bufferedBytes'],\n defaultSort: { column: 'id', direction: 'asc' } },\n _react2.default.createElement(\n Thead,\n null,\n _react2.default.createElement(\n Th,\n { column: \"id\" },\n \"ID\"\n ),\n _react2.default.createElement(\n Th,\n { column: \"host\" },\n \"Host\"\n ),\n _react2.default.createElement(\n Th,\n { column: \"state\" },\n \"State\"\n ),\n _react2.default.createElement(\n Th,\n { column: \"splitsPending\" },\n _react2.default.createElement(\"span\", { className: \"glyphicon glyphicon-pause\", style: _utils.GLYPHICON_HIGHLIGHT, \"data-toggle\": \"tooltip\", \"data-placement\": \"top\",\n title: \"Pending splits\" })\n ),\n _react2.default.createElement(\n Th,\n { column: \"splitsRunning\" },\n _react2.default.createElement(\"span\", { className: \"glyphicon glyphicon-play\", style: _utils.GLYPHICON_HIGHLIGHT, \"data-toggle\": \"tooltip\", \"data-placement\": \"top\",\n title: \"Running splits\" })\n ),\n _react2.default.createElement(\n Th,\n { column: \"splitsBlocked\" },\n _react2.default.createElement(\"span\", { className: \"glyphicon glyphicon-bookmark\", style: _utils.GLYPHICON_HIGHLIGHT, \"data-toggle\": \"tooltip\", \"data-placement\": \"top\",\n title: \"Blocked splits\" })\n ),\n _react2.default.createElement(\n Th,\n { column: \"splitsDone\" },\n _react2.default.createElement(\"span\", { className: \"glyphicon glyphicon-ok\", style: _utils.GLYPHICON_HIGHLIGHT, \"data-toggle\": \"tooltip\", \"data-placement\": \"top\",\n title: \"Completed splits\" })\n ),\n _react2.default.createElement(\n Th,\n { column: \"rows\" },\n \"Rows\"\n ),\n _react2.default.createElement(\n Th,\n { column: \"rowsSec\" },\n \"Rows/s\"\n ),\n _react2.default.createElement(\n Th,\n { column: \"bytes\" },\n \"Bytes\"\n ),\n _react2.default.createElement(\n Th,\n { column: \"bytesSec\" },\n \"Bytes/s\"\n ),\n _react2.default.createElement(\n Th,\n { column: \"elapsedTime\" },\n \"Elapsed\"\n ),\n _react2.default.createElement(\n Th,\n { column: \"cpuTime\" },\n \"CPU Time\"\n ),\n _react2.default.createElement(\n Th,\n { column: \"bufferedBytes\" },\n \"Buffered\"\n )\n ),\n renderedTasks\n );\n }\n }], [{\n key: \"removeQueryId\",\n value: function removeQueryId(id) {\n var pos = id.indexOf('.');\n if (pos !== -1) {\n return id.substring(pos + 1);\n }\n return id;\n }\n }, {\n key: \"compareTaskId\",\n value: function compareTaskId(taskA, taskB) {\n var taskIdArrA = TaskList.removeQueryId(taskA).split(\".\");\n var taskIdArrB = TaskList.removeQueryId(taskB).split(\".\");\n\n if (taskIdArrA.length > taskIdArrB.length) {\n return 1;\n }\n for (var i = 0; i < taskIdArrA.length; i++) {\n var anum = Number.parseInt(taskIdArrA[i]);\n var bnum = Number.parseInt(taskIdArrB[i]);\n if (anum !== bnum) {\n return anum > bnum ? 1 : -1;\n }\n }\n\n return 0;\n }\n }, {\n key: \"showPortNumbers\",\n value: function showPortNumbers(tasks) {\n // check if any host has multiple port numbers\n var hostToPortNumber = {};\n for (var i = 0; i < tasks.length; i++) {\n var taskUri = tasks[i].taskStatus.self;\n var hostname = (0, _utils.getHostname)(taskUri);\n var port = (0, _utils.getPort)(taskUri);\n if (hostname in hostToPortNumber && hostToPortNumber[hostname] !== port) {\n return true;\n }\n hostToPortNumber[hostname] = port;\n }\n\n return false;\n }\n }, {\n key: \"formatState\",\n value: function formatState(state, fullyBlocked) {\n if (fullyBlocked && state === \"RUNNING\") {\n return \"BLOCKED\";\n } else {\n return state;\n }\n }\n }]);\n\n return TaskList;\n}(_react2.default.Component);\n\nvar BAR_CHART_WIDTH = 800;\n\nvar BAR_CHART_PROPERTIES = {\n type: 'bar',\n barSpacing: '0',\n height: '80px',\n barColor: '#747F96',\n zeroColor: '#8997B3',\n chartRangeMin: 0,\n tooltipClassname: 'sparkline-tooltip',\n tooltipFormat: 'Task {{offset:offset}} - {{value}}',\n disableHiddenCheck: true\n};\n\nvar HISTOGRAM_WIDTH = 175;\n\nvar HISTOGRAM_PROPERTIES = {\n type: 'bar',\n barSpacing: '0',\n height: '80px',\n barColor: '#747F96',\n zeroColor: '#747F96',\n zeroAxis: true,\n chartRangeMin: 0,\n tooltipClassname: 'sparkline-tooltip',\n tooltipFormat: '{{offset:offset}} -- {{value}} tasks',\n disableHiddenCheck: true\n};\n\nvar StageSummary = function (_React$Component2) {\n _inherits(StageSummary, _React$Component2);\n\n function StageSummary(props) {\n _classCallCheck(this, StageSummary);\n\n var _this2 = _possibleConstructorReturn(this, (StageSummary.__proto__ || Object.getPrototypeOf(StageSummary)).call(this, props));\n\n _this2.state = {\n expanded: false,\n lastRender: null\n };\n return _this2;\n }\n\n _createClass(StageSummary, [{\n key: \"getExpandedIcon\",\n value: function getExpandedIcon() {\n return this.state.expanded ? \"glyphicon-chevron-up\" : \"glyphicon-chevron-down\";\n }\n }, {\n key: \"getExpandedStyle\",\n value: function getExpandedStyle() {\n return this.state.expanded ? {} : { display: \"none\" };\n }\n }, {\n key: \"toggleExpanded\",\n value: function toggleExpanded() {\n this.setState({\n expanded: !this.state.expanded\n });\n }\n }, {\n key: \"componentDidUpdate\",\n value: function componentDidUpdate() {\n var stage = this.props.stage;\n var numTasks = stage.tasks.length;\n\n // sort the x-axis\n stage.tasks.sort(function (taskA, taskB) {\n return (0, _utils.getTaskNumber)(taskA.taskStatus.taskId) - (0, _utils.getTaskNumber)(taskB.taskStatus.taskId);\n });\n\n var scheduledTimes = stage.tasks.map(function (task) {\n return (0, _utils.parseDuration)(task.stats.totalScheduledTime);\n });\n var cpuTimes = stage.tasks.map(function (task) {\n return (0, _utils.parseDuration)(task.stats.totalCpuTime);\n });\n\n // prevent multiple calls to componentDidUpdate (resulting from calls to setState or otherwise) within the refresh interval from re-rendering sparklines/charts\n if (this.state.lastRender === null || Date.now() - this.state.lastRender >= 1000) {\n var renderTimestamp = Date.now();\n var stageId = (0, _utils.getStageNumber)(stage.stageId);\n\n StageSummary.renderHistogram('#scheduled-time-histogram-' + stageId, scheduledTimes, _utils.formatDuration);\n StageSummary.renderHistogram('#cpu-time-histogram-' + stageId, cpuTimes, _utils.formatDuration);\n\n if (this.state.expanded) {\n // this needs to be a string otherwise it will also be passed to numberFormatter\n var tooltipValueLookups = { 'offset': {} };\n for (var i = 0; i < numTasks; i++) {\n tooltipValueLookups['offset'][i] = (0, _utils.getStageNumber)(stage.stageId) + \".\" + i;\n }\n\n var stageBarChartProperties = $.extend({}, BAR_CHART_PROPERTIES, { barWidth: BAR_CHART_WIDTH / numTasks, tooltipValueLookups: tooltipValueLookups });\n\n $('#scheduled-time-bar-chart-' + stageId).sparkline(scheduledTimes, $.extend({}, stageBarChartProperties, { numberFormatter: _utils.formatDuration }));\n $('#cpu-time-bar-chart-' + stageId).sparkline(cpuTimes, $.extend({}, stageBarChartProperties, { numberFormatter: _utils.formatDuration }));\n }\n\n this.setState({\n lastRender: renderTimestamp\n });\n }\n }\n }, {\n key: \"render\",\n value: function render() {\n var stage = this.props.stage;\n if (stage === undefined || !stage.hasOwnProperty('plan')) {\n return _react2.default.createElement(\n \"tr\",\n null,\n _react2.default.createElement(\n \"td\",\n null,\n \"Information about this stage is unavailable.\"\n )\n );\n }\n\n var totalBufferedBytes = stage.tasks.map(function (task) {\n return task.outputBuffers.totalBufferedBytes;\n }).reduce(function (a, b) {\n return a + b;\n }, 0);\n\n var stageId = (0, _utils.getStageNumber)(stage.stageId);\n\n return _react2.default.createElement(\n \"tr\",\n null,\n _react2.default.createElement(\n \"td\",\n { className: \"stage-id\" },\n _react2.default.createElement(\n \"div\",\n { className: \"stage-state-color\", style: { borderLeftColor: (0, _utils.getStageStateColor)(stage) } },\n stageId\n )\n ),\n _react2.default.createElement(\n \"td\",\n null,\n _react2.default.createElement(\n \"table\",\n { className: \"table single-stage-table\" },\n _react2.default.createElement(\n \"tbody\",\n null,\n _react2.default.createElement(\n \"tr\",\n null,\n _react2.default.createElement(\n \"td\",\n null,\n _react2.default.createElement(\n \"table\",\n { className: \"stage-table stage-table-time\" },\n _react2.default.createElement(\n \"thead\",\n null,\n _react2.default.createElement(\n \"tr\",\n null,\n _react2.default.createElement(\n \"th\",\n { className: \"stage-table-stat-title stage-table-stat-header\" },\n \"Time\"\n ),\n _react2.default.createElement(\"th\", null)\n )\n ),\n _react2.default.createElement(\n \"tbody\",\n null,\n _react2.default.createElement(\n \"tr\",\n null,\n _react2.default.createElement(\n \"td\",\n { className: \"stage-table-stat-title\" },\n \"Scheduled\"\n ),\n _react2.default.createElement(\n \"td\",\n { className: \"stage-table-stat-text\" },\n stage.stageStats.totalScheduledTime\n )\n ),\n _react2.default.createElement(\n \"tr\",\n null,\n _react2.default.createElement(\n \"td\",\n { className: \"stage-table-stat-title\" },\n \"Blocked\"\n ),\n _react2.default.createElement(\n \"td\",\n { className: \"stage-table-stat-text\" },\n stage.stageStats.totalBlockedTime\n )\n ),\n _react2.default.createElement(\n \"tr\",\n null,\n _react2.default.createElement(\n \"td\",\n { className: \"stage-table-stat-title\" },\n \"CPU\"\n ),\n _react2.default.createElement(\n \"td\",\n { className: \"stage-table-stat-text\" },\n stage.stageStats.totalCpuTime\n )\n )\n )\n )\n ),\n _react2.default.createElement(\n \"td\",\n null,\n _react2.default.createElement(\n \"table\",\n { className: \"stage-table stage-table-memory\" },\n _react2.default.createElement(\n \"thead\",\n null,\n _react2.default.createElement(\n \"tr\",\n null,\n _react2.default.createElement(\n \"th\",\n { className: \"stage-table-stat-title stage-table-stat-header\" },\n \"Memory\"\n ),\n _react2.default.createElement(\"th\", null)\n )\n ),\n _react2.default.createElement(\n \"tbody\",\n null,\n _react2.default.createElement(\n \"tr\",\n null,\n _react2.default.createElement(\n \"td\",\n { className: \"stage-table-stat-title\" },\n \"Cumulative\"\n ),\n _react2.default.createElement(\n \"td\",\n { className: \"stage-table-stat-text\" },\n (0, _utils.formatDataSizeBytes)(stage.stageStats.cumulativeUserMemory / 1000)\n )\n ),\n _react2.default.createElement(\n \"tr\",\n null,\n _react2.default.createElement(\n \"td\",\n { className: \"stage-table-stat-title\" },\n \"Current\"\n ),\n _react2.default.createElement(\n \"td\",\n { className: \"stage-table-stat-text\" },\n (0, _utils.parseAndFormatDataSize)(stage.stageStats.userMemoryReservation)\n )\n ),\n _react2.default.createElement(\n \"tr\",\n null,\n _react2.default.createElement(\n \"td\",\n { className: \"stage-table-stat-title\" },\n \"Buffers\"\n ),\n _react2.default.createElement(\n \"td\",\n { className: \"stage-table-stat-text\" },\n (0, _utils.formatDataSize)(totalBufferedBytes)\n )\n ),\n _react2.default.createElement(\n \"tr\",\n null,\n _react2.default.createElement(\n \"td\",\n { className: \"stage-table-stat-title\" },\n \"Peak\"\n ),\n _react2.default.createElement(\n \"td\",\n { className: \"stage-table-stat-text\" },\n (0, _utils.parseAndFormatDataSize)(stage.stageStats.peakUserMemoryReservation)\n )\n )\n )\n )\n ),\n _react2.default.createElement(\n \"td\",\n null,\n _react2.default.createElement(\n \"table\",\n { className: \"stage-table stage-table-tasks\" },\n _react2.default.createElement(\n \"thead\",\n null,\n _react2.default.createElement(\n \"tr\",\n null,\n _react2.default.createElement(\n \"th\",\n { className: \"stage-table-stat-title stage-table-stat-header\" },\n \"Tasks\"\n ),\n _react2.default.createElement(\"th\", null)\n )\n ),\n _react2.default.createElement(\n \"tbody\",\n null,\n _react2.default.createElement(\n \"tr\",\n null,\n _react2.default.createElement(\n \"td\",\n { className: \"stage-table-stat-title\" },\n \"Pending\"\n ),\n _react2.default.createElement(\n \"td\",\n { className: \"stage-table-stat-text\" },\n stage.tasks.filter(function (task) {\n return task.taskStatus.state === \"PLANNED\";\n }).length\n )\n ),\n _react2.default.createElement(\n \"tr\",\n null,\n _react2.default.createElement(\n \"td\",\n { className: \"stage-table-stat-title\" },\n \"Running\"\n ),\n _react2.default.createElement(\n \"td\",\n { className: \"stage-table-stat-text\" },\n stage.tasks.filter(function (task) {\n return task.taskStatus.state === \"RUNNING\";\n }).length\n )\n ),\n _react2.default.createElement(\n \"tr\",\n null,\n _react2.default.createElement(\n \"td\",\n { className: \"stage-table-stat-title\" },\n \"Blocked\"\n ),\n _react2.default.createElement(\n \"td\",\n { className: \"stage-table-stat-text\" },\n stage.tasks.filter(function (task) {\n return task.stats.fullyBlocked;\n }).length\n )\n ),\n _react2.default.createElement(\n \"tr\",\n null,\n _react2.default.createElement(\n \"td\",\n { className: \"stage-table-stat-title\" },\n \"Total\"\n ),\n _react2.default.createElement(\n \"td\",\n { className: \"stage-table-stat-text\" },\n stage.tasks.length\n )\n )\n )\n )\n ),\n _react2.default.createElement(\n \"td\",\n null,\n _react2.default.createElement(\n \"table\",\n { className: \"stage-table histogram-table\" },\n _react2.default.createElement(\n \"thead\",\n null,\n _react2.default.createElement(\n \"tr\",\n null,\n _react2.default.createElement(\n \"th\",\n { className: \"stage-table-stat-title stage-table-chart-header\" },\n \"Scheduled Time Skew\"\n )\n )\n ),\n _react2.default.createElement(\n \"tbody\",\n null,\n _react2.default.createElement(\n \"tr\",\n null,\n _react2.default.createElement(\n \"td\",\n { className: \"histogram-container\" },\n _react2.default.createElement(\n \"span\",\n { className: \"histogram\", id: \"scheduled-time-histogram-\" + stageId },\n _react2.default.createElement(\"div\", { className: \"loader\" })\n )\n )\n )\n )\n )\n ),\n _react2.default.createElement(\n \"td\",\n null,\n _react2.default.createElement(\n \"table\",\n { className: \"stage-table histogram-table\" },\n _react2.default.createElement(\n \"thead\",\n null,\n _react2.default.createElement(\n \"tr\",\n null,\n _react2.default.createElement(\n \"th\",\n { className: \"stage-table-stat-title stage-table-chart-header\" },\n \"CPU Time Skew\"\n )\n )\n ),\n _react2.default.createElement(\n \"tbody\",\n null,\n _react2.default.createElement(\n \"tr\",\n null,\n _react2.default.createElement(\n \"td\",\n { className: \"histogram-container\" },\n _react2.default.createElement(\n \"span\",\n { className: \"histogram\", id: \"cpu-time-histogram-\" + stageId },\n _react2.default.createElement(\"div\", { className: \"loader\" })\n )\n )\n )\n )\n )\n ),\n _react2.default.createElement(\n \"td\",\n { className: \"expand-charts-container\" },\n _react2.default.createElement(\n \"a\",\n { onClick: this.toggleExpanded.bind(this), className: \"expand-charts-button\" },\n _react2.default.createElement(\"span\", { className: \"glyphicon \" + this.getExpandedIcon(), style: _utils.GLYPHICON_HIGHLIGHT, \"data-toggle\": \"tooltip\", \"data-placement\": \"top\", title: \"More\" })\n )\n )\n ),\n _react2.default.createElement(\n \"tr\",\n { style: this.getExpandedStyle() },\n _react2.default.createElement(\n \"td\",\n { colSpan: \"6\" },\n _react2.default.createElement(\n \"table\",\n { className: \"expanded-chart\" },\n _react2.default.createElement(\n \"tbody\",\n null,\n _react2.default.createElement(\n \"tr\",\n null,\n _react2.default.createElement(\n \"td\",\n { className: \"stage-table-stat-title expanded-chart-title\" },\n \"Task Scheduled Time\"\n ),\n _react2.default.createElement(\n \"td\",\n { className: \"bar-chart-container\" },\n _react2.default.createElement(\n \"span\",\n { className: \"bar-chart\", id: \"scheduled-time-bar-chart-\" + stageId },\n _react2.default.createElement(\"div\", { className: \"loader\" })\n )\n )\n )\n )\n )\n )\n ),\n _react2.default.createElement(\n \"tr\",\n { style: this.getExpandedStyle() },\n _react2.default.createElement(\n \"td\",\n { colSpan: \"6\" },\n _react2.default.createElement(\n \"table\",\n { className: \"expanded-chart\" },\n _react2.default.createElement(\n \"tbody\",\n null,\n _react2.default.createElement(\n \"tr\",\n null,\n _react2.default.createElement(\n \"td\",\n { className: \"stage-table-stat-title expanded-chart-title\" },\n \"Task CPU Time\"\n ),\n _react2.default.createElement(\n \"td\",\n { className: \"bar-chart-container\" },\n _react2.default.createElement(\n \"span\",\n { className: \"bar-chart\", id: \"cpu-time-bar-chart-\" + stageId },\n _react2.default.createElement(\"div\", { className: \"loader\" })\n )\n )\n )\n )\n )\n )\n )\n )\n )\n )\n );\n }\n }], [{\n key: \"renderHistogram\",\n value: function renderHistogram(histogramId, inputData, numberFormatter) {\n var numBuckets = Math.min(HISTOGRAM_WIDTH, Math.sqrt(inputData.length));\n var dataMin = Math.min.apply(null, inputData);\n var dataMax = Math.max.apply(null, inputData);\n var bucketSize = (dataMax - dataMin) / numBuckets;\n\n var histogramData = [];\n if (bucketSize === 0) {\n histogramData = [inputData.length];\n } else {\n for (var i = 0; i < numBuckets + 1; i++) {\n histogramData.push(0);\n }\n\n for (var _i in inputData) {\n var dataPoint = inputData[_i];\n var bucket = Math.floor((dataPoint - dataMin) / bucketSize);\n histogramData[bucket] = histogramData[bucket] + 1;\n }\n }\n\n var tooltipValueLookups = { 'offset': {} };\n for (var _i2 = 0; _i2 < histogramData.length; _i2++) {\n tooltipValueLookups['offset'][_i2] = numberFormatter(dataMin + _i2 * bucketSize) + \"-\" + numberFormatter(dataMin + (_i2 + 1) * bucketSize);\n }\n\n var stageHistogramProperties = $.extend({}, HISTOGRAM_PROPERTIES, { barWidth: HISTOGRAM_WIDTH / histogramData.length, tooltipValueLookups: tooltipValueLookups });\n $(histogramId).sparkline(histogramData, stageHistogramProperties);\n }\n }]);\n\n return StageSummary;\n}(_react2.default.Component);\n\nvar StageList = function (_React$Component3) {\n _inherits(StageList, _React$Component3);\n\n function StageList() {\n _classCallCheck(this, StageList);\n\n return _possibleConstructorReturn(this, (StageList.__proto__ || Object.getPrototypeOf(StageList)).apply(this, arguments));\n }\n\n _createClass(StageList, [{\n key: \"getStages\",\n value: function getStages(stage) {\n if (stage === undefined || !stage.hasOwnProperty('subStages')) {\n return [];\n }\n\n return [].concat.apply(stage, stage.subStages.map(this.getStages, this));\n }\n }, {\n key: \"render\",\n value: function render() {\n var stages = this.getStages(this.props.outputStage);\n\n if (stages === undefined || stages.length === 0) {\n return _react2.default.createElement(\n \"div\",\n { className: \"row\" },\n _react2.default.createElement(\n \"div\",\n { className: \"col-xs-12\" },\n \"No stage information available.\"\n )\n );\n }\n\n var renderedStages = stages.map(function (stage) {\n return _react2.default.createElement(StageSummary, { key: stage.stageId, stage: stage });\n });\n\n return _react2.default.createElement(\n \"div\",\n { className: \"row\" },\n _react2.default.createElement(\n \"div\",\n { className: \"col-xs-12\" },\n _react2.default.createElement(\n \"table\",\n { className: \"table\", id: \"stage-list\" },\n _react2.default.createElement(\n \"tbody\",\n null,\n renderedStages\n )\n )\n )\n );\n }\n }]);\n\n return StageList;\n}(_react2.default.Component);\n\nvar SMALL_SPARKLINE_PROPERTIES = {\n width: '100%',\n height: '57px',\n fillColor: '#3F4552',\n lineColor: '#747F96',\n spotColor: '#1EDCFF',\n tooltipClassname: 'sparkline-tooltip',\n disableHiddenCheck: true\n};\n\nvar TASK_FILTER = {\n ALL: function ALL() {\n return true;\n },\n PLANNED: function PLANNED(state) {\n return state === 'PLANNED';\n },\n RUNNING: function RUNNING(state) {\n return state === 'RUNNING';\n },\n FINISHED: function FINISHED(state) {\n return state === 'FINISHED';\n },\n FAILED: function FAILED(state) {\n return state === 'FAILED' || state === 'ABORTED' || state === 'CANCELED';\n }\n};\n\nvar QueryDetail = exports.QueryDetail = function (_React$Component4) {\n _inherits(QueryDetail, _React$Component4);\n\n function QueryDetail(props) {\n _classCallCheck(this, QueryDetail);\n\n var _this4 = _possibleConstructorReturn(this, (QueryDetail.__proto__ || Object.getPrototypeOf(QueryDetail)).call(this, props));\n\n _this4.state = {\n query: null,\n lastSnapshotStages: null,\n lastSnapshotTasks: null,\n\n lastScheduledTime: 0,\n lastCpuTime: 0,\n lastRowInput: 0,\n lastByteInput: 0,\n lastPhysicalInput: 0,\n lastPhysicalTime: 0,\n\n scheduledTimeRate: [],\n cpuTimeRate: [],\n rowInputRate: [],\n byteInputRate: [],\n physicalInputRate: [],\n\n reservedMemory: [],\n\n initialized: false,\n queryEnded: false,\n renderingEnded: false,\n\n lastRefresh: null,\n lastRender: null,\n\n stageRefresh: true,\n taskRefresh: true,\n\n taskFilter: TASK_FILTER.ALL\n };\n\n _this4.refreshLoop = _this4.refreshLoop.bind(_this4);\n return _this4;\n }\n\n _createClass(QueryDetail, [{\n key: \"resetTimer\",\n value: function resetTimer() {\n clearTimeout(this.timeoutId);\n // stop refreshing when query finishes or fails\n if (this.state.query === null || !this.state.queryEnded) {\n // task.info-update-interval is set to 3 seconds by default\n this.timeoutId = setTimeout(this.refreshLoop, 3000);\n }\n }\n }, {\n key: \"refreshLoop\",\n value: function refreshLoop() {\n var _this5 = this;\n\n clearTimeout(this.timeoutId); // to stop multiple series of refreshLoop from going on simultaneously\n var queryId = (0, _utils.getFirstParameter)(window.location.search);\n $.get('/ui/api/query/' + queryId, function (query) {\n var lastSnapshotStages = this.state.lastSnapshotStage;\n if (this.state.stageRefresh) {\n lastSnapshotStages = query.outputStage;\n }\n var lastSnapshotTasks = this.state.lastSnapshotTasks;\n if (this.state.taskRefresh) {\n lastSnapshotTasks = query.outputStage;\n }\n\n var lastRefresh = this.state.lastRefresh;\n var lastScheduledTime = this.state.lastScheduledTime;\n var lastCpuTime = this.state.lastCpuTime;\n var lastRowInput = this.state.lastRowInput;\n var lastByteInput = this.state.lastByteInput;\n var lastPhysicalInput = this.state.lastPhysicalInput;\n var lastPhysicalTime = this.state.lastPhysicalTime;\n var alreadyEnded = this.state.queryEnded;\n var nowMillis = Date.now();\n\n this.setState({\n query: query,\n lastSnapshotStage: lastSnapshotStages,\n lastSnapshotTasks: lastSnapshotTasks,\n\n lastPhysicalTime: (0, _utils.parseDuration)(query.queryStats.physicalInputReadTime),\n lastScheduledTime: (0, _utils.parseDuration)(query.queryStats.totalScheduledTime),\n lastCpuTime: (0, _utils.parseDuration)(query.queryStats.totalCpuTime),\n lastRowInput: query.queryStats.processedInputPositions,\n lastByteInput: (0, _utils.parseDataSize)(query.queryStats.processedInputDataSize),\n lastPhysicalInput: (0, _utils.parseDataSize)(query.queryStats.physicalInputDataSize),\n\n initialized: true,\n queryEnded: !!query.finalQueryInfo,\n\n lastRefresh: nowMillis\n });\n\n // i.e. don't show sparklines if we've already decided not to update or if we don't have one previous measurement\n if (alreadyEnded || lastRefresh === null && query.state === \"RUNNING\") {\n this.resetTimer();\n return;\n }\n\n if (lastRefresh === null) {\n lastRefresh = nowMillis - (0, _utils.parseDuration)(query.queryStats.elapsedTime);\n }\n\n var elapsedSecsSinceLastRefresh = (nowMillis - lastRefresh) / 1000.0;\n if (elapsedSecsSinceLastRefresh >= 0) {\n var currentScheduledTimeRate = ((0, _utils.parseDuration)(query.queryStats.totalScheduledTime) - lastScheduledTime) / (elapsedSecsSinceLastRefresh * 1000);\n var currentCpuTimeRate = ((0, _utils.parseDuration)(query.queryStats.totalCpuTime) - lastCpuTime) / (elapsedSecsSinceLastRefresh * 1000);\n var currentPhysicalReadTime = ((0, _utils.parseDuration)(query.queryStats.physicalInputReadTime) - lastPhysicalTime) / 1000;\n var currentRowInputRate = (query.queryStats.processedInputPositions - lastRowInput) / elapsedSecsSinceLastRefresh;\n var currentByteInputRate = ((0, _utils.parseDataSize)(query.queryStats.processedInputDataSize) - lastByteInput) / elapsedSecsSinceLastRefresh;\n var currentPhysicalInputRate = currentPhysicalReadTime > 0 ? ((0, _utils.parseDataSize)(query.queryStats.physicalInputDataSize) - lastPhysicalInput) / currentPhysicalReadTime : 0;\n\n this.setState({\n scheduledTimeRate: (0, _utils.addToHistory)(currentScheduledTimeRate, this.state.scheduledTimeRate),\n cpuTimeRate: (0, _utils.addToHistory)(currentCpuTimeRate, this.state.cpuTimeRate),\n rowInputRate: (0, _utils.addToHistory)(currentRowInputRate, this.state.rowInputRate),\n byteInputRate: (0, _utils.addToHistory)(currentByteInputRate, this.state.byteInputRate),\n reservedMemory: (0, _utils.addToHistory)((0, _utils.parseDataSize)(query.queryStats.totalMemoryReservation), this.state.reservedMemory),\n physicalInputRate: (0, _utils.addToHistory)(currentPhysicalInputRate, this.state.physicalInputRate)\n });\n }\n this.resetTimer();\n }.bind(this)).fail(function () {\n _this5.setState({\n initialized: true\n });\n _this5.resetTimer();\n });\n }\n }, {\n key: \"handleTaskRefreshClick\",\n value: function handleTaskRefreshClick() {\n if (this.state.taskRefresh) {\n this.setState({\n taskRefresh: false,\n lastSnapshotTasks: this.state.query.outputStage\n });\n } else {\n this.setState({\n taskRefresh: true\n });\n }\n }\n }, {\n key: \"renderTaskRefreshButton\",\n value: function renderTaskRefreshButton() {\n if (this.state.taskRefresh) {\n return _react2.default.createElement(\n \"button\",\n { className: \"btn btn-info live-button\", onClick: this.handleTaskRefreshClick.bind(this) },\n \"Auto-Refresh: On\"\n );\n } else {\n return _react2.default.createElement(\n \"button\",\n { className: \"btn btn-info live-button\", onClick: this.handleTaskRefreshClick.bind(this) },\n \"Auto-Refresh: Off\"\n );\n }\n }\n }, {\n key: \"handleStageRefreshClick\",\n value: function handleStageRefreshClick() {\n if (this.state.stageRefresh) {\n this.setState({\n stageRefresh: false,\n lastSnapshotStages: this.state.query.outputStage\n });\n } else {\n this.setState({\n stageRefresh: true\n });\n }\n }\n }, {\n key: \"renderStageRefreshButton\",\n value: function renderStageRefreshButton() {\n if (this.state.stageRefresh) {\n return _react2.default.createElement(\n \"button\",\n { className: \"btn btn-info live-button\", onClick: this.handleStageRefreshClick.bind(this) },\n \"Auto-Refresh: On\"\n );\n } else {\n return _react2.default.createElement(\n \"button\",\n { className: \"btn btn-info live-button\", onClick: this.handleStageRefreshClick.bind(this) },\n \"Auto-Refresh: Off\"\n );\n }\n }\n }, {\n key: \"renderTaskFilterListItem\",\n value: function renderTaskFilterListItem(taskFilter, taskFilterText) {\n return _react2.default.createElement(\n \"li\",\n null,\n _react2.default.createElement(\n \"a\",\n { href: \"#\", className: this.state.taskFilter === taskFilter ? \"selected\" : \"\", onClick: this.handleTaskFilterClick.bind(this, taskFilter) },\n taskFilterText\n )\n );\n }\n }, {\n key: \"handleTaskFilterClick\",\n value: function handleTaskFilterClick(filter, event) {\n this.setState({\n taskFilter: filter\n });\n event.preventDefault();\n }\n }, {\n key: \"getTasksFromStage\",\n value: function getTasksFromStage(stage) {\n if (stage === undefined || !stage.hasOwnProperty('subStages') || !stage.hasOwnProperty('tasks')) {\n return [];\n }\n\n return [].concat.apply(stage.tasks, stage.subStages.map(this.getTasksFromStage, this));\n }\n }, {\n key: \"componentDidMount\",\n value: function componentDidMount() {\n this.refreshLoop();\n }\n }, {\n key: \"componentDidUpdate\",\n value: function componentDidUpdate() {\n // prevent multiple calls to componentDidUpdate (resulting from calls to setState or otherwise) within the refresh interval from re-rendering sparklines/charts\n if (this.state.lastRender === null || Date.now() - this.state.lastRender >= 1000 || this.state.ended && !this.state.renderingEnded) {\n var renderTimestamp = Date.now();\n $('#scheduled-time-rate-sparkline').sparkline(this.state.scheduledTimeRate, $.extend({}, SMALL_SPARKLINE_PROPERTIES, {\n chartRangeMin: 0,\n numberFormatter: _utils.precisionRound\n }));\n $('#cpu-time-rate-sparkline').sparkline(this.state.cpuTimeRate, $.extend({}, SMALL_SPARKLINE_PROPERTIES, { chartRangeMin: 0, numberFormatter: _utils.precisionRound }));\n $('#row-input-rate-sparkline').sparkline(this.state.rowInputRate, $.extend({}, SMALL_SPARKLINE_PROPERTIES, { numberFormatter: _utils.formatCount }));\n $('#byte-input-rate-sparkline').sparkline(this.state.byteInputRate, $.extend({}, SMALL_SPARKLINE_PROPERTIES, { numberFormatter: _utils.formatDataSize }));\n $('#reserved-memory-sparkline').sparkline(this.state.reservedMemory, $.extend({}, SMALL_SPARKLINE_PROPERTIES, { numberFormatter: _utils.formatDataSize }));\n $('#physical-input-rate-sparkline').sparkline(this.state.physicalInputRate, $.extend({}, SMALL_SPARKLINE_PROPERTIES, { numberFormatter: _utils.formatDataSize }));\n\n if (this.state.lastRender === null) {\n $('#query').each(function (i, block) {\n hljs.highlightBlock(block);\n });\n\n $('#prepared-query').each(function (i, block) {\n hljs.highlightBlock(block);\n });\n }\n\n this.setState({\n renderingEnded: this.state.ended,\n lastRender: renderTimestamp\n });\n }\n\n $('[data-toggle=\"tooltip\"]').tooltip();\n new window.ClipboardJS('.copy-button');\n }\n }, {\n key: \"renderTasks\",\n value: function renderTasks() {\n var _this6 = this;\n\n if (this.state.lastSnapshotTasks === null) {\n return;\n }\n\n var tasks = this.getTasksFromStage(this.state.lastSnapshotTasks).filter(function (task) {\n return _this6.state.taskFilter(task.taskStatus.state);\n }, this);\n\n return _react2.default.createElement(\n \"div\",\n null,\n _react2.default.createElement(\n \"div\",\n { className: \"row\" },\n _react2.default.createElement(\n \"div\",\n { className: \"col-xs-9\" },\n _react2.default.createElement(\n \"h3\",\n null,\n \"Tasks\"\n )\n ),\n _react2.default.createElement(\n \"div\",\n { className: \"col-xs-3\" },\n _react2.default.createElement(\n \"table\",\n { className: \"header-inline-links\" },\n _react2.default.createElement(\n \"tbody\",\n null,\n _react2.default.createElement(\n \"tr\",\n null,\n _react2.default.createElement(\n \"td\",\n null,\n _react2.default.createElement(\n \"div\",\n { className: \"input-group-btn text-right\" },\n _react2.default.createElement(\n \"button\",\n { type: \"button\", className: \"btn btn-default dropdown-toggle pull-right text-right\", \"data-toggle\": \"dropdown\", \"aria-haspopup\": \"true\",\n \"aria-expanded\": \"false\" },\n \"Show \",\n _react2.default.createElement(\"span\", { className: \"caret\" })\n ),\n _react2.default.createElement(\n \"ul\",\n { className: \"dropdown-menu\" },\n this.renderTaskFilterListItem(TASK_FILTER.ALL, \"All\"),\n this.renderTaskFilterListItem(TASK_FILTER.PLANNED, \"Planned\"),\n this.renderTaskFilterListItem(TASK_FILTER.RUNNING, \"Running\"),\n this.renderTaskFilterListItem(TASK_FILTER.FINISHED, \"Finished\"),\n this.renderTaskFilterListItem(TASK_FILTER.FAILED, \"Aborted/Canceled/Failed\")\n )\n )\n ),\n _react2.default.createElement(\n \"td\",\n null,\n \"\\xA0\\xA0\",\n this.renderTaskRefreshButton()\n )\n )\n )\n )\n )\n ),\n _react2.default.createElement(\n \"div\",\n { className: \"row\" },\n _react2.default.createElement(\n \"div\",\n { className: \"col-xs-12\" },\n _react2.default.createElement(TaskList, { key: this.state.query.queryId, tasks: tasks })\n )\n )\n );\n }\n }, {\n key: \"renderStages\",\n value: function renderStages() {\n if (this.state.lastSnapshotStage === null) {\n return;\n }\n\n return _react2.default.createElement(\n \"div\",\n null,\n _react2.default.createElement(\n \"div\",\n { className: \"row\" },\n _react2.default.createElement(\n \"div\",\n { className: \"col-xs-9\" },\n _react2.default.createElement(\n \"h3\",\n null,\n \"Stages\"\n )\n ),\n _react2.default.createElement(\n \"div\",\n { className: \"col-xs-3\" },\n _react2.default.createElement(\n \"table\",\n { className: \"header-inline-links\" },\n _react2.default.createElement(\n \"tbody\",\n null,\n _react2.default.createElement(\n \"tr\",\n null,\n _react2.default.createElement(\n \"td\",\n null,\n this.renderStageRefreshButton()\n )\n )\n )\n )\n )\n ),\n _react2.default.createElement(\n \"div\",\n { className: \"row\" },\n _react2.default.createElement(\n \"div\",\n { className: \"col-xs-12\" },\n _react2.default.createElement(StageList, { key: this.state.query.queryId, outputStage: this.state.lastSnapshotStage })\n )\n )\n );\n }\n }, {\n key: \"renderPreparedQuery\",\n value: function renderPreparedQuery() {\n var query = this.state.query;\n if (!query.hasOwnProperty('preparedQuery') || query.preparedQuery === null) {\n return;\n }\n\n return _react2.default.createElement(\n \"div\",\n { className: \"col-xs-12\" },\n _react2.default.createElement(\n \"h3\",\n null,\n \"Prepared Query\",\n _react2.default.createElement(\n \"a\",\n { className: \"btn copy-button\", \"data-clipboard-target\": \"#prepared-query-text\", \"data-toggle\": \"tooltip\", \"data-placement\": \"right\", title: \"Copy to clipboard\" },\n _react2.default.createElement(\"span\", { className: \"glyphicon glyphicon-copy\", \"aria-hidden\": \"true\", alt: \"Copy to clipboard\" })\n )\n ),\n _react2.default.createElement(\n \"pre\",\n { id: \"prepared-query\" },\n _react2.default.createElement(\n \"code\",\n { className: \"lang-sql\", id: \"prepared-query-text\" },\n query.preparedQuery\n )\n )\n );\n }\n }, {\n key: \"renderSessionProperties\",\n value: function renderSessionProperties() {\n var query = this.state.query;\n\n var properties = [];\n for (var property in query.session.systemProperties) {\n if (query.session.systemProperties.hasOwnProperty(property)) {\n properties.push(_react2.default.createElement(\n \"span\",\n null,\n \"- \",\n property + \"=\" + query.session.systemProperties[property],\n \" \",\n _react2.default.createElement(\"br\", null)\n ));\n }\n }\n\n for (var catalog in query.session.catalogProperties) {\n if (query.session.catalogProperties.hasOwnProperty(catalog)) {\n for (var _property in query.session.catalogProperties[catalog]) {\n if (query.session.catalogProperties[catalog].hasOwnProperty(_property)) {\n properties.push(_react2.default.createElement(\n \"span\",\n null,\n \"- \",\n catalog + \".\" + _property + \"=\" + query.session.catalogProperties[catalog][_property],\n \" \",\n _react2.default.createElement(\"br\", null)\n ));\n }\n }\n }\n }\n\n return properties;\n }\n }, {\n key: \"renderResourceEstimates\",\n value: function renderResourceEstimates() {\n var query = this.state.query;\n var estimates = query.session.resourceEstimates;\n var renderedEstimates = [];\n\n for (var resource in estimates) {\n if (estimates.hasOwnProperty(resource)) {\n var upperChars = resource.match(/([A-Z])/g) || [];\n var snakeCased = resource;\n for (var i = 0, n = upperChars.length; i < n; i++) {\n snakeCased = snakeCased.replace(new RegExp(upperChars[i]), '_' + upperChars[i].toLowerCase());\n }\n\n renderedEstimates.push(_react2.default.createElement(\n \"span\",\n null,\n \"- \",\n snakeCased + \"=\" + query.session.resourceEstimates[resource],\n \" \",\n _react2.default.createElement(\"br\", null)\n ));\n }\n }\n\n return renderedEstimates;\n }\n }, {\n key: \"renderWarningInfo\",\n value: function renderWarningInfo() {\n var query = this.state.query;\n if (query.warnings.length > 0) {\n return _react2.default.createElement(\n \"div\",\n { className: \"row\" },\n _react2.default.createElement(\n \"div\",\n { className: \"col-xs-12\" },\n _react2.default.createElement(\n \"h3\",\n null,\n \"Warnings\"\n ),\n _react2.default.createElement(\"hr\", { className: \"h3-hr\" }),\n _react2.default.createElement(\n \"table\",\n { className: \"table\", id: \"warnings-table\" },\n query.warnings.map(function (warning) {\n return _react2.default.createElement(\n \"tr\",\n null,\n _react2.default.createElement(\n \"td\",\n null,\n warning.warningCode.name\n ),\n _react2.default.createElement(\n \"td\",\n null,\n warning.message\n )\n );\n })\n )\n )\n );\n } else {\n return null;\n }\n }\n }, {\n key: \"renderFailureInfo\",\n value: function renderFailureInfo() {\n var query = this.state.query;\n if (query.failureInfo) {\n return _react2.default.createElement(\n \"div\",\n { className: \"row\" },\n _react2.default.createElement(\n \"div\",\n { className: \"col-xs-12\" },\n _react2.default.createElement(\n \"h3\",\n null,\n \"Error Information\"\n ),\n _react2.default.createElement(\"hr\", { className: \"h3-hr\" }),\n _react2.default.createElement(\n \"table\",\n { className: \"table\" },\n _react2.default.createElement(\n \"tbody\",\n null,\n _react2.default.createElement(\n \"tr\",\n null,\n _react2.default.createElement(\n \"td\",\n { className: \"info-title\" },\n \"Error Type\"\n ),\n _react2.default.createElement(\n \"td\",\n { className: \"info-text\" },\n query.errorType\n )\n ),\n _react2.default.createElement(\n \"tr\",\n null,\n _react2.default.createElement(\n \"td\",\n { className: \"info-title\" },\n \"Error Code\"\n ),\n _react2.default.createElement(\n \"td\",\n { className: \"info-text\" },\n query.errorCode.name + \" (\" + this.state.query.errorCode.code + \")\"\n )\n ),\n _react2.default.createElement(\n \"tr\",\n null,\n _react2.default.createElement(\n \"td\",\n { className: \"info-title\" },\n \"Stack Trace\",\n _react2.default.createElement(\n \"a\",\n { className: \"btn copy-button\", \"data-clipboard-target\": \"#stack-trace\", \"data-toggle\": \"tooltip\", \"data-placement\": \"right\", title: \"Copy to clipboard\" },\n _react2.default.createElement(\"span\", { className: \"glyphicon glyphicon-copy\", \"aria-hidden\": \"true\", alt: \"Copy to clipboard\" })\n )\n ),\n _react2.default.createElement(\n \"td\",\n { className: \"info-text\" },\n _react2.default.createElement(\n \"pre\",\n { id: \"stack-trace\" },\n QueryDetail.formatStackTrace(query.failureInfo)\n )\n )\n )\n )\n )\n )\n );\n } else {\n return \"\";\n }\n }\n }, {\n key: \"render\",\n value: function render() {\n var query = this.state.query;\n\n if (query === null || this.state.initialized === false) {\n var label = _react2.default.createElement(\n \"div\",\n { className: \"loader\" },\n \"Loading...\"\n );\n if (this.state.initialized) {\n label = \"Query not found\";\n }\n return _react2.default.createElement(\n \"div\",\n { className: \"row error-message\" },\n _react2.default.createElement(\n \"div\",\n { className: \"col-xs-12\" },\n _react2.default.createElement(\n \"h4\",\n null,\n label\n )\n )\n );\n }\n\n return _react2.default.createElement(\n \"div\",\n null,\n _react2.default.createElement(_QueryHeader.QueryHeader, { query: query }),\n _react2.default.createElement(\n \"div\",\n { className: \"row\" },\n _react2.default.createElement(\n \"div\",\n { className: \"col-xs-6\" },\n _react2.default.createElement(\n \"h3\",\n null,\n \"Session\"\n ),\n _react2.default.createElement(\"hr\", { className: \"h3-hr\" }),\n _react2.default.createElement(\n \"table\",\n { className: \"table\" },\n _react2.default.createElement(\n \"tbody\",\n null,\n _react2.default.createElement(\n \"tr\",\n null,\n _react2.default.createElement(\n \"td\",\n { className: \"info-title\" },\n \"User\"\n ),\n _react2.default.createElement(\n \"td\",\n { className: \"info-text wrap-text\" },\n _react2.default.createElement(\n \"span\",\n { id: \"query-user\" },\n query.session.user\n ),\n \"\\xA0\\xA0\",\n _react2.default.createElement(\n \"a\",\n { href: \"#\", className: \"copy-button\", \"data-clipboard-target\": \"#query-user\", \"data-toggle\": \"tooltip\", \"data-placement\": \"right\", title: \"Copy to clipboard\" },\n _react2.default.createElement(\"span\", { className: \"glyphicon glyphicon-copy\", \"aria-hidden\": \"true\", alt: \"Copy to clipboard\" })\n )\n )\n ),\n _react2.default.createElement(\n \"tr\",\n null,\n _react2.default.createElement(\n \"td\",\n { className: \"info-title\" },\n \"Principal\"\n ),\n _react2.default.createElement(\n \"td\",\n { className: \"info-text wrap-text\" },\n query.session.principal\n )\n ),\n _react2.default.createElement(\n \"tr\",\n null,\n _react2.default.createElement(\n \"td\",\n { className: \"info-title\" },\n \"Source\"\n ),\n _react2.default.createElement(\n \"td\",\n { className: \"info-text wrap-text\" },\n query.session.source\n )\n ),\n _react2.default.createElement(\n \"tr\",\n null,\n _react2.default.createElement(\n \"td\",\n { className: \"info-title\" },\n \"Catalog\"\n ),\n _react2.default.createElement(\n \"td\",\n { className: \"info-text\" },\n query.session.catalog\n )\n ),\n _react2.default.createElement(\n \"tr\",\n null,\n _react2.default.createElement(\n \"td\",\n { className: \"info-title\" },\n \"Schema\"\n ),\n _react2.default.createElement(\n \"td\",\n { className: \"info-text\" },\n query.session.schema\n )\n ),\n _react2.default.createElement(\n \"tr\",\n null,\n _react2.default.createElement(\n \"td\",\n { className: \"info-title\" },\n \"Time zone\"\n ),\n _react2.default.createElement(\n \"td\",\n { className: \"info-text\" },\n query.session.timeZone\n )\n ),\n _react2.default.createElement(\n \"tr\",\n null,\n _react2.default.createElement(\n \"td\",\n { className: \"info-title\" },\n \"Client Address\"\n ),\n _react2.default.createElement(\n \"td\",\n { className: \"info-text\" },\n query.session.remoteUserAddress\n )\n ),\n _react2.default.createElement(\n \"tr\",\n null,\n _react2.default.createElement(\n \"td\",\n { className: \"info-title\" },\n \"Client Tags\"\n ),\n _react2.default.createElement(\n \"td\",\n { className: \"info-text\" },\n query.session.clientTags.join(\", \")\n )\n ),\n _react2.default.createElement(\n \"tr\",\n null,\n _react2.default.createElement(\n \"td\",\n { className: \"info-title\" },\n \"Session Properties\"\n ),\n _react2.default.createElement(\n \"td\",\n { className: \"info-text wrap-text\" },\n this.renderSessionProperties()\n )\n ),\n _react2.default.createElement(\n \"tr\",\n null,\n _react2.default.createElement(\n \"td\",\n { className: \"info-title\" },\n \"Resource Estimates\"\n ),\n _react2.default.createElement(\n \"td\",\n { className: \"info-text wrap-text\" },\n this.renderResourceEstimates()\n )\n )\n )\n )\n ),\n _react2.default.createElement(\n \"div\",\n { className: \"col-xs-6\" },\n _react2.default.createElement(\n \"h3\",\n null,\n \"Execution\"\n ),\n _react2.default.createElement(\"hr\", { className: \"h3-hr\" }),\n _react2.default.createElement(\n \"table\",\n { className: \"table\" },\n _react2.default.createElement(\n \"tbody\",\n null,\n _react2.default.createElement(\n \"tr\",\n null,\n _react2.default.createElement(\n \"td\",\n { className: \"info-title\" },\n \"Resource Group\"\n ),\n _react2.default.createElement(\n \"td\",\n { className: \"info-text wrap-text\" },\n query.resourceGroupId ? query.resourceGroupId.join(\".\") : \"n/a\"\n )\n ),\n _react2.default.createElement(\n \"tr\",\n null,\n _react2.default.createElement(\n \"td\",\n { className: \"info-title\" },\n \"Submission Time\"\n ),\n _react2.default.createElement(\n \"td\",\n { className: \"info-text\" },\n (0, _utils.formatShortDateTime)(new Date(query.queryStats.createTime))\n )\n ),\n _react2.default.createElement(\n \"tr\",\n null,\n _react2.default.createElement(\n \"td\",\n { className: \"info-title\" },\n \"Completion Time\"\n ),\n _react2.default.createElement(\n \"td\",\n { className: \"info-text\" },\n query.queryStats.endTime ? (0, _utils.formatShortDateTime)(new Date(query.queryStats.endTime)) : \"\"\n )\n ),\n _react2.default.createElement(\n \"tr\",\n null,\n _react2.default.createElement(\n \"td\",\n { className: \"info-title\" },\n \"Elapsed Time\"\n ),\n _react2.default.createElement(\n \"td\",\n { className: \"info-text\" },\n query.queryStats.elapsedTime\n )\n ),\n _react2.default.createElement(\n \"tr\",\n null,\n _react2.default.createElement(\n \"td\",\n { className: \"info-title\" },\n \"Queued Time\"\n ),\n _react2.default.createElement(\n \"td\",\n { className: \"info-text\" },\n query.queryStats.queuedTime\n )\n ),\n _react2.default.createElement(\n \"tr\",\n null,\n _react2.default.createElement(\n \"td\",\n { className: \"info-title\" },\n \"Analysis Time\"\n ),\n _react2.default.createElement(\n \"td\",\n { className: \"info-text\" },\n query.queryStats.analysisTime\n )\n ),\n _react2.default.createElement(\n \"tr\",\n null,\n _react2.default.createElement(\n \"td\",\n { className: \"info-title\" },\n \"Planning Time\"\n ),\n _react2.default.createElement(\n \"td\",\n { className: \"info-text\" },\n query.queryStats.planningTime\n )\n ),\n _react2.default.createElement(\n \"tr\",\n null,\n _react2.default.createElement(\n \"td\",\n { className: \"info-title\" },\n \"Execution Time\"\n ),\n _react2.default.createElement(\n \"td\",\n { className: \"info-text\" },\n query.queryStats.executionTime\n )\n )\n )\n )\n )\n ),\n _react2.default.createElement(\n \"div\",\n { className: \"row\" },\n _react2.default.createElement(\n \"div\",\n { className: \"col-xs-12\" },\n _react2.default.createElement(\n \"div\",\n { className: \"row\" },\n _react2.default.createElement(\n \"div\",\n { className: \"col-xs-6\" },\n _react2.default.createElement(\n \"h3\",\n null,\n \"Resource Utilization Summary\"\n ),\n _react2.default.createElement(\"hr\", { className: \"h3-hr\" }),\n _react2.default.createElement(\n \"table\",\n { className: \"table\" },\n _react2.default.createElement(\n \"tbody\",\n null,\n _react2.default.createElement(\n \"tr\",\n null,\n _react2.default.createElement(\n \"td\",\n { className: \"info-title\" },\n \"CPU Time\"\n ),\n _react2.default.createElement(\n \"td\",\n { className: \"info-text\" },\n query.queryStats.totalCpuTime\n )\n ),\n _react2.default.createElement(\n \"tr\",\n null,\n _react2.default.createElement(\n \"td\",\n { className: \"info-title\" },\n \"Scheduled Time\"\n ),\n _react2.default.createElement(\n \"td\",\n { className: \"info-text\" },\n query.queryStats.totalScheduledTime\n )\n ),\n _react2.default.createElement(\n \"tr\",\n null,\n _react2.default.createElement(\n \"td\",\n { className: \"info-title\" },\n \"Input Rows\"\n ),\n _react2.default.createElement(\n \"td\",\n { className: \"info-text\" },\n (0, _utils.formatCount)(query.queryStats.processedInputPositions)\n )\n ),\n _react2.default.createElement(\n \"tr\",\n null,\n _react2.default.createElement(\n \"td\",\n { className: \"info-title\" },\n \"Input Data\"\n ),\n _react2.default.createElement(\n \"td\",\n { className: \"info-text\" },\n (0, _utils.parseAndFormatDataSize)(query.queryStats.processedInputDataSize)\n )\n ),\n _react2.default.createElement(\n \"tr\",\n null,\n _react2.default.createElement(\n \"td\",\n { className: \"info-title\" },\n \"Physical Input Rows\"\n ),\n _react2.default.createElement(\n \"td\",\n { className: \"info-text\" },\n (0, _utils.formatCount)(query.queryStats.physicalInputPositions)\n )\n ),\n _react2.default.createElement(\n \"tr\",\n null,\n _react2.default.createElement(\n \"td\",\n { className: \"info-title\" },\n \"Physical Input Data\"\n ),\n _react2.default.createElement(\n \"td\",\n { className: \"info-text\" },\n (0, _utils.parseAndFormatDataSize)(query.queryStats.physicalInputDataSize)\n )\n ),\n _react2.default.createElement(\n \"tr\",\n null,\n _react2.default.createElement(\n \"td\",\n { className: \"info-title\" },\n \"Physical Input Read Time\"\n ),\n _react2.default.createElement(\n \"td\",\n { className: \"info-text\" },\n query.queryStats.physicalInputReadTime\n )\n ),\n _react2.default.createElement(\n \"tr\",\n null,\n _react2.default.createElement(\n \"td\",\n { className: \"info-title\" },\n \"Internal Network Rows\"\n ),\n _react2.default.createElement(\n \"td\",\n { className: \"info-text\" },\n (0, _utils.formatCount)(query.queryStats.internalNetworkInputPositions)\n )\n ),\n _react2.default.createElement(\n \"tr\",\n null,\n _react2.default.createElement(\n \"td\",\n { className: \"info-title\" },\n \"Internal Network Data\"\n ),\n _react2.default.createElement(\n \"td\",\n { className: \"info-text\" },\n (0, _utils.parseAndFormatDataSize)(query.queryStats.internalNetworkInputDataSize)\n )\n ),\n _react2.default.createElement(\n \"tr\",\n null,\n _react2.default.createElement(\n \"td\",\n { className: \"info-title\" },\n \"Peak User Memory\"\n ),\n _react2.default.createElement(\n \"td\",\n { className: \"info-text\" },\n (0, _utils.parseAndFormatDataSize)(query.queryStats.peakUserMemoryReservation)\n )\n ),\n (0, _utils.parseDataSize)(query.queryStats.peakRevocableMemoryReservation) > 0 && _react2.default.createElement(\n \"tr\",\n null,\n _react2.default.createElement(\n \"td\",\n { className: \"info-title\" },\n \"Peak Revocable Memory\"\n ),\n _react2.default.createElement(\n \"td\",\n { className: \"info-text\" },\n (0, _utils.parseAndFormatDataSize)(query.queryStats.peakRevocableMemoryReservation)\n )\n ),\n _react2.default.createElement(\n \"tr\",\n null,\n _react2.default.createElement(\n \"td\",\n { className: \"info-title\" },\n \"Peak Total Memory\"\n ),\n _react2.default.createElement(\n \"td\",\n { className: \"info-text\" },\n (0, _utils.parseAndFormatDataSize)(query.queryStats.peakTotalMemoryReservation)\n )\n ),\n _react2.default.createElement(\n \"tr\",\n null,\n _react2.default.createElement(\n \"td\",\n { className: \"info-title\" },\n \"Memory Pool\"\n ),\n _react2.default.createElement(\n \"td\",\n { className: \"info-text\" },\n query.memoryPool\n )\n ),\n _react2.default.createElement(\n \"tr\",\n null,\n _react2.default.createElement(\n \"td\",\n { className: \"info-title\" },\n \"Cumulative User Memory\"\n ),\n _react2.default.createElement(\n \"td\",\n { className: \"info-text\" },\n (0, _utils.formatDataSizeBytes)(query.queryStats.cumulativeUserMemory / 1000.0) + \" seconds\"\n )\n ),\n _react2.default.createElement(\n \"tr\",\n null,\n _react2.default.createElement(\n \"td\",\n { className: \"info-title\" },\n \"Output Rows\"\n ),\n _react2.default.createElement(\n \"td\",\n { className: \"info-text\" },\n (0, _utils.formatCount)(query.queryStats.outputPositions)\n )\n ),\n _react2.default.createElement(\n \"tr\",\n null,\n _react2.default.createElement(\n \"td\",\n { className: \"info-title\" },\n \"Output Data\"\n ),\n _react2.default.createElement(\n \"td\",\n { className: \"info-text\" },\n (0, _utils.parseAndFormatDataSize)(query.queryStats.outputDataSize)\n )\n ),\n _react2.default.createElement(\n \"tr\",\n null,\n _react2.default.createElement(\n \"td\",\n { className: \"info-title\" },\n \"Written Rows\"\n ),\n _react2.default.createElement(\n \"td\",\n { className: \"info-text\" },\n (0, _utils.formatCount)(query.queryStats.writtenPositions)\n )\n ),\n _react2.default.createElement(\n \"tr\",\n null,\n _react2.default.createElement(\n \"td\",\n { className: \"info-title\" },\n \"Logical Written Data\"\n ),\n _react2.default.createElement(\n \"td\",\n { className: \"info-text\" },\n (0, _utils.parseAndFormatDataSize)(query.queryStats.logicalWrittenDataSize)\n )\n ),\n _react2.default.createElement(\n \"tr\",\n null,\n _react2.default.createElement(\n \"td\",\n { className: \"info-title\" },\n \"Physical Written Data\"\n ),\n _react2.default.createElement(\n \"td\",\n { className: \"info-text\" },\n (0, _utils.parseAndFormatDataSize)(query.queryStats.physicalWrittenDataSize)\n )\n ),\n (0, _utils.parseDataSize)(query.queryStats.spilledDataSize) > 0 && _react2.default.createElement(\n \"tr\",\n null,\n _react2.default.createElement(\n \"td\",\n { className: \"info-title\" },\n \"Spilled Data\"\n ),\n _react2.default.createElement(\n \"td\",\n { className: \"info-text\" },\n (0, _utils.parseAndFormatDataSize)(query.queryStats.spilledDataSize)\n )\n )\n )\n )\n ),\n _react2.default.createElement(\n \"div\",\n { className: \"col-xs-6\" },\n _react2.default.createElement(\n \"h3\",\n null,\n \"Timeline\"\n ),\n _react2.default.createElement(\"hr\", { className: \"h3-hr\" }),\n _react2.default.createElement(\n \"table\",\n { className: \"table\" },\n _react2.default.createElement(\n \"tbody\",\n null,\n _react2.default.createElement(\n \"tr\",\n null,\n _react2.default.createElement(\n \"td\",\n { className: \"info-title\" },\n \"Parallelism\"\n ),\n _react2.default.createElement(\n \"td\",\n { rowSpan: \"2\" },\n _react2.default.createElement(\n \"div\",\n { className: \"query-stats-sparkline-container\" },\n _react2.default.createElement(\n \"span\",\n { className: \"sparkline\", id: \"cpu-time-rate-sparkline\" },\n _react2.default.createElement(\n \"div\",\n { className: \"loader\" },\n \"Loading ...\"\n )\n )\n )\n )\n ),\n _react2.default.createElement(\n \"tr\",\n { className: \"tr-noborder\" },\n _react2.default.createElement(\n \"td\",\n { className: \"info-sparkline-text\" },\n (0, _utils.formatCount)(this.state.cpuTimeRate[this.state.cpuTimeRate.length - 1])\n )\n ),\n _react2.default.createElement(\n \"tr\",\n null,\n _react2.default.createElement(\n \"td\",\n { className: \"info-title\" },\n \"Scheduled Time/s\"\n ),\n _react2.default.createElement(\n \"td\",\n { rowSpan: \"2\" },\n _react2.default.createElement(\n \"div\",\n { className: \"query-stats-sparkline-container\" },\n _react2.default.createElement(\n \"span\",\n { className: \"sparkline\", id: \"scheduled-time-rate-sparkline\" },\n _react2.default.createElement(\n \"div\",\n { className: \"loader\" },\n \"Loading ...\"\n )\n )\n )\n )\n ),\n _react2.default.createElement(\n \"tr\",\n { className: \"tr-noborder\" },\n _react2.default.createElement(\n \"td\",\n { className: \"info-sparkline-text\" },\n (0, _utils.formatCount)(this.state.scheduledTimeRate[this.state.scheduledTimeRate.length - 1])\n )\n ),\n _react2.default.createElement(\n \"tr\",\n null,\n _react2.default.createElement(\n \"td\",\n { className: \"info-title\" },\n \"Input Rows/s\"\n ),\n _react2.default.createElement(\n \"td\",\n { rowSpan: \"2\" },\n _react2.default.createElement(\n \"div\",\n { className: \"query-stats-sparkline-container\" },\n _react2.default.createElement(\n \"span\",\n { className: \"sparkline\", id: \"row-input-rate-sparkline\" },\n _react2.default.createElement(\n \"div\",\n { className: \"loader\" },\n \"Loading ...\"\n )\n )\n )\n )\n ),\n _react2.default.createElement(\n \"tr\",\n { className: \"tr-noborder\" },\n _react2.default.createElement(\n \"td\",\n { className: \"info-sparkline-text\" },\n (0, _utils.formatCount)(this.state.rowInputRate[this.state.rowInputRate.length - 1])\n )\n ),\n _react2.default.createElement(\n \"tr\",\n null,\n _react2.default.createElement(\n \"td\",\n { className: \"info-title\" },\n \"Input Bytes/s\"\n ),\n _react2.default.createElement(\n \"td\",\n { rowSpan: \"2\" },\n _react2.default.createElement(\n \"div\",\n { className: \"query-stats-sparkline-container\" },\n _react2.default.createElement(\n \"span\",\n { className: \"sparkline\", id: \"byte-input-rate-sparkline\" },\n _react2.default.createElement(\n \"div\",\n { className: \"loader\" },\n \"Loading ...\"\n )\n )\n )\n )\n ),\n _react2.default.createElement(\n \"tr\",\n { className: \"tr-noborder\" },\n _react2.default.createElement(\n \"td\",\n { className: \"info-sparkline-text\" },\n (0, _utils.formatDataSize)(this.state.byteInputRate[this.state.byteInputRate.length - 1])\n )\n ),\n _react2.default.createElement(\n \"tr\",\n null,\n _react2.default.createElement(\n \"td\",\n { className: \"info-title\" },\n \"Physical Input Bytes/s\"\n ),\n _react2.default.createElement(\n \"td\",\n { rowSpan: \"2\" },\n _react2.default.createElement(\n \"div\",\n { className: \"query-stats-sparkline-container\" },\n _react2.default.createElement(\n \"span\",\n { className: \"sparkline\", id: \"physical-input-rate-sparkline\" },\n _react2.default.createElement(\n \"div\",\n { className: \"loader\" },\n \"Loading ...\"\n )\n )\n )\n )\n ),\n _react2.default.createElement(\n \"tr\",\n { className: \"tr-noborder\" },\n _react2.default.createElement(\n \"td\",\n { className: \"info-sparkline-text\" },\n (0, _utils.formatDataSize)(this.state.physicalInputRate[this.state.physicalInputRate.length - 1])\n )\n ),\n _react2.default.createElement(\n \"tr\",\n null,\n _react2.default.createElement(\n \"td\",\n { className: \"info-title\" },\n \"Memory Utilization\"\n ),\n _react2.default.createElement(\n \"td\",\n { rowSpan: \"2\" },\n _react2.default.createElement(\n \"div\",\n { className: \"query-stats-sparkline-container\" },\n _react2.default.createElement(\n \"span\",\n { className: \"sparkline\", id: \"reserved-memory-sparkline\" },\n _react2.default.createElement(\n \"div\",\n { className: \"loader\" },\n \"Loading ...\"\n )\n )\n )\n )\n ),\n _react2.default.createElement(\n \"tr\",\n { className: \"tr-noborder\" },\n _react2.default.createElement(\n \"td\",\n { className: \"info-sparkline-text\" },\n (0, _utils.formatDataSize)(this.state.reservedMemory[this.state.reservedMemory.length - 1])\n )\n )\n )\n )\n )\n )\n )\n ),\n this.renderWarningInfo(),\n this.renderFailureInfo(),\n _react2.default.createElement(\n \"div\",\n { className: \"row\" },\n _react2.default.createElement(\n \"div\",\n { className: \"col-xs-12\" },\n _react2.default.createElement(\n \"h3\",\n null,\n \"Query\",\n _react2.default.createElement(\n \"a\",\n { className: \"btn copy-button\", \"data-clipboard-target\": \"#query-text\", \"data-toggle\": \"tooltip\", \"data-placement\": \"right\", title: \"Copy to clipboard\" },\n _react2.default.createElement(\"span\", { className: \"glyphicon glyphicon-copy\", \"aria-hidden\": \"true\", alt: \"Copy to clipboard\" })\n )\n ),\n _react2.default.createElement(\n \"pre\",\n { id: \"query\" },\n _react2.default.createElement(\n \"code\",\n { className: \"lang-sql\", id: \"query-text\" },\n query.query\n )\n )\n ),\n this.renderPreparedQuery()\n ),\n this.renderStages(),\n this.renderTasks()\n );\n }\n }], [{\n key: \"formatStackTrace\",\n value: function formatStackTrace(info) {\n return QueryDetail.formatStackTraceHelper(info, [], \"\", \"\");\n }\n }, {\n key: \"formatStackTraceHelper\",\n value: function formatStackTraceHelper(info, parentStack, prefix, linePrefix) {\n var s = linePrefix + prefix + QueryDetail.failureInfoToString(info) + \"\\n\";\n\n if (info.stack) {\n var sharedStackFrames = 0;\n if (parentStack !== null) {\n sharedStackFrames = QueryDetail.countSharedStackFrames(info.stack, parentStack);\n }\n\n for (var i = 0; i < info.stack.length - sharedStackFrames; i++) {\n s += linePrefix + \"\\tat \" + info.stack[i] + \"\\n\";\n }\n if (sharedStackFrames !== 0) {\n s += linePrefix + \"\\t... \" + sharedStackFrames + \" more\" + \"\\n\";\n }\n }\n\n if (info.suppressed) {\n for (var _i3 = 0; _i3 < info.suppressed.length; _i3++) {\n s += QueryDetail.formatStackTraceHelper(info.suppressed[_i3], info.stack, \"Suppressed: \", linePrefix + \"\\t\");\n }\n }\n\n if (info.cause) {\n s += QueryDetail.formatStackTraceHelper(info.cause, info.stack, \"Caused by: \", linePrefix);\n }\n\n return s;\n }\n }, {\n key: \"countSharedStackFrames\",\n value: function countSharedStackFrames(stack, parentStack) {\n var n = 0;\n var minStackLength = Math.min(stack.length, parentStack.length);\n while (n < minStackLength && stack[stack.length - 1 - n] === parentStack[parentStack.length - 1 - n]) {\n n++;\n }\n return n;\n }\n }, {\n key: \"failureInfoToString\",\n value: function failureInfoToString(t) {\n return t.message !== null ? t.type + \": \" + t.message : t.type;\n }\n }]);\n\n return QueryDetail;\n}(_react2.default.Component);\n\n//# sourceURL=webpack:///./components/QueryDetail.jsx?"); +eval("\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\nexports.QueryDetail = undefined;\n\nvar _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if (\"value\" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();\n\nvar _react = __webpack_require__(/*! react */ \"./node_modules/react/index.js\");\n\nvar _react2 = _interopRequireDefault(_react);\n\nvar _reactable = __webpack_require__(/*! reactable */ \"./node_modules/reactable/lib/reactable.js\");\n\nvar _reactable2 = _interopRequireDefault(_reactable);\n\nvar _utils = __webpack_require__(/*! ../utils */ \"./utils.js\");\n\nvar _QueryHeader = __webpack_require__(/*! ./QueryHeader */ \"./components/QueryHeader.jsx\");\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\nfunction _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError(\"Cannot call a class as a function\"); } }\n\nfunction _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); } return call && (typeof call === \"object\" || typeof call === \"function\") ? call : self; }\n\nfunction _inherits(subClass, superClass) { if (typeof superClass !== \"function\" && superClass !== null) { throw new TypeError(\"Super expression must either be null or a function, not \" + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } /*\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nvar Table = _reactable2.default.Table,\n Thead = _reactable2.default.Thead,\n Th = _reactable2.default.Th,\n Tr = _reactable2.default.Tr,\n Td = _reactable2.default.Td;\n\nvar TaskList = function (_React$Component) {\n _inherits(TaskList, _React$Component);\n\n function TaskList() {\n _classCallCheck(this, TaskList);\n\n return _possibleConstructorReturn(this, (TaskList.__proto__ || Object.getPrototypeOf(TaskList)).apply(this, arguments));\n }\n\n _createClass(TaskList, [{\n key: \"render\",\n value: function render() {\n var tasks = this.props.tasks;\n\n if (tasks === undefined || tasks.length === 0) {\n return _react2.default.createElement(\n \"div\",\n { className: \"row error-message\" },\n _react2.default.createElement(\n \"div\",\n { className: \"col-xs-12\" },\n _react2.default.createElement(\n \"h4\",\n null,\n \"No threads in the selected group\"\n )\n )\n );\n }\n\n var showPortNumbers = TaskList.showPortNumbers(tasks);\n\n var renderedTasks = tasks.map(function (task) {\n var elapsedTime = (0, _utils.parseDuration)(task.stats.elapsedTime);\n if (elapsedTime === 0) {\n elapsedTime = Date.now() - Date.parse(task.stats.createTime);\n }\n\n return _react2.default.createElement(\n Tr,\n { key: task.taskStatus.taskId },\n _react2.default.createElement(\n Td,\n { column: \"id\", value: task.taskStatus.taskId },\n _react2.default.createElement(\n \"a\",\n { href: \"/ui/api/worker/\" + task.taskStatus.nodeId + \"/task/\" + task.taskStatus.taskId + \"?pretty\" },\n (0, _utils.getTaskIdSuffix)(task.taskStatus.taskId)\n )\n ),\n _react2.default.createElement(\n Td,\n { column: \"host\", value: (0, _utils.getHostname)(task.taskStatus.self) },\n _react2.default.createElement(\n \"a\",\n { href: \"worker.html?\" + task.taskStatus.nodeId, className: \"font-light\", target: \"_blank\" },\n showPortNumbers ? (0, _utils.getHostAndPort)(task.taskStatus.self) : (0, _utils.getHostname)(task.taskStatus.self)\n )\n ),\n _react2.default.createElement(\n Td,\n { column: \"state\", value: TaskList.formatState(task.taskStatus.state, task.stats.fullyBlocked) },\n TaskList.formatState(task.taskStatus.state, task.stats.fullyBlocked)\n ),\n _react2.default.createElement(\n Td,\n { column: \"rows\", value: task.stats.rawInputPositions },\n (0, _utils.formatCount)(task.stats.rawInputPositions)\n ),\n _react2.default.createElement(\n Td,\n { column: \"rowsSec\", value: (0, _utils.computeRate)(task.stats.rawInputPositions, elapsedTime) },\n (0, _utils.formatCount)((0, _utils.computeRate)(task.stats.rawInputPositions, elapsedTime))\n ),\n _react2.default.createElement(\n Td,\n { column: \"bytes\", value: (0, _utils.parseDataSize)(task.stats.rawInputDataSize) },\n (0, _utils.formatDataSizeBytes)((0, _utils.parseDataSize)(task.stats.rawInputDataSize))\n ),\n _react2.default.createElement(\n Td,\n { column: \"bytesSec\", value: (0, _utils.computeRate)((0, _utils.parseDataSize)(task.stats.rawInputDataSize), elapsedTime) },\n (0, _utils.formatDataSizeBytes)((0, _utils.computeRate)((0, _utils.parseDataSize)(task.stats.rawInputDataSize), elapsedTime))\n ),\n _react2.default.createElement(\n Td,\n { column: \"splitsPending\", value: task.stats.queuedDrivers },\n task.stats.queuedDrivers\n ),\n _react2.default.createElement(\n Td,\n { column: \"splitsRunning\", value: task.stats.runningDrivers },\n task.stats.runningDrivers\n ),\n _react2.default.createElement(\n Td,\n { column: \"splitsBlocked\", value: task.stats.blockedDrivers },\n task.stats.blockedDrivers\n ),\n _react2.default.createElement(\n Td,\n { column: \"splitsDone\", value: task.stats.completedDrivers },\n task.stats.completedDrivers\n ),\n _react2.default.createElement(\n Td,\n { column: \"elapsedTime\", value: (0, _utils.parseDuration)(task.stats.elapsedTime) },\n task.stats.elapsedTime\n ),\n _react2.default.createElement(\n Td,\n { column: \"cpuTime\", value: (0, _utils.parseDuration)(task.stats.totalCpuTime) },\n task.stats.totalCpuTime\n ),\n _react2.default.createElement(\n Td,\n { column: \"bufferedBytes\", value: task.outputBuffers.totalBufferedBytes },\n (0, _utils.formatDataSizeBytes)(task.outputBuffers.totalBufferedBytes)\n )\n );\n });\n\n return _react2.default.createElement(\n Table,\n { id: \"tasks\", className: \"table table-striped sortable\", sortable: [{\n column: 'id',\n sortFunction: TaskList.compareTaskId\n }, 'host', 'state', 'splitsPending', 'splitsRunning', 'splitsBlocked', 'splitsDone', 'rows', 'rowsSec', 'bytes', 'bytesSec', 'elapsedTime', 'cpuTime', 'bufferedBytes'],\n defaultSort: { column: 'id', direction: 'asc' } },\n _react2.default.createElement(\n Thead,\n null,\n _react2.default.createElement(\n Th,\n { column: \"id\" },\n \"ID\"\n ),\n _react2.default.createElement(\n Th,\n { column: \"host\" },\n \"Host\"\n ),\n _react2.default.createElement(\n Th,\n { column: \"state\" },\n \"State\"\n ),\n _react2.default.createElement(\n Th,\n { column: \"splitsPending\" },\n _react2.default.createElement(\"span\", { className: \"glyphicon glyphicon-pause\", style: _utils.GLYPHICON_HIGHLIGHT, \"data-toggle\": \"tooltip\", \"data-placement\": \"top\",\n title: \"Pending splits\" })\n ),\n _react2.default.createElement(\n Th,\n { column: \"splitsRunning\" },\n _react2.default.createElement(\"span\", { className: \"glyphicon glyphicon-play\", style: _utils.GLYPHICON_HIGHLIGHT, \"data-toggle\": \"tooltip\", \"data-placement\": \"top\",\n title: \"Running splits\" })\n ),\n _react2.default.createElement(\n Th,\n { column: \"splitsBlocked\" },\n _react2.default.createElement(\"span\", { className: \"glyphicon glyphicon-bookmark\", style: _utils.GLYPHICON_HIGHLIGHT, \"data-toggle\": \"tooltip\", \"data-placement\": \"top\",\n title: \"Blocked splits\" })\n ),\n _react2.default.createElement(\n Th,\n { column: \"splitsDone\" },\n _react2.default.createElement(\"span\", { className: \"glyphicon glyphicon-ok\", style: _utils.GLYPHICON_HIGHLIGHT, \"data-toggle\": \"tooltip\", \"data-placement\": \"top\",\n title: \"Completed splits\" })\n ),\n _react2.default.createElement(\n Th,\n { column: \"rows\" },\n \"Rows\"\n ),\n _react2.default.createElement(\n Th,\n { column: \"rowsSec\" },\n \"Rows/s\"\n ),\n _react2.default.createElement(\n Th,\n { column: \"bytes\" },\n \"Bytes\"\n ),\n _react2.default.createElement(\n Th,\n { column: \"bytesSec\" },\n \"Bytes/s\"\n ),\n _react2.default.createElement(\n Th,\n { column: \"elapsedTime\" },\n \"Elapsed\"\n ),\n _react2.default.createElement(\n Th,\n { column: \"cpuTime\" },\n \"CPU Time\"\n ),\n _react2.default.createElement(\n Th,\n { column: \"bufferedBytes\" },\n \"Buffered\"\n )\n ),\n renderedTasks\n );\n }\n }], [{\n key: \"removeQueryId\",\n value: function removeQueryId(id) {\n var pos = id.indexOf('.');\n if (pos !== -1) {\n return id.substring(pos + 1);\n }\n return id;\n }\n }, {\n key: \"compareTaskId\",\n value: function compareTaskId(taskA, taskB) {\n var taskIdArrA = TaskList.removeQueryId(taskA).split(\".\");\n var taskIdArrB = TaskList.removeQueryId(taskB).split(\".\");\n\n if (taskIdArrA.length > taskIdArrB.length) {\n return 1;\n }\n for (var i = 0; i < taskIdArrA.length; i++) {\n var anum = Number.parseInt(taskIdArrA[i]);\n var bnum = Number.parseInt(taskIdArrB[i]);\n if (anum !== bnum) {\n return anum > bnum ? 1 : -1;\n }\n }\n\n return 0;\n }\n }, {\n key: \"showPortNumbers\",\n value: function showPortNumbers(tasks) {\n // check if any host has multiple port numbers\n var hostToPortNumber = {};\n for (var i = 0; i < tasks.length; i++) {\n var taskUri = tasks[i].taskStatus.self;\n var hostname = (0, _utils.getHostname)(taskUri);\n var port = (0, _utils.getPort)(taskUri);\n if (hostname in hostToPortNumber && hostToPortNumber[hostname] !== port) {\n return true;\n }\n hostToPortNumber[hostname] = port;\n }\n\n return false;\n }\n }, {\n key: \"formatState\",\n value: function formatState(state, fullyBlocked) {\n if (fullyBlocked && state === \"RUNNING\") {\n return \"BLOCKED\";\n } else {\n return state;\n }\n }\n }]);\n\n return TaskList;\n}(_react2.default.Component);\n\nvar BAR_CHART_WIDTH = 800;\n\nvar BAR_CHART_PROPERTIES = {\n type: 'bar',\n barSpacing: '0',\n height: '80px',\n barColor: '#747F96',\n zeroColor: '#8997B3',\n chartRangeMin: 0,\n tooltipClassname: 'sparkline-tooltip',\n tooltipFormat: 'Task {{offset:offset}} - {{value}}',\n disableHiddenCheck: true\n};\n\nvar HISTOGRAM_WIDTH = 175;\n\nvar HISTOGRAM_PROPERTIES = {\n type: 'bar',\n barSpacing: '0',\n height: '80px',\n barColor: '#747F96',\n zeroColor: '#747F96',\n zeroAxis: true,\n chartRangeMin: 0,\n tooltipClassname: 'sparkline-tooltip',\n tooltipFormat: '{{offset:offset}} -- {{value}} tasks',\n disableHiddenCheck: true\n};\n\nvar StageSummary = function (_React$Component2) {\n _inherits(StageSummary, _React$Component2);\n\n function StageSummary(props) {\n _classCallCheck(this, StageSummary);\n\n var _this2 = _possibleConstructorReturn(this, (StageSummary.__proto__ || Object.getPrototypeOf(StageSummary)).call(this, props));\n\n _this2.state = {\n expanded: false,\n lastRender: null\n };\n return _this2;\n }\n\n _createClass(StageSummary, [{\n key: \"getExpandedIcon\",\n value: function getExpandedIcon() {\n return this.state.expanded ? \"glyphicon-chevron-up\" : \"glyphicon-chevron-down\";\n }\n }, {\n key: \"getExpandedStyle\",\n value: function getExpandedStyle() {\n return this.state.expanded ? {} : { display: \"none\" };\n }\n }, {\n key: \"toggleExpanded\",\n value: function toggleExpanded() {\n this.setState({\n expanded: !this.state.expanded\n });\n }\n }, {\n key: \"componentDidUpdate\",\n value: function componentDidUpdate() {\n var stage = this.props.stage;\n var numTasks = stage.tasks.length;\n\n // sort the x-axis\n stage.tasks.sort(function (taskA, taskB) {\n return (0, _utils.getTaskNumber)(taskA.taskStatus.taskId) - (0, _utils.getTaskNumber)(taskB.taskStatus.taskId);\n });\n\n var scheduledTimes = stage.tasks.map(function (task) {\n return (0, _utils.parseDuration)(task.stats.totalScheduledTime);\n });\n var cpuTimes = stage.tasks.map(function (task) {\n return (0, _utils.parseDuration)(task.stats.totalCpuTime);\n });\n\n // prevent multiple calls to componentDidUpdate (resulting from calls to setState or otherwise) within the refresh interval from re-rendering sparklines/charts\n if (this.state.lastRender === null || Date.now() - this.state.lastRender >= 1000) {\n var renderTimestamp = Date.now();\n var stageId = (0, _utils.getStageNumber)(stage.stageId);\n\n StageSummary.renderHistogram('#scheduled-time-histogram-' + stageId, scheduledTimes, _utils.formatDuration);\n StageSummary.renderHistogram('#cpu-time-histogram-' + stageId, cpuTimes, _utils.formatDuration);\n\n if (this.state.expanded) {\n // this needs to be a string otherwise it will also be passed to numberFormatter\n var tooltipValueLookups = { 'offset': {} };\n for (var i = 0; i < numTasks; i++) {\n tooltipValueLookups['offset'][i] = (0, _utils.getStageNumber)(stage.stageId) + \".\" + i;\n }\n\n var stageBarChartProperties = $.extend({}, BAR_CHART_PROPERTIES, { barWidth: BAR_CHART_WIDTH / numTasks, tooltipValueLookups: tooltipValueLookups });\n\n $('#scheduled-time-bar-chart-' + stageId).sparkline(scheduledTimes, $.extend({}, stageBarChartProperties, { numberFormatter: _utils.formatDuration }));\n $('#cpu-time-bar-chart-' + stageId).sparkline(cpuTimes, $.extend({}, stageBarChartProperties, { numberFormatter: _utils.formatDuration }));\n }\n\n this.setState({\n lastRender: renderTimestamp\n });\n }\n }\n }, {\n key: \"render\",\n value: function render() {\n var stage = this.props.stage;\n if (stage === undefined || !stage.hasOwnProperty('plan')) {\n return _react2.default.createElement(\n \"tr\",\n null,\n _react2.default.createElement(\n \"td\",\n null,\n \"Information about this stage is unavailable.\"\n )\n );\n }\n\n var totalBufferedBytes = stage.tasks.map(function (task) {\n return task.outputBuffers.totalBufferedBytes;\n }).reduce(function (a, b) {\n return a + b;\n }, 0);\n\n var stageId = (0, _utils.getStageNumber)(stage.stageId);\n\n return _react2.default.createElement(\n \"tr\",\n null,\n _react2.default.createElement(\n \"td\",\n { className: \"stage-id\" },\n _react2.default.createElement(\n \"div\",\n { className: \"stage-state-color\", style: { borderLeftColor: (0, _utils.getStageStateColor)(stage) } },\n stageId\n )\n ),\n _react2.default.createElement(\n \"td\",\n null,\n _react2.default.createElement(\n \"table\",\n { className: \"table single-stage-table\" },\n _react2.default.createElement(\n \"tbody\",\n null,\n _react2.default.createElement(\n \"tr\",\n null,\n _react2.default.createElement(\n \"td\",\n null,\n _react2.default.createElement(\n \"table\",\n { className: \"stage-table stage-table-time\" },\n _react2.default.createElement(\n \"thead\",\n null,\n _react2.default.createElement(\n \"tr\",\n null,\n _react2.default.createElement(\n \"th\",\n { className: \"stage-table-stat-title stage-table-stat-header\" },\n \"Time\"\n ),\n _react2.default.createElement(\"th\", null)\n )\n ),\n _react2.default.createElement(\n \"tbody\",\n null,\n _react2.default.createElement(\n \"tr\",\n null,\n _react2.default.createElement(\n \"td\",\n { className: \"stage-table-stat-title\" },\n \"Scheduled\"\n ),\n _react2.default.createElement(\n \"td\",\n { className: \"stage-table-stat-text\" },\n stage.stageStats.totalScheduledTime\n )\n ),\n _react2.default.createElement(\n \"tr\",\n null,\n _react2.default.createElement(\n \"td\",\n { className: \"stage-table-stat-title\" },\n \"Blocked\"\n ),\n _react2.default.createElement(\n \"td\",\n { className: \"stage-table-stat-text\" },\n stage.stageStats.totalBlockedTime\n )\n ),\n _react2.default.createElement(\n \"tr\",\n null,\n _react2.default.createElement(\n \"td\",\n { className: \"stage-table-stat-title\" },\n \"CPU\"\n ),\n _react2.default.createElement(\n \"td\",\n { className: \"stage-table-stat-text\" },\n stage.stageStats.totalCpuTime\n )\n )\n )\n )\n ),\n _react2.default.createElement(\n \"td\",\n null,\n _react2.default.createElement(\n \"table\",\n { className: \"stage-table stage-table-memory\" },\n _react2.default.createElement(\n \"thead\",\n null,\n _react2.default.createElement(\n \"tr\",\n null,\n _react2.default.createElement(\n \"th\",\n { className: \"stage-table-stat-title stage-table-stat-header\" },\n \"Memory\"\n ),\n _react2.default.createElement(\"th\", null)\n )\n ),\n _react2.default.createElement(\n \"tbody\",\n null,\n _react2.default.createElement(\n \"tr\",\n null,\n _react2.default.createElement(\n \"td\",\n { className: \"stage-table-stat-title\" },\n \"Cumulative\"\n ),\n _react2.default.createElement(\n \"td\",\n { className: \"stage-table-stat-text\" },\n (0, _utils.formatDataSizeBytes)(stage.stageStats.cumulativeUserMemory / 1000)\n )\n ),\n _react2.default.createElement(\n \"tr\",\n null,\n _react2.default.createElement(\n \"td\",\n { className: \"stage-table-stat-title\" },\n \"Current\"\n ),\n _react2.default.createElement(\n \"td\",\n { className: \"stage-table-stat-text\" },\n (0, _utils.parseAndFormatDataSize)(stage.stageStats.userMemoryReservation)\n )\n ),\n _react2.default.createElement(\n \"tr\",\n null,\n _react2.default.createElement(\n \"td\",\n { className: \"stage-table-stat-title\" },\n \"Buffers\"\n ),\n _react2.default.createElement(\n \"td\",\n { className: \"stage-table-stat-text\" },\n (0, _utils.formatDataSize)(totalBufferedBytes)\n )\n ),\n _react2.default.createElement(\n \"tr\",\n null,\n _react2.default.createElement(\n \"td\",\n { className: \"stage-table-stat-title\" },\n \"Peak\"\n ),\n _react2.default.createElement(\n \"td\",\n { className: \"stage-table-stat-text\" },\n (0, _utils.parseAndFormatDataSize)(stage.stageStats.peakUserMemoryReservation)\n )\n )\n )\n )\n ),\n _react2.default.createElement(\n \"td\",\n null,\n _react2.default.createElement(\n \"table\",\n { className: \"stage-table stage-table-tasks\" },\n _react2.default.createElement(\n \"thead\",\n null,\n _react2.default.createElement(\n \"tr\",\n null,\n _react2.default.createElement(\n \"th\",\n { className: \"stage-table-stat-title stage-table-stat-header\" },\n \"Tasks\"\n ),\n _react2.default.createElement(\"th\", null)\n )\n ),\n _react2.default.createElement(\n \"tbody\",\n null,\n _react2.default.createElement(\n \"tr\",\n null,\n _react2.default.createElement(\n \"td\",\n { className: \"stage-table-stat-title\" },\n \"Pending\"\n ),\n _react2.default.createElement(\n \"td\",\n { className: \"stage-table-stat-text\" },\n stage.tasks.filter(function (task) {\n return task.taskStatus.state === \"PLANNED\";\n }).length\n )\n ),\n _react2.default.createElement(\n \"tr\",\n null,\n _react2.default.createElement(\n \"td\",\n { className: \"stage-table-stat-title\" },\n \"Running\"\n ),\n _react2.default.createElement(\n \"td\",\n { className: \"stage-table-stat-text\" },\n stage.tasks.filter(function (task) {\n return task.taskStatus.state === \"RUNNING\";\n }).length\n )\n ),\n _react2.default.createElement(\n \"tr\",\n null,\n _react2.default.createElement(\n \"td\",\n { className: \"stage-table-stat-title\" },\n \"Blocked\"\n ),\n _react2.default.createElement(\n \"td\",\n { className: \"stage-table-stat-text\" },\n stage.tasks.filter(function (task) {\n return task.stats.fullyBlocked;\n }).length\n )\n ),\n _react2.default.createElement(\n \"tr\",\n null,\n _react2.default.createElement(\n \"td\",\n { className: \"stage-table-stat-title\" },\n \"Total\"\n ),\n _react2.default.createElement(\n \"td\",\n { className: \"stage-table-stat-text\" },\n stage.tasks.length\n )\n )\n )\n )\n ),\n _react2.default.createElement(\n \"td\",\n null,\n _react2.default.createElement(\n \"table\",\n { className: \"stage-table histogram-table\" },\n _react2.default.createElement(\n \"thead\",\n null,\n _react2.default.createElement(\n \"tr\",\n null,\n _react2.default.createElement(\n \"th\",\n { className: \"stage-table-stat-title stage-table-chart-header\" },\n \"Scheduled Time Skew\"\n )\n )\n ),\n _react2.default.createElement(\n \"tbody\",\n null,\n _react2.default.createElement(\n \"tr\",\n null,\n _react2.default.createElement(\n \"td\",\n { className: \"histogram-container\" },\n _react2.default.createElement(\n \"span\",\n { className: \"histogram\", id: \"scheduled-time-histogram-\" + stageId },\n _react2.default.createElement(\"div\", { className: \"loader\" })\n )\n )\n )\n )\n )\n ),\n _react2.default.createElement(\n \"td\",\n null,\n _react2.default.createElement(\n \"table\",\n { className: \"stage-table histogram-table\" },\n _react2.default.createElement(\n \"thead\",\n null,\n _react2.default.createElement(\n \"tr\",\n null,\n _react2.default.createElement(\n \"th\",\n { className: \"stage-table-stat-title stage-table-chart-header\" },\n \"CPU Time Skew\"\n )\n )\n ),\n _react2.default.createElement(\n \"tbody\",\n null,\n _react2.default.createElement(\n \"tr\",\n null,\n _react2.default.createElement(\n \"td\",\n { className: \"histogram-container\" },\n _react2.default.createElement(\n \"span\",\n { className: \"histogram\", id: \"cpu-time-histogram-\" + stageId },\n _react2.default.createElement(\"div\", { className: \"loader\" })\n )\n )\n )\n )\n )\n ),\n _react2.default.createElement(\n \"td\",\n { className: \"expand-charts-container\" },\n _react2.default.createElement(\n \"a\",\n { onClick: this.toggleExpanded.bind(this), className: \"expand-charts-button\" },\n _react2.default.createElement(\"span\", { className: \"glyphicon \" + this.getExpandedIcon(), style: _utils.GLYPHICON_HIGHLIGHT, \"data-toggle\": \"tooltip\", \"data-placement\": \"top\", title: \"More\" })\n )\n )\n ),\n _react2.default.createElement(\n \"tr\",\n { style: this.getExpandedStyle() },\n _react2.default.createElement(\n \"td\",\n { colSpan: \"6\" },\n _react2.default.createElement(\n \"table\",\n { className: \"expanded-chart\" },\n _react2.default.createElement(\n \"tbody\",\n null,\n _react2.default.createElement(\n \"tr\",\n null,\n _react2.default.createElement(\n \"td\",\n { className: \"stage-table-stat-title expanded-chart-title\" },\n \"Task Scheduled Time\"\n ),\n _react2.default.createElement(\n \"td\",\n { className: \"bar-chart-container\" },\n _react2.default.createElement(\n \"span\",\n { className: \"bar-chart\", id: \"scheduled-time-bar-chart-\" + stageId },\n _react2.default.createElement(\"div\", { className: \"loader\" })\n )\n )\n )\n )\n )\n )\n ),\n _react2.default.createElement(\n \"tr\",\n { style: this.getExpandedStyle() },\n _react2.default.createElement(\n \"td\",\n { colSpan: \"6\" },\n _react2.default.createElement(\n \"table\",\n { className: \"expanded-chart\" },\n _react2.default.createElement(\n \"tbody\",\n null,\n _react2.default.createElement(\n \"tr\",\n null,\n _react2.default.createElement(\n \"td\",\n { className: \"stage-table-stat-title expanded-chart-title\" },\n \"Task CPU Time\"\n ),\n _react2.default.createElement(\n \"td\",\n { className: \"bar-chart-container\" },\n _react2.default.createElement(\n \"span\",\n { className: \"bar-chart\", id: \"cpu-time-bar-chart-\" + stageId },\n _react2.default.createElement(\"div\", { className: \"loader\" })\n )\n )\n )\n )\n )\n )\n )\n )\n )\n )\n );\n }\n }], [{\n key: \"renderHistogram\",\n value: function renderHistogram(histogramId, inputData, numberFormatter) {\n var numBuckets = Math.min(HISTOGRAM_WIDTH, Math.sqrt(inputData.length));\n var dataMin = Math.min.apply(null, inputData);\n var dataMax = Math.max.apply(null, inputData);\n var bucketSize = (dataMax - dataMin) / numBuckets;\n\n var histogramData = [];\n if (bucketSize === 0) {\n histogramData = [inputData.length];\n } else {\n for (var i = 0; i < numBuckets + 1; i++) {\n histogramData.push(0);\n }\n\n for (var _i in inputData) {\n var dataPoint = inputData[_i];\n var bucket = Math.floor((dataPoint - dataMin) / bucketSize);\n histogramData[bucket] = histogramData[bucket] + 1;\n }\n }\n\n var tooltipValueLookups = { 'offset': {} };\n for (var _i2 = 0; _i2 < histogramData.length; _i2++) {\n tooltipValueLookups['offset'][_i2] = numberFormatter(dataMin + _i2 * bucketSize) + \"-\" + numberFormatter(dataMin + (_i2 + 1) * bucketSize);\n }\n\n var stageHistogramProperties = $.extend({}, HISTOGRAM_PROPERTIES, { barWidth: HISTOGRAM_WIDTH / histogramData.length, tooltipValueLookups: tooltipValueLookups });\n $(histogramId).sparkline(histogramData, stageHistogramProperties);\n }\n }]);\n\n return StageSummary;\n}(_react2.default.Component);\n\nvar StageList = function (_React$Component3) {\n _inherits(StageList, _React$Component3);\n\n function StageList() {\n _classCallCheck(this, StageList);\n\n return _possibleConstructorReturn(this, (StageList.__proto__ || Object.getPrototypeOf(StageList)).apply(this, arguments));\n }\n\n _createClass(StageList, [{\n key: \"getStages\",\n value: function getStages(stage) {\n if (stage === undefined || !stage.hasOwnProperty('subStages')) {\n return [];\n }\n\n return [].concat.apply(stage, stage.subStages.map(this.getStages, this));\n }\n }, {\n key: \"render\",\n value: function render() {\n var stages = this.getStages(this.props.outputStage);\n\n if (stages === undefined || stages.length === 0) {\n return _react2.default.createElement(\n \"div\",\n { className: \"row\" },\n _react2.default.createElement(\n \"div\",\n { className: \"col-xs-12\" },\n \"No stage information available.\"\n )\n );\n }\n\n var renderedStages = stages.map(function (stage) {\n return _react2.default.createElement(StageSummary, { key: stage.stageId, stage: stage });\n });\n\n return _react2.default.createElement(\n \"div\",\n { className: \"row\" },\n _react2.default.createElement(\n \"div\",\n { className: \"col-xs-12\" },\n _react2.default.createElement(\n \"table\",\n { className: \"table\", id: \"stage-list\" },\n _react2.default.createElement(\n \"tbody\",\n null,\n renderedStages\n )\n )\n )\n );\n }\n }]);\n\n return StageList;\n}(_react2.default.Component);\n\nvar SMALL_SPARKLINE_PROPERTIES = {\n width: '100%',\n height: '57px',\n fillColor: '#3F4552',\n lineColor: '#747F96',\n spotColor: '#1EDCFF',\n tooltipClassname: 'sparkline-tooltip',\n disableHiddenCheck: true\n};\n\nvar TASK_FILTER = {\n ALL: function ALL() {\n return true;\n },\n PLANNED: function PLANNED(state) {\n return state === 'PLANNED';\n },\n RUNNING: function RUNNING(state) {\n return state === 'RUNNING';\n },\n FINISHED: function FINISHED(state) {\n return state === 'FINISHED';\n },\n FAILED: function FAILED(state) {\n return state === 'FAILED' || state === 'ABORTED' || state === 'CANCELED';\n }\n};\n\nvar QueryDetail = exports.QueryDetail = function (_React$Component4) {\n _inherits(QueryDetail, _React$Component4);\n\n function QueryDetail(props) {\n _classCallCheck(this, QueryDetail);\n\n var _this4 = _possibleConstructorReturn(this, (QueryDetail.__proto__ || Object.getPrototypeOf(QueryDetail)).call(this, props));\n\n _this4.state = {\n query: null,\n lastSnapshotStages: null,\n lastSnapshotTasks: null,\n\n lastScheduledTime: 0,\n lastCpuTime: 0,\n lastRowInput: 0,\n lastByteInput: 0,\n lastPhysicalInput: 0,\n lastPhysicalTime: 0,\n\n scheduledTimeRate: [],\n cpuTimeRate: [],\n rowInputRate: [],\n byteInputRate: [],\n physicalInputRate: [],\n\n reservedMemory: [],\n\n initialized: false,\n queryEnded: false,\n renderingEnded: false,\n\n lastRefresh: null,\n lastRender: null,\n\n stageRefresh: true,\n taskRefresh: true,\n\n taskFilter: TASK_FILTER.ALL\n };\n\n _this4.refreshLoop = _this4.refreshLoop.bind(_this4);\n return _this4;\n }\n\n _createClass(QueryDetail, [{\n key: \"resetTimer\",\n value: function resetTimer() {\n clearTimeout(this.timeoutId);\n // stop refreshing when query finishes or fails\n if (this.state.query === null || !this.state.queryEnded) {\n // task.info-update-interval is set to 3 seconds by default\n this.timeoutId = setTimeout(this.refreshLoop, 3000);\n }\n }\n }, {\n key: \"refreshLoop\",\n value: function refreshLoop() {\n var _this5 = this;\n\n clearTimeout(this.timeoutId); // to stop multiple series of refreshLoop from going on simultaneously\n var queryId = (0, _utils.getFirstParameter)(window.location.search);\n $.get('/ui/api/query/' + queryId, function (query) {\n var lastSnapshotStages = this.state.lastSnapshotStage;\n if (this.state.stageRefresh) {\n lastSnapshotStages = query.outputStage;\n }\n var lastSnapshotTasks = this.state.lastSnapshotTasks;\n if (this.state.taskRefresh) {\n lastSnapshotTasks = query.outputStage;\n }\n\n var lastRefresh = this.state.lastRefresh;\n var lastScheduledTime = this.state.lastScheduledTime;\n var lastCpuTime = this.state.lastCpuTime;\n var lastRowInput = this.state.lastRowInput;\n var lastByteInput = this.state.lastByteInput;\n var lastPhysicalInput = this.state.lastPhysicalInput;\n var lastPhysicalTime = this.state.lastPhysicalTime;\n var alreadyEnded = this.state.queryEnded;\n var nowMillis = Date.now();\n\n this.setState({\n query: query,\n lastSnapshotStage: lastSnapshotStages,\n lastSnapshotTasks: lastSnapshotTasks,\n\n lastPhysicalTime: (0, _utils.parseDuration)(query.queryStats.physicalInputReadTime),\n lastScheduledTime: (0, _utils.parseDuration)(query.queryStats.totalScheduledTime),\n lastCpuTime: (0, _utils.parseDuration)(query.queryStats.totalCpuTime),\n lastRowInput: query.queryStats.processedInputPositions,\n lastByteInput: (0, _utils.parseDataSize)(query.queryStats.processedInputDataSize),\n lastPhysicalInput: (0, _utils.parseDataSize)(query.queryStats.physicalInputDataSize),\n\n initialized: true,\n queryEnded: !!query.finalQueryInfo,\n\n lastRefresh: nowMillis\n });\n\n // i.e. don't show sparklines if we've already decided not to update or if we don't have one previous measurement\n if (alreadyEnded || lastRefresh === null && query.state === \"RUNNING\") {\n this.resetTimer();\n return;\n }\n\n if (lastRefresh === null) {\n lastRefresh = nowMillis - (0, _utils.parseDuration)(query.queryStats.elapsedTime);\n }\n\n var elapsedSecsSinceLastRefresh = (nowMillis - lastRefresh) / 1000.0;\n if (elapsedSecsSinceLastRefresh >= 0) {\n var currentScheduledTimeRate = ((0, _utils.parseDuration)(query.queryStats.totalScheduledTime) - lastScheduledTime) / (elapsedSecsSinceLastRefresh * 1000);\n var currentCpuTimeRate = ((0, _utils.parseDuration)(query.queryStats.totalCpuTime) - lastCpuTime) / (elapsedSecsSinceLastRefresh * 1000);\n var currentPhysicalReadTime = ((0, _utils.parseDuration)(query.queryStats.physicalInputReadTime) - lastPhysicalTime) / 1000;\n var currentRowInputRate = (query.queryStats.processedInputPositions - lastRowInput) / elapsedSecsSinceLastRefresh;\n var currentByteInputRate = ((0, _utils.parseDataSize)(query.queryStats.processedInputDataSize) - lastByteInput) / elapsedSecsSinceLastRefresh;\n var currentPhysicalInputRate = currentPhysicalReadTime > 0 ? ((0, _utils.parseDataSize)(query.queryStats.physicalInputDataSize) - lastPhysicalInput) / currentPhysicalReadTime : 0;\n\n this.setState({\n scheduledTimeRate: (0, _utils.addToHistory)(currentScheduledTimeRate, this.state.scheduledTimeRate),\n cpuTimeRate: (0, _utils.addToHistory)(currentCpuTimeRate, this.state.cpuTimeRate),\n rowInputRate: (0, _utils.addToHistory)(currentRowInputRate, this.state.rowInputRate),\n byteInputRate: (0, _utils.addToHistory)(currentByteInputRate, this.state.byteInputRate),\n reservedMemory: (0, _utils.addToHistory)((0, _utils.parseDataSize)(query.queryStats.totalMemoryReservation), this.state.reservedMemory),\n physicalInputRate: (0, _utils.addToHistory)(currentPhysicalInputRate, this.state.physicalInputRate)\n });\n }\n this.resetTimer();\n }.bind(this)).fail(function () {\n _this5.setState({\n initialized: true\n });\n _this5.resetTimer();\n });\n }\n }, {\n key: \"handleTaskRefreshClick\",\n value: function handleTaskRefreshClick() {\n if (this.state.taskRefresh) {\n this.setState({\n taskRefresh: false,\n lastSnapshotTasks: this.state.query.outputStage\n });\n } else {\n this.setState({\n taskRefresh: true\n });\n }\n }\n }, {\n key: \"renderTaskRefreshButton\",\n value: function renderTaskRefreshButton() {\n if (this.state.taskRefresh) {\n return _react2.default.createElement(\n \"button\",\n { className: \"btn btn-info live-button\", onClick: this.handleTaskRefreshClick.bind(this) },\n \"Auto-Refresh: On\"\n );\n } else {\n return _react2.default.createElement(\n \"button\",\n { className: \"btn btn-info live-button\", onClick: this.handleTaskRefreshClick.bind(this) },\n \"Auto-Refresh: Off\"\n );\n }\n }\n }, {\n key: \"handleStageRefreshClick\",\n value: function handleStageRefreshClick() {\n if (this.state.stageRefresh) {\n this.setState({\n stageRefresh: false,\n lastSnapshotStages: this.state.query.outputStage\n });\n } else {\n this.setState({\n stageRefresh: true\n });\n }\n }\n }, {\n key: \"renderStageRefreshButton\",\n value: function renderStageRefreshButton() {\n if (this.state.stageRefresh) {\n return _react2.default.createElement(\n \"button\",\n { className: \"btn btn-info live-button\", onClick: this.handleStageRefreshClick.bind(this) },\n \"Auto-Refresh: On\"\n );\n } else {\n return _react2.default.createElement(\n \"button\",\n { className: \"btn btn-info live-button\", onClick: this.handleStageRefreshClick.bind(this) },\n \"Auto-Refresh: Off\"\n );\n }\n }\n }, {\n key: \"renderTaskFilterListItem\",\n value: function renderTaskFilterListItem(taskFilter, taskFilterText) {\n return _react2.default.createElement(\n \"li\",\n null,\n _react2.default.createElement(\n \"a\",\n { href: \"#\", className: this.state.taskFilter === taskFilter ? \"selected\" : \"\", onClick: this.handleTaskFilterClick.bind(this, taskFilter) },\n taskFilterText\n )\n );\n }\n }, {\n key: \"handleTaskFilterClick\",\n value: function handleTaskFilterClick(filter, event) {\n this.setState({\n taskFilter: filter\n });\n event.preventDefault();\n }\n }, {\n key: \"getTasksFromStage\",\n value: function getTasksFromStage(stage) {\n if (stage === undefined || !stage.hasOwnProperty('subStages') || !stage.hasOwnProperty('tasks')) {\n return [];\n }\n\n return [].concat.apply(stage.tasks, stage.subStages.map(this.getTasksFromStage, this));\n }\n }, {\n key: \"componentDidMount\",\n value: function componentDidMount() {\n this.refreshLoop();\n }\n }, {\n key: \"componentDidUpdate\",\n value: function componentDidUpdate() {\n // prevent multiple calls to componentDidUpdate (resulting from calls to setState or otherwise) within the refresh interval from re-rendering sparklines/charts\n if (this.state.lastRender === null || Date.now() - this.state.lastRender >= 1000 || this.state.ended && !this.state.renderingEnded) {\n var renderTimestamp = Date.now();\n $('#scheduled-time-rate-sparkline').sparkline(this.state.scheduledTimeRate, $.extend({}, SMALL_SPARKLINE_PROPERTIES, {\n chartRangeMin: 0,\n numberFormatter: _utils.precisionRound\n }));\n $('#cpu-time-rate-sparkline').sparkline(this.state.cpuTimeRate, $.extend({}, SMALL_SPARKLINE_PROPERTIES, { chartRangeMin: 0, numberFormatter: _utils.precisionRound }));\n $('#row-input-rate-sparkline').sparkline(this.state.rowInputRate, $.extend({}, SMALL_SPARKLINE_PROPERTIES, { numberFormatter: _utils.formatCount }));\n $('#byte-input-rate-sparkline').sparkline(this.state.byteInputRate, $.extend({}, SMALL_SPARKLINE_PROPERTIES, { numberFormatter: _utils.formatDataSize }));\n $('#reserved-memory-sparkline').sparkline(this.state.reservedMemory, $.extend({}, SMALL_SPARKLINE_PROPERTIES, { numberFormatter: _utils.formatDataSize }));\n $('#physical-input-rate-sparkline').sparkline(this.state.physicalInputRate, $.extend({}, SMALL_SPARKLINE_PROPERTIES, { numberFormatter: _utils.formatDataSize }));\n\n if (this.state.lastRender === null) {\n $('#query').each(function (i, block) {\n hljs.highlightBlock(block);\n });\n\n $('#prepared-query').each(function (i, block) {\n hljs.highlightBlock(block);\n });\n }\n\n this.setState({\n renderingEnded: this.state.ended,\n lastRender: renderTimestamp\n });\n }\n\n $('[data-toggle=\"tooltip\"]').tooltip();\n new window.ClipboardJS('.copy-button');\n }\n }, {\n key: \"renderTasks\",\n value: function renderTasks() {\n var _this6 = this;\n\n if (this.state.lastSnapshotTasks === null) {\n return;\n }\n\n var tasks = this.getTasksFromStage(this.state.lastSnapshotTasks).filter(function (task) {\n return _this6.state.taskFilter(task.taskStatus.state);\n }, this);\n\n return _react2.default.createElement(\n \"div\",\n null,\n _react2.default.createElement(\n \"div\",\n { className: \"row\" },\n _react2.default.createElement(\n \"div\",\n { className: \"col-xs-9\" },\n _react2.default.createElement(\n \"h3\",\n null,\n \"Tasks\"\n )\n ),\n _react2.default.createElement(\n \"div\",\n { className: \"col-xs-3\" },\n _react2.default.createElement(\n \"table\",\n { className: \"header-inline-links\" },\n _react2.default.createElement(\n \"tbody\",\n null,\n _react2.default.createElement(\n \"tr\",\n null,\n _react2.default.createElement(\n \"td\",\n null,\n _react2.default.createElement(\n \"div\",\n { className: \"input-group-btn text-right\" },\n _react2.default.createElement(\n \"button\",\n { type: \"button\", className: \"btn btn-default dropdown-toggle pull-right text-right\", \"data-toggle\": \"dropdown\", \"aria-haspopup\": \"true\",\n \"aria-expanded\": \"false\" },\n \"Show \",\n _react2.default.createElement(\"span\", { className: \"caret\" })\n ),\n _react2.default.createElement(\n \"ul\",\n { className: \"dropdown-menu\" },\n this.renderTaskFilterListItem(TASK_FILTER.ALL, \"All\"),\n this.renderTaskFilterListItem(TASK_FILTER.PLANNED, \"Planned\"),\n this.renderTaskFilterListItem(TASK_FILTER.RUNNING, \"Running\"),\n this.renderTaskFilterListItem(TASK_FILTER.FINISHED, \"Finished\"),\n this.renderTaskFilterListItem(TASK_FILTER.FAILED, \"Aborted/Canceled/Failed\")\n )\n )\n ),\n _react2.default.createElement(\n \"td\",\n null,\n \"\\xA0\\xA0\",\n this.renderTaskRefreshButton()\n )\n )\n )\n )\n )\n ),\n _react2.default.createElement(\n \"div\",\n { className: \"row\" },\n _react2.default.createElement(\n \"div\",\n { className: \"col-xs-12\" },\n _react2.default.createElement(TaskList, { key: this.state.query.queryId, tasks: tasks })\n )\n )\n );\n }\n }, {\n key: \"renderStages\",\n value: function renderStages() {\n if (this.state.lastSnapshotStage === null) {\n return;\n }\n\n return _react2.default.createElement(\n \"div\",\n null,\n _react2.default.createElement(\n \"div\",\n { className: \"row\" },\n _react2.default.createElement(\n \"div\",\n { className: \"col-xs-9\" },\n _react2.default.createElement(\n \"h3\",\n null,\n \"Stages\"\n )\n ),\n _react2.default.createElement(\n \"div\",\n { className: \"col-xs-3\" },\n _react2.default.createElement(\n \"table\",\n { className: \"header-inline-links\" },\n _react2.default.createElement(\n \"tbody\",\n null,\n _react2.default.createElement(\n \"tr\",\n null,\n _react2.default.createElement(\n \"td\",\n null,\n this.renderStageRefreshButton()\n )\n )\n )\n )\n )\n ),\n _react2.default.createElement(\n \"div\",\n { className: \"row\" },\n _react2.default.createElement(\n \"div\",\n { className: \"col-xs-12\" },\n _react2.default.createElement(StageList, { key: this.state.query.queryId, outputStage: this.state.lastSnapshotStage })\n )\n )\n );\n }\n }, {\n key: \"renderPreparedQuery\",\n value: function renderPreparedQuery() {\n var query = this.state.query;\n if (!query.hasOwnProperty('preparedQuery') || query.preparedQuery === null) {\n return;\n }\n\n return _react2.default.createElement(\n \"div\",\n { className: \"col-xs-12\" },\n _react2.default.createElement(\n \"h3\",\n null,\n \"Prepared Query\",\n _react2.default.createElement(\n \"a\",\n { className: \"btn copy-button\", \"data-clipboard-target\": \"#prepared-query-text\", \"data-toggle\": \"tooltip\", \"data-placement\": \"right\", title: \"Copy to clipboard\" },\n _react2.default.createElement(\"span\", { className: \"glyphicon glyphicon-copy\", \"aria-hidden\": \"true\", alt: \"Copy to clipboard\" })\n )\n ),\n _react2.default.createElement(\n \"pre\",\n { id: \"prepared-query\" },\n _react2.default.createElement(\n \"code\",\n { className: \"lang-sql\", id: \"prepared-query-text\" },\n query.preparedQuery\n )\n )\n );\n }\n }, {\n key: \"renderSessionProperties\",\n value: function renderSessionProperties() {\n var query = this.state.query;\n\n var properties = [];\n for (var property in query.session.systemProperties) {\n if (query.session.systemProperties.hasOwnProperty(property)) {\n properties.push(_react2.default.createElement(\n \"span\",\n null,\n \"- \",\n property + \"=\" + query.session.systemProperties[property],\n \" \",\n _react2.default.createElement(\"br\", null)\n ));\n }\n }\n\n for (var catalog in query.session.catalogProperties) {\n if (query.session.catalogProperties.hasOwnProperty(catalog)) {\n for (var _property in query.session.catalogProperties[catalog]) {\n if (query.session.catalogProperties[catalog].hasOwnProperty(_property)) {\n properties.push(_react2.default.createElement(\n \"span\",\n null,\n \"- \",\n catalog + \".\" + _property + \"=\" + query.session.catalogProperties[catalog][_property],\n \" \",\n _react2.default.createElement(\"br\", null)\n ));\n }\n }\n }\n }\n\n return properties;\n }\n }, {\n key: \"renderResourceEstimates\",\n value: function renderResourceEstimates() {\n var query = this.state.query;\n var estimates = query.session.resourceEstimates;\n var renderedEstimates = [];\n\n for (var resource in estimates) {\n if (estimates.hasOwnProperty(resource)) {\n var upperChars = resource.match(/([A-Z])/g) || [];\n var snakeCased = resource;\n for (var i = 0, n = upperChars.length; i < n; i++) {\n snakeCased = snakeCased.replace(new RegExp(upperChars[i]), '_' + upperChars[i].toLowerCase());\n }\n\n renderedEstimates.push(_react2.default.createElement(\n \"span\",\n null,\n \"- \",\n snakeCased + \"=\" + query.session.resourceEstimates[resource],\n \" \",\n _react2.default.createElement(\"br\", null)\n ));\n }\n }\n\n return renderedEstimates;\n }\n }, {\n key: \"renderWarningInfo\",\n value: function renderWarningInfo() {\n var query = this.state.query;\n if (query.warnings.length > 0) {\n return _react2.default.createElement(\n \"div\",\n { className: \"row\" },\n _react2.default.createElement(\n \"div\",\n { className: \"col-xs-12\" },\n _react2.default.createElement(\n \"h3\",\n null,\n \"Warnings\"\n ),\n _react2.default.createElement(\"hr\", { className: \"h3-hr\" }),\n _react2.default.createElement(\n \"table\",\n { className: \"table\", id: \"warnings-table\" },\n query.warnings.map(function (warning) {\n return _react2.default.createElement(\n \"tr\",\n null,\n _react2.default.createElement(\n \"td\",\n null,\n warning.warningCode.name\n ),\n _react2.default.createElement(\n \"td\",\n null,\n warning.message\n )\n );\n })\n )\n )\n );\n } else {\n return null;\n }\n }\n }, {\n key: \"renderFailureInfo\",\n value: function renderFailureInfo() {\n var query = this.state.query;\n if (query.failureInfo) {\n return _react2.default.createElement(\n \"div\",\n { className: \"row\" },\n _react2.default.createElement(\n \"div\",\n { className: \"col-xs-12\" },\n _react2.default.createElement(\n \"h3\",\n null,\n \"Error Information\"\n ),\n _react2.default.createElement(\"hr\", { className: \"h3-hr\" }),\n _react2.default.createElement(\n \"table\",\n { className: \"table\" },\n _react2.default.createElement(\n \"tbody\",\n null,\n _react2.default.createElement(\n \"tr\",\n null,\n _react2.default.createElement(\n \"td\",\n { className: \"info-title\" },\n \"Error Type\"\n ),\n _react2.default.createElement(\n \"td\",\n { className: \"info-text\" },\n query.errorType\n )\n ),\n _react2.default.createElement(\n \"tr\",\n null,\n _react2.default.createElement(\n \"td\",\n { className: \"info-title\" },\n \"Error Code\"\n ),\n _react2.default.createElement(\n \"td\",\n { className: \"info-text\" },\n query.errorCode.name + \" (\" + this.state.query.errorCode.code + \")\"\n )\n ),\n _react2.default.createElement(\n \"tr\",\n null,\n _react2.default.createElement(\n \"td\",\n { className: \"info-title\" },\n \"Stack Trace\",\n _react2.default.createElement(\n \"a\",\n { className: \"btn copy-button\", \"data-clipboard-target\": \"#stack-trace\", \"data-toggle\": \"tooltip\", \"data-placement\": \"right\", title: \"Copy to clipboard\" },\n _react2.default.createElement(\"span\", { className: \"glyphicon glyphicon-copy\", \"aria-hidden\": \"true\", alt: \"Copy to clipboard\" })\n )\n ),\n _react2.default.createElement(\n \"td\",\n { className: \"info-text\" },\n _react2.default.createElement(\n \"pre\",\n { id: \"stack-trace\" },\n QueryDetail.formatStackTrace(query.failureInfo)\n )\n )\n )\n )\n )\n )\n );\n } else {\n return \"\";\n }\n }\n }, {\n key: \"render\",\n value: function render() {\n var query = this.state.query;\n\n if (query === null || this.state.initialized === false) {\n var label = _react2.default.createElement(\n \"div\",\n { className: \"loader\" },\n \"Loading...\"\n );\n if (this.state.initialized) {\n label = \"Query not found\";\n }\n return _react2.default.createElement(\n \"div\",\n { className: \"row error-message\" },\n _react2.default.createElement(\n \"div\",\n { className: \"col-xs-12\" },\n _react2.default.createElement(\n \"h4\",\n null,\n label\n )\n )\n );\n }\n\n return _react2.default.createElement(\n \"div\",\n null,\n _react2.default.createElement(_QueryHeader.QueryHeader, { query: query }),\n _react2.default.createElement(\n \"div\",\n { className: \"row\" },\n _react2.default.createElement(\n \"div\",\n { className: \"col-xs-6\" },\n _react2.default.createElement(\n \"h3\",\n null,\n \"Session\"\n ),\n _react2.default.createElement(\"hr\", { className: \"h3-hr\" }),\n _react2.default.createElement(\n \"table\",\n { className: \"table\" },\n _react2.default.createElement(\n \"tbody\",\n null,\n _react2.default.createElement(\n \"tr\",\n null,\n _react2.default.createElement(\n \"td\",\n { className: \"info-title\" },\n \"User\"\n ),\n _react2.default.createElement(\n \"td\",\n { className: \"info-text wrap-text\" },\n _react2.default.createElement(\n \"span\",\n { id: \"query-user\" },\n query.session.user\n ),\n \"\\xA0\\xA0\",\n _react2.default.createElement(\n \"a\",\n { href: \"#\", className: \"copy-button\", \"data-clipboard-target\": \"#query-user\", \"data-toggle\": \"tooltip\", \"data-placement\": \"right\", title: \"Copy to clipboard\" },\n _react2.default.createElement(\"span\", { className: \"glyphicon glyphicon-copy\", \"aria-hidden\": \"true\", alt: \"Copy to clipboard\" })\n )\n )\n ),\n _react2.default.createElement(\n \"tr\",\n null,\n _react2.default.createElement(\n \"td\",\n { className: \"info-title\" },\n \"Principal\"\n ),\n _react2.default.createElement(\n \"td\",\n { className: \"info-text wrap-text\" },\n query.session.principal\n )\n ),\n _react2.default.createElement(\n \"tr\",\n null,\n _react2.default.createElement(\n \"td\",\n { className: \"info-title\" },\n \"Source\"\n ),\n _react2.default.createElement(\n \"td\",\n { className: \"info-text wrap-text\" },\n query.session.source\n )\n ),\n _react2.default.createElement(\n \"tr\",\n null,\n _react2.default.createElement(\n \"td\",\n { className: \"info-title\" },\n \"Catalog\"\n ),\n _react2.default.createElement(\n \"td\",\n { className: \"info-text\" },\n query.session.catalog\n )\n ),\n _react2.default.createElement(\n \"tr\",\n null,\n _react2.default.createElement(\n \"td\",\n { className: \"info-title\" },\n \"Schema\"\n ),\n _react2.default.createElement(\n \"td\",\n { className: \"info-text\" },\n query.session.schema\n )\n ),\n _react2.default.createElement(\n \"tr\",\n null,\n _react2.default.createElement(\n \"td\",\n { className: \"info-title\" },\n \"Time zone\"\n ),\n _react2.default.createElement(\n \"td\",\n { className: \"info-text\" },\n query.session.timeZone\n )\n ),\n _react2.default.createElement(\n \"tr\",\n null,\n _react2.default.createElement(\n \"td\",\n { className: \"info-title\" },\n \"Client Address\"\n ),\n _react2.default.createElement(\n \"td\",\n { className: \"info-text\" },\n query.session.remoteUserAddress\n )\n ),\n _react2.default.createElement(\n \"tr\",\n null,\n _react2.default.createElement(\n \"td\",\n { className: \"info-title\" },\n \"Client Tags\"\n ),\n _react2.default.createElement(\n \"td\",\n { className: \"info-text\" },\n query.session.clientTags.join(\", \")\n )\n ),\n _react2.default.createElement(\n \"tr\",\n null,\n _react2.default.createElement(\n \"td\",\n { className: \"info-title\" },\n \"Session Properties\"\n ),\n _react2.default.createElement(\n \"td\",\n { className: \"info-text wrap-text\" },\n this.renderSessionProperties()\n )\n ),\n _react2.default.createElement(\n \"tr\",\n null,\n _react2.default.createElement(\n \"td\",\n { className: \"info-title\" },\n \"Resource Estimates\"\n ),\n _react2.default.createElement(\n \"td\",\n { className: \"info-text wrap-text\" },\n this.renderResourceEstimates()\n )\n )\n )\n )\n ),\n _react2.default.createElement(\n \"div\",\n { className: \"col-xs-6\" },\n _react2.default.createElement(\n \"h3\",\n null,\n \"Execution\"\n ),\n _react2.default.createElement(\"hr\", { className: \"h3-hr\" }),\n _react2.default.createElement(\n \"table\",\n { className: \"table\" },\n _react2.default.createElement(\n \"tbody\",\n null,\n _react2.default.createElement(\n \"tr\",\n null,\n _react2.default.createElement(\n \"td\",\n { className: \"info-title\" },\n \"Resource Group\"\n ),\n _react2.default.createElement(\n \"td\",\n { className: \"info-text wrap-text\" },\n query.resourceGroupId ? query.resourceGroupId.join(\".\") : \"n/a\"\n )\n ),\n _react2.default.createElement(\n \"tr\",\n null,\n _react2.default.createElement(\n \"td\",\n { className: \"info-title\" },\n \"Submission Time\"\n ),\n _react2.default.createElement(\n \"td\",\n { className: \"info-text\" },\n (0, _utils.formatShortDateTime)(new Date(query.queryStats.createTime))\n )\n ),\n _react2.default.createElement(\n \"tr\",\n null,\n _react2.default.createElement(\n \"td\",\n { className: \"info-title\" },\n \"Completion Time\"\n ),\n _react2.default.createElement(\n \"td\",\n { className: \"info-text\" },\n query.queryStats.endTime ? (0, _utils.formatShortDateTime)(new Date(query.queryStats.endTime)) : \"\"\n )\n ),\n _react2.default.createElement(\n \"tr\",\n null,\n _react2.default.createElement(\n \"td\",\n { className: \"info-title\" },\n \"Elapsed Time\"\n ),\n _react2.default.createElement(\n \"td\",\n { className: \"info-text\" },\n query.queryStats.elapsedTime\n )\n ),\n _react2.default.createElement(\n \"tr\",\n null,\n _react2.default.createElement(\n \"td\",\n { className: \"info-title\" },\n \"Queued Time\"\n ),\n _react2.default.createElement(\n \"td\",\n { className: \"info-text\" },\n query.queryStats.queuedTime\n )\n ),\n _react2.default.createElement(\n \"tr\",\n null,\n _react2.default.createElement(\n \"td\",\n { className: \"info-title\" },\n \"Analysis Time\"\n ),\n _react2.default.createElement(\n \"td\",\n { className: \"info-text\" },\n query.queryStats.analysisTime\n )\n ),\n _react2.default.createElement(\n \"tr\",\n null,\n _react2.default.createElement(\n \"td\",\n { className: \"info-title\" },\n \"Planning Time\"\n ),\n _react2.default.createElement(\n \"td\",\n { className: \"info-text\" },\n query.queryStats.planningTime\n )\n ),\n _react2.default.createElement(\n \"tr\",\n null,\n _react2.default.createElement(\n \"td\",\n { className: \"info-title\" },\n \"Execution Time\"\n ),\n _react2.default.createElement(\n \"td\",\n { className: \"info-text\" },\n query.queryStats.executionTime\n )\n )\n )\n )\n )\n ),\n _react2.default.createElement(\n \"div\",\n { className: \"row\" },\n _react2.default.createElement(\n \"div\",\n { className: \"col-xs-12\" },\n _react2.default.createElement(\n \"div\",\n { className: \"row\" },\n _react2.default.createElement(\n \"div\",\n { className: \"col-xs-6\" },\n _react2.default.createElement(\n \"h3\",\n null,\n \"Resource Utilization Summary\"\n ),\n _react2.default.createElement(\"hr\", { className: \"h3-hr\" }),\n _react2.default.createElement(\n \"table\",\n { className: \"table\" },\n _react2.default.createElement(\n \"tbody\",\n null,\n _react2.default.createElement(\n \"tr\",\n null,\n _react2.default.createElement(\n \"td\",\n { className: \"info-title\" },\n \"CPU Time\"\n ),\n _react2.default.createElement(\n \"td\",\n { className: \"info-text\" },\n query.queryStats.totalCpuTime\n )\n ),\n _react2.default.createElement(\n \"tr\",\n null,\n _react2.default.createElement(\n \"td\",\n { className: \"info-title\" },\n \"Scheduled Time\"\n ),\n _react2.default.createElement(\n \"td\",\n { className: \"info-text\" },\n query.queryStats.totalScheduledTime\n )\n ),\n _react2.default.createElement(\n \"tr\",\n null,\n _react2.default.createElement(\n \"td\",\n { className: \"info-title\" },\n \"Input Rows\"\n ),\n _react2.default.createElement(\n \"td\",\n { className: \"info-text\" },\n (0, _utils.formatCount)(query.queryStats.processedInputPositions)\n )\n ),\n _react2.default.createElement(\n \"tr\",\n null,\n _react2.default.createElement(\n \"td\",\n { className: \"info-title\" },\n \"Input Data\"\n ),\n _react2.default.createElement(\n \"td\",\n { className: \"info-text\" },\n (0, _utils.parseAndFormatDataSize)(query.queryStats.processedInputDataSize)\n )\n ),\n _react2.default.createElement(\n \"tr\",\n null,\n _react2.default.createElement(\n \"td\",\n { className: \"info-title\" },\n \"Physical Input Rows\"\n ),\n _react2.default.createElement(\n \"td\",\n { className: \"info-text\" },\n (0, _utils.formatCount)(query.queryStats.physicalInputPositions)\n )\n ),\n _react2.default.createElement(\n \"tr\",\n null,\n _react2.default.createElement(\n \"td\",\n { className: \"info-title\" },\n \"Physical Input Data\"\n ),\n _react2.default.createElement(\n \"td\",\n { className: \"info-text\" },\n (0, _utils.parseAndFormatDataSize)(query.queryStats.physicalInputDataSize)\n )\n ),\n _react2.default.createElement(\n \"tr\",\n null,\n _react2.default.createElement(\n \"td\",\n { className: \"info-title\" },\n \"Physical Input Read Time\"\n ),\n _react2.default.createElement(\n \"td\",\n { className: \"info-text\" },\n query.queryStats.physicalInputReadTime\n )\n ),\n _react2.default.createElement(\n \"tr\",\n null,\n _react2.default.createElement(\n \"td\",\n { className: \"info-title\" },\n \"Internal Network Rows\"\n ),\n _react2.default.createElement(\n \"td\",\n { className: \"info-text\" },\n (0, _utils.formatCount)(query.queryStats.internalNetworkInputPositions)\n )\n ),\n _react2.default.createElement(\n \"tr\",\n null,\n _react2.default.createElement(\n \"td\",\n { className: \"info-title\" },\n \"Internal Network Data\"\n ),\n _react2.default.createElement(\n \"td\",\n { className: \"info-text\" },\n (0, _utils.parseAndFormatDataSize)(query.queryStats.internalNetworkInputDataSize)\n )\n ),\n _react2.default.createElement(\n \"tr\",\n null,\n _react2.default.createElement(\n \"td\",\n { className: \"info-title\" },\n \"Peak User Memory\"\n ),\n _react2.default.createElement(\n \"td\",\n { className: \"info-text\" },\n (0, _utils.parseAndFormatDataSize)(query.queryStats.peakUserMemoryReservation)\n )\n ),\n (0, _utils.parseDataSize)(query.queryStats.peakRevocableMemoryReservation) > 0 && _react2.default.createElement(\n \"tr\",\n null,\n _react2.default.createElement(\n \"td\",\n { className: \"info-title\" },\n \"Peak Revocable Memory\"\n ),\n _react2.default.createElement(\n \"td\",\n { className: \"info-text\" },\n (0, _utils.parseAndFormatDataSize)(query.queryStats.peakRevocableMemoryReservation)\n )\n ),\n _react2.default.createElement(\n \"tr\",\n null,\n _react2.default.createElement(\n \"td\",\n { className: \"info-title\" },\n \"Peak Total Memory\"\n ),\n _react2.default.createElement(\n \"td\",\n { className: \"info-text\" },\n (0, _utils.parseAndFormatDataSize)(query.queryStats.peakTotalMemoryReservation)\n )\n ),\n _react2.default.createElement(\n \"tr\",\n null,\n _react2.default.createElement(\n \"td\",\n { className: \"info-title\" },\n \"Cumulative User Memory\"\n ),\n _react2.default.createElement(\n \"td\",\n { className: \"info-text\" },\n (0, _utils.formatDataSizeBytes)(query.queryStats.cumulativeUserMemory / 1000.0) + \" seconds\"\n )\n ),\n _react2.default.createElement(\n \"tr\",\n null,\n _react2.default.createElement(\n \"td\",\n { className: \"info-title\" },\n \"Output Rows\"\n ),\n _react2.default.createElement(\n \"td\",\n { className: \"info-text\" },\n (0, _utils.formatCount)(query.queryStats.outputPositions)\n )\n ),\n _react2.default.createElement(\n \"tr\",\n null,\n _react2.default.createElement(\n \"td\",\n { className: \"info-title\" },\n \"Output Data\"\n ),\n _react2.default.createElement(\n \"td\",\n { className: \"info-text\" },\n (0, _utils.parseAndFormatDataSize)(query.queryStats.outputDataSize)\n )\n ),\n _react2.default.createElement(\n \"tr\",\n null,\n _react2.default.createElement(\n \"td\",\n { className: \"info-title\" },\n \"Written Rows\"\n ),\n _react2.default.createElement(\n \"td\",\n { className: \"info-text\" },\n (0, _utils.formatCount)(query.queryStats.writtenPositions)\n )\n ),\n _react2.default.createElement(\n \"tr\",\n null,\n _react2.default.createElement(\n \"td\",\n { className: \"info-title\" },\n \"Logical Written Data\"\n ),\n _react2.default.createElement(\n \"td\",\n { className: \"info-text\" },\n (0, _utils.parseAndFormatDataSize)(query.queryStats.logicalWrittenDataSize)\n )\n ),\n _react2.default.createElement(\n \"tr\",\n null,\n _react2.default.createElement(\n \"td\",\n { className: \"info-title\" },\n \"Physical Written Data\"\n ),\n _react2.default.createElement(\n \"td\",\n { className: \"info-text\" },\n (0, _utils.parseAndFormatDataSize)(query.queryStats.physicalWrittenDataSize)\n )\n ),\n (0, _utils.parseDataSize)(query.queryStats.spilledDataSize) > 0 && _react2.default.createElement(\n \"tr\",\n null,\n _react2.default.createElement(\n \"td\",\n { className: \"info-title\" },\n \"Spilled Data\"\n ),\n _react2.default.createElement(\n \"td\",\n { className: \"info-text\" },\n (0, _utils.parseAndFormatDataSize)(query.queryStats.spilledDataSize)\n )\n )\n )\n )\n ),\n _react2.default.createElement(\n \"div\",\n { className: \"col-xs-6\" },\n _react2.default.createElement(\n \"h3\",\n null,\n \"Timeline\"\n ),\n _react2.default.createElement(\"hr\", { className: \"h3-hr\" }),\n _react2.default.createElement(\n \"table\",\n { className: \"table\" },\n _react2.default.createElement(\n \"tbody\",\n null,\n _react2.default.createElement(\n \"tr\",\n null,\n _react2.default.createElement(\n \"td\",\n { className: \"info-title\" },\n \"Parallelism\"\n ),\n _react2.default.createElement(\n \"td\",\n { rowSpan: \"2\" },\n _react2.default.createElement(\n \"div\",\n { className: \"query-stats-sparkline-container\" },\n _react2.default.createElement(\n \"span\",\n { className: \"sparkline\", id: \"cpu-time-rate-sparkline\" },\n _react2.default.createElement(\n \"div\",\n { className: \"loader\" },\n \"Loading ...\"\n )\n )\n )\n )\n ),\n _react2.default.createElement(\n \"tr\",\n { className: \"tr-noborder\" },\n _react2.default.createElement(\n \"td\",\n { className: \"info-sparkline-text\" },\n (0, _utils.formatCount)(this.state.cpuTimeRate[this.state.cpuTimeRate.length - 1])\n )\n ),\n _react2.default.createElement(\n \"tr\",\n null,\n _react2.default.createElement(\n \"td\",\n { className: \"info-title\" },\n \"Scheduled Time/s\"\n ),\n _react2.default.createElement(\n \"td\",\n { rowSpan: \"2\" },\n _react2.default.createElement(\n \"div\",\n { className: \"query-stats-sparkline-container\" },\n _react2.default.createElement(\n \"span\",\n { className: \"sparkline\", id: \"scheduled-time-rate-sparkline\" },\n _react2.default.createElement(\n \"div\",\n { className: \"loader\" },\n \"Loading ...\"\n )\n )\n )\n )\n ),\n _react2.default.createElement(\n \"tr\",\n { className: \"tr-noborder\" },\n _react2.default.createElement(\n \"td\",\n { className: \"info-sparkline-text\" },\n (0, _utils.formatCount)(this.state.scheduledTimeRate[this.state.scheduledTimeRate.length - 1])\n )\n ),\n _react2.default.createElement(\n \"tr\",\n null,\n _react2.default.createElement(\n \"td\",\n { className: \"info-title\" },\n \"Input Rows/s\"\n ),\n _react2.default.createElement(\n \"td\",\n { rowSpan: \"2\" },\n _react2.default.createElement(\n \"div\",\n { className: \"query-stats-sparkline-container\" },\n _react2.default.createElement(\n \"span\",\n { className: \"sparkline\", id: \"row-input-rate-sparkline\" },\n _react2.default.createElement(\n \"div\",\n { className: \"loader\" },\n \"Loading ...\"\n )\n )\n )\n )\n ),\n _react2.default.createElement(\n \"tr\",\n { className: \"tr-noborder\" },\n _react2.default.createElement(\n \"td\",\n { className: \"info-sparkline-text\" },\n (0, _utils.formatCount)(this.state.rowInputRate[this.state.rowInputRate.length - 1])\n )\n ),\n _react2.default.createElement(\n \"tr\",\n null,\n _react2.default.createElement(\n \"td\",\n { className: \"info-title\" },\n \"Input Bytes/s\"\n ),\n _react2.default.createElement(\n \"td\",\n { rowSpan: \"2\" },\n _react2.default.createElement(\n \"div\",\n { className: \"query-stats-sparkline-container\" },\n _react2.default.createElement(\n \"span\",\n { className: \"sparkline\", id: \"byte-input-rate-sparkline\" },\n _react2.default.createElement(\n \"div\",\n { className: \"loader\" },\n \"Loading ...\"\n )\n )\n )\n )\n ),\n _react2.default.createElement(\n \"tr\",\n { className: \"tr-noborder\" },\n _react2.default.createElement(\n \"td\",\n { className: \"info-sparkline-text\" },\n (0, _utils.formatDataSize)(this.state.byteInputRate[this.state.byteInputRate.length - 1])\n )\n ),\n _react2.default.createElement(\n \"tr\",\n null,\n _react2.default.createElement(\n \"td\",\n { className: \"info-title\" },\n \"Physical Input Bytes/s\"\n ),\n _react2.default.createElement(\n \"td\",\n { rowSpan: \"2\" },\n _react2.default.createElement(\n \"div\",\n { className: \"query-stats-sparkline-container\" },\n _react2.default.createElement(\n \"span\",\n { className: \"sparkline\", id: \"physical-input-rate-sparkline\" },\n _react2.default.createElement(\n \"div\",\n { className: \"loader\" },\n \"Loading ...\"\n )\n )\n )\n )\n ),\n _react2.default.createElement(\n \"tr\",\n { className: \"tr-noborder\" },\n _react2.default.createElement(\n \"td\",\n { className: \"info-sparkline-text\" },\n (0, _utils.formatDataSize)(this.state.physicalInputRate[this.state.physicalInputRate.length - 1])\n )\n ),\n _react2.default.createElement(\n \"tr\",\n null,\n _react2.default.createElement(\n \"td\",\n { className: \"info-title\" },\n \"Memory Utilization\"\n ),\n _react2.default.createElement(\n \"td\",\n { rowSpan: \"2\" },\n _react2.default.createElement(\n \"div\",\n { className: \"query-stats-sparkline-container\" },\n _react2.default.createElement(\n \"span\",\n { className: \"sparkline\", id: \"reserved-memory-sparkline\" },\n _react2.default.createElement(\n \"div\",\n { className: \"loader\" },\n \"Loading ...\"\n )\n )\n )\n )\n ),\n _react2.default.createElement(\n \"tr\",\n { className: \"tr-noborder\" },\n _react2.default.createElement(\n \"td\",\n { className: \"info-sparkline-text\" },\n (0, _utils.formatDataSize)(this.state.reservedMemory[this.state.reservedMemory.length - 1])\n )\n )\n )\n )\n )\n )\n )\n ),\n this.renderWarningInfo(),\n this.renderFailureInfo(),\n _react2.default.createElement(\n \"div\",\n { className: \"row\" },\n _react2.default.createElement(\n \"div\",\n { className: \"col-xs-12\" },\n _react2.default.createElement(\n \"h3\",\n null,\n \"Query\",\n _react2.default.createElement(\n \"a\",\n { className: \"btn copy-button\", \"data-clipboard-target\": \"#query-text\", \"data-toggle\": \"tooltip\", \"data-placement\": \"right\", title: \"Copy to clipboard\" },\n _react2.default.createElement(\"span\", { className: \"glyphicon glyphicon-copy\", \"aria-hidden\": \"true\", alt: \"Copy to clipboard\" })\n )\n ),\n _react2.default.createElement(\n \"pre\",\n { id: \"query\" },\n _react2.default.createElement(\n \"code\",\n { className: \"lang-sql\", id: \"query-text\" },\n query.query\n )\n )\n ),\n this.renderPreparedQuery()\n ),\n this.renderStages(),\n this.renderTasks()\n );\n }\n }], [{\n key: \"formatStackTrace\",\n value: function formatStackTrace(info) {\n return QueryDetail.formatStackTraceHelper(info, [], \"\", \"\");\n }\n }, {\n key: \"formatStackTraceHelper\",\n value: function formatStackTraceHelper(info, parentStack, prefix, linePrefix) {\n var s = linePrefix + prefix + QueryDetail.failureInfoToString(info) + \"\\n\";\n\n if (info.stack) {\n var sharedStackFrames = 0;\n if (parentStack !== null) {\n sharedStackFrames = QueryDetail.countSharedStackFrames(info.stack, parentStack);\n }\n\n for (var i = 0; i < info.stack.length - sharedStackFrames; i++) {\n s += linePrefix + \"\\tat \" + info.stack[i] + \"\\n\";\n }\n if (sharedStackFrames !== 0) {\n s += linePrefix + \"\\t... \" + sharedStackFrames + \" more\" + \"\\n\";\n }\n }\n\n if (info.suppressed) {\n for (var _i3 = 0; _i3 < info.suppressed.length; _i3++) {\n s += QueryDetail.formatStackTraceHelper(info.suppressed[_i3], info.stack, \"Suppressed: \", linePrefix + \"\\t\");\n }\n }\n\n if (info.cause) {\n s += QueryDetail.formatStackTraceHelper(info.cause, info.stack, \"Caused by: \", linePrefix);\n }\n\n return s;\n }\n }, {\n key: \"countSharedStackFrames\",\n value: function countSharedStackFrames(stack, parentStack) {\n var n = 0;\n var minStackLength = Math.min(stack.length, parentStack.length);\n while (n < minStackLength && stack[stack.length - 1 - n] === parentStack[parentStack.length - 1 - n]) {\n n++;\n }\n return n;\n }\n }, {\n key: \"failureInfoToString\",\n value: function failureInfoToString(t) {\n return t.message !== null ? t.type + \": \" + t.message : t.type;\n }\n }]);\n\n return QueryDetail;\n}(_react2.default.Component);\n\n//# sourceURL=webpack:///./components/QueryDetail.jsx?"); /***/ }), diff --git a/core/trino-main/src/main/resources/webapp/dist/worker.js b/core/trino-main/src/main/resources/webapp/dist/worker.js index fce55f271937..0546676c3c65 100644 --- a/core/trino-main/src/main/resources/webapp/dist/worker.js +++ b/core/trino-main/src/main/resources/webapp/dist/worker.js @@ -106,7 +106,7 @@ eval("\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n}); /***/ (function(module, exports, __webpack_require__) { "use strict"; -eval("\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\nexports.WorkerStatus = undefined;\n\nvar _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if (\"value\" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();\n\nvar _react = __webpack_require__(/*! react */ \"./node_modules/react/index.js\");\n\nvar _react2 = _interopRequireDefault(_react);\n\nvar _utils = __webpack_require__(/*! ../utils */ \"./utils.js\");\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\nfunction _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError(\"Cannot call a class as a function\"); } }\n\nfunction _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); } return call && (typeof call === \"object\" || typeof call === \"function\") ? call : self; }\n\nfunction _inherits(subClass, superClass) { if (typeof superClass !== \"function\" && superClass !== null) { throw new TypeError(\"Super expression must either be null or a function, not \" + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } /*\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nvar SMALL_SPARKLINE_PROPERTIES = {\n width: '100%',\n height: '57px',\n fillColor: '#3F4552',\n lineColor: '#747F96',\n spotColor: '#1EDCFF',\n tooltipClassname: 'sparkline-tooltip',\n disableHiddenCheck: true\n};\n\nvar WorkerStatus = exports.WorkerStatus = function (_React$Component) {\n _inherits(WorkerStatus, _React$Component);\n\n function WorkerStatus(props) {\n _classCallCheck(this, WorkerStatus);\n\n var _this = _possibleConstructorReturn(this, (WorkerStatus.__proto__ || Object.getPrototypeOf(WorkerStatus)).call(this, props));\n\n _this.state = {\n serverInfo: null,\n initialized: false,\n ended: false,\n\n processCpuLoad: [],\n systemCpuLoad: [],\n heapPercentUsed: [],\n nonHeapUsed: []\n };\n\n _this.refreshLoop = _this.refreshLoop.bind(_this);\n return _this;\n }\n\n _createClass(WorkerStatus, [{\n key: \"resetTimer\",\n value: function resetTimer() {\n clearTimeout(this.timeoutId);\n // stop refreshing when query finishes or fails\n if (this.state.query === null || !this.state.ended) {\n this.timeoutId = setTimeout(this.refreshLoop, 1000);\n }\n }\n }, {\n key: \"refreshLoop\",\n value: function refreshLoop() {\n clearTimeout(this.timeoutId); // to stop multiple series of refreshLoop from going on simultaneously\n var nodeId = (0, _utils.getFirstParameter)(window.location.search);\n $.get('/ui/api/worker/' + nodeId + '/status', function (serverInfo) {\n this.setState({\n serverInfo: serverInfo,\n initialized: true,\n\n processCpuLoad: (0, _utils.addToHistory)(serverInfo.processCpuLoad * 100.0, this.state.processCpuLoad),\n systemCpuLoad: (0, _utils.addToHistory)(serverInfo.systemCpuLoad * 100.0, this.state.systemCpuLoad),\n heapPercentUsed: (0, _utils.addToHistory)(serverInfo.heapUsed * 100.0 / serverInfo.heapAvailable, this.state.heapPercentUsed),\n nonHeapUsed: (0, _utils.addToHistory)(serverInfo.nonHeapUsed, this.state.nonHeapUsed)\n });\n\n this.resetTimer();\n }.bind(this)).fail(function () {\n this.setState({\n initialized: true\n });\n this.resetTimer();\n }.bind(this));\n }\n }, {\n key: \"componentDidMount\",\n value: function componentDidMount() {\n this.refreshLoop();\n }\n }, {\n key: \"componentDidUpdate\",\n value: function componentDidUpdate() {\n $('#process-cpu-load-sparkline').sparkline(this.state.processCpuLoad, $.extend({}, SMALL_SPARKLINE_PROPERTIES, { chartRangeMin: 0, numberFormatter: _utils.precisionRound }));\n $('#system-cpu-load-sparkline').sparkline(this.state.systemCpuLoad, $.extend({}, SMALL_SPARKLINE_PROPERTIES, { chartRangeMin: 0, numberFormatter: _utils.precisionRound }));\n $('#heap-percent-used-sparkline').sparkline(this.state.heapPercentUsed, $.extend({}, SMALL_SPARKLINE_PROPERTIES, { chartRangeMin: 0, numberFormatter: _utils.precisionRound }));\n $('#nonheap-used-sparkline').sparkline(this.state.nonHeapUsed, $.extend({}, SMALL_SPARKLINE_PROPERTIES, { chartRangeMin: 0, numberFormatter: _utils.formatDataSize }));\n\n $('[data-toggle=\"tooltip\"]').tooltip();\n new window.ClipboardJS('.copy-button');\n }\n }, {\n key: \"renderPoolQueries\",\n value: function renderPoolQueries(pool) {\n if (!pool) {\n return;\n }\n\n var queries = {};\n var reservations = pool.queryMemoryReservations;\n var revocableReservations = pool.queryMemoryRevocableReservations;\n\n for (var query in reservations) {\n queries[query] = [reservations[query], 0];\n }\n\n for (var _query in revocableReservations) {\n if (queries.hasOwnProperty(_query)) {\n queries[_query][1] = revocableReservations[_query];\n } else {\n queries[_query] = [0, revocableReservations[_query]];\n }\n }\n\n var size = pool.maxBytes;\n\n if (Object.keys(queries).length === 0) {\n return _react2.default.createElement(\n \"div\",\n null,\n _react2.default.createElement(\n \"table\",\n { className: \"table table-condensed\" },\n _react2.default.createElement(\n \"tbody\",\n null,\n _react2.default.createElement(\n \"tr\",\n null,\n _react2.default.createElement(\n \"td\",\n null,\n \"No queries using pool\"\n )\n )\n )\n )\n );\n }\n\n return _react2.default.createElement(\n \"div\",\n null,\n _react2.default.createElement(\n \"table\",\n { className: \"table\" },\n _react2.default.createElement(\n \"tbody\",\n null,\n Object.keys(queries).map(function (key) {\n return WorkerStatus.renderPoolQuery(key, queries[key][0], queries[key][1], size);\n })\n )\n )\n );\n }\n }, {\n key: \"render\",\n value: function render() {\n var serverInfo = this.state.serverInfo;\n\n if (serverInfo === null) {\n if (this.state.initialized === false) {\n return _react2.default.createElement(\n \"div\",\n { className: \"loader\" },\n \"Loading...\"\n );\n } else {\n return _react2.default.createElement(\n \"div\",\n { className: \"row error-message\" },\n _react2.default.createElement(\n \"div\",\n { className: \"col-xs-12\" },\n _react2.default.createElement(\n \"h4\",\n null,\n \"Node information could not be loaded\"\n )\n )\n );\n }\n }\n\n return _react2.default.createElement(\n \"div\",\n null,\n _react2.default.createElement(\n \"div\",\n { className: \"row\" },\n _react2.default.createElement(\n \"div\",\n { className: \"col-xs-12\" },\n _react2.default.createElement(\n \"h3\",\n null,\n \"Overview\"\n ),\n _react2.default.createElement(\"hr\", { className: \"h3-hr\" }),\n _react2.default.createElement(\n \"div\",\n { className: \"row\" },\n _react2.default.createElement(\n \"div\",\n { className: \"col-xs-6\" },\n _react2.default.createElement(\n \"table\",\n { className: \"table\" },\n _react2.default.createElement(\n \"tbody\",\n null,\n _react2.default.createElement(\n \"tr\",\n null,\n _react2.default.createElement(\n \"td\",\n { className: \"info-title\" },\n \"Node ID\"\n ),\n _react2.default.createElement(\n \"td\",\n { className: \"info-text wrap-text\" },\n _react2.default.createElement(\n \"span\",\n { id: \"node-id\" },\n serverInfo.nodeId\n ),\n \"\\xA0\\xA0\",\n _react2.default.createElement(\n \"a\",\n { href: \"#\", className: \"copy-button\", \"data-clipboard-target\": \"#node-id\", \"data-toggle\": \"tooltip\", \"data-placement\": \"right\",\n title: \"Copy to clipboard\" },\n _react2.default.createElement(\"span\", { className: \"glyphicon glyphicon-copy\", alt: \"Copy to clipboard\" })\n )\n )\n ),\n _react2.default.createElement(\n \"tr\",\n null,\n _react2.default.createElement(\n \"td\",\n { className: \"info-title\" },\n \"Heap Memory\"\n ),\n _react2.default.createElement(\n \"td\",\n { className: \"info-text wrap-text\" },\n _react2.default.createElement(\n \"span\",\n { id: \"node-heap-available\" },\n (0, _utils.formatDataSize)(serverInfo.heapAvailable)\n )\n )\n ),\n _react2.default.createElement(\n \"tr\",\n null,\n _react2.default.createElement(\n \"td\",\n { className: \"info-title\" },\n \"Processors\"\n ),\n _react2.default.createElement(\n \"td\",\n { className: \"info-text wrap-text\" },\n _react2.default.createElement(\n \"span\",\n { id: \"node-processors\" },\n serverInfo.processors\n )\n )\n )\n )\n )\n ),\n _react2.default.createElement(\n \"div\",\n { className: \"col-xs-6\" },\n _react2.default.createElement(\n \"table\",\n { className: \"table\" },\n _react2.default.createElement(\n \"tbody\",\n null,\n _react2.default.createElement(\n \"tr\",\n null,\n _react2.default.createElement(\n \"td\",\n { className: \"info-title\" },\n \"Uptime\"\n ),\n _react2.default.createElement(\n \"td\",\n { className: \"info-text wrap-text\" },\n serverInfo.uptime\n )\n ),\n _react2.default.createElement(\n \"tr\",\n null,\n _react2.default.createElement(\n \"td\",\n { className: \"info-title\" },\n \"External Address\"\n ),\n _react2.default.createElement(\n \"td\",\n { className: \"info-text wrap-text\" },\n _react2.default.createElement(\n \"span\",\n { id: \"external-address\" },\n serverInfo.externalAddress\n ),\n \"\\xA0\\xA0\",\n _react2.default.createElement(\n \"a\",\n { href: \"#\", className: \"copy-button\", \"data-clipboard-target\": \"#external-address\", \"data-toggle\": \"tooltip\", \"data-placement\": \"right\",\n title: \"Copy to clipboard\" },\n _react2.default.createElement(\"span\", { className: \"glyphicon glyphicon-copy\", alt: \"Copy to clipboard\" })\n )\n )\n ),\n _react2.default.createElement(\n \"tr\",\n null,\n _react2.default.createElement(\n \"td\",\n { className: \"info-title\" },\n \"Internal Address\"\n ),\n _react2.default.createElement(\n \"td\",\n { className: \"info-text wrap-text\" },\n _react2.default.createElement(\n \"span\",\n { id: \"internal-address\" },\n serverInfo.internalAddress\n ),\n \"\\xA0\\xA0\",\n _react2.default.createElement(\n \"a\",\n { href: \"#\", className: \"copy-button\", \"data-clipboard-target\": \"#internal-address\", \"data-toggle\": \"tooltip\", \"data-placement\": \"right\",\n title: \"Copy to clipboard\" },\n _react2.default.createElement(\"span\", { className: \"glyphicon glyphicon-copy\", alt: \"Copy to clipboard\" })\n )\n )\n )\n )\n )\n )\n ),\n _react2.default.createElement(\n \"div\",\n { className: \"row\" },\n _react2.default.createElement(\n \"div\",\n { className: \"col-xs-12\" },\n _react2.default.createElement(\n \"h3\",\n null,\n \"Resource Utilization\"\n ),\n _react2.default.createElement(\"hr\", { className: \"h3-hr\" }),\n _react2.default.createElement(\n \"div\",\n { className: \"row\" },\n _react2.default.createElement(\n \"div\",\n { className: \"col-xs-6\" },\n _react2.default.createElement(\n \"table\",\n { className: \"table\" },\n _react2.default.createElement(\n \"tbody\",\n null,\n _react2.default.createElement(\n \"tr\",\n null,\n _react2.default.createElement(\n \"td\",\n { className: \"info-title\" },\n \"Process CPU Utilization\"\n ),\n _react2.default.createElement(\n \"td\",\n { rowSpan: \"2\" },\n _react2.default.createElement(\n \"div\",\n { className: \"query-stats-sparkline-container\" },\n _react2.default.createElement(\n \"span\",\n { className: \"sparkline\", id: \"process-cpu-load-sparkline\" },\n _react2.default.createElement(\n \"div\",\n { className: \"loader\" },\n \"Loading ...\"\n )\n )\n )\n )\n ),\n _react2.default.createElement(\n \"tr\",\n { className: \"tr-noborder\" },\n _react2.default.createElement(\n \"td\",\n { className: \"info-sparkline-text\" },\n (0, _utils.formatCount)(this.state.processCpuLoad[this.state.processCpuLoad.length - 1]),\n \"%\"\n )\n ),\n _react2.default.createElement(\n \"tr\",\n null,\n _react2.default.createElement(\n \"td\",\n { className: \"info-title\" },\n \"System CPU Utilization\"\n ),\n _react2.default.createElement(\n \"td\",\n { rowSpan: \"2\" },\n _react2.default.createElement(\n \"div\",\n { className: \"query-stats-sparkline-container\" },\n _react2.default.createElement(\n \"span\",\n { className: \"sparkline\", id: \"system-cpu-load-sparkline\" },\n _react2.default.createElement(\n \"div\",\n { className: \"loader\" },\n \"Loading ...\"\n )\n )\n )\n )\n ),\n _react2.default.createElement(\n \"tr\",\n { className: \"tr-noborder\" },\n _react2.default.createElement(\n \"td\",\n { className: \"info-sparkline-text\" },\n (0, _utils.formatCount)(this.state.systemCpuLoad[this.state.systemCpuLoad.length - 1]),\n \"%\"\n )\n )\n )\n )\n ),\n _react2.default.createElement(\n \"div\",\n { className: \"col-xs-6\" },\n _react2.default.createElement(\n \"table\",\n { className: \"table\" },\n _react2.default.createElement(\n \"tbody\",\n null,\n _react2.default.createElement(\n \"tr\",\n null,\n _react2.default.createElement(\n \"td\",\n { className: \"info-title\" },\n \"Heap Utilization\"\n ),\n _react2.default.createElement(\n \"td\",\n { rowSpan: \"2\" },\n _react2.default.createElement(\n \"div\",\n { className: \"query-stats-sparkline-container\" },\n _react2.default.createElement(\n \"span\",\n { className: \"sparkline\", id: \"heap-percent-used-sparkline\" },\n _react2.default.createElement(\n \"div\",\n { className: \"loader\" },\n \"Loading ...\"\n )\n )\n )\n )\n ),\n _react2.default.createElement(\n \"tr\",\n { className: \"tr-noborder\" },\n _react2.default.createElement(\n \"td\",\n { className: \"info-sparkline-text\" },\n (0, _utils.formatCount)(this.state.heapPercentUsed[this.state.heapPercentUsed.length - 1]),\n \"%\"\n )\n ),\n _react2.default.createElement(\n \"tr\",\n null,\n _react2.default.createElement(\n \"td\",\n { className: \"info-title\" },\n \"Non-Heap Memory Used\"\n ),\n _react2.default.createElement(\n \"td\",\n { rowSpan: \"2\" },\n _react2.default.createElement(\n \"div\",\n { className: \"query-stats-sparkline-container\" },\n _react2.default.createElement(\n \"span\",\n { className: \"sparkline\", id: \"nonheap-used-sparkline\" },\n _react2.default.createElement(\n \"div\",\n { className: \"loader\" },\n \"Loading ...\"\n )\n )\n )\n )\n ),\n _react2.default.createElement(\n \"tr\",\n { className: \"tr-noborder\" },\n _react2.default.createElement(\n \"td\",\n { className: \"info-sparkline-text\" },\n (0, _utils.formatDataSize)(this.state.nonHeapUsed[this.state.nonHeapUsed.length - 1])\n )\n )\n )\n )\n )\n )\n )\n )\n )\n ),\n _react2.default.createElement(\n \"div\",\n { className: \"row\" },\n _react2.default.createElement(\n \"div\",\n { className: \"col-xs-12\" },\n _react2.default.createElement(\n \"h3\",\n null,\n \"Memory Pools\"\n ),\n _react2.default.createElement(\"hr\", { className: \"h3-hr\" }),\n _react2.default.createElement(\n \"div\",\n { className: \"row\" },\n _react2.default.createElement(\n \"div\",\n { className: \"col-xs-6\" },\n WorkerStatus.renderPoolBar(\"General\", serverInfo.memoryInfo.pools.general),\n this.renderPoolQueries(serverInfo.memoryInfo.pools.general)\n )\n )\n )\n )\n );\n }\n }], [{\n key: \"renderPoolBar\",\n value: function renderPoolBar(name, pool) {\n if (!pool) {\n return;\n }\n\n var size = pool.maxBytes;\n var reserved = pool.reservedBytes;\n var revocable = pool.reservedRevocableBytes;\n\n var percentageReservedNonRevocable = reserved === 0 ? 0 : Math.max(Math.round(reserved * 100.0 / size), 15);\n var percentageRevocable = revocable === 0 ? 0 : Math.max(Math.round(revocable * 100.0 / size), 15);\n var percentageFree = 100 - (percentageRevocable + percentageReservedNonRevocable);\n\n return _react2.default.createElement(\n \"div\",\n { className: \"row\" },\n _react2.default.createElement(\n \"div\",\n { className: \"col-xs-12\" },\n _react2.default.createElement(\n \"div\",\n { className: \"row\" },\n _react2.default.createElement(\n \"div\",\n { className: \"col-xs-8\" },\n _react2.default.createElement(\n \"h4\",\n null,\n name,\n \" Pool\"\n )\n ),\n _react2.default.createElement(\n \"div\",\n { className: \"col-xs-4\" },\n _react2.default.createElement(\n \"div\",\n { className: \"progress\", style: { marginTop: \"6px\" } },\n _react2.default.createElement(\n \"div\",\n { className: \"progress-bar memory-progress-bar memory-progress-bar-info\", role: \"progressbar\", style: { width: \"100%\" } },\n (0, _utils.formatDataSize)(size),\n \" total\"\n )\n )\n )\n ),\n _react2.default.createElement(\n \"div\",\n { className: \"row\" },\n _react2.default.createElement(\n \"div\",\n { className: \"col-xs-12\" },\n _react2.default.createElement(\"hr\", { className: \"h4-hr\" }),\n _react2.default.createElement(\n \"div\",\n { className: \"progress\" },\n _react2.default.createElement(\n \"div\",\n { className: \"progress-bar memory-progress-bar progress-bar-warning progress-bar-striped active\", role: \"progressbar\",\n style: { width: percentageReservedNonRevocable + \"%\" } },\n (0, _utils.formatDataSize)(reserved)\n ),\n _react2.default.createElement(\n \"div\",\n { className: \"progress-bar memory-progress-bar progress-bar-danger progress-bar-striped active\", role: \"progressbar\",\n style: { width: percentageRevocable + \"%\" } },\n (0, _utils.formatDataSize)(revocable)\n ),\n _react2.default.createElement(\n \"div\",\n { className: \"progress-bar memory-progress-bar progress-bar-success\", role: \"progressbar\", style: { width: percentageFree + \"%\" } },\n (0, _utils.formatDataSize)(size - reserved - revocable)\n )\n )\n )\n )\n )\n );\n }\n }, {\n key: \"renderPoolQuery\",\n value: function renderPoolQuery(query, reserved, revocable, total) {\n return _react2.default.createElement(\n \"tr\",\n null,\n _react2.default.createElement(\n \"td\",\n null,\n _react2.default.createElement(\n \"div\",\n { className: \"row query-memory-list-header\" },\n _react2.default.createElement(\n \"div\",\n { className: \"col-xs-7\" },\n _react2.default.createElement(\n \"a\",\n { href: \"query.html?\" + query, target: \"_blank\" },\n query\n )\n ),\n _react2.default.createElement(\n \"div\",\n { className: \"col-xs-5\" },\n _react2.default.createElement(\n \"div\",\n { className: \"row text-right\" },\n _react2.default.createElement(\n \"div\",\n { className: \"col-xs-6\" },\n _react2.default.createElement(\n \"span\",\n { \"data-toggle\": \"tooltip\", \"data-placement\": \"top\", title: \"% of pool memory reserved\" },\n Math.round(reserved * 100.0 / total),\n \"%\"\n )\n ),\n _react2.default.createElement(\n \"div\",\n { className: \"col-xs-6\" },\n _react2.default.createElement(\n \"span\",\n { \"data-toggle\": \"tooltip\", \"data-placement\": \"top\",\n title: \"Reserved: \" + (0, _utils.formatDataSize)(reserved) + \". Revocable: \" + (0, _utils.formatDataSize)(revocable) },\n (0, _utils.formatDataSize)(reserved)\n )\n )\n )\n )\n )\n )\n );\n }\n }]);\n\n return WorkerStatus;\n}(_react2.default.Component);\n\n//# sourceURL=webpack:///./components/WorkerStatus.jsx?"); +eval("\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\nexports.WorkerStatus = undefined;\n\nvar _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if (\"value\" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();\n\nvar _react = __webpack_require__(/*! react */ \"./node_modules/react/index.js\");\n\nvar _react2 = _interopRequireDefault(_react);\n\nvar _utils = __webpack_require__(/*! ../utils */ \"./utils.js\");\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\nfunction _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError(\"Cannot call a class as a function\"); } }\n\nfunction _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); } return call && (typeof call === \"object\" || typeof call === \"function\") ? call : self; }\n\nfunction _inherits(subClass, superClass) { if (typeof superClass !== \"function\" && superClass !== null) { throw new TypeError(\"Super expression must either be null or a function, not \" + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } /*\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nvar SMALL_SPARKLINE_PROPERTIES = {\n width: '100%',\n height: '57px',\n fillColor: '#3F4552',\n lineColor: '#747F96',\n spotColor: '#1EDCFF',\n tooltipClassname: 'sparkline-tooltip',\n disableHiddenCheck: true\n};\n\nvar WorkerStatus = exports.WorkerStatus = function (_React$Component) {\n _inherits(WorkerStatus, _React$Component);\n\n function WorkerStatus(props) {\n _classCallCheck(this, WorkerStatus);\n\n var _this = _possibleConstructorReturn(this, (WorkerStatus.__proto__ || Object.getPrototypeOf(WorkerStatus)).call(this, props));\n\n _this.state = {\n serverInfo: null,\n initialized: false,\n ended: false,\n\n processCpuLoad: [],\n systemCpuLoad: [],\n heapPercentUsed: [],\n nonHeapUsed: []\n };\n\n _this.refreshLoop = _this.refreshLoop.bind(_this);\n return _this;\n }\n\n _createClass(WorkerStatus, [{\n key: \"resetTimer\",\n value: function resetTimer() {\n clearTimeout(this.timeoutId);\n // stop refreshing when query finishes or fails\n if (this.state.query === null || !this.state.ended) {\n this.timeoutId = setTimeout(this.refreshLoop, 1000);\n }\n }\n }, {\n key: \"refreshLoop\",\n value: function refreshLoop() {\n clearTimeout(this.timeoutId); // to stop multiple series of refreshLoop from going on simultaneously\n var nodeId = (0, _utils.getFirstParameter)(window.location.search);\n $.get('/ui/api/worker/' + nodeId + '/status', function (serverInfo) {\n this.setState({\n serverInfo: serverInfo,\n initialized: true,\n\n processCpuLoad: (0, _utils.addToHistory)(serverInfo.processCpuLoad * 100.0, this.state.processCpuLoad),\n systemCpuLoad: (0, _utils.addToHistory)(serverInfo.systemCpuLoad * 100.0, this.state.systemCpuLoad),\n heapPercentUsed: (0, _utils.addToHistory)(serverInfo.heapUsed * 100.0 / serverInfo.heapAvailable, this.state.heapPercentUsed),\n nonHeapUsed: (0, _utils.addToHistory)(serverInfo.nonHeapUsed, this.state.nonHeapUsed)\n });\n\n this.resetTimer();\n }.bind(this)).fail(function () {\n this.setState({\n initialized: true\n });\n this.resetTimer();\n }.bind(this));\n }\n }, {\n key: \"componentDidMount\",\n value: function componentDidMount() {\n this.refreshLoop();\n }\n }, {\n key: \"componentDidUpdate\",\n value: function componentDidUpdate() {\n $('#process-cpu-load-sparkline').sparkline(this.state.processCpuLoad, $.extend({}, SMALL_SPARKLINE_PROPERTIES, { chartRangeMin: 0, numberFormatter: _utils.precisionRound }));\n $('#system-cpu-load-sparkline').sparkline(this.state.systemCpuLoad, $.extend({}, SMALL_SPARKLINE_PROPERTIES, { chartRangeMin: 0, numberFormatter: _utils.precisionRound }));\n $('#heap-percent-used-sparkline').sparkline(this.state.heapPercentUsed, $.extend({}, SMALL_SPARKLINE_PROPERTIES, { chartRangeMin: 0, numberFormatter: _utils.precisionRound }));\n $('#nonheap-used-sparkline').sparkline(this.state.nonHeapUsed, $.extend({}, SMALL_SPARKLINE_PROPERTIES, { chartRangeMin: 0, numberFormatter: _utils.formatDataSize }));\n\n $('[data-toggle=\"tooltip\"]').tooltip();\n new window.ClipboardJS('.copy-button');\n }\n }, {\n key: \"renderPoolQueries\",\n value: function renderPoolQueries(pool) {\n if (!pool) {\n return;\n }\n\n var queries = {};\n var reservations = pool.queryMemoryReservations;\n var revocableReservations = pool.queryMemoryRevocableReservations;\n\n for (var query in reservations) {\n queries[query] = [reservations[query], 0];\n }\n\n for (var _query in revocableReservations) {\n if (queries.hasOwnProperty(_query)) {\n queries[_query][1] = revocableReservations[_query];\n } else {\n queries[_query] = [0, revocableReservations[_query]];\n }\n }\n\n var size = pool.maxBytes;\n\n if (Object.keys(queries).length === 0) {\n return _react2.default.createElement(\n \"div\",\n null,\n _react2.default.createElement(\n \"table\",\n { className: \"table table-condensed\" },\n _react2.default.createElement(\n \"tbody\",\n null,\n _react2.default.createElement(\n \"tr\",\n null,\n _react2.default.createElement(\n \"td\",\n null,\n \"No queries using pool\"\n )\n )\n )\n )\n );\n }\n\n return _react2.default.createElement(\n \"div\",\n null,\n _react2.default.createElement(\n \"table\",\n { className: \"table\" },\n _react2.default.createElement(\n \"tbody\",\n null,\n Object.keys(queries).map(function (key) {\n return WorkerStatus.renderPoolQuery(key, queries[key][0], queries[key][1], size);\n })\n )\n )\n );\n }\n }, {\n key: \"render\",\n value: function render() {\n var serverInfo = this.state.serverInfo;\n\n if (serverInfo === null) {\n if (this.state.initialized === false) {\n return _react2.default.createElement(\n \"div\",\n { className: \"loader\" },\n \"Loading...\"\n );\n } else {\n return _react2.default.createElement(\n \"div\",\n { className: \"row error-message\" },\n _react2.default.createElement(\n \"div\",\n { className: \"col-xs-12\" },\n _react2.default.createElement(\n \"h4\",\n null,\n \"Node information could not be loaded\"\n )\n )\n );\n }\n }\n\n return _react2.default.createElement(\n \"div\",\n null,\n _react2.default.createElement(\n \"div\",\n { className: \"row\" },\n _react2.default.createElement(\n \"div\",\n { className: \"col-xs-12\" },\n _react2.default.createElement(\n \"h3\",\n null,\n \"Overview\"\n ),\n _react2.default.createElement(\"hr\", { className: \"h3-hr\" }),\n _react2.default.createElement(\n \"div\",\n { className: \"row\" },\n _react2.default.createElement(\n \"div\",\n { className: \"col-xs-6\" },\n _react2.default.createElement(\n \"table\",\n { className: \"table\" },\n _react2.default.createElement(\n \"tbody\",\n null,\n _react2.default.createElement(\n \"tr\",\n null,\n _react2.default.createElement(\n \"td\",\n { className: \"info-title\" },\n \"Node ID\"\n ),\n _react2.default.createElement(\n \"td\",\n { className: \"info-text wrap-text\" },\n _react2.default.createElement(\n \"span\",\n { id: \"node-id\" },\n serverInfo.nodeId\n ),\n \"\\xA0\\xA0\",\n _react2.default.createElement(\n \"a\",\n { href: \"#\", className: \"copy-button\", \"data-clipboard-target\": \"#node-id\", \"data-toggle\": \"tooltip\", \"data-placement\": \"right\",\n title: \"Copy to clipboard\" },\n _react2.default.createElement(\"span\", { className: \"glyphicon glyphicon-copy\", alt: \"Copy to clipboard\" })\n )\n )\n ),\n _react2.default.createElement(\n \"tr\",\n null,\n _react2.default.createElement(\n \"td\",\n { className: \"info-title\" },\n \"Heap Memory\"\n ),\n _react2.default.createElement(\n \"td\",\n { className: \"info-text wrap-text\" },\n _react2.default.createElement(\n \"span\",\n { id: \"node-heap-available\" },\n (0, _utils.formatDataSize)(serverInfo.heapAvailable)\n )\n )\n ),\n _react2.default.createElement(\n \"tr\",\n null,\n _react2.default.createElement(\n \"td\",\n { className: \"info-title\" },\n \"Processors\"\n ),\n _react2.default.createElement(\n \"td\",\n { className: \"info-text wrap-text\" },\n _react2.default.createElement(\n \"span\",\n { id: \"node-processors\" },\n serverInfo.processors\n )\n )\n )\n )\n )\n ),\n _react2.default.createElement(\n \"div\",\n { className: \"col-xs-6\" },\n _react2.default.createElement(\n \"table\",\n { className: \"table\" },\n _react2.default.createElement(\n \"tbody\",\n null,\n _react2.default.createElement(\n \"tr\",\n null,\n _react2.default.createElement(\n \"td\",\n { className: \"info-title\" },\n \"Uptime\"\n ),\n _react2.default.createElement(\n \"td\",\n { className: \"info-text wrap-text\" },\n serverInfo.uptime\n )\n ),\n _react2.default.createElement(\n \"tr\",\n null,\n _react2.default.createElement(\n \"td\",\n { className: \"info-title\" },\n \"External Address\"\n ),\n _react2.default.createElement(\n \"td\",\n { className: \"info-text wrap-text\" },\n _react2.default.createElement(\n \"span\",\n { id: \"external-address\" },\n serverInfo.externalAddress\n ),\n \"\\xA0\\xA0\",\n _react2.default.createElement(\n \"a\",\n { href: \"#\", className: \"copy-button\", \"data-clipboard-target\": \"#external-address\", \"data-toggle\": \"tooltip\", \"data-placement\": \"right\",\n title: \"Copy to clipboard\" },\n _react2.default.createElement(\"span\", { className: \"glyphicon glyphicon-copy\", alt: \"Copy to clipboard\" })\n )\n )\n ),\n _react2.default.createElement(\n \"tr\",\n null,\n _react2.default.createElement(\n \"td\",\n { className: \"info-title\" },\n \"Internal Address\"\n ),\n _react2.default.createElement(\n \"td\",\n { className: \"info-text wrap-text\" },\n _react2.default.createElement(\n \"span\",\n { id: \"internal-address\" },\n serverInfo.internalAddress\n ),\n \"\\xA0\\xA0\",\n _react2.default.createElement(\n \"a\",\n { href: \"#\", className: \"copy-button\", \"data-clipboard-target\": \"#internal-address\", \"data-toggle\": \"tooltip\", \"data-placement\": \"right\",\n title: \"Copy to clipboard\" },\n _react2.default.createElement(\"span\", { className: \"glyphicon glyphicon-copy\", alt: \"Copy to clipboard\" })\n )\n )\n )\n )\n )\n )\n ),\n _react2.default.createElement(\n \"div\",\n { className: \"row\" },\n _react2.default.createElement(\n \"div\",\n { className: \"col-xs-12\" },\n _react2.default.createElement(\n \"h3\",\n null,\n \"Resource Utilization\"\n ),\n _react2.default.createElement(\"hr\", { className: \"h3-hr\" }),\n _react2.default.createElement(\n \"div\",\n { className: \"row\" },\n _react2.default.createElement(\n \"div\",\n { className: \"col-xs-6\" },\n _react2.default.createElement(\n \"table\",\n { className: \"table\" },\n _react2.default.createElement(\n \"tbody\",\n null,\n _react2.default.createElement(\n \"tr\",\n null,\n _react2.default.createElement(\n \"td\",\n { className: \"info-title\" },\n \"Process CPU Utilization\"\n ),\n _react2.default.createElement(\n \"td\",\n { rowSpan: \"2\" },\n _react2.default.createElement(\n \"div\",\n { className: \"query-stats-sparkline-container\" },\n _react2.default.createElement(\n \"span\",\n { className: \"sparkline\", id: \"process-cpu-load-sparkline\" },\n _react2.default.createElement(\n \"div\",\n { className: \"loader\" },\n \"Loading ...\"\n )\n )\n )\n )\n ),\n _react2.default.createElement(\n \"tr\",\n { className: \"tr-noborder\" },\n _react2.default.createElement(\n \"td\",\n { className: \"info-sparkline-text\" },\n (0, _utils.formatCount)(this.state.processCpuLoad[this.state.processCpuLoad.length - 1]),\n \"%\"\n )\n ),\n _react2.default.createElement(\n \"tr\",\n null,\n _react2.default.createElement(\n \"td\",\n { className: \"info-title\" },\n \"System CPU Utilization\"\n ),\n _react2.default.createElement(\n \"td\",\n { rowSpan: \"2\" },\n _react2.default.createElement(\n \"div\",\n { className: \"query-stats-sparkline-container\" },\n _react2.default.createElement(\n \"span\",\n { className: \"sparkline\", id: \"system-cpu-load-sparkline\" },\n _react2.default.createElement(\n \"div\",\n { className: \"loader\" },\n \"Loading ...\"\n )\n )\n )\n )\n ),\n _react2.default.createElement(\n \"tr\",\n { className: \"tr-noborder\" },\n _react2.default.createElement(\n \"td\",\n { className: \"info-sparkline-text\" },\n (0, _utils.formatCount)(this.state.systemCpuLoad[this.state.systemCpuLoad.length - 1]),\n \"%\"\n )\n )\n )\n )\n ),\n _react2.default.createElement(\n \"div\",\n { className: \"col-xs-6\" },\n _react2.default.createElement(\n \"table\",\n { className: \"table\" },\n _react2.default.createElement(\n \"tbody\",\n null,\n _react2.default.createElement(\n \"tr\",\n null,\n _react2.default.createElement(\n \"td\",\n { className: \"info-title\" },\n \"Heap Utilization\"\n ),\n _react2.default.createElement(\n \"td\",\n { rowSpan: \"2\" },\n _react2.default.createElement(\n \"div\",\n { className: \"query-stats-sparkline-container\" },\n _react2.default.createElement(\n \"span\",\n { className: \"sparkline\", id: \"heap-percent-used-sparkline\" },\n _react2.default.createElement(\n \"div\",\n { className: \"loader\" },\n \"Loading ...\"\n )\n )\n )\n )\n ),\n _react2.default.createElement(\n \"tr\",\n { className: \"tr-noborder\" },\n _react2.default.createElement(\n \"td\",\n { className: \"info-sparkline-text\" },\n (0, _utils.formatCount)(this.state.heapPercentUsed[this.state.heapPercentUsed.length - 1]),\n \"%\"\n )\n ),\n _react2.default.createElement(\n \"tr\",\n null,\n _react2.default.createElement(\n \"td\",\n { className: \"info-title\" },\n \"Non-Heap Memory Used\"\n ),\n _react2.default.createElement(\n \"td\",\n { rowSpan: \"2\" },\n _react2.default.createElement(\n \"div\",\n { className: \"query-stats-sparkline-container\" },\n _react2.default.createElement(\n \"span\",\n { className: \"sparkline\", id: \"nonheap-used-sparkline\" },\n _react2.default.createElement(\n \"div\",\n { className: \"loader\" },\n \"Loading ...\"\n )\n )\n )\n )\n ),\n _react2.default.createElement(\n \"tr\",\n { className: \"tr-noborder\" },\n _react2.default.createElement(\n \"td\",\n { className: \"info-sparkline-text\" },\n (0, _utils.formatDataSize)(this.state.nonHeapUsed[this.state.nonHeapUsed.length - 1])\n )\n )\n )\n )\n )\n )\n )\n )\n )\n ),\n _react2.default.createElement(\n \"div\",\n { className: \"row\" },\n _react2.default.createElement(\n \"div\",\n { className: \"col-xs-12\" },\n _react2.default.createElement(\n \"h3\",\n null,\n \"Memory\"\n ),\n _react2.default.createElement(\"hr\", { className: \"h3-hr\" }),\n _react2.default.createElement(\n \"div\",\n { className: \"row\" },\n _react2.default.createElement(\n \"div\",\n { className: \"col-xs-6\" },\n WorkerStatus.renderPoolBar(\"Memory Usage\", serverInfo.memoryInfo.pool),\n this.renderPoolQueries(serverInfo.memoryInfo.pool)\n )\n )\n )\n )\n );\n }\n }], [{\n key: \"renderPoolBar\",\n value: function renderPoolBar(name, pool) {\n if (!pool) {\n return;\n }\n\n var size = pool.maxBytes;\n var reserved = pool.reservedBytes;\n var revocable = pool.reservedRevocableBytes;\n\n var percentageReservedNonRevocable = reserved === 0 ? 0 : Math.max(Math.round(reserved * 100.0 / size), 15);\n var percentageRevocable = revocable === 0 ? 0 : Math.max(Math.round(revocable * 100.0 / size), 15);\n var percentageFree = 100 - (percentageRevocable + percentageReservedNonRevocable);\n\n return _react2.default.createElement(\n \"div\",\n { className: \"row\" },\n _react2.default.createElement(\n \"div\",\n { className: \"col-xs-12\" },\n _react2.default.createElement(\n \"div\",\n { className: \"row\" },\n _react2.default.createElement(\n \"div\",\n { className: \"col-xs-8\" },\n _react2.default.createElement(\n \"h4\",\n null,\n name,\n \" Pool\"\n )\n ),\n _react2.default.createElement(\n \"div\",\n { className: \"col-xs-4\" },\n _react2.default.createElement(\n \"div\",\n { className: \"progress\", style: { marginTop: \"6px\" } },\n _react2.default.createElement(\n \"div\",\n { className: \"progress-bar memory-progress-bar memory-progress-bar-info\", role: \"progressbar\", style: { width: \"100%\" } },\n (0, _utils.formatDataSize)(size),\n \" total\"\n )\n )\n )\n ),\n _react2.default.createElement(\n \"div\",\n { className: \"row\" },\n _react2.default.createElement(\n \"div\",\n { className: \"col-xs-12\" },\n _react2.default.createElement(\"hr\", { className: \"h4-hr\" }),\n _react2.default.createElement(\n \"div\",\n { className: \"progress\" },\n _react2.default.createElement(\n \"div\",\n { className: \"progress-bar memory-progress-bar progress-bar-warning progress-bar-striped active\", role: \"progressbar\",\n style: { width: percentageReservedNonRevocable + \"%\" } },\n (0, _utils.formatDataSize)(reserved)\n ),\n _react2.default.createElement(\n \"div\",\n { className: \"progress-bar memory-progress-bar progress-bar-danger progress-bar-striped active\", role: \"progressbar\",\n style: { width: percentageRevocable + \"%\" } },\n (0, _utils.formatDataSize)(revocable)\n ),\n _react2.default.createElement(\n \"div\",\n { className: \"progress-bar memory-progress-bar progress-bar-success\", role: \"progressbar\", style: { width: percentageFree + \"%\" } },\n (0, _utils.formatDataSize)(size - reserved - revocable)\n )\n )\n )\n )\n )\n );\n }\n }, {\n key: \"renderPoolQuery\",\n value: function renderPoolQuery(query, reserved, revocable, total) {\n return _react2.default.createElement(\n \"tr\",\n null,\n _react2.default.createElement(\n \"td\",\n null,\n _react2.default.createElement(\n \"div\",\n { className: \"row query-memory-list-header\" },\n _react2.default.createElement(\n \"div\",\n { className: \"col-xs-7\" },\n _react2.default.createElement(\n \"a\",\n { href: \"query.html?\" + query, target: \"_blank\" },\n query\n )\n ),\n _react2.default.createElement(\n \"div\",\n { className: \"col-xs-5\" },\n _react2.default.createElement(\n \"div\",\n { className: \"row text-right\" },\n _react2.default.createElement(\n \"div\",\n { className: \"col-xs-6\" },\n _react2.default.createElement(\n \"span\",\n { \"data-toggle\": \"tooltip\", \"data-placement\": \"top\", title: \"% of pool memory reserved\" },\n Math.round(reserved * 100.0 / total),\n \"%\"\n )\n ),\n _react2.default.createElement(\n \"div\",\n { className: \"col-xs-6\" },\n _react2.default.createElement(\n \"span\",\n { \"data-toggle\": \"tooltip\", \"data-placement\": \"top\",\n title: \"Reserved: \" + (0, _utils.formatDataSize)(reserved) + \". Revocable: \" + (0, _utils.formatDataSize)(revocable) },\n (0, _utils.formatDataSize)(reserved)\n )\n )\n )\n )\n )\n )\n );\n }\n }]);\n\n return WorkerStatus;\n}(_react2.default.Component);\n\n//# sourceURL=webpack:///./components/WorkerStatus.jsx?"); /***/ }), diff --git a/core/trino-main/src/main/resources/webapp/src/components/QueryDetail.jsx b/core/trino-main/src/main/resources/webapp/src/components/QueryDetail.jsx index e0e479e57c9b..91778522a0a2 100644 --- a/core/trino-main/src/main/resources/webapp/src/components/QueryDetail.jsx +++ b/core/trino-main/src/main/resources/webapp/src/components/QueryDetail.jsx @@ -1426,14 +1426,6 @@ export class QueryDetail extends React.Component { {parseAndFormatDataSize(query.queryStats.peakTotalMemoryReservation)} - - - Memory Pool - - - {query.memoryPool} - - Cumulative User Memory diff --git a/core/trino-main/src/main/resources/webapp/src/components/WorkerStatus.jsx b/core/trino-main/src/main/resources/webapp/src/components/WorkerStatus.jsx index 9c47cce5ce63..f00b2e125555 100644 --- a/core/trino-main/src/main/resources/webapp/src/components/WorkerStatus.jsx +++ b/core/trino-main/src/main/resources/webapp/src/components/WorkerStatus.jsx @@ -414,12 +414,12 @@ export class WorkerStatus extends React.Component {
-

Memory Pools

+

Memory


- {WorkerStatus.renderPoolBar("General", serverInfo.memoryInfo.pools.general)} - {this.renderPoolQueries(serverInfo.memoryInfo.pools.general)} + {WorkerStatus.renderPoolBar("Memory Usage", serverInfo.memoryInfo.pool)} + {this.renderPoolQueries(serverInfo.memoryInfo.pool)}
diff --git a/core/trino-main/src/test/java/io/trino/execution/MockManagedQueryExecution.java b/core/trino-main/src/test/java/io/trino/execution/MockManagedQueryExecution.java index 9d76bec04705..f25bf98c422e 100644 --- a/core/trino-main/src/test/java/io/trino/execution/MockManagedQueryExecution.java +++ b/core/trino-main/src/test/java/io/trino/execution/MockManagedQueryExecution.java @@ -24,7 +24,6 @@ import io.trino.server.BasicQueryStats; import io.trino.spi.ErrorCode; import io.trino.spi.QueryId; -import io.trino.spi.memory.MemoryPoolId; import org.joda.time.DateTime; import java.net.URI; @@ -113,7 +112,6 @@ public BasicQueryInfo getBasicQueryInfo() session.toSessionRepresentation(), Optional.empty(), state, - new MemoryPoolId("test"), !state.isDone(), URI.create("http://test"), "SELECT 1", @@ -154,7 +152,6 @@ public QueryInfo getFullQueryInfo() new QueryId("test"), session.toSessionRepresentation(), state, - new MemoryPoolId("test"), !state.isDone(), URI.create("http://test"), ImmutableList.of(), diff --git a/core/trino-main/src/test/java/io/trino/execution/MockRemoteTaskFactory.java b/core/trino-main/src/test/java/io/trino/execution/MockRemoteTaskFactory.java index 45a417a2866a..6c74f5ae9269 100644 --- a/core/trino-main/src/test/java/io/trino/execution/MockRemoteTaskFactory.java +++ b/core/trino-main/src/test/java/io/trino/execution/MockRemoteTaskFactory.java @@ -40,7 +40,6 @@ import io.trino.operator.TaskContext; import io.trino.operator.TaskStats; import io.trino.spi.SplitWeight; -import io.trino.spi.memory.MemoryPoolId; import io.trino.spiller.SpillSpaceTracker; import io.trino.sql.planner.Partitioning; import io.trino.sql.planner.PartitioningScheme; @@ -193,7 +192,7 @@ public MockRemoteTask( { this.taskStateMachine = new TaskStateMachine(requireNonNull(taskId, "taskId is null"), requireNonNull(executor, "executor is null")); - MemoryPool memoryPool = new MemoryPool(new MemoryPoolId("test"), DataSize.of(1, GIGABYTE)); + MemoryPool memoryPool = new MemoryPool(DataSize.of(1, GIGABYTE)); SpillSpaceTracker spillSpaceTracker = new SpillSpaceTracker(DataSize.of(1, GIGABYTE)); QueryContext queryContext = new QueryContext(taskId.getQueryId(), DataSize.of(1, MEGABYTE), diff --git a/core/trino-main/src/test/java/io/trino/execution/TestMemoryRevokingScheduler.java b/core/trino-main/src/test/java/io/trino/execution/TestMemoryRevokingScheduler.java index e2c7d2be1bae..c54a5614a920 100644 --- a/core/trino-main/src/test/java/io/trino/execution/TestMemoryRevokingScheduler.java +++ b/core/trino-main/src/test/java/io/trino/execution/TestMemoryRevokingScheduler.java @@ -32,7 +32,6 @@ import io.trino.operator.PipelineContext; import io.trino.operator.TaskContext; import io.trino.spi.QueryId; -import io.trino.spi.memory.MemoryPoolId; import io.trino.spiller.SpillSpaceTracker; import io.trino.sql.planner.LocalExecutionPlanner; import io.trino.sql.planner.plan.PlanNodeId; @@ -61,8 +60,6 @@ import static io.trino.execution.TestSqlTask.OUT; import static io.trino.execution.buffer.OutputBuffers.BufferType.PARTITIONED; import static io.trino.execution.buffer.OutputBuffers.createInitialEmptyOutputBuffers; -import static io.trino.memory.LocalMemoryManager.GENERAL_POOL; -import static java.util.Arrays.asList; import static java.util.Collections.singletonList; import static java.util.concurrent.Executors.newScheduledThreadPool; import static org.testng.Assert.assertEquals; @@ -86,7 +83,7 @@ public class TestMemoryRevokingScheduler @BeforeMethod public void setUp() { - memoryPool = new MemoryPool(GENERAL_POOL, DataSize.ofBytes(10)); + memoryPool = new MemoryPool(DataSize.ofBytes(10)); TaskExecutor taskExecutor = new TaskExecutor(8, 16, 3, 4, Ticker.systemTicker()); taskExecutor.start(); @@ -141,7 +138,7 @@ public void testScheduleMemoryRevoking() OperatorContext operatorContext5 = driverContext211.addOperatorContext(5, new PlanNodeId("na"), "na"); Collection tasks = ImmutableList.of(sqlTask1, sqlTask2); - MemoryRevokingScheduler scheduler = new MemoryRevokingScheduler(singletonList(memoryPool), () -> tasks, executor, 1.0, 1.0); + MemoryRevokingScheduler scheduler = new MemoryRevokingScheduler(memoryPool, () -> tasks, executor, 1.0, 1.0); allOperatorContexts = ImmutableSet.of(operatorContext1, operatorContext2, operatorContext3, operatorContext4, operatorContext5); assertMemoryRevokingNotRequested(); @@ -194,42 +191,6 @@ public void testScheduleMemoryRevoking() assertMemoryRevokingRequestedFor(operatorContext3, operatorContext4); } - @Test - public void testCountAlreadyRevokedMemoryWithinAPool() - throws Exception - { - // Given - SqlTask sqlTask1 = newSqlTask(new QueryId("q1")); - MemoryPool anotherMemoryPool = new MemoryPool(new MemoryPoolId("test"), DataSize.ofBytes(10)); - sqlTask1.getQueryContext().setMemoryPool(anotherMemoryPool); - OperatorContext operatorContext1 = createContexts(sqlTask1); - - SqlTask sqlTask2 = newSqlTask(new QueryId("q2")); - OperatorContext operatorContext2 = createContexts(sqlTask2); - - List tasks = ImmutableList.of(sqlTask1, sqlTask2); - MemoryRevokingScheduler scheduler = new MemoryRevokingScheduler(asList(memoryPool, anotherMemoryPool), () -> tasks, executor, 1.0, 1.0); - allOperatorContexts = ImmutableSet.of(operatorContext1, operatorContext2); - - /* - * sqlTask1 fills its pool - */ - operatorContext1.localRevocableMemoryContext().setBytes(12); - requestMemoryRevoking(scheduler); - assertMemoryRevokingRequestedFor(operatorContext1); - - /* - * When sqlTask2 fills its pool - */ - operatorContext2.localRevocableMemoryContext().setBytes(12); - requestMemoryRevoking(scheduler); - - /* - * Then sqlTask2 should be asked to revoke its memory too - */ - assertMemoryRevokingRequestedFor(operatorContext1, operatorContext2); - } - /** * Test that when a {@link MemoryPool} is over-allocated, revocable memory is revoked without delay (although asynchronously). */ @@ -243,7 +204,7 @@ public void testImmediateMemoryRevoking() allOperatorContexts = ImmutableSet.of(operatorContext); List tasks = ImmutableList.of(sqlTask); - MemoryRevokingScheduler scheduler = new MemoryRevokingScheduler(singletonList(memoryPool), () -> tasks, executor, 1.0, 1.0); + MemoryRevokingScheduler scheduler = new MemoryRevokingScheduler(memoryPool, () -> tasks, executor, 1.0, 1.0); scheduler.registerPoolListeners(); // no periodic check initiated // When diff --git a/core/trino-main/src/test/java/io/trino/execution/TestQueryStateMachine.java b/core/trino-main/src/test/java/io/trino/execution/TestQueryStateMachine.java index 07d4659de248..d6375d60de01 100644 --- a/core/trino-main/src/test/java/io/trino/execution/TestQueryStateMachine.java +++ b/core/trino-main/src/test/java/io/trino/execution/TestQueryStateMachine.java @@ -21,14 +21,12 @@ import io.trino.Session; import io.trino.client.FailureInfo; import io.trino.execution.warnings.WarningCollector; -import io.trino.memory.VersionedMemoryPoolId; import io.trino.metadata.Metadata; import io.trino.plugin.base.security.AllowAllSystemAccessControl; import io.trino.plugin.base.security.DefaultSystemAccessControl; import io.trino.security.AccessControlConfig; import io.trino.security.AccessControlManager; import io.trino.spi.TrinoException; -import io.trino.spi.memory.MemoryPoolId; import io.trino.spi.resourcegroups.QueryType; import io.trino.spi.resourcegroups.ResourceGroupId; import io.trino.spi.type.Type; @@ -74,7 +72,6 @@ import static org.testng.Assert.assertFalse; import static org.testng.Assert.assertNotNull; import static org.testng.Assert.assertNull; -import static org.testng.Assert.assertSame; import static org.testng.Assert.assertTrue; public class TestQueryStateMachine @@ -94,7 +91,6 @@ public class TestQueryStateMachine private static final List OUTPUT_FIELD_NAMES = ImmutableList.of("a", "b", "c"); private static final List OUTPUT_FIELD_TYPES = ImmutableList.of(BIGINT, BIGINT, BIGINT); private static final String UPDATE_TYPE = "update type"; - private static final VersionedMemoryPoolId MEMORY_POOL = new VersionedMemoryPoolId(new MemoryPoolId("pool"), 42); private static final Map SET_SESSION_PROPERTIES = ImmutableMap.builder() .put("fruit", "apple") .put("drink", "coffee") @@ -439,7 +435,6 @@ private static void assertState(QueryStateMachine stateMachine, QueryState expec { assertEquals(stateMachine.getQueryId(), TEST_SESSION.getQueryId()); assertEqualSessionsWithoutTransactionId(stateMachine.getSession(), TEST_SESSION); - assertSame(stateMachine.getMemoryPool(), MEMORY_POOL); assertEquals(stateMachine.getSetSessionProperties(), SET_SESSION_PROPERTIES); assertEquals(stateMachine.getResetSessionProperties(), RESET_SESSION_PROPERTIES); @@ -452,7 +447,6 @@ private static void assertState(QueryStateMachine stateMachine, QueryState expec assertEquals(queryInfo.getOutput(), OUTPUT); assertEquals(queryInfo.getFieldNames(), OUTPUT_FIELD_NAMES); assertEquals(queryInfo.getUpdateType(), UPDATE_TYPE); - assertEquals(queryInfo.getMemoryPool(), MEMORY_POOL.getId()); assertTrue(queryInfo.getQueryType().isPresent()); assertEquals(queryInfo.getQueryType().get(), QUERY_TYPE.get()); @@ -534,7 +528,6 @@ private QueryStateMachine createQueryStateMachineWithTicker(Ticker ticker) stateMachine.setOutput(OUTPUT); stateMachine.setColumns(OUTPUT_FIELD_NAMES, OUTPUT_FIELD_TYPES); stateMachine.setUpdateType(UPDATE_TYPE); - stateMachine.setMemoryPool(MEMORY_POOL); for (Entry entry : SET_SESSION_PROPERTIES.entrySet()) { stateMachine.addSetSessionProperties(entry.getKey(), entry.getValue()); } diff --git a/core/trino-main/src/test/java/io/trino/execution/TestSqlTask.java b/core/trino-main/src/test/java/io/trino/execution/TestSqlTask.java index d04cfecb2e68..f6db181ccf07 100644 --- a/core/trino-main/src/test/java/io/trino/execution/TestSqlTask.java +++ b/core/trino-main/src/test/java/io/trino/execution/TestSqlTask.java @@ -32,7 +32,6 @@ import io.trino.metadata.ExchangeHandleResolver; import io.trino.operator.TaskContext; import io.trino.spi.QueryId; -import io.trino.spi.memory.MemoryPoolId; import io.trino.spi.predicate.Domain; import io.trino.spiller.SpillSpaceTracker; import io.trino.sql.planner.LocalExecutionPlanner; @@ -348,7 +347,7 @@ private SqlTask createInitialTask() QueryContext queryContext = new QueryContext(new QueryId("query"), DataSize.of(1, MEGABYTE), Optional.empty(), - new MemoryPool(new MemoryPoolId("test"), DataSize.of(1, GIGABYTE)), + new MemoryPool(DataSize.of(1, GIGABYTE)), new TestingGcMonitor(), taskNotificationExecutor, driverYieldExecutor, diff --git a/core/trino-main/src/test/java/io/trino/execution/TestSqlTaskExecution.java b/core/trino-main/src/test/java/io/trino/execution/TestSqlTaskExecution.java index 9041863a97a9..2e6f91ec2728 100644 --- a/core/trino-main/src/test/java/io/trino/execution/TestSqlTaskExecution.java +++ b/core/trino-main/src/test/java/io/trino/execution/TestSqlTaskExecution.java @@ -56,7 +56,6 @@ import io.trino.spi.block.TestingBlockEncodingSerde; import io.trino.spi.connector.ConnectorSplit; import io.trino.spi.connector.UpdatablePageSource; -import io.trino.spi.memory.MemoryPoolId; import io.trino.spi.type.Type; import io.trino.spiller.SpillSpaceTracker; import io.trino.sql.planner.LocalExecutionPlanner.LocalExecutionPlan; @@ -598,7 +597,7 @@ private TaskContext newTestingTaskContext(ScheduledExecutorService taskNotificat new QueryId("queryid"), DataSize.of(1, MEGABYTE), Optional.empty(), - new MemoryPool(new MemoryPoolId("test"), DataSize.of(1, GIGABYTE)), + new MemoryPool(DataSize.of(1, GIGABYTE)), new TestingGcMonitor(), taskNotificationExecutor, driverYieldExecutor, diff --git a/core/trino-main/src/test/java/io/trino/memory/LowMemoryKillerTestingUtils.java b/core/trino-main/src/test/java/io/trino/memory/LowMemoryKillerTestingUtils.java index 87c278a7ba07..85762cf242d4 100644 --- a/core/trino-main/src/test/java/io/trino/memory/LowMemoryKillerTestingUtils.java +++ b/core/trino-main/src/test/java/io/trino/memory/LowMemoryKillerTestingUtils.java @@ -16,11 +16,9 @@ import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; -import io.airlift.units.DataSize; import io.trino.client.NodeVersion; import io.trino.metadata.InternalNode; import io.trino.spi.QueryId; -import io.trino.spi.memory.MemoryPoolId; import io.trino.spi.memory.MemoryPoolInfo; import java.net.URI; @@ -28,13 +26,11 @@ import java.util.List; import java.util.Map; -import static io.trino.memory.LocalMemoryManager.GENERAL_POOL; - public final class LowMemoryKillerTestingUtils { private LowMemoryKillerTestingUtils() {} - static List toNodeMemoryInfoList(long maxGeneralPoolBytes, Map> queries) + static List toNodeMemoryInfoList(long memoryPoolMaxBytes, Map> queries) { Map nodeReservations = new HashMap<>(); @@ -48,26 +44,21 @@ static List toNodeMemoryInfoList(long maxGeneralPoolBytes, Map new NodeReservation()).getGeneral().add(queryId, bytes); + nodeReservations.computeIfAbsent(node, ignored -> new NodeReservation()).add(queryId, bytes); } } ImmutableList.Builder result = ImmutableList.builder(); for (Map.Entry entry : nodeReservations.entrySet()) { NodeReservation nodeReservation = entry.getValue(); - ImmutableMap.Builder pools = ImmutableMap.builder(); - if (nodeReservation.getGeneral().getTotalReservedBytes() > 0) { - pools.put( - GENERAL_POOL, - new MemoryPoolInfo( - maxGeneralPoolBytes, - nodeReservation.getGeneral().getTotalReservedBytes(), - 0, - nodeReservation.getGeneral().getReservationByQuery(), - ImmutableMap.of(), - ImmutableMap.of())); - } - result.add(new MemoryInfo(7, DataSize.ofBytes(maxGeneralPoolBytes), pools.buildOrThrow())); + MemoryPoolInfo memoryPoolInfo = new MemoryPoolInfo( + memoryPoolMaxBytes, + nodeReservation.getTotalReservedBytes(), + 0, + nodeReservation.getReservationByQuery(), + ImmutableMap.of(), + ImmutableMap.of()); + result.add(new MemoryInfo(7, memoryPoolInfo)); } return result.build(); } @@ -80,22 +71,12 @@ static List toQueryMemoryInfoList(Map x) .sum(); - result.add(new LowMemoryKiller.QueryMemoryInfo(new QueryId(queryId), GENERAL_POOL, totalReservation)); + result.add(new LowMemoryKiller.QueryMemoryInfo(new QueryId(queryId), totalReservation)); } return result.build(); } private static class NodeReservation - { - private final PoolReservation general = new PoolReservation(); - - public PoolReservation getGeneral() - { - return general; - } - } - - private static class PoolReservation { private long totalReservedBytes; private final Map reservationByQuery = new HashMap<>(); diff --git a/core/trino-main/src/test/java/io/trino/memory/TestLocalMemoryManager.java b/core/trino-main/src/test/java/io/trino/memory/TestLocalMemoryManager.java index f1ded908186b..b67470e1100f 100644 --- a/core/trino-main/src/test/java/io/trino/memory/TestLocalMemoryManager.java +++ b/core/trino-main/src/test/java/io/trino/memory/TestLocalMemoryManager.java @@ -18,21 +18,9 @@ import static io.airlift.units.DataSize.Unit.GIGABYTE; import static org.assertj.core.api.Assertions.assertThatThrownBy; -import static org.testng.Assert.assertEquals; public class TestLocalMemoryManager { - @Test - public void testLocalMemoryManger() - { - NodeMemoryConfig config = new NodeMemoryConfig() - .setHeapHeadroom(DataSize.of(10, GIGABYTE)) - .setMaxQueryMemoryPerNode(DataSize.of(20, GIGABYTE)); - - LocalMemoryManager localMemoryManager = new LocalMemoryManager(config, DataSize.of(60, GIGABYTE).toBytes()); - assertEquals(localMemoryManager.getPools().size(), 1); - } - @Test public void testNotEnoughAvailableMemory() { diff --git a/core/trino-main/src/test/java/io/trino/memory/TestMemoryPools.java b/core/trino-main/src/test/java/io/trino/memory/TestMemoryPools.java index 536507b50236..da190489cc97 100644 --- a/core/trino-main/src/test/java/io/trino/memory/TestMemoryPools.java +++ b/core/trino-main/src/test/java/io/trino/memory/TestMemoryPools.java @@ -31,7 +31,6 @@ import io.trino.plugin.tpch.TpchConnectorFactory; import io.trino.spi.Page; import io.trino.spi.QueryId; -import io.trino.spi.memory.MemoryPoolId; import io.trino.spiller.SpillSpaceTracker; import io.trino.sql.planner.plan.PlanNodeId; import io.trino.testing.LocalQueryRunner; @@ -58,7 +57,6 @@ import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertFalse; -import static org.testng.Assert.assertNull; import static org.testng.Assert.assertTrue; @Test(singleThreaded = true) @@ -91,7 +89,7 @@ private void setUp(Supplier> driversSupplier) // add tpch localQueryRunner.createCatalog("tpch", new TpchConnectorFactory(1), ImmutableMap.of()); - userPool = new MemoryPool(new MemoryPoolId("test"), TEN_MEGABYTES); + userPool = new MemoryPool(TEN_MEGABYTES); fakeQueryId = new QueryId("fake"); SpillSpaceTracker spillSpaceTracker = new SpillSpaceTracker(DataSize.of(1, GIGABYTE)); QueryContext queryContext = new QueryContext(new QueryId("query"), @@ -230,7 +228,7 @@ public void testBlockingOnRevocableMemoryFreeViaRevoke() public void testTaggedAllocations() { QueryId testQuery = new QueryId("test_query"); - MemoryPool testPool = new MemoryPool(new MemoryPoolId("test"), DataSize.ofBytes(1000)); + MemoryPool testPool = new MemoryPool(DataSize.ofBytes(1000)); testPool.reserve(testQuery, "test_tag", 10); @@ -253,43 +251,6 @@ public void testTaggedAllocations() assertEquals(testPool.getTaggedMemoryAllocations().size(), 0); } - @Test - public void testMoveQuery() - { - QueryId testQuery = new QueryId("test_query"); - MemoryPool pool1 = new MemoryPool(new MemoryPoolId("test"), DataSize.ofBytes(1000)); - MemoryPool pool2 = new MemoryPool(new MemoryPoolId("test"), DataSize.ofBytes(1000)); - pool1.reserve(testQuery, "test_tag", 10); - - Map allocations = pool1.getTaggedMemoryAllocations().get(testQuery); - assertEquals(allocations, ImmutableMap.of("test_tag", 10L)); - - pool1.moveQuery(testQuery, pool2); - assertNull(pool1.getTaggedMemoryAllocations().get(testQuery)); - allocations = pool2.getTaggedMemoryAllocations().get(testQuery); - assertEquals(allocations, ImmutableMap.of("test_tag", 10L)); - - assertEquals(pool1.getFreeBytes(), 1000); - assertEquals(pool2.getFreeBytes(), 990); - - pool2.free(testQuery, "test", 10); - assertEquals(pool2.getFreeBytes(), 1000); - } - - @Test - public void testMoveUnknownQuery() - { - QueryId testQuery = new QueryId("test_query"); - MemoryPool pool1 = new MemoryPool(new MemoryPoolId("test"), DataSize.ofBytes(1000)); - MemoryPool pool2 = new MemoryPool(new MemoryPoolId("test"), DataSize.ofBytes(1000)); - - assertNull(pool1.getTaggedMemoryAllocations().get(testQuery)); - - pool1.moveQuery(testQuery, pool2); - assertNull(pool1.getTaggedMemoryAllocations().get(testQuery)); - assertNull(pool2.getTaggedMemoryAllocations().get(testQuery)); - } - private long runDriversUntilBlocked(Predicate reason) { long iterationsCount = 0; diff --git a/core/trino-main/src/test/java/io/trino/memory/TestMemoryTracking.java b/core/trino-main/src/test/java/io/trino/memory/TestMemoryTracking.java index 5840c833fb62..331b5af2705b 100644 --- a/core/trino-main/src/test/java/io/trino/memory/TestMemoryTracking.java +++ b/core/trino-main/src/test/java/io/trino/memory/TestMemoryTracking.java @@ -30,7 +30,6 @@ import io.trino.operator.TaskContext; import io.trino.operator.TaskStats; import io.trino.spi.QueryId; -import io.trino.spi.memory.MemoryPoolId; import io.trino.spiller.SpillSpaceTracker; import io.trino.sql.planner.plan.PlanNodeId; import org.testng.annotations.AfterClass; @@ -100,7 +99,7 @@ public void setUpTest() private void setupTestWithLimits(DataSize queryMaxMemory, Optional queryMaxTaskMemory) { - memoryPool = new MemoryPool(new MemoryPoolId("test"), memoryPoolSize); + memoryPool = new MemoryPool(memoryPoolSize); queryContext = new QueryContext( new QueryId("test_query"), queryMaxMemory, diff --git a/core/trino-main/src/test/java/io/trino/memory/TestQueryContext.java b/core/trino-main/src/test/java/io/trino/memory/TestQueryContext.java index 982cdd916d81..84e96f13ab13 100644 --- a/core/trino-main/src/test/java/io/trino/memory/TestQueryContext.java +++ b/core/trino-main/src/test/java/io/trino/memory/TestQueryContext.java @@ -27,7 +27,6 @@ import static io.airlift.concurrent.Threads.threadsNamed; import static io.trino.SessionTestUtils.TEST_SESSION; -import static io.trino.memory.LocalMemoryManager.GENERAL_POOL; import static java.util.concurrent.Executors.newScheduledThreadPool; import static org.testng.Assert.assertTrue; @@ -49,7 +48,7 @@ public void testSetMemoryPool() new QueryId("query"), DataSize.ofBytes(10), Optional.empty(), - new MemoryPool(GENERAL_POOL, DataSize.ofBytes(10)), + new MemoryPool(DataSize.ofBytes(10)), new TestingGcMonitor(), localQueryRunner.getExecutor(), localQueryRunner.getScheduler(), diff --git a/core/trino-main/src/test/java/io/trino/memory/TestTotalReservationLowMemoryKiller.java b/core/trino-main/src/test/java/io/trino/memory/TestTotalReservationLowMemoryKiller.java index eb2895341c4d..5f7f27a3ec56 100644 --- a/core/trino-main/src/test/java/io/trino/memory/TestTotalReservationLowMemoryKiller.java +++ b/core/trino-main/src/test/java/io/trino/memory/TestTotalReservationLowMemoryKiller.java @@ -30,25 +30,25 @@ public class TestTotalReservationLowMemoryKiller private final LowMemoryKiller lowMemoryKiller = new TotalReservationLowMemoryKiller(); @Test - public void testGeneralPoolHasNoReservation() + public void testMemoryPoolHasNoReservation() { - int generalPool = 12; + int memoryPool = 12; Map> queries = ImmutableMap.>builder() .put("q_1", ImmutableMap.of("n1", 0L, "n2", 0L, "n3", 0L, "n4", 0L, "n5", 0L)) .buildOrThrow(); assertEquals( lowMemoryKiller.chooseQueryToKill( toQueryMemoryInfoList(queries), - toNodeMemoryInfoList(generalPool, queries)), + toNodeMemoryInfoList(memoryPool, queries)), Optional.empty()); } @Test public void testSkewedQuery() { - int generalPool = 12; + int memoryPool = 12; // q2 is the query with the most total memory reservation, but not the query with the max memory reservation. - // This also tests the corner case where a node doesn't have a general pool. + // This also tests the corner case where a node has an empty memory pool Map> queries = ImmutableMap.>builder() .put("q_1", ImmutableMap.of("n1", 0L, "n2", 8L, "n3", 0L, "n4", 0L, "n5", 0L)) .put("q_2", ImmutableMap.of("n1", 3L, "n2", 5L, "n3", 2L, "n4", 4L, "n5", 0L)) @@ -57,7 +57,7 @@ public void testSkewedQuery() assertEquals( lowMemoryKiller.chooseQueryToKill( toQueryMemoryInfoList(queries), - toNodeMemoryInfoList(generalPool, queries)), + toNodeMemoryInfoList(memoryPool, queries)), Optional.of(new QueryId("q_2"))); } } diff --git a/core/trino-main/src/test/java/io/trino/memory/TestTotalReservationOnBlockedNodesLowMemoryKiller.java b/core/trino-main/src/test/java/io/trino/memory/TestTotalReservationOnBlockedNodesLowMemoryKiller.java index 15b917d477a0..dfe825ea357f 100644 --- a/core/trino-main/src/test/java/io/trino/memory/TestTotalReservationOnBlockedNodesLowMemoryKiller.java +++ b/core/trino-main/src/test/java/io/trino/memory/TestTotalReservationOnBlockedNodesLowMemoryKiller.java @@ -30,23 +30,23 @@ public class TestTotalReservationOnBlockedNodesLowMemoryKiller private final LowMemoryKiller lowMemoryKiller = new TotalReservationOnBlockedNodesLowMemoryKiller(); @Test - public void testGeneralPoolHasNoReservation() + public void testMemoryPoolHasNoReservation() { - int generalPool = 12; + int memoryPool = 12; Map> queries = ImmutableMap.>builder() .put("q_1", ImmutableMap.of("n1", 0L, "n2", 0L, "n3", 0L, "n4", 0L, "n5", 0L)) .buildOrThrow(); assertEquals( lowMemoryKiller.chooseQueryToKill( toQueryMemoryInfoList(queries), - toNodeMemoryInfoList(generalPool, queries)), + toNodeMemoryInfoList(memoryPool, queries)), Optional.empty()); } @Test - public void testGeneralPoolNotBlocked() + public void testMemoryPoolNotBlocked() { - int generalPool = 12; + int memoryPool = 12; Map> queries = ImmutableMap.>builder() .put("q_1", ImmutableMap.of("n1", 0L, "n2", 6L, "n3", 0L, "n4", 0L, "n5", 0L)) .put("q_2", ImmutableMap.of("n1", 3L, "n2", 5L, "n3", 2L, "n4", 4L, "n5", 0L)) @@ -54,16 +54,16 @@ public void testGeneralPoolNotBlocked() assertEquals( lowMemoryKiller.chooseQueryToKill( toQueryMemoryInfoList(queries), - toNodeMemoryInfoList(generalPool, queries)), + toNodeMemoryInfoList(memoryPool, queries)), Optional.empty()); } @Test public void testSkewedQuery() { - int generalPool = 12; + int memoryPool = 12; // q1 is neither the query with the most total memory reservation, nor the query with the max memory reservation. - // This also tests the corner case where a node doesn't have a general pool. + // This also tests the corner case where a node has an empty memory pool Map> queries = ImmutableMap.>builder() .put("q_1", ImmutableMap.of("n1", 0L, "n2", 8L, "n3", 0L, "n4", 0L, "n5", 0L)) .put("q_2", ImmutableMap.of("n1", 3L, "n2", 5L, "n3", 2L, "n4", 4L, "n5", 0L)) @@ -72,7 +72,7 @@ public void testSkewedQuery() assertEquals( lowMemoryKiller.chooseQueryToKill( toQueryMemoryInfoList(queries), - toNodeMemoryInfoList(generalPool, queries)), + toNodeMemoryInfoList(memoryPool, queries)), Optional.of(new QueryId("q_1"))); } } diff --git a/core/trino-main/src/test/java/io/trino/operator/GroupByHashYieldAssertion.java b/core/trino-main/src/test/java/io/trino/operator/GroupByHashYieldAssertion.java index 2ef903cd19e4..3165b6647886 100644 --- a/core/trino-main/src/test/java/io/trino/operator/GroupByHashYieldAssertion.java +++ b/core/trino-main/src/test/java/io/trino/operator/GroupByHashYieldAssertion.java @@ -21,7 +21,6 @@ import io.trino.memory.QueryContext; import io.trino.spi.Page; import io.trino.spi.QueryId; -import io.trino.spi.memory.MemoryPoolId; import io.trino.spi.type.Type; import io.trino.spiller.SpillSpaceTracker; @@ -79,7 +78,7 @@ public static GroupByHashYieldResult finishOperatorWithYieldingGroupByHash(List< // mock an adjustable memory pool QueryId queryId = new QueryId("test_query"); - MemoryPool memoryPool = new MemoryPool(new MemoryPoolId("test"), DataSize.of(1, GIGABYTE)); + MemoryPool memoryPool = new MemoryPool(DataSize.of(1, GIGABYTE)); QueryContext queryContext = new QueryContext( queryId, DataSize.of(512, MEGABYTE), diff --git a/core/trino-main/src/test/java/io/trino/server/TestBasicQueryInfo.java b/core/trino-main/src/test/java/io/trino/server/TestBasicQueryInfo.java index 1ba32d7fc31b..72eee365a042 100644 --- a/core/trino-main/src/test/java/io/trino/server/TestBasicQueryInfo.java +++ b/core/trino-main/src/test/java/io/trino/server/TestBasicQueryInfo.java @@ -24,7 +24,6 @@ import io.trino.spi.QueryId; import io.trino.spi.StandardErrorCode; import io.trino.spi.eventlistener.StageGcStatistics; -import io.trino.spi.memory.MemoryPoolId; import io.trino.spi.resourcegroups.QueryType; import org.joda.time.DateTime; import org.testng.annotations.Test; @@ -50,7 +49,6 @@ public void testConstructor() new QueryId("0"), TEST_SESSION.toSessionRepresentation(), RUNNING, - new MemoryPoolId("reserved"), false, URI.create("1"), ImmutableList.of("2", "3"), @@ -140,7 +138,6 @@ public void testConstructor() assertEquals(basicInfo.getQueryId().getId(), "0"); assertEquals(basicInfo.getState(), RUNNING); - assertEquals(basicInfo.getMemoryPool().getId(), "reserved"); assertEquals(basicInfo.isScheduled(), false); assertEquals(basicInfo.getQuery(), "SELECT 4"); assertEquals(basicInfo.getQueryType().get(), QueryType.SELECT); diff --git a/core/trino-main/src/test/java/io/trino/server/TestQueryStateInfo.java b/core/trino-main/src/test/java/io/trino/server/TestQueryStateInfo.java index 1f1986bf3875..9d83b5791875 100644 --- a/core/trino-main/src/test/java/io/trino/server/TestQueryStateInfo.java +++ b/core/trino-main/src/test/java/io/trino/server/TestQueryStateInfo.java @@ -23,7 +23,6 @@ import io.trino.execution.QueryStats; import io.trino.execution.resourcegroups.InternalResourceGroup; import io.trino.spi.QueryId; -import io.trino.spi.memory.MemoryPoolId; import io.trino.spi.resourcegroups.QueryType; import org.joda.time.DateTime; import org.testng.annotations.Test; @@ -101,7 +100,6 @@ private QueryInfo createQueryInfo(String queryId, QueryState state, String query new QueryId(queryId), TEST_SESSION.toSessionRepresentation(), state, - new MemoryPoolId("reserved"), true, URI.create("1"), ImmutableList.of("2", "3"), diff --git a/core/trino-spi/src/main/java/io/trino/spi/connector/ConnectorPageSink.java b/core/trino-spi/src/main/java/io/trino/spi/connector/ConnectorPageSink.java index 82cadab320aa..b7fc9e2897ad 100644 --- a/core/trino-spi/src/main/java/io/trino/spi/connector/ConnectorPageSink.java +++ b/core/trino-spi/src/main/java/io/trino/spi/connector/ConnectorPageSink.java @@ -33,7 +33,7 @@ default long getCompletedBytes() } /** - * Get the total memory that needs to be reserved in the general memory pool. + * Get the total memory that needs to be reserved in the memory pool. * This memory should include any buffers, etc. that are used for reading data. * * @return the memory used so far in table read diff --git a/core/trino-spi/src/main/java/io/trino/spi/connector/ConnectorPageSource.java b/core/trino-spi/src/main/java/io/trino/spi/connector/ConnectorPageSource.java index b316151d7a60..9fd9f898e3c5 100644 --- a/core/trino-spi/src/main/java/io/trino/spi/connector/ConnectorPageSource.java +++ b/core/trino-spi/src/main/java/io/trino/spi/connector/ConnectorPageSource.java @@ -59,7 +59,7 @@ default OptionalLong getCompletedPositions() Page getNextPage(); /** - * Get the total memory that needs to be reserved in the general memory pool. + * Get the total memory that needs to be reserved in the memory pool. * This memory should include any buffers, etc. that are used for reading data. * * @return the memory used so far in table read diff --git a/core/trino-spi/src/main/java/io/trino/spi/exchange/ExchangeSink.java b/core/trino-spi/src/main/java/io/trino/spi/exchange/ExchangeSink.java index c3835573abdb..3ba58b66d4db 100644 --- a/core/trino-spi/src/main/java/io/trino/spi/exchange/ExchangeSink.java +++ b/core/trino-spi/src/main/java/io/trino/spi/exchange/ExchangeSink.java @@ -42,7 +42,7 @@ public interface ExchangeSink void add(int partitionId, Slice data); /** - * Get the total memory that needs to be reserved in the general memory pool. + * Get the total memory that needs to be reserved in the memory pool. * This memory should include any buffers, etc. that are used for writing data */ long getMemoryUsage(); diff --git a/core/trino-spi/src/main/java/io/trino/spi/exchange/ExchangeSource.java b/core/trino-spi/src/main/java/io/trino/spi/exchange/ExchangeSource.java index c349d8787d2a..21f1aa52f3d7 100644 --- a/core/trino-spi/src/main/java/io/trino/spi/exchange/ExchangeSource.java +++ b/core/trino-spi/src/main/java/io/trino/spi/exchange/ExchangeSource.java @@ -51,7 +51,7 @@ public interface ExchangeSource Slice read(); /** - * Get the total memory that needs to be reserved in the general memory pool. + * Get the total memory that needs to be reserved in the memory pool. * This memory should include any buffers, etc. that are used for reading data */ long getMemoryUsage(); diff --git a/core/trino-spi/src/main/java/io/trino/spi/memory/ClusterMemoryPoolManager.java b/core/trino-spi/src/main/java/io/trino/spi/memory/ClusterMemoryPoolManager.java index e3e1db38357a..d4cd2a4dce1c 100644 --- a/core/trino-spi/src/main/java/io/trino/spi/memory/ClusterMemoryPoolManager.java +++ b/core/trino-spi/src/main/java/io/trino/spi/memory/ClusterMemoryPoolManager.java @@ -17,5 +17,5 @@ public interface ClusterMemoryPoolManager { - void addChangeListener(MemoryPoolId poolId, Consumer listener); + void addChangeListener(Consumer listener); } diff --git a/core/trino-spi/src/main/java/io/trino/spi/memory/MemoryPoolId.java b/core/trino-spi/src/main/java/io/trino/spi/memory/MemoryPoolId.java deleted file mode 100644 index 5bfaf9fda9d1..000000000000 --- a/core/trino-spi/src/main/java/io/trino/spi/memory/MemoryPoolId.java +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package io.trino.spi.memory; - -import com.fasterxml.jackson.annotation.JsonCreator; -import com.fasterxml.jackson.annotation.JsonValue; - -import java.util.Objects; - -import static java.util.Objects.requireNonNull; - -public final class MemoryPoolId -{ - private final String id; - - @JsonCreator - public MemoryPoolId(String id) - { - requireNonNull(id, "id is null"); - if (id.isEmpty()) { - throw new IllegalArgumentException("id is empty"); - } - this.id = id; - } - - @JsonValue - public String getId() - { - return id; - } - - @Override - public boolean equals(Object o) - { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - MemoryPoolId that = (MemoryPoolId) o; - return Objects.equals(id, that.id); - } - - @Override - public int hashCode() - { - return Objects.hash(id); - } - - @Override - public String toString() - { - // Return id here, because Jackson uses toString() when MemoryPoolId is the key of a Map - return id; - } -} diff --git a/plugin/trino-resource-group-managers/src/main/java/io/trino/plugin/resourcegroups/AbstractResourceConfigurationManager.java b/plugin/trino-resource-group-managers/src/main/java/io/trino/plugin/resourcegroups/AbstractResourceConfigurationManager.java index 06992df58979..867c3f3727bf 100644 --- a/plugin/trino-resource-group-managers/src/main/java/io/trino/plugin/resourcegroups/AbstractResourceConfigurationManager.java +++ b/plugin/trino-resource-group-managers/src/main/java/io/trino/plugin/resourcegroups/AbstractResourceConfigurationManager.java @@ -18,7 +18,6 @@ import io.airlift.units.Duration; import io.trino.spi.TrinoException; import io.trino.spi.memory.ClusterMemoryPoolManager; -import io.trino.spi.memory.MemoryPoolId; import io.trino.spi.resourcegroups.QueryType; import io.trino.spi.resourcegroups.ResourceGroup; import io.trino.spi.resourcegroups.ResourceGroupConfigurationManager; @@ -46,10 +45,10 @@ public abstract class AbstractResourceConfigurationManager implements ResourceGroupConfigurationManager { - @GuardedBy("generalPoolMemoryFraction") - private final Map generalPoolMemoryFraction = new HashMap<>(); - @GuardedBy("generalPoolMemoryFraction") - private long generalPoolBytes; + @GuardedBy("memoryPoolFraction") + private final Map memoryPoolFraction = new HashMap<>(); + @GuardedBy("memoryPoolFraction") + private long memoryPoolBytes; protected abstract Optional getCpuQuotaPeriod(); @@ -137,15 +136,15 @@ private void validateQueryType(String queryType) protected AbstractResourceConfigurationManager(ClusterMemoryPoolManager memoryPoolManager) { - memoryPoolManager.addChangeListener(new MemoryPoolId("general"), poolInfo -> { + memoryPoolManager.addChangeListener(poolInfo -> { Map memoryLimits = new HashMap<>(); - synchronized (generalPoolMemoryFraction) { - for (Map.Entry entry : generalPoolMemoryFraction.entrySet()) { + synchronized (memoryPoolFraction) { + for (Map.Entry entry : memoryPoolFraction.entrySet()) { long bytes = Math.round(poolInfo.getMaxBytes() * entry.getValue()); - // setSoftMemoryLimit() acquires a lock on the root group of its tree, which could cause a deadlock if done while holding the "generalPoolMemoryFraction" lock + // setSoftMemoryLimit() acquires a lock on the root group of its tree, which could cause a deadlock if done while holding the "memoryPoolFraction" lock memoryLimits.put(entry.getKey(), DataSize.ofBytes(bytes)); } - generalPoolBytes = poolInfo.getMaxBytes(); + memoryPoolBytes = poolInfo.getMaxBytes(); } memoryLimits.forEach((group, limit) -> group.setSoftMemoryLimitBytes(limit.toBytes())); @@ -198,10 +197,10 @@ protected void configureGroup(ResourceGroup group, ResourceGroupSpec match) group.setSoftMemoryLimitBytes(match.getSoftMemoryLimit().get().toBytes()); } else { - synchronized (generalPoolMemoryFraction) { + synchronized (memoryPoolFraction) { double fraction = match.getSoftMemoryLimitFraction().get(); - generalPoolMemoryFraction.put(group, fraction); - group.setSoftMemoryLimitBytes((long) (generalPoolBytes * fraction)); + memoryPoolFraction.put(group, fraction); + group.setSoftMemoryLimitBytes((long) (memoryPoolBytes * fraction)); } } group.setMaxQueuedQueries(match.getMaxQueued()); diff --git a/plugin/trino-resource-group-managers/src/test/java/io/trino/plugin/resourcegroups/TestFileResourceGroupConfigurationManager.java b/plugin/trino-resource-group-managers/src/test/java/io/trino/plugin/resourcegroups/TestFileResourceGroupConfigurationManager.java index edeee58f3e23..0a85ffdcffd5 100644 --- a/plugin/trino-resource-group-managers/src/test/java/io/trino/plugin/resourcegroups/TestFileResourceGroupConfigurationManager.java +++ b/plugin/trino-resource-group-managers/src/test/java/io/trino/plugin/resourcegroups/TestFileResourceGroupConfigurationManager.java @@ -31,7 +31,6 @@ import static com.google.common.io.Resources.getResource; import static io.airlift.units.DataSize.Unit.MEGABYTE; -import static io.trino.memory.LocalMemoryManager.GENERAL_POOL; import static io.trino.plugin.resourcegroups.TestingResourceGroups.groupIdTemplate; import static io.trino.plugin.resourcegroups.TestingResourceGroups.managerSpec; import static io.trino.plugin.resourcegroups.TestingResourceGroups.resourceGroupSpec; @@ -86,7 +85,7 @@ public void testMatchByUserGroups() ImmutableList.of(selectorSpec(groupIdTemplate("group")) .userGroups("first matching", "second matching"))); - FileResourceGroupConfigurationManager groupManager = new FileResourceGroupConfigurationManager((poolId, listener) -> {}, managerSpec); + FileResourceGroupConfigurationManager groupManager = new FileResourceGroupConfigurationManager(listener -> {}, managerSpec); assertThat(groupManager.match(userGroupsSelectionCriteria("not matching"))).isEmpty(); assertThat(groupManager.match(userGroupsSelectionCriteria("first matching"))) @@ -102,7 +101,7 @@ public void testMatchByUsers() ImmutableList.of(selectorSpec(groupIdTemplate("group")) .users("First matching user", "Second matching user"))); - FileResourceGroupConfigurationManager groupManager = new FileResourceGroupConfigurationManager((poolId, listener) -> {}, managerSpec); + FileResourceGroupConfigurationManager groupManager = new FileResourceGroupConfigurationManager(listener -> {}, managerSpec); assertThat(groupManager.match(userSelectionCriteria("Not matching user"))).isEmpty(); assertThat(groupManager.match(userSelectionCriteria("First matching user"))) @@ -119,7 +118,7 @@ public void testMatchByUsersAndGroups() .userGroups("Matching group") .users("Matching user"))); - FileResourceGroupConfigurationManager groupManager = new FileResourceGroupConfigurationManager((poolId, listener) -> {}, managerSpec); + FileResourceGroupConfigurationManager groupManager = new FileResourceGroupConfigurationManager(listener -> {}, managerSpec); assertThat(groupManager.match(userAndUserGroupsSelectionCriteria("Matching user", "Not matching group"))).isEmpty(); assertThat(groupManager.match(userAndUserGroupsSelectionCriteria("Not matching user", "Matching group"))).isEmpty(); @@ -189,13 +188,9 @@ public void testExtractVariableConfiguration() @Test public void testDocsExample() { - long generalPoolSize = 31415926535900L; // arbitrary uneven value for testing + long memoryPoolSize = 31415926535900L; // arbitrary uneven value for testing FileResourceGroupConfigurationManager manager = new FileResourceGroupConfigurationManager( - (poolId, listener) -> { - if (poolId.equals(GENERAL_POOL)) { - listener.accept(new MemoryPoolInfo(generalPoolSize, 0, 0, ImmutableMap.of(), ImmutableMap.of(), ImmutableMap.of())); - } - }, + (listener) -> listener.accept(new MemoryPoolInfo(memoryPoolSize, 0, 0, ImmutableMap.of(), ImmutableMap.of(), ImmutableMap.of())), new FileResourceGroupConfig() // TODO: figure out a better way to validate documentation .setConfigFile("../../docs/src/main/sphinx/admin/resource-groups-example.json")); @@ -213,7 +208,7 @@ public void testDocsExample() manager.configure(resourceGroup, selectionContext); assertEquals(resourceGroup.getHardConcurrencyLimit(), 3); assertEquals(resourceGroup.getMaxQueuedQueries(), 10); - assertEquals(resourceGroup.getSoftMemoryLimitBytes(), generalPoolSize / 10); + assertEquals(resourceGroup.getSoftMemoryLimitBytes(), memoryPoolSize / 10); } @Test @@ -249,7 +244,7 @@ private static FileResourceGroupConfigurationManager parse(String fileName) { FileResourceGroupConfig config = new FileResourceGroupConfig(); config.setConfigFile(getResource(fileName).getPath()); - return new FileResourceGroupConfigurationManager((poolId, listener) -> {}, config); + return new FileResourceGroupConfigurationManager(listener -> {}, config); } private static ManagerSpec parseManagerSpec(String fileName) diff --git a/plugin/trino-resource-group-managers/src/test/java/io/trino/plugin/resourcegroups/db/TestDbResourceGroupConfigurationManager.java b/plugin/trino-resource-group-managers/src/test/java/io/trino/plugin/resourcegroups/db/TestDbResourceGroupConfigurationManager.java index b86fe4ff3f4b..3c24a7fd123e 100644 --- a/plugin/trino-resource-group-managers/src/test/java/io/trino/plugin/resourcegroups/db/TestDbResourceGroupConfigurationManager.java +++ b/plugin/trino-resource-group-managers/src/test/java/io/trino/plugin/resourcegroups/db/TestDbResourceGroupConfigurationManager.java @@ -79,7 +79,7 @@ public void testEnvironments() dao.insertSelector(2, 2, ".*dev_user.*", null, null, null, null, null); // check the prod configuration - DbResourceGroupConfigurationManager manager = new DbResourceGroupConfigurationManager((poolId, listener) -> {}, new DbResourceGroupConfig(), daoProvider.get(), prodEnvironment); + DbResourceGroupConfigurationManager manager = new DbResourceGroupConfigurationManager(listener -> {}, new DbResourceGroupConfig(), daoProvider.get(), prodEnvironment); List groups = manager.getRootGroups(); assertEquals(groups.size(), 1); InternalResourceGroup prodGlobal = new InternalResourceGroup("prod_global", (group, export) -> {}, directExecutor()); @@ -91,7 +91,7 @@ public void testEnvironments() assertEquals(prodResourceGroupId.toString(), "prod_global"); // check the dev configuration - manager = new DbResourceGroupConfigurationManager((poolId, listener) -> {}, new DbResourceGroupConfig(), daoProvider.get(), devEnvironment); + manager = new DbResourceGroupConfigurationManager(listener -> {}, new DbResourceGroupConfig(), daoProvider.get(), devEnvironment); assertEquals(groups.size(), 1); InternalResourceGroup devGlobal = new InternalResourceGroup("dev_global", (group, export) -> {}, directExecutor()); manager.configure(devGlobal, new SelectionContext<>(prodGlobal.getId(), new ResourceGroupIdTemplate("dev_global"))); @@ -114,7 +114,7 @@ public void testConfiguration() dao.insertResourceGroup(1, "global", "1MB", 1000, 100, 100, "weighted", null, true, "1h", "1d", null, ENVIRONMENT); dao.insertResourceGroup(2, "sub", "2MB", 4, 3, 3, null, 5, null, null, null, 1L, ENVIRONMENT); dao.insertSelector(2, 1, null, null, null, null, null, null); - DbResourceGroupConfigurationManager manager = new DbResourceGroupConfigurationManager((poolId, listener) -> {}, new DbResourceGroupConfig(), daoProvider.get(), ENVIRONMENT); + DbResourceGroupConfigurationManager manager = new DbResourceGroupConfigurationManager(listener -> {}, new DbResourceGroupConfig(), daoProvider.get(), ENVIRONMENT); AtomicBoolean exported = new AtomicBoolean(); InternalResourceGroup global = new InternalResourceGroup("global", (group, export) -> exported.set(export), directExecutor()); manager.configure(global, new SelectionContext<>(global.getId(), new ResourceGroupIdTemplate("global"))); @@ -172,7 +172,7 @@ public void testMissing() dao.insertResourceGroup(2, "sub", "2MB", 4, 3, 3, null, 5, null, null, null, 1L, ENVIRONMENT); dao.insertResourceGroupsGlobalProperties("cpu_quota_period", "1h"); dao.insertSelector(2, 1, null, null, null, null, null, null); - DbResourceGroupConfigurationManager manager = new DbResourceGroupConfigurationManager((poolId, listener) -> {}, new DbResourceGroupConfig(), daoProvider.get(), ENVIRONMENT); + DbResourceGroupConfigurationManager manager = new DbResourceGroupConfigurationManager(listener -> {}, new DbResourceGroupConfig(), daoProvider.get(), ENVIRONMENT); InternalResourceGroup missing = new InternalResourceGroup("missing", (group, export) -> {}, directExecutor()); assertThatThrownBy(() -> manager.configure(missing, new SelectionContext<>(missing.getId(), new ResourceGroupIdTemplate("missing")))) @@ -193,7 +193,7 @@ public void testReconfig() dao.insertResourceGroup(2, "sub", "2MB", 4, 3, 3, null, 5, null, null, null, 1L, ENVIRONMENT); dao.insertSelector(2, 1, null, null, null, null, null, null); dao.insertResourceGroupsGlobalProperties("cpu_quota_period", "1h"); - DbResourceGroupConfigurationManager manager = new DbResourceGroupConfigurationManager((poolId, listener) -> {}, new DbResourceGroupConfig(), daoProvider.get(), ENVIRONMENT); + DbResourceGroupConfigurationManager manager = new DbResourceGroupConfigurationManager(listener -> {}, new DbResourceGroupConfig(), daoProvider.get(), ENVIRONMENT); manager.start(); AtomicBoolean exported = new AtomicBoolean(); InternalResourceGroup global = new InternalResourceGroup("global", (group, export) -> exported.set(export), directExecutor()); @@ -233,13 +233,13 @@ public void testExactMatchSelector() dao.insertResourceGroupsGlobalProperties("cpu_quota_period", "1h"); DbResourceGroupConfig config = new DbResourceGroupConfig(); config.setExactMatchSelectorEnabled(true); - DbResourceGroupConfigurationManager manager = new DbResourceGroupConfigurationManager((poolId, listener) -> {}, config, daoProvider.get(), ENVIRONMENT); + DbResourceGroupConfigurationManager manager = new DbResourceGroupConfigurationManager(listener -> {}, config, daoProvider.get(), ENVIRONMENT); manager.load(); assertEquals(manager.getSelectors().size(), 2); assertTrue(manager.getSelectors().get(0) instanceof DbSourceExactMatchSelector); config.setExactMatchSelectorEnabled(false); - manager = new DbResourceGroupConfigurationManager((poolId, listener) -> {}, config, daoProvider.get(), ENVIRONMENT); + manager = new DbResourceGroupConfigurationManager(listener -> {}, config, daoProvider.get(), ENVIRONMENT); manager.load(); assertEquals(manager.getSelectors().size(), 1); assertFalse(manager.getSelectors().get(0) instanceof DbSourceExactMatchSelector); @@ -272,7 +272,7 @@ public void testSelectorPriority() expectedUsers.add(user); } - DbResourceGroupConfigurationManager manager = new DbResourceGroupConfigurationManager((poolId, listener) -> {}, new DbResourceGroupConfig(), daoProvider.get(), ENVIRONMENT); + DbResourceGroupConfigurationManager manager = new DbResourceGroupConfigurationManager(listener -> {}, new DbResourceGroupConfig(), daoProvider.get(), ENVIRONMENT); manager.load(); List selectors = manager.getSelectors(); @@ -299,7 +299,7 @@ public void testInvalidConfiguration() dao.insertResourceGroup(1, "global", "100%", 100, 100, 100, null, null, null, null, null, null, ENVIRONMENT); DbResourceGroupConfigurationManager manager = new DbResourceGroupConfigurationManager( - (poolId, listener) -> {}, + listener -> {}, new DbResourceGroupConfig().setMaxRefreshInterval(new io.airlift.units.Duration(1, MILLISECONDS)), daoProvider.get(), ENVIRONMENT); @@ -319,7 +319,7 @@ public void testRefreshInterval() dao.insertResourceGroup(1, "global", "100%", 100, 100, 100, null, null, null, null, null, null, ENVIRONMENT); DbResourceGroupConfigurationManager manager = new DbResourceGroupConfigurationManager( - (poolId, listener) -> {}, + listener -> {}, new DbResourceGroupConfig().setMaxRefreshInterval(new io.airlift.units.Duration(1, MILLISECONDS)), daoProvider.get(), ENVIRONMENT); @@ -348,7 +348,7 @@ public void testMatchByUserGroups() dao.insertSelector(1, 1, null, "first matching|second matching", null, null, null, null); DbResourceGroupConfigurationManager manager = new DbResourceGroupConfigurationManager( - (poolId, listener) -> {}, + listener -> {}, new DbResourceGroupConfig().setMaxRefreshInterval(new io.airlift.units.Duration(1, MILLISECONDS)), daoProvider.get(), ENVIRONMENT); @@ -371,7 +371,7 @@ public void testMatchByUsersAndGroups() dao.insertSelector(1, 1, "Matching user", "Matching group", null, null, null, null); DbResourceGroupConfigurationManager manager = new DbResourceGroupConfigurationManager( - (poolId, listener) -> {}, + listener -> {}, new DbResourceGroupConfig().setMaxRefreshInterval(new io.airlift.units.Duration(1, MILLISECONDS)), daoProvider.get(), ENVIRONMENT); diff --git a/testing/trino-benchmark/src/main/java/io/trino/benchmark/AbstractOperatorBenchmark.java b/testing/trino-benchmark/src/main/java/io/trino/benchmark/AbstractOperatorBenchmark.java index 3cc81eb85a08..9b20bfa9ba5a 100644 --- a/testing/trino-benchmark/src/main/java/io/trino/benchmark/AbstractOperatorBenchmark.java +++ b/testing/trino-benchmark/src/main/java/io/trino/benchmark/AbstractOperatorBenchmark.java @@ -49,7 +49,6 @@ import io.trino.spi.connector.ColumnHandle; import io.trino.spi.connector.ConnectorPageSource; import io.trino.spi.connector.DynamicFilter; -import io.trino.spi.memory.MemoryPoolId; import io.trino.spi.type.Type; import io.trino.spiller.SpillSpaceTracker; import io.trino.split.SplitSource; @@ -295,7 +294,7 @@ protected Map runOnce() .setSystemProperty("optimizer.optimize-hash-generation", "true") .setTransactionId(this.session.getRequiredTransactionId()) .build(); - MemoryPool memoryPool = new MemoryPool(new MemoryPoolId("test"), DataSize.of(1, GIGABYTE)); + MemoryPool memoryPool = new MemoryPool(DataSize.of(1, GIGABYTE)); SpillSpaceTracker spillSpaceTracker = new SpillSpaceTracker(DataSize.of(1, GIGABYTE)); TaskContext taskContext = new QueryContext( diff --git a/testing/trino-benchmark/src/test/java/io/trino/benchmark/MemoryLocalQueryRunner.java b/testing/trino-benchmark/src/test/java/io/trino/benchmark/MemoryLocalQueryRunner.java index ccba74ab1b99..fe8d5607e6f5 100644 --- a/testing/trino-benchmark/src/test/java/io/trino/benchmark/MemoryLocalQueryRunner.java +++ b/testing/trino-benchmark/src/test/java/io/trino/benchmark/MemoryLocalQueryRunner.java @@ -32,7 +32,6 @@ import io.trino.plugin.tpch.TpchConnectorFactory; import io.trino.spi.Page; import io.trino.spi.QueryId; -import io.trino.spi.memory.MemoryPoolId; import io.trino.spiller.SpillSpaceTracker; import io.trino.testing.LocalQueryRunner; import io.trino.testing.PageConsumerOperator; @@ -68,7 +67,7 @@ public MemoryLocalQueryRunner(Map properties) public List execute(@Language("SQL") String query) { - MemoryPool memoryPool = new MemoryPool(new MemoryPoolId("test"), DataSize.of(2, GIGABYTE)); + MemoryPool memoryPool = new MemoryPool(DataSize.of(2, GIGABYTE)); SpillSpaceTracker spillSpaceTracker = new SpillSpaceTracker(DataSize.of(1, GIGABYTE)); QueryContext queryContext = new QueryContext( new QueryId("test"), diff --git a/testing/trino-tests/src/test/java/io/trino/memory/TestClusterMemoryLeakDetector.java b/testing/trino-tests/src/test/java/io/trino/memory/TestClusterMemoryLeakDetector.java index b294ff948647..4602b89cdae7 100644 --- a/testing/trino-tests/src/test/java/io/trino/memory/TestClusterMemoryLeakDetector.java +++ b/testing/trino-tests/src/test/java/io/trino/memory/TestClusterMemoryLeakDetector.java @@ -33,7 +33,6 @@ import static io.trino.SessionTestUtils.TEST_SESSION; import static io.trino.execution.QueryState.FINISHED; import static io.trino.execution.QueryState.RUNNING; -import static io.trino.memory.LocalMemoryManager.GENERAL_POOL; import static io.trino.operator.BlockedReason.WAITING_FOR_MEMORY; import static java.util.concurrent.TimeUnit.MINUTES; import static org.testng.Assert.assertEquals; @@ -73,7 +72,6 @@ private static BasicQueryInfo createQueryInfo(String queryId, QueryState state) TEST_SESSION.toSessionRepresentation(), Optional.of(new ResourceGroupId("global")), state, - GENERAL_POOL, true, URI.create("1"), "", diff --git a/testing/trino-tests/src/test/java/io/trino/memory/TestMemoryManager.java b/testing/trino-tests/src/test/java/io/trino/memory/TestMemoryManager.java index 7b163c6e0838..5587df7de6b8 100644 --- a/testing/trino-tests/src/test/java/io/trino/memory/TestMemoryManager.java +++ b/testing/trino-tests/src/test/java/io/trino/memory/TestMemoryManager.java @@ -37,13 +37,11 @@ import static io.trino.SystemSessionProperties.RESOURCE_OVERCOMMIT; import static io.trino.execution.QueryState.FINISHED; -import static io.trino.memory.LocalMemoryManager.GENERAL_POOL; import static io.trino.operator.BlockedReason.WAITING_FOR_MEMORY; import static io.trino.spi.StandardErrorCode.CLUSTER_OUT_OF_MEMORY; import static io.trino.testing.TestingSession.testSessionBuilder; import static java.util.concurrent.Executors.newCachedThreadPool; import static java.util.concurrent.TimeUnit.MILLISECONDS; -import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertFalse; @@ -115,9 +113,8 @@ public void testOutOfMemoryKiller() // Reserve all the memory QueryId fakeQueryId = new QueryId("fake"); for (TestingTrinoServer server : queryRunner.getServers()) { - List memoryPools = server.getLocalMemoryManager().getPools(); - assertEquals(memoryPools.size(), 1, "Only general pool should exist"); - assertTrue(memoryPools.get(0).tryReserve(fakeQueryId, "test", memoryPools.get(0).getMaxBytes())); + MemoryPool memoryPool = server.getLocalMemoryManager().getMemoryPool(); + assertTrue(memoryPool.tryReserve(fakeQueryId, "test", memoryPool.getMaxBytes())); } List> queryFutures = new ArrayList<>(); @@ -129,11 +126,11 @@ public void testOutOfMemoryKiller() waitForQueryToBeKilled(queryRunner); for (TestingTrinoServer server : queryRunner.getServers()) { - MemoryPool general = server.getLocalMemoryManager().getGeneralPool(); - assertTrue(general.getReservedBytes() > 0); + MemoryPool pool = server.getLocalMemoryManager().getMemoryPool(); + assertTrue(pool.getReservedBytes() > 0); // Free up the entire pool - general.free(fakeQueryId, "test", general.getMaxBytes()); - assertTrue(general.getFreeBytes() > 0); + pool.free(fakeQueryId, "test", pool.getMaxBytes()); + assertTrue(pool.getFreeBytes() > 0); } for (Future query : queryFutures) { @@ -181,8 +178,8 @@ private void testNoLeak(@Language("SQL") String query) // Make sure we didn't leak any memory on the workers for (TestingTrinoServer worker : queryRunner.getServers()) { - MemoryPool general = worker.getLocalMemoryManager().getGeneralPool(); - assertEquals(general.getMaxBytes(), general.getFreeBytes()); + MemoryPool pool = worker.getLocalMemoryManager().getMemoryPool(); + assertEquals(pool.getMaxBytes(), pool.getFreeBytes()); } } } @@ -199,9 +196,8 @@ public void testClusterPools() // Reserve all the memory QueryId fakeQueryId = new QueryId("fake"); for (TestingTrinoServer server : queryRunner.getServers()) { - for (MemoryPool pool : server.getLocalMemoryManager().getPools()) { - assertTrue(pool.tryReserve(fakeQueryId, "test", pool.getMaxBytes())); - } + MemoryPool pool = server.getLocalMemoryManager().getMemoryPool(); + assertTrue(pool.tryReserve(fakeQueryId, "test", pool.getMaxBytes())); } List> queryFutures = new ArrayList<>(); @@ -211,11 +207,11 @@ public void testClusterPools() ClusterMemoryManager memoryManager = queryRunner.getCoordinator().getClusterMemoryManager(); - ClusterMemoryPool generalPool = memoryManager.getPools().get(GENERAL_POOL); - assertNotNull(generalPool); + ClusterMemoryPool clusterPool = memoryManager.getPool(); + assertNotNull(clusterPool); // Wait for the pools to become blocked - while (generalPool.getBlockedNodes() != 2) { + while (clusterPool.getBlockedNodes() != 2) { MILLISECONDS.sleep(10); } @@ -231,10 +227,6 @@ public void testClusterPools() assertFalse(info.getState().isDone()); } - // Check that queries are assigned to expected pools - assertThat(currentQueryInfos.get(0).getMemoryPool()).isIn(GENERAL_POOL); - assertThat(currentQueryInfos.get(1).getMemoryPool()).isIn(GENERAL_POOL); - while (!currentQueryInfos.stream().allMatch(TestMemoryManager::isBlockedWaitingForMemory)) { MILLISECONDS.sleep(10); currentQueryInfos = queryRunner.getCoordinator().getQueryManager().getQueries(); @@ -243,15 +235,15 @@ public void testClusterPools() } } - // Release the memory in the general pool + // Release the memory in the memory pool for (TestingTrinoServer server : queryRunner.getServers()) { - MemoryPool general = server.getLocalMemoryManager().getGeneralPool(); + MemoryPool pool = server.getLocalMemoryManager().getMemoryPool(); // Free up the entire pool - general.free(fakeQueryId, "test", general.getMaxBytes()); - assertTrue(general.getFreeBytes() > 0); + pool.free(fakeQueryId, "test", pool.getMaxBytes()); + assertTrue(pool.getFreeBytes() > 0); } - // Make sure both queries finish now that there's memory free in the general pool. + // Make sure both queries finish now that there's memory free in the memory pool. for (Future query : queryFutures) { query.get(); } @@ -262,8 +254,8 @@ public void testClusterPools() // Make sure we didn't leak any memory on the workers for (TestingTrinoServer worker : queryRunner.getServers()) { - MemoryPool general = worker.getLocalMemoryManager().getGeneralPool(); - assertEquals(general.getMaxBytes(), general.getFreeBytes()); + MemoryPool pool = worker.getLocalMemoryManager().getMemoryPool(); + assertEquals(pool.getMaxBytes(), pool.getFreeBytes()); } } }