diff --git a/api/src/main/java/org/eclipse/daanse/olap/api/CacheCommand.java b/api/src/main/java/org/eclipse/daanse/olap/api/CacheCommand.java index 37b1704..9f6fad1 100644 --- a/api/src/main/java/org/eclipse/daanse/olap/api/CacheCommand.java +++ b/api/src/main/java/org/eclipse/daanse/olap/api/CacheCommand.java @@ -13,9 +13,11 @@ */ package org.eclipse.daanse.olap.api; +import org.eclipse.daanse.olap.api.execution.ExecutionContext; + public interface CacheCommand extends Message { - - Locus getLocus(); - + + ExecutionContext getExecutionContext(); + T call() throws Exception; } diff --git a/api/src/main/java/org/eclipse/daanse/olap/api/ISegmentCacheIndex.java b/api/src/main/java/org/eclipse/daanse/olap/api/ISegmentCacheIndex.java index ce456d2..11b7e5d 100644 --- a/api/src/main/java/org/eclipse/daanse/olap/api/ISegmentCacheIndex.java +++ b/api/src/main/java/org/eclipse/daanse/olap/api/ISegmentCacheIndex.java @@ -13,6 +13,8 @@ */ package org.eclipse.daanse.olap.api; +import org.eclipse.daanse.olap.api.execution.Execution; + public interface ISegmentCacheIndex { void cancelExecutionSegments(Execution executionImpl); diff --git a/api/src/main/java/org/eclipse/daanse/olap/api/ISegmentCacheManager.java b/api/src/main/java/org/eclipse/daanse/olap/api/ISegmentCacheManager.java index e425051..12f946e 100644 --- a/api/src/main/java/org/eclipse/daanse/olap/api/ISegmentCacheManager.java +++ b/api/src/main/java/org/eclipse/daanse/olap/api/ISegmentCacheManager.java @@ -17,6 +17,7 @@ import java.io.PrintWriter; import org.eclipse.daanse.olap.api.CacheControl.CellRegion; +import org.eclipse.daanse.olap.api.execution.ExecutionContext; public interface ISegmentCacheManager { @@ -25,7 +26,7 @@ public interface ISegmentCacheManager { */ void shutdown(); - void printCacheState(CellRegion region, PrintWriter pw, Locus locus); + void printCacheState(CellRegion region, PrintWriter pw, ExecutionContext executionContext); T execute( CacheCommand command ); diff --git a/api/src/main/java/org/eclipse/daanse/olap/api/Locus.java b/api/src/main/java/org/eclipse/daanse/olap/api/Locus.java deleted file mode 100644 index 9136f6d..0000000 --- a/api/src/main/java/org/eclipse/daanse/olap/api/Locus.java +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright (c) 2024 Contributors to the Eclipse Foundation. - * - * This program and the accompanying materials are made - * available under the terms of the Eclipse Public License 2.0 - * which is available at https://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * SmartCity Jena, Stefan Bischof - initial - * - */ -package org.eclipse.daanse.olap.api; - - -//todo: https://docs.oracle.com/en/java/javase/21/docs/api/java.base/java/lang/ScopedValue.html -//TODO: https://openjdk.org/jeps/462 -public interface Locus { - - Execution getExecution(); - - Context getContext(); - -} diff --git a/api/src/main/java/org/eclipse/daanse/olap/api/ResultShepherd.java b/api/src/main/java/org/eclipse/daanse/olap/api/ResultShepherd.java index 86cc238..5908efa 100644 --- a/api/src/main/java/org/eclipse/daanse/olap/api/ResultShepherd.java +++ b/api/src/main/java/org/eclipse/daanse/olap/api/ResultShepherd.java @@ -15,6 +15,7 @@ import java.util.concurrent.Callable; +import org.eclipse.daanse.olap.api.execution.Execution; import org.eclipse.daanse.olap.api.result.Result; public interface ResultShepherd { diff --git a/api/src/main/java/org/eclipse/daanse/olap/api/Statement.java b/api/src/main/java/org/eclipse/daanse/olap/api/Statement.java index d2f3d3e..d818132 100644 --- a/api/src/main/java/org/eclipse/daanse/olap/api/Statement.java +++ b/api/src/main/java/org/eclipse/daanse/olap/api/Statement.java @@ -19,6 +19,7 @@ import org.eclipse.daanse.olap.api.connection.Connection; import org.eclipse.daanse.olap.api.element.Catalog; +import org.eclipse.daanse.olap.api.execution.Execution; import org.eclipse.daanse.olap.api.query.component.Query; import org.eclipse.daanse.olap.api.query.component.QueryComponent; import org.eclipse.daanse.olap.api.result.CellSet; diff --git a/api/src/main/java/org/eclipse/daanse/olap/api/connection/Connection.java b/api/src/main/java/org/eclipse/daanse/olap/api/connection/Connection.java index fa53302..8067e72 100644 --- a/api/src/main/java/org/eclipse/daanse/olap/api/connection/Connection.java +++ b/api/src/main/java/org/eclipse/daanse/olap/api/connection/Connection.java @@ -37,10 +37,10 @@ import org.eclipse.daanse.olap.api.CacheControl; import org.eclipse.daanse.olap.api.CatalogReader; import org.eclipse.daanse.olap.api.Context; -import org.eclipse.daanse.olap.api.Execution; import org.eclipse.daanse.olap.api.Statement; import org.eclipse.daanse.olap.api.access.Role; import org.eclipse.daanse.olap.api.element.Catalog; +import org.eclipse.daanse.olap.api.execution.Execution; import org.eclipse.daanse.olap.api.query.component.Expression; import org.eclipse.daanse.olap.api.query.component.Query; import org.eclipse.daanse.olap.api.query.component.QueryComponent; diff --git a/api/src/main/java/org/eclipse/daanse/olap/api/Execution.java b/api/src/main/java/org/eclipse/daanse/olap/api/execution/Execution.java similarity index 80% rename from api/src/main/java/org/eclipse/daanse/olap/api/Execution.java rename to api/src/main/java/org/eclipse/daanse/olap/api/execution/Execution.java index 0e2c8d2..75e7fee 100644 --- a/api/src/main/java/org/eclipse/daanse/olap/api/Execution.java +++ b/api/src/main/java/org/eclipse/daanse/olap/api/execution/Execution.java @@ -26,10 +26,13 @@ * SmartCity Jena - initial * Stefan Bischof (bipolis.org) - initial */ -package org.eclipse.daanse.olap.api; +package org.eclipse.daanse.olap.api.execution; import java.time.Duration; +import org.eclipse.daanse.olap.api.QueryTiming; +import org.eclipse.daanse.olap.api.Statement; + public interface Execution { void cancelSqlStatements(); @@ -56,8 +59,6 @@ public interface Execution { void setExpCacheCounts(int expResultCacheHitCount, int expResultCacheMissCount); - void registerStatement(Locus locus, java.sql.Statement stmt); - void end(); void start(); @@ -70,6 +71,15 @@ public interface Execution { int getExpCacheMissCount(); + /** + * Converts this Execution to an ExecutionContext for use with ScopedValue-based + * context propagation. This method provides a bridge between the legacy + * Execution interface and the new ExecutionContext approach. + * + * @return the ExecutionContext representation of this execution + */ + ExecutionContext asContext(); + /** * Enumeration of the states of an Execution instance. */ diff --git a/api/src/main/java/org/eclipse/daanse/olap/api/execution/ExecutionContext.java b/api/src/main/java/org/eclipse/daanse/olap/api/execution/ExecutionContext.java new file mode 100644 index 0000000..85b514f --- /dev/null +++ b/api/src/main/java/org/eclipse/daanse/olap/api/execution/ExecutionContext.java @@ -0,0 +1,368 @@ +/* + * Copyright (c) 2025 Contributors to the Eclipse Foundation. + * + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * SmartCity Jena - initial + * Stefan Bischof (bipolis.org) - initial + */ +package org.eclipse.daanse.olap.api.execution; + +import java.sql.Statement; +import java.time.Duration; +import java.time.Instant; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Objects; +import java.util.Optional; +import java.util.concurrent.atomic.AtomicLong; +import java.util.concurrent.atomic.AtomicReference; + +/** + * Execution context using JDK 25 ScopedValues for thread-safe, immutable + * context propagation. + * + *

+ * Replaces the ThreadLocal-based Locus/LocusImpl system with modern ScopedValue + * approach. This provides better performance, memory characteristics, and + * clearer lifecycle management compared to ThreadLocal. + *

+ * + *

+ * ExecutionContext tracks the state of a query execution including: + *

    + *
  • Unique execution ID
  • + *
  • Start time and timeout
  • + *
  • Execution state (RUNNING, CANCELED, TIMEOUT, ERROR, DONE)
  • + *
  • Parent execution for nested queries
  • + *
  • SQL statements registered for cancellation
  • + *
  • Metadata for tracing and monitoring
  • + *
+ * + *

+ * Usage example: + * + *

+ * // Create root context with metadata
+ * ExecutionMetadata rootMetadata = ExecutionMetadata.of("QueryExecution", "MDX Query", null, 0);
+ * ExecutionContext ctx = ExecutionContext.root(Duration.ofMinutes(5), rootMetadata);
+ *
+ * ExecutionContext.where(ctx, () -> {
+ *     // Your code here has access to ctx via ExecutionContext.current()
+ *     ExecutionContext current = ExecutionContext.current();
+ *     current.checkCancelOrTimeout();
+ *
+ *     // Create child context inheriting parent timeout
+ *     ExecutionMetadata childMetadata = ExecutionMetadata.of("Component", "message", null, 0);
+ *     ExecutionContext child1 = current.createChild(childMetadata, Optional.empty());
+ *
+ *     // Create child context with custom timeout (shorter than parent)
+ *     ExecutionMetadata fastMetadata = ExecutionMetadata.of("FastOp", "quick operation", null, 0);
+ *     ExecutionContext child2 = current.createChild(fastMetadata, Optional.of(Duration.ofSeconds(30)));
+ *
+ *     return performQuery();
+ * });
+ * 
+ * + * @see ScopedValue + */ +public final class ExecutionContext { + private static final ScopedValue CURRENT = ScopedValue.newInstance(); + private static final AtomicLong ID_GENERATOR = new AtomicLong(0); + + // Core state + private final long id; + private final Instant startTime; + private final Duration timeout; + private final AtomicReference state; + + // Hierarchy + private final ExecutionContext parent; + + // SQL Statements for cancellation + private final List sqlStatements; + + // Execution reference (for compatibility with legacy code during migration) + private Execution execution; + + // Metadata for tracing, monitoring, and debugging (OpenTelemetry support) + private final ExecutionMetadata metadata; + + /** + * Unified constructor for both root and child contexts. + * + * @param parent the parent context (null for root contexts) + * @param metadata the metadata (defaults to empty if null) + * @param timeout the timeout duration (inherits from parent if empty and parent exists) + */ + private ExecutionContext(ExecutionContext parent, ExecutionMetadata metadata, Optional timeout) { + this.id = ID_GENERATOR.incrementAndGet(); + this.parent = parent; + this.startTime = Instant.now(); + this.state = new AtomicReference<>(State.RUNNING); + this.sqlStatements = Collections.synchronizedList(new ArrayList<>()); + + // Timeout: explicit > parent > default + if (timeout.isPresent()) { + this.timeout = timeout.get(); + } else if (parent != null) { + this.timeout = parent.timeout; + } else { + this.timeout = Duration.ofMinutes(5); + } + + // Metadata: explicit > empty + this.metadata = metadata != null ? metadata : ExecutionMetadata.empty(); + } + + /** + * Creates a root execution context with the specified timeout and metadata. + * + * @param timeout the timeout duration + * @param metadata the metadata for the root context + * @return a new root ExecutionContext + */ + public static ExecutionContext root(Optional timeout, ExecutionMetadata metadata) { + return new ExecutionContext(null, Objects.requireNonNull(metadata, "metadata"), timeout); + } + + /** + * Returns the current execution context. + * + * @return the current ExecutionContext + * @throws NoExecutionContextException if no context is bound to the current scope + */ + public static ExecutionContext current() { + if (!CURRENT.isBound()) { + throw new NoExecutionContextException(); + } + return CURRENT.get(); + } + + /** + * Returns the current execution context, or null if not in execution scope. + * Use this method only when you explicitly need to handle the case where + * no context is available. + * + * @return the current ExecutionContext, or null if outside execution scope + */ + public static ExecutionContext currentOrNull() { + return CURRENT.isBound() ? CURRENT.get() : null; + } + + /** + * Returns true if an ExecutionContext is currently bound to this scope. + * + * @return true if a context is bound, false otherwise + */ + public static boolean isBound() { + return CURRENT.isBound(); + } + + /** + * Executes the given task within the scope of this execution context. The + * context will be available via {@link #current()} during task execution. + * + * @param ctx the execution context to bind + * @param task the task to execute + * @param the result type + * @param the exception type + * @return the result of the task + * @throws X if the task throws an exception + */ + public static R where(ExecutionContext ctx, CallableTask task) throws X { + return ScopedValue.where(CURRENT, ctx).call(() -> task.call()); + } + + /** + * Executes the given task within the scope of this execution context. The + * context will be available via {@link #current()} during task execution. + * + * @param ctx the execution context to bind + * @param task the task to execute + */ + public static void where(ExecutionContext ctx, Runnable task) { + ScopedValue.where(CURRENT, ctx).run(task); + } + + /** + * Functional interface for tasks that can throw checked exceptions. + * + * @param the result type + * @param the exception type + */ + @FunctionalInterface + public interface CallableTask { + /** + * Executes the task. + * + * @return the result + * @throws X if an error occurs + */ + R call() throws X; + } + + /** + * Checks if this execution has been canceled or timed out. Throws an exception + * if the execution has been canceled or exceeded its timeout. + * + * @throws QueryCanceledException if the execution was canceled + * @throws QueryTimeoutException if the execution has timed out + */ + public void checkCancelOrTimeout() { + State currentState = state.get(); + + if (currentState == State.CANCELED) { + throw new QueryCanceledException("Query canceled"); + } + + if (currentState == State.TIMEOUT) { + throw new QueryTimeoutException("Query timeout"); + } + + // Check timeout + if (Duration.between(startTime, Instant.now()).compareTo(timeout) > 0) { + if (state.compareAndSet(State.RUNNING, State.TIMEOUT)) { + cancel(); // Cancel all statements + } + throw new QueryTimeoutException("Query timeout"); + } + } + + /** + * Cancels this execution and all registered SQL statements. This method is + * idempotent - calling it multiple times has the same effect as calling it + * once. + */ + public void cancel() { + state.set(State.CANCELED); + + // Cancel all SQL statements + synchronized (sqlStatements) { + for (Statement stmt : sqlStatements) { + try { + stmt.cancel(); + } catch (Exception e) { + // Log but continue canceling others + // Intentionally swallow exception to ensure all statements are canceled + } + } + } + } + + /** + * Registers a SQL statement for automatic cancellation when this execution is + * canceled. + * + * @param stmt the SQL statement to register + * @throws NullPointerException if stmt is null + */ + public void registerStatement(Statement stmt) { + Objects.requireNonNull(stmt, "statement"); + sqlStatements.add(stmt); + } + + /** + * Returns the unique ID of this execution. + * + * @return the execution ID + */ + public long id() { + return id; + } + + /** + * Returns the start time of this execution. + * + * @return the start time + */ + public Instant startTime() { + return startTime; + } + + /** + * Returns the timeout duration for this execution. + * + * @return the timeout duration + */ + public Duration timeout() { + return timeout; + } + + /** + * Returns the current state of this execution. + * + * @return the current state + */ + public State state() { + return state.get(); + } + + /** + * Returns the parent execution context, or null if this is a top-level + * execution. + * + * @return the parent execution context, or null + */ + public ExecutionContext parent() { + return parent; + } + + /** + * Returns the Execution object associated with this context. This is provided + * for compatibility with legacy code during migration. If this context doesn't + * have an execution, walks up the parent chain. + * + * @return the Execution object, or null if not set in this context or any + * parent + */ + public Execution getExecution() { + if (execution != null) { + return execution; + } + // Walk up the parent chain to find an execution + if (parent != null) { + return parent.getExecution(); + } + return null; + } + + /** + * Sets the Execution object for this context. This is called by ExecutionImpl + * during initialization. + * + * @param execution the Execution object + */ + public void setExecution(Execution execution) { + this.execution = execution; + } + + /** + * Returns the metadata associated with this execution context. The metadata + * contains component name, message, purpose, and cell request count used for + * tracing, monitoring, and debugging (OpenTelemetry support). + * + * @return the ExecutionMetadata, never null + */ + public ExecutionMetadata metadata() { + return metadata; + } + + /** + * Creates a child execution context with new metadata and custom timeout. + * + * @param metadata the metadata for the child context + * @param timeout the timeout for the child context (empty to inherit from parent) + * @return a new child ExecutionContext with the specified metadata and timeout + */ + public ExecutionContext createChild(ExecutionMetadata metadata, Optional timeout) { + return new ExecutionContext(this, metadata, timeout); + } + +} diff --git a/api/src/main/java/org/eclipse/daanse/olap/api/execution/ExecutionMetadata.java b/api/src/main/java/org/eclipse/daanse/olap/api/execution/ExecutionMetadata.java new file mode 100644 index 0000000..687b412 --- /dev/null +++ b/api/src/main/java/org/eclipse/daanse/olap/api/execution/ExecutionMetadata.java @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2025 Contributors to the Eclipse Foundation. + * + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * SmartCity Jena - initial + * Stefan Bischof (bipolis.org) - initial + */ +package org.eclipse.daanse.olap.api.execution; + +import org.eclipse.daanse.olap.api.monitor.event.SqlStatementEvent; + +/** + * Metadata associated with an execution context for tracing, monitoring, and debugging. + * + *

This metadata is primarily used for: + *

    + *
  • OpenTelemetry tracing and spans
  • + *
  • Logging and debugging
  • + *
  • Performance monitoring
  • + *
  • Error reporting and diagnostics
  • + *
+ * + * @since 2.0 + */ +public interface ExecutionMetadata { + + /** + * Returns the component name that initiated this execution. + * Examples: "SqlStatisticsProvider.getTableCardinality", "RolapCell.getDrillThroughCount" + * + * @return the component name, or null if not set + */ + String component(); + + /** + * Returns a descriptive message about what this execution is doing. + * Examples: "Reading row count from table ...", "Error while counting drill-through" + * + * @return the message, or null if not set + */ + String message(); + + /** + * Returns the purpose of the SQL statement execution. + * Used to categorize SQL operations for monitoring. + * + * @return the purpose, or null if not set + */ + SqlStatementEvent.Purpose purpose(); + + /** + * Returns the number of cell requests associated with this execution. + * Returns 0 if not applicable. + * + * @return the cell request count + */ + int cellRequestCount(); + + /** + * Creates an empty metadata instance with no values set. + * + * @return an empty ExecutionMetadata + */ + static ExecutionMetadata empty() { + return new ExecutionMetadataRecord(null, null, null, 0); + } + + /** + * Creates a metadata instance with the given values. + * + * @param component the component name (may be null) + * @param message the descriptive message (may be null) + * @param purpose the SQL statement purpose (may be null) + * @param cellRequestCount the cell request count + * @return an ExecutionMetadata instance + */ + static ExecutionMetadata of(String component, String message, SqlStatementEvent.Purpose purpose, int cellRequestCount) { + return new ExecutionMetadataRecord(component, message, purpose, cellRequestCount); + } +} diff --git a/api/src/main/java/org/eclipse/daanse/olap/api/execution/ExecutionMetadataRecord.java b/api/src/main/java/org/eclipse/daanse/olap/api/execution/ExecutionMetadataRecord.java new file mode 100644 index 0000000..33dca9a --- /dev/null +++ b/api/src/main/java/org/eclipse/daanse/olap/api/execution/ExecutionMetadataRecord.java @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2025 Contributors to the Eclipse Foundation. + * + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * SmartCity Jena - initial + * Stefan Bischof (bipolis.org) - initial + */ +package org.eclipse.daanse.olap.api.execution; + +import org.eclipse.daanse.olap.api.monitor.event.SqlStatementEvent; + +/** + * Record implementation of ExecutionMetadata. + * + * @param component the component name (may be null) + * @param message the descriptive message (may be null) + * @param purpose the SQL statement purpose (may be null) + * @param cellRequestCount the cell request count + */ +record ExecutionMetadataRecord( + String component, + String message, + SqlStatementEvent.Purpose purpose, + int cellRequestCount +) implements ExecutionMetadata { +} diff --git a/api/src/main/java/org/eclipse/daanse/olap/api/execution/NoExecutionContextException.java b/api/src/main/java/org/eclipse/daanse/olap/api/execution/NoExecutionContextException.java new file mode 100644 index 0000000..cacb838 --- /dev/null +++ b/api/src/main/java/org/eclipse/daanse/olap/api/execution/NoExecutionContextException.java @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2025 Contributors to the Eclipse Foundation. + * + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * SmartCity Jena - initial + * Stefan Bischof (bipolis.org) - initial + */ +package org.eclipse.daanse.olap.api.execution; + +/** + * Exception thrown when code attempts to access the current ExecutionContext + * but none is bound to the current scope. + * + *

This typically happens when: + *

    + *
  • Code runs outside of an {@link ExecutionContext#where} block
  • + *
  • Background threads (timers, executors) try to access context
  • + *
  • Async operations lose the scoped context
  • + *
+ * + *

To fix this, ensure the code runs within an ExecutionContext scope: + *

+ * ExecutionContext.where(execution.asContext(), () -> {
+ *     // Your code here can safely call ExecutionContext.current()
+ * });
+ * 
+ * + * @see ExecutionContext#current() + * @see ExecutionContext#where(ExecutionContext, Runnable) + */ +public class NoExecutionContextException extends RuntimeException { + + private static final long serialVersionUID = 1L; + + /** + * Creates a new NoExecutionContextException with a default message. + */ + public NoExecutionContextException() { + super("No ExecutionContext is bound to the current scope. " + + "Ensure code runs within ExecutionContext.where() block."); + } + + /** + * Creates a new NoExecutionContextException with a custom message. + * + * @param message the detail message + */ + public NoExecutionContextException(String message) { + super(message); + } + + /** + * Creates a new NoExecutionContextException with a message and cause. + * + * @param message the detail message + * @param cause the cause + */ + public NoExecutionContextException(String message, Throwable cause) { + super(message, cause); + } +} diff --git a/api/src/main/java/org/eclipse/daanse/olap/api/execution/QueryCanceledException.java b/api/src/main/java/org/eclipse/daanse/olap/api/execution/QueryCanceledException.java new file mode 100644 index 0000000..d34fa38 --- /dev/null +++ b/api/src/main/java/org/eclipse/daanse/olap/api/execution/QueryCanceledException.java @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2025 Contributors to the Eclipse Foundation. + * + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * SmartCity Jena - initial + * Stefan Bischof (bipolis.org) - initial + */ +package org.eclipse.daanse.olap.api.execution; + +/** + * Exception thrown when a query execution has been canceled. + * + *

This exception is thrown by {@link ExecutionContext#checkCancelOrTimeout()} + * when the execution state is {@link State#CANCELED}.

+ * + * @see ExecutionContext#cancel() + * @see ExecutionContext#checkCancelOrTimeout() + */ +@SuppressWarnings("serial") +public class QueryCanceledException extends RuntimeException { + + /** + * Constructs a new query canceled exception with the specified detail message. + * + * @param message the detail message + */ + public QueryCanceledException(String message) { + super(message); + } + + /** + * Constructs a new query canceled exception with the specified detail message and cause. + * + * @param message the detail message + * @param cause the cause + */ + public QueryCanceledException(String message, Throwable cause) { + super(message, cause); + } +} diff --git a/api/src/main/java/org/eclipse/daanse/olap/api/execution/QueryTimeoutException.java b/api/src/main/java/org/eclipse/daanse/olap/api/execution/QueryTimeoutException.java new file mode 100644 index 0000000..195ff2a --- /dev/null +++ b/api/src/main/java/org/eclipse/daanse/olap/api/execution/QueryTimeoutException.java @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2025 Contributors to the Eclipse Foundation. + * + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * SmartCity Jena - initial + * Stefan Bischof (bipolis.org) - initial + */ +package org.eclipse.daanse.olap.api.execution; + +/** + * Exception thrown when a query execution has exceeded its timeout. + * + *

This exception is thrown by {@link ExecutionContext#checkCancelOrTimeout()} + * when the execution has exceeded its configured timeout duration.

+ * + * @see ExecutionContext#timeout() + * @see ExecutionContext#checkCancelOrTimeout() + */ +@SuppressWarnings("serial") +public class QueryTimeoutException extends RuntimeException { + + /** + * Constructs a new query timeout exception with the specified detail message. + * + * @param message the detail message + */ + public QueryTimeoutException(String message) { + super(message); + } + + /** + * Constructs a new query timeout exception with the specified detail message and cause. + * + * @param message the detail message + * @param cause the cause + */ + public QueryTimeoutException(String message, Throwable cause) { + super(message, cause); + } +} diff --git a/api/src/main/java/org/eclipse/daanse/olap/api/execution/State.java b/api/src/main/java/org/eclipse/daanse/olap/api/execution/State.java new file mode 100644 index 0000000..5e91188 --- /dev/null +++ b/api/src/main/java/org/eclipse/daanse/olap/api/execution/State.java @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2025 Contributors to the Eclipse Foundation. + * + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * SmartCity Jena - initial + * Stefan Bischof (bipolis.org) - initial + */ +package org.eclipse.daanse.olap.api.execution; + +/** + * Represents the state of an execution context. + * + *

+ * The state transitions are: + * + *

+ * RUNNING → CANCELED (via cancel())
+ * RUNNING → TIMEOUT  (via checkCancelOrTimeout() when timeout exceeded)
+ * RUNNING → ERROR    (when an error occurs)
+ * RUNNING → DONE     (when execution completes successfully)
+ * 
+ * + * @see ExecutionContext#state() + */ +public enum State { + /** + * The execution is currently running. + */ + RUNNING, + + /** + * The execution has been canceled by a user or system request. + */ + CANCELED, + + /** + * The execution has exceeded its timeout duration. + */ + TIMEOUT, + + /** + * The execution has encountered an error. + */ + ERROR, + + /** + * The execution has completed successfully. + */ + DONE; + +} diff --git a/api/src/main/java/org/eclipse/daanse/olap/api/execution/package-info.java b/api/src/main/java/org/eclipse/daanse/olap/api/execution/package-info.java new file mode 100644 index 0000000..5b45298 --- /dev/null +++ b/api/src/main/java/org/eclipse/daanse/olap/api/execution/package-info.java @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2025 Contributors to the Eclipse Foundation. + * + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * SmartCity Jena - initial + * Stefan Bischof (bipolis.org) - initial + */ +/** + * Execution context management using JDK 25 ScopedValue for thread-safe context propagation. + * + *

This package provides the ExecutionContext class that replaces the ThreadLocal-based + * Locus system with modern ScopedValue-based context management. + */ +@org.osgi.annotation.bundle.Export +@org.osgi.annotation.versioning.Version("1.0.0") +package org.eclipse.daanse.olap.api.execution; diff --git a/api/src/main/java/org/eclipse/daanse/olap/api/monitor/event/ExecutionEndEvent.java b/api/src/main/java/org/eclipse/daanse/olap/api/monitor/event/ExecutionEndEvent.java index 779ad3d..14c2dcd 100644 --- a/api/src/main/java/org/eclipse/daanse/olap/api/monitor/event/ExecutionEndEvent.java +++ b/api/src/main/java/org/eclipse/daanse/olap/api/monitor/event/ExecutionEndEvent.java @@ -12,7 +12,7 @@ */ package org.eclipse.daanse.olap.api.monitor.event; -import org.eclipse.daanse.olap.api.Execution; +import org.eclipse.daanse.olap.api.execution.Execution; public record ExecutionEndEvent(ExecutionEventCommon executionEventCommon, int phaseCount, Execution.State state, int cellCacheHitCount, int cellCacheMissCount, int cellCachePendingCount, int expCacheHitCount, diff --git a/api/src/main/java/org/eclipse/daanse/olap/api/result/Result.java b/api/src/main/java/org/eclipse/daanse/olap/api/result/Result.java index 06e3596..4deaeef 100644 --- a/api/src/main/java/org/eclipse/daanse/olap/api/result/Result.java +++ b/api/src/main/java/org/eclipse/daanse/olap/api/result/Result.java @@ -32,8 +32,8 @@ import java.io.PrintWriter; -import org.eclipse.daanse.olap.api.Execution; import org.eclipse.daanse.olap.api.element.Member; +import org.eclipse.daanse.olap.api.execution.Execution; import org.eclipse.daanse.olap.api.query.component.Query; /** diff --git a/common/src/main/java/org/eclipse/daanse/olap/access/RoleImpl.java b/common/src/main/java/org/eclipse/daanse/olap/access/RoleImpl.java index 6f69272..19ecd6e 100644 --- a/common/src/main/java/org/eclipse/daanse/olap/access/RoleImpl.java +++ b/common/src/main/java/org/eclipse/daanse/olap/access/RoleImpl.java @@ -35,16 +35,17 @@ import org.eclipse.daanse.olap.api.access.AccessCatalog; import org.eclipse.daanse.olap.api.access.AccessCube; -import org.eclipse.daanse.olap.api.access.AccessDimension; -import org.eclipse.daanse.olap.api.access.AccessHierarchy; +import org.eclipse.daanse.olap.api.access.AccessDatabaseColumn; import org.eclipse.daanse.olap.api.access.AccessDatabaseSchema; import org.eclipse.daanse.olap.api.access.AccessDatabaseTable; -import org.eclipse.daanse.olap.api.access.AccessDatabaseColumn; +import org.eclipse.daanse.olap.api.access.AccessDimension; +import org.eclipse.daanse.olap.api.access.AccessHierarchy; import org.eclipse.daanse.olap.api.access.AccessMember; import org.eclipse.daanse.olap.api.access.AllHierarchyAccess; import org.eclipse.daanse.olap.api.access.HierarchyAccess; import org.eclipse.daanse.olap.api.access.Role; import org.eclipse.daanse.olap.api.access.RollupPolicy; +import org.eclipse.daanse.olap.api.element.Catalog; import org.eclipse.daanse.olap.api.element.Cube; import org.eclipse.daanse.olap.api.element.DatabaseColumn; import org.eclipse.daanse.olap.api.element.DatabaseSchema; @@ -56,13 +57,14 @@ import org.eclipse.daanse.olap.api.element.NamedSet; import org.eclipse.daanse.olap.api.element.OlapElement; import org.eclipse.daanse.olap.api.element.VirtualCube; -import org.eclipse.daanse.olap.element.OlapElementBase; import org.eclipse.daanse.olap.common.SystemWideProperties; import org.eclipse.daanse.olap.common.Util; -import org.eclipse.daanse.olap.api.element.Catalog; +import org.eclipse.daanse.olap.element.OlapElementBase; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import aQute.bnd.compatibility.Access; + /** * Default implementation of the {@link Role} interface. * diff --git a/common/src/main/java/org/eclipse/daanse/olap/access/UnionRoleImpl.java b/common/src/main/java/org/eclipse/daanse/olap/access/UnionRoleImpl.java index a85871a..ffaabc6 100644 --- a/common/src/main/java/org/eclipse/daanse/olap/access/UnionRoleImpl.java +++ b/common/src/main/java/org/eclipse/daanse/olap/access/UnionRoleImpl.java @@ -40,6 +40,7 @@ import org.eclipse.daanse.olap.api.access.HierarchyAccess; import org.eclipse.daanse.olap.api.access.Role; import org.eclipse.daanse.olap.api.access.RollupPolicy; +import org.eclipse.daanse.olap.api.element.Catalog; import org.eclipse.daanse.olap.api.element.Cube; import org.eclipse.daanse.olap.api.element.DatabaseColumn; import org.eclipse.daanse.olap.api.element.DatabaseSchema; @@ -51,7 +52,6 @@ import org.eclipse.daanse.olap.api.element.NamedSet; import org.eclipse.daanse.olap.api.element.OlapElement; import org.eclipse.daanse.olap.common.Util; -import org.eclipse.daanse.olap.api.element.Catalog; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/common/src/main/java/org/eclipse/daanse/olap/calc/base/nested/AbstractProfilingNestedVoidCalc.java b/common/src/main/java/org/eclipse/daanse/olap/calc/base/nested/AbstractProfilingNestedVoidCalc.java index f91c60a..2fe6679 100644 --- a/common/src/main/java/org/eclipse/daanse/olap/calc/base/nested/AbstractProfilingNestedVoidCalc.java +++ b/common/src/main/java/org/eclipse/daanse/olap/calc/base/nested/AbstractProfilingNestedVoidCalc.java @@ -17,7 +17,6 @@ import org.eclipse.daanse.olap.api.calc.Calc; import org.eclipse.daanse.olap.api.calc.VoidCalc; import org.eclipse.daanse.olap.api.type.Type; -import org.eclipse.daanse.olap.calc.base.AbstractProfilingCalc; import org.eclipse.daanse.olap.calc.base.AbstractProfilingNestedCalc; /** diff --git a/common/src/main/java/org/eclipse/daanse/olap/calc/base/type/tuplebase/DelegatingTupleList.java b/common/src/main/java/org/eclipse/daanse/olap/calc/base/type/tuplebase/DelegatingTupleList.java index 77cd57d..6e9d611 100644 --- a/common/src/main/java/org/eclipse/daanse/olap/calc/base/type/tuplebase/DelegatingTupleList.java +++ b/common/src/main/java/org/eclipse/daanse/olap/calc/base/type/tuplebase/DelegatingTupleList.java @@ -31,7 +31,6 @@ import org.eclipse.daanse.olap.api.calc.todo.TupleIterator; import org.eclipse.daanse.olap.api.calc.todo.TupleList; import org.eclipse.daanse.olap.api.element.Member; -import org.eclipse.daanse.olap.common.Util; /** * Implementation of {@link org.eclipse.daanse.olap.api.calc.todo.TupleList} based on a list of diff --git a/common/src/main/java/org/eclipse/daanse/olap/calc/base/util/DimensionUtil.java b/common/src/main/java/org/eclipse/daanse/olap/calc/base/util/DimensionUtil.java index 42e84ad..1fe8fbf 100644 --- a/common/src/main/java/org/eclipse/daanse/olap/calc/base/util/DimensionUtil.java +++ b/common/src/main/java/org/eclipse/daanse/olap/calc/base/util/DimensionUtil.java @@ -19,7 +19,6 @@ import org.eclipse.daanse.olap.api.element.Dimension; import org.eclipse.daanse.olap.api.element.Hierarchy; -import org.eclipse.daanse.olap.common.SystemWideProperties; public class DimensionUtil { diff --git a/common/src/main/java/org/eclipse/daanse/olap/common/DelegatingCatalogReader.java b/common/src/main/java/org/eclipse/daanse/olap/common/DelegatingCatalogReader.java index fed827f..b6d38e6 100644 --- a/common/src/main/java/org/eclipse/daanse/olap/common/DelegatingCatalogReader.java +++ b/common/src/main/java/org/eclipse/daanse/olap/common/DelegatingCatalogReader.java @@ -368,7 +368,7 @@ public CatalogReader withoutAccessControl() { @Override public CatalogReader withLocus() { - return Util.locusCatalogReader( + return Util.executionCatalogReader( schemaReader.getCatalog().getInternalConnection(), this); } diff --git a/common/src/main/java/org/eclipse/daanse/olap/common/IdBatchResolver.java b/common/src/main/java/org/eclipse/daanse/olap/common/IdBatchResolver.java index 3ae2081..49ec665 100644 --- a/common/src/main/java/org/eclipse/daanse/olap/common/IdBatchResolver.java +++ b/common/src/main/java/org/eclipse/daanse/olap/common/IdBatchResolver.java @@ -36,7 +36,6 @@ import java.util.Set; import java.util.SortedSet; import java.util.TreeSet; -import java.util.stream.Stream; import org.eclipse.daanse.olap.api.MatchType; import org.eclipse.daanse.olap.api.NameSegment; diff --git a/common/src/main/java/org/eclipse/daanse/olap/common/QueryTimingImpl.java b/common/src/main/java/org/eclipse/daanse/olap/common/QueryTimingImpl.java index 26d6ee0..f2f17db 100644 --- a/common/src/main/java/org/eclipse/daanse/olap/common/QueryTimingImpl.java +++ b/common/src/main/java/org/eclipse/daanse/olap/common/QueryTimingImpl.java @@ -34,7 +34,6 @@ import java.util.Map; import org.eclipse.daanse.olap.api.QueryTiming; - import org.eclipse.daanse.olap.util.ArrayStack; /** diff --git a/common/src/main/java/org/eclipse/daanse/olap/common/ResultBase.java b/common/src/main/java/org/eclipse/daanse/olap/common/ResultBase.java index 9d91118..3ff049f 100644 --- a/common/src/main/java/org/eclipse/daanse/olap/common/ResultBase.java +++ b/common/src/main/java/org/eclipse/daanse/olap/common/ResultBase.java @@ -30,10 +30,10 @@ import java.io.PrintWriter; import java.util.List; -import org.eclipse.daanse.olap.api.Execution; import org.eclipse.daanse.olap.api.Statement; import org.eclipse.daanse.olap.api.element.Hierarchy; import org.eclipse.daanse.olap.api.element.Member; +import org.eclipse.daanse.olap.api.execution.Execution; import org.eclipse.daanse.olap.api.query.component.Query; import org.eclipse.daanse.olap.api.result.Axis; import org.eclipse.daanse.olap.api.result.Cell; diff --git a/common/src/main/java/org/eclipse/daanse/olap/common/Util.java b/common/src/main/java/org/eclipse/daanse/olap/common/Util.java index 1942e55..c250da9 100644 --- a/common/src/main/java/org/eclipse/daanse/olap/common/Util.java +++ b/common/src/main/java/org/eclipse/daanse/olap/common/Util.java @@ -30,7 +30,16 @@ import static org.eclipse.daanse.olap.fun.FunUtil.DOUBLE_EMPTY; -import java.io.*; +import java.io.BufferedReader; +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.PrintWriter; +import java.io.Reader; +import java.io.Serializable; +import java.io.StringWriter; import java.lang.ref.Reference; import java.lang.reflect.Array; import java.net.MalformedURLException; @@ -82,7 +91,6 @@ import org.eclipse.daanse.olap.api.DataType; import org.eclipse.daanse.olap.api.IdentifierSegment; import org.eclipse.daanse.olap.api.KeyIdentifierSegment; -import org.eclipse.daanse.olap.api.Locus; import org.eclipse.daanse.olap.api.MatchType; import org.eclipse.daanse.olap.api.NameIdentifierSegment; import org.eclipse.daanse.olap.api.Parameter; @@ -124,6 +132,8 @@ import org.eclipse.daanse.olap.exceptions.MdxCantFindMemberException; import org.eclipse.daanse.olap.exceptions.MdxChildObjectNotFoundException; import org.eclipse.daanse.olap.exceptions.MemberNotFoundException; +import org.eclipse.daanse.olap.execution.ExecutionImpl; +import org.eclipse.daanse.olap.execution.ExecutionCatalogReaderWrapper; import org.eclipse.daanse.olap.fun.FunUtil; import org.eclipse.daanse.olap.fun.sort.Sorter; import org.eclipse.daanse.olap.function.def.member.validmeasure.ValidMeasureFunDef; @@ -140,16 +150,12 @@ import org.eclipse.daanse.olap.query.component.QueryPrintWriter; import org.eclipse.daanse.olap.query.component.ResolvedFunCallImpl; import org.eclipse.daanse.olap.query.component.UnresolvedFunCallImpl; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import org.eclipse.daanse.olap.server.ExecutionImpl; -import org.eclipse.daanse.olap.server.LocusCatalogReaderWrapper; -import org.eclipse.daanse.olap.server.LocusImpl; import org.eclipse.daanse.olap.util.ArraySortedSet; import org.eclipse.daanse.olap.util.ConcatenableList; import org.eclipse.daanse.olap.util.UtilCompatible; import org.eclipse.daanse.olap.util.UtilCompatibleJdk16; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** * Utility functions used throughout mondrian. All methods are static. @@ -2817,21 +2823,20 @@ public static void explain( ProfileHandler handler, String title, Calc calc, * Wraps a CatalogReader so that each call has a locus for profiling purposes. * *

This method creates a {@link LocusCatalogReaderWrapper} that automatically - * manages the Locus context using {@link LocusImpl#execute} for every method - * call on the CatalogReader interface. + * manages the execution context for every method call on the CatalogReader interface. * * @param connection Connection providing execution context * @param schemaReader CatalogReader to wrap - * @return Wrapped CatalogReader with automatic Locus management + * @return Wrapped CatalogReader with automatic execution context management */ - public static CatalogReader locusCatalogReader( + public static CatalogReader executionCatalogReader( org.eclipse.daanse.olap.api.connection.Connection connection, final CatalogReader schemaReader) { final org.eclipse.daanse.olap.api.Statement statement = connection.getInternalStatement(); final ExecutionImpl execution = new ExecutionImpl(statement, ExecuteDurationUtil.executeDurationValue(connection.getContext())); - return new LocusCatalogReaderWrapper(execution, "Schema reader", schemaReader); + return new ExecutionCatalogReaderWrapper(execution, "Schema reader", schemaReader); } /** diff --git a/common/src/main/java/org/eclipse/daanse/olap/common/ValidatorImpl.java b/common/src/main/java/org/eclipse/daanse/olap/common/ValidatorImpl.java index 5cc521b..52e12e5 100644 --- a/common/src/main/java/org/eclipse/daanse/olap/common/ValidatorImpl.java +++ b/common/src/main/java/org/eclipse/daanse/olap/common/ValidatorImpl.java @@ -35,9 +35,9 @@ import org.eclipse.daanse.mdx.model.api.expression.operation.OperationAtom; import org.eclipse.daanse.mdx.model.api.expression.operation.ParenthesesOperationAtom; +import org.eclipse.daanse.olap.api.CatalogReader; import org.eclipse.daanse.olap.api.DataType; import org.eclipse.daanse.olap.api.Parameter; -import org.eclipse.daanse.olap.api.CatalogReader; import org.eclipse.daanse.olap.api.Validator; import org.eclipse.daanse.olap.api.exception.OlapRuntimeException; import org.eclipse.daanse.olap.api.function.FunctionDefinition; @@ -59,9 +59,8 @@ import org.eclipse.daanse.olap.query.component.QueryAxisImpl; import org.eclipse.daanse.olap.query.component.ResolvedFunCallImpl; import org.eclipse.daanse.olap.query.component.UnresolvedFunCallImpl; -import org.eclipse.daanse.olap.util.type.TypeUtil; - import org.eclipse.daanse.olap.util.ArrayStack; +import org.eclipse.daanse.olap.util.type.TypeUtil; /** * Default implementation of {@link org.eclipse.daanse.olap.api.Validator}. diff --git a/common/src/main/java/org/eclipse/daanse/olap/common/Walker.java b/common/src/main/java/org/eclipse/daanse/olap/common/Walker.java index 338fff0..e36725c 100644 --- a/common/src/main/java/org/eclipse/daanse/olap/common/Walker.java +++ b/common/src/main/java/org/eclipse/daanse/olap/common/Walker.java @@ -32,7 +32,6 @@ import java.util.Enumeration; import org.eclipse.daanse.olap.api.Walkable; - import org.eclipse.daanse.olap.util.ArrayStack; /** diff --git a/common/src/main/java/org/eclipse/daanse/olap/core/BasicContextGroup.java b/common/src/main/java/org/eclipse/daanse/olap/core/BasicContextGroup.java index 4a29996..cfc38a9 100644 --- a/common/src/main/java/org/eclipse/daanse/olap/core/BasicContextGroup.java +++ b/common/src/main/java/org/eclipse/daanse/olap/core/BasicContextGroup.java @@ -20,9 +20,9 @@ import java.util.concurrent.CopyOnWriteArrayList; import java.util.stream.Collectors; -import org.eclipse.daanse.olap.core.api.Constants; import org.eclipse.daanse.olap.api.Context; import org.eclipse.daanse.olap.api.ContextGroup; +import org.eclipse.daanse.olap.core.api.Constants; import org.osgi.namespace.unresolvable.UnresolvableNamespace; import org.osgi.service.component.annotations.Activate; import org.osgi.service.component.annotations.Component; diff --git a/common/src/main/java/org/eclipse/daanse/olap/element/DimensionBase.java b/common/src/main/java/org/eclipse/daanse/olap/element/DimensionBase.java index 7f5cc1a..c661819 100644 --- a/common/src/main/java/org/eclipse/daanse/olap/element/DimensionBase.java +++ b/common/src/main/java/org/eclipse/daanse/olap/element/DimensionBase.java @@ -30,9 +30,9 @@ import java.text.MessageFormat; import java.util.List; +import org.eclipse.daanse.olap.api.CatalogReader; import org.eclipse.daanse.olap.api.MatchType; import org.eclipse.daanse.olap.api.NameSegment; -import org.eclipse.daanse.olap.api.CatalogReader; import org.eclipse.daanse.olap.api.Segment; import org.eclipse.daanse.olap.api.element.Dimension; import org.eclipse.daanse.olap.api.element.DimensionType; diff --git a/common/src/main/java/org/eclipse/daanse/olap/element/HierarchyBase.java b/common/src/main/java/org/eclipse/daanse/olap/element/HierarchyBase.java index d57852e..89666d1 100644 --- a/common/src/main/java/org/eclipse/daanse/olap/element/HierarchyBase.java +++ b/common/src/main/java/org/eclipse/daanse/olap/element/HierarchyBase.java @@ -32,9 +32,9 @@ import java.util.ArrayList; import java.util.List; +import org.eclipse.daanse.olap.api.CatalogReader; import org.eclipse.daanse.olap.api.MatchType; import org.eclipse.daanse.olap.api.NameSegment; -import org.eclipse.daanse.olap.api.CatalogReader; import org.eclipse.daanse.olap.api.Segment; import org.eclipse.daanse.olap.api.element.Dimension; import org.eclipse.daanse.olap.api.element.DimensionType; diff --git a/common/src/main/java/org/eclipse/daanse/olap/element/LevelBase.java b/common/src/main/java/org/eclipse/daanse/olap/element/LevelBase.java index d16e013..f2d4437 100644 --- a/common/src/main/java/org/eclipse/daanse/olap/element/LevelBase.java +++ b/common/src/main/java/org/eclipse/daanse/olap/element/LevelBase.java @@ -30,9 +30,9 @@ import java.text.MessageFormat; import java.util.List; +import org.eclipse.daanse.olap.api.CatalogReader; import org.eclipse.daanse.olap.api.MatchType; import org.eclipse.daanse.olap.api.NameSegment; -import org.eclipse.daanse.olap.api.CatalogReader; import org.eclipse.daanse.olap.api.Segment; import org.eclipse.daanse.olap.api.element.Dimension; import org.eclipse.daanse.olap.api.element.Hierarchy; diff --git a/common/src/main/java/org/eclipse/daanse/olap/element/MemberBase.java b/common/src/main/java/org/eclipse/daanse/olap/element/MemberBase.java index 49f999d..38f04b0 100644 --- a/common/src/main/java/org/eclipse/daanse/olap/element/MemberBase.java +++ b/common/src/main/java/org/eclipse/daanse/olap/element/MemberBase.java @@ -30,8 +30,8 @@ import java.util.ArrayList; import java.util.List; -import org.eclipse.daanse.olap.api.MatchType; import org.eclipse.daanse.olap.api.CatalogReader; +import org.eclipse.daanse.olap.api.MatchType; import org.eclipse.daanse.olap.api.Segment; import org.eclipse.daanse.olap.api.element.Dimension; import org.eclipse.daanse.olap.api.element.Hierarchy; diff --git a/common/src/main/java/org/eclipse/daanse/olap/element/SetBase.java b/common/src/main/java/org/eclipse/daanse/olap/element/SetBase.java index 8b460f4..3d9e4c9 100644 --- a/common/src/main/java/org/eclipse/daanse/olap/element/SetBase.java +++ b/common/src/main/java/org/eclipse/daanse/olap/element/SetBase.java @@ -29,8 +29,8 @@ import java.util.List; -import org.eclipse.daanse.olap.api.MatchType; import org.eclipse.daanse.olap.api.CatalogReader; +import org.eclipse.daanse.olap.api.MatchType; import org.eclipse.daanse.olap.api.Segment; import org.eclipse.daanse.olap.api.Validator; import org.eclipse.daanse.olap.api.element.Dimension; diff --git a/common/src/main/java/org/eclipse/daanse/olap/server/LocusCatalogReaderWrapper.java b/common/src/main/java/org/eclipse/daanse/olap/execution/ExecutionCatalogReaderWrapper.java similarity index 56% rename from common/src/main/java/org/eclipse/daanse/olap/server/LocusCatalogReaderWrapper.java rename to common/src/main/java/org/eclipse/daanse/olap/execution/ExecutionCatalogReaderWrapper.java index 8b6be4f..4b8bd3f 100644 --- a/common/src/main/java/org/eclipse/daanse/olap/server/LocusCatalogReaderWrapper.java +++ b/common/src/main/java/org/eclipse/daanse/olap/execution/ExecutionCatalogReaderWrapper.java @@ -11,7 +11,7 @@ * SmartCity Jena - initial * Stefan Bischof (bipolis.org) - initial */ -package org.eclipse.daanse.olap.server; +package org.eclipse.daanse.olap.execution; import java.util.List; import java.util.Map; @@ -23,7 +23,6 @@ import org.eclipse.daanse.olap.api.Context; import org.eclipse.daanse.olap.api.DataType; import org.eclipse.daanse.olap.api.Evaluator; -import org.eclipse.daanse.olap.api.Execution; import org.eclipse.daanse.olap.api.MatchType; import org.eclipse.daanse.olap.api.NameResolver; import org.eclipse.daanse.olap.api.NameSegment; @@ -42,40 +41,42 @@ import org.eclipse.daanse.olap.api.element.Member; import org.eclipse.daanse.olap.api.element.NamedSet; import org.eclipse.daanse.olap.api.element.OlapElement; +import org.eclipse.daanse.olap.api.execution.Execution; +import org.eclipse.daanse.olap.api.execution.ExecutionContext; import org.eclipse.daanse.olap.api.function.FunctionDefinition; import org.eclipse.daanse.olap.api.query.component.Expression; /** - * Decorator for {@link CatalogReader} that wraps each method call with Locus context. + * Decorator for {@link CatalogReader} that wraps each method call with ExecutionContext. * *

This class replaces the InvocationHandler-based Proxy approach to provide * better type safety, debuggability, and performance. Each method call is - * automatically wrapped with {@link LocusImpl#execute} to ensure proper - * Locus tracking for profiling and monitoring. + * automatically wrapped with {@link ExecutionContext#where} to ensure proper + * execution context propagation using ScopedValues. * *

Usage: *

- * CatalogReader reader = new LocusCatalogReaderWrapper(
+ * CatalogReader reader = new ExecutionCatalogReaderWrapper(
  *     execution, "Schema reader", delegateReader);
  * 
* - * @see org.eclipse.daanse.olap.common.Util#locusCatalogReader + * @see org.eclipse.daanse.olap.common.Util#executionCatalogReader */ -public class LocusCatalogReaderWrapper implements CatalogReader { +public class ExecutionCatalogReaderWrapper implements CatalogReader { private final Execution execution; private final String component; private final CatalogReader delegate; /** - * Creates a wrapper that adds Locus context to all CatalogReader operations. + * Creates a wrapper that adds ExecutionContext to all CatalogReader operations. * - * @param execution Execution context for Locus + * @param execution Execution context * @param component Component name for profiling (e.g., "Schema reader") * @param delegate The actual CatalogReader to delegate to * @throws NullPointerException if any parameter is null */ - public LocusCatalogReaderWrapper( + public ExecutionCatalogReaderWrapper( Execution execution, String component, CatalogReader delegate) { @@ -86,67 +87,67 @@ public LocusCatalogReaderWrapper( @Override public Catalog getCatalog() { - return LocusImpl.execute(execution, component, () -> delegate.getCatalog()); + return ExecutionContext.where(execution.asContext(), () -> delegate.getCatalog()); } @Override public Role getRole() { - return LocusImpl.execute(execution, component, () -> delegate.getRole()); + return ExecutionContext.where(execution.asContext(), () -> delegate.getRole()); } @Override public List getCubeDimensions(Cube cube) { - return LocusImpl.execute(execution, component, () -> delegate.getCubeDimensions(cube)); + return ExecutionContext.where(execution.asContext(), () -> delegate.getCubeDimensions(cube)); } @Override public List getDimensionHierarchies(Dimension dimension) { - return LocusImpl.execute(execution, component, () -> delegate.getDimensionHierarchies(dimension)); + return ExecutionContext.where(execution.asContext(), () -> delegate.getDimensionHierarchies(dimension)); } @Override public List getHierarchyRootMembers(Hierarchy hierarchy) { - return LocusImpl.execute(execution, component, () -> delegate.getHierarchyRootMembers(hierarchy)); + return ExecutionContext.where(execution.asContext(), () -> delegate.getHierarchyRootMembers(hierarchy)); } @Override public int getChildrenCountFromCache(Member member) { - return LocusImpl.execute(execution, component, () -> delegate.getChildrenCountFromCache(member)); + return ExecutionContext.where(execution.asContext(), () -> delegate.getChildrenCountFromCache(member)); } @Override public int getLevelCardinality(Level level, boolean approximate, boolean materialize) { - return LocusImpl.execute(execution, component, () -> delegate.getLevelCardinality(level, approximate, materialize)); + return ExecutionContext.where(execution.asContext(), () -> delegate.getLevelCardinality(level, approximate, materialize)); } @Override public Member substitute(Member member) { - return LocusImpl.execute(execution, component, () -> delegate.substitute(member)); + return ExecutionContext.where(execution.asContext(), () -> delegate.substitute(member)); } @Override public List getMemberChildren(Member member) { - return LocusImpl.execute(execution, component, () -> delegate.getMemberChildren(member)); + return ExecutionContext.where(execution.asContext(), () -> delegate.getMemberChildren(member)); } @Override public List getMemberChildren(Member member, Evaluator context) { - return LocusImpl.execute(execution, component, () -> delegate.getMemberChildren(member, context)); + return ExecutionContext.where(execution.asContext(), () -> delegate.getMemberChildren(member, context)); } @Override public List getMemberChildren(List members) { - return LocusImpl.execute(execution, component, () -> delegate.getMemberChildren(members)); + return ExecutionContext.where(execution.asContext(), () -> delegate.getMemberChildren(members)); } @Override public List getMemberChildren(List members, Evaluator context) { - return LocusImpl.execute(execution, component, () -> delegate.getMemberChildren(members, context)); + return ExecutionContext.where(execution.asContext(), () -> delegate.getMemberChildren(members, context)); } @Override public void getParentChildContributingChildren(Member dataMember, Hierarchy hierarchy, List list) { - LocusImpl.execute(execution, component, () -> { + ExecutionContext.where(execution.asContext(), () -> { delegate.getParentChildContributingChildren(dataMember, hierarchy, list); return null; }); @@ -154,12 +155,12 @@ public void getParentChildContributingChildren(Member dataMember, Hierarchy hier @Override public Member getMemberParent(Member member) { - return LocusImpl.execute(execution, component, () -> delegate.getMemberParent(member)); + return ExecutionContext.where(execution.asContext(), () -> delegate.getMemberParent(member)); } @Override public void getMemberAncestors(Member member, List ancestorList) { - LocusImpl.execute(execution, component, () -> { + ExecutionContext.where(execution.asContext(), () -> { delegate.getMemberAncestors(member, ancestorList); return null; }); @@ -167,42 +168,42 @@ public void getMemberAncestors(Member member, List ancestorList) { @Override public int getMemberDepth(Member member) { - return LocusImpl.execute(execution, component, () -> delegate.getMemberDepth(member)); + return ExecutionContext.where(execution.asContext(), () -> delegate.getMemberDepth(member)); } @Override public Member getMemberByUniqueName(List uniqueNameParts, boolean failIfNotFound, MatchType matchType) { - return LocusImpl.execute(execution, component, () -> delegate.getMemberByUniqueName(uniqueNameParts, failIfNotFound, matchType)); + return ExecutionContext.where(execution.asContext(), () -> delegate.getMemberByUniqueName(uniqueNameParts, failIfNotFound, matchType)); } @Override public Member getMemberByUniqueName(List uniqueNameParts, boolean failIfNotFound) { - return LocusImpl.execute(execution, component, () -> delegate.getMemberByUniqueName(uniqueNameParts, failIfNotFound)); + return ExecutionContext.where(execution.asContext(), () -> delegate.getMemberByUniqueName(uniqueNameParts, failIfNotFound)); } @Override public OlapElement lookupCompound(OlapElement parent, List names, boolean failIfNotFound, DataType category, MatchType matchType) { - return LocusImpl.execute(execution, component, () -> delegate.lookupCompound(parent, names, failIfNotFound, category, matchType)); + return ExecutionContext.where(execution.asContext(), () -> delegate.lookupCompound(parent, names, failIfNotFound, category, matchType)); } @Override public OlapElement lookupCompound(OlapElement parent, List names, boolean failIfNotFound, DataType category) { - return LocusImpl.execute(execution, component, () -> delegate.lookupCompound(parent, names, failIfNotFound, category)); + return ExecutionContext.where(execution.asContext(), () -> delegate.lookupCompound(parent, names, failIfNotFound, category)); } @Override public Member getCalculatedMember(List nameParts) { - return LocusImpl.execute(execution, component, () -> delegate.getCalculatedMember(nameParts)); + return ExecutionContext.where(execution.asContext(), () -> delegate.getCalculatedMember(nameParts)); } @Override public NamedSet getNamedSet(List nameParts) { - return LocusImpl.execute(execution, component, () -> delegate.getNamedSet(nameParts)); + return ExecutionContext.where(execution.asContext(), () -> delegate.getNamedSet(nameParts)); } @Override public void getMemberRange(Level level, Member startMember, Member endMember, List list) { - LocusImpl.execute(execution, component, () -> { + ExecutionContext.where(execution.asContext(), () -> { delegate.getMemberRange(level, startMember, endMember, list); return null; }); @@ -210,132 +211,132 @@ public void getMemberRange(Level level, Member startMember, Member endMember, Li @Override public Member getLeadMember(Member member, int n) { - return LocusImpl.execute(execution, component, () -> delegate.getLeadMember(member, n)); + return ExecutionContext.where(execution.asContext(), () -> delegate.getLeadMember(member, n)); } @Override public int compareMembersHierarchically(Member m1, Member m2) { - return LocusImpl.execute(execution, component, () -> delegate.compareMembersHierarchically(m1, m2)); + return ExecutionContext.where(execution.asContext(), () -> delegate.compareMembersHierarchically(m1, m2)); } @Override public OlapElement getElementChild(OlapElement parent, Segment name, MatchType matchType) { - return LocusImpl.execute(execution, component, () -> delegate.getElementChild(parent, name, matchType)); + return ExecutionContext.where(execution.asContext(), () -> delegate.getElementChild(parent, name, matchType)); } @Override public OlapElement getElementChild(OlapElement parent, Segment name) { - return LocusImpl.execute(execution, component, () -> delegate.getElementChild(parent, name)); + return ExecutionContext.where(execution.asContext(), () -> delegate.getElementChild(parent, name)); } @Override public List getLevelMembers(Level level, boolean includeCalculated) { - return LocusImpl.execute(execution, component, () -> delegate.getLevelMembers(level, includeCalculated)); + return ExecutionContext.where(execution.asContext(), () -> delegate.getLevelMembers(level, includeCalculated)); } @Override public List getLevelMembers(Level level, boolean includeCalculated, Evaluator context) { - return LocusImpl.execute(execution, component, () -> delegate.getLevelMembers(level, includeCalculated, context)); + return ExecutionContext.where(execution.asContext(), () -> delegate.getLevelMembers(level, includeCalculated, context)); } @Override public List getLevelMembers(Level level, Evaluator context) { - return LocusImpl.execute(execution, component, () -> delegate.getLevelMembers(level, context)); + return ExecutionContext.where(execution.asContext(), () -> delegate.getLevelMembers(level, context)); } @Override public List getHierarchyLevels(Hierarchy hierarchy) { - return LocusImpl.execute(execution, component, () -> delegate.getHierarchyLevels(hierarchy)); + return ExecutionContext.where(execution.asContext(), () -> delegate.getHierarchyLevels(hierarchy)); } @Override public Member getHierarchyDefaultMember(Hierarchy hierarchy) { - return LocusImpl.execute(execution, component, () -> delegate.getHierarchyDefaultMember(hierarchy)); + return ExecutionContext.where(execution.asContext(), () -> delegate.getHierarchyDefaultMember(hierarchy)); } @Override public boolean isDrillable(Member member) { - return LocusImpl.execute(execution, component, () -> delegate.isDrillable(member)); + return ExecutionContext.where(execution.asContext(), () -> delegate.isDrillable(member)); } @Override public boolean isVisible(Member member) { - return LocusImpl.execute(execution, component, () -> delegate.isVisible(member)); + return ExecutionContext.where(execution.asContext(), () -> delegate.isVisible(member)); } @Override public List getCubes() { - return LocusImpl.execute(execution, component, () -> delegate.getCubes()); + return ExecutionContext.where(execution.asContext(), () -> delegate.getCubes()); } @Override public List getCalculatedMembers(Hierarchy hierarchy) { - return LocusImpl.execute(execution, component, () -> delegate.getCalculatedMembers(hierarchy)); + return ExecutionContext.where(execution.asContext(), () -> delegate.getCalculatedMembers(hierarchy)); } @Override public List getCalculatedMembers(Level level) { - return LocusImpl.execute(execution, component, () -> delegate.getCalculatedMembers(level)); + return ExecutionContext.where(execution.asContext(), () -> delegate.getCalculatedMembers(level)); } @Override public List getCalculatedMembers() { - return LocusImpl.execute(execution, component, () -> delegate.getCalculatedMembers()); + return ExecutionContext.where(execution.asContext(), () -> delegate.getCalculatedMembers()); } @Override public Member lookupMemberChildByName(Member parent, Segment childName, MatchType matchType) { - return LocusImpl.execute(execution, component, () -> delegate.lookupMemberChildByName(parent, childName, matchType)); + return ExecutionContext.where(execution.asContext(), () -> delegate.lookupMemberChildByName(parent, childName, matchType)); } @Override public List lookupMemberChildrenByNames(Member parent, List childNames, MatchType matchType) { - return LocusImpl.execute(execution, component, () -> delegate.lookupMemberChildrenByNames(parent, childNames, matchType)); + return ExecutionContext.where(execution.asContext(), () -> delegate.lookupMemberChildrenByNames(parent, childNames, matchType)); } @Override public NativeEvaluator getNativeSetEvaluator(FunctionDefinition fun, Expression[] args, Evaluator evaluator, Calc calc) { - return LocusImpl.execute(execution, component, () -> delegate.getNativeSetEvaluator(fun, args, evaluator, calc)); + return ExecutionContext.where(execution.asContext(), () -> delegate.getNativeSetEvaluator(fun, args, evaluator, calc)); } @Override public Parameter getParameter(String name) { - return LocusImpl.execute(execution, component, () -> delegate.getParameter(name)); + return ExecutionContext.where(execution.asContext(), () -> delegate.getParameter(name)); } @Override @Deprecated public DataSource getDataSource() { - return LocusImpl.execute(execution, component, () -> delegate.getDataSource()); + return ExecutionContext.where(execution.asContext(), () -> delegate.getDataSource()); } @Override public CatalogReader withoutAccessControl() { - return LocusImpl.execute(execution, component, () -> delegate.withoutAccessControl()); + return ExecutionContext.where(execution.asContext(), () -> delegate.withoutAccessControl()); } @Override public CatalogReader withLocus() { - return LocusImpl.execute(execution, component, () -> delegate.withLocus()); + return ExecutionContext.where(execution.asContext(), () -> delegate.withLocus()); } @Override public List getNamespaces() { - return LocusImpl.execute(execution, component, () -> delegate.getNamespaces()); + return ExecutionContext.where(execution.asContext(), () -> delegate.getNamespaces()); } @Override public Map getMemberChildrenWithDetails(Member member, Evaluator evaluator) { - return LocusImpl.execute(execution, component, () -> delegate.getMemberChildrenWithDetails(member, evaluator)); + return ExecutionContext.where(execution.asContext(), () -> delegate.getMemberChildrenWithDetails(member, evaluator)); } @Override public Context getContext() { - return LocusImpl.execute(execution, component, () -> delegate.getContext()); + return ExecutionContext.where(execution.asContext(), () -> delegate.getContext()); } @Override public List getDatabaseSchemas() { - return LocusImpl.execute(execution, component, () -> delegate.getDatabaseSchemas()); + return ExecutionContext.where(execution.asContext(), () -> delegate.getDatabaseSchemas()); } } diff --git a/common/src/main/java/org/eclipse/daanse/olap/execution/ExecutionImpl.java b/common/src/main/java/org/eclipse/daanse/olap/execution/ExecutionImpl.java new file mode 100644 index 0000000..0edf31a --- /dev/null +++ b/common/src/main/java/org/eclipse/daanse/olap/execution/ExecutionImpl.java @@ -0,0 +1,465 @@ +/* + * This software is subject to the terms of the Eclipse Public License v1.0 + * Agreement, available at the following URL: + * http://www.eclipse.org/legal/epl-v10.html. + * You must accept the terms of that agreement to use this software. + * + * Copyright (C) 2002-2005 Julian Hyde + * Copyright (C) 2005-2021 Hitachi Vantara and others + * All Rights Reserved. + * + * ---- All changes after Fork in 2023 ------------------------ + * + * Project: Eclipse daanse + * + * Copyright (c) 2023 Contributors to the Eclipse Foundation. + * + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors after Fork in 2023: + * SmartCity Jena - initial + */ + +package org.eclipse.daanse.olap.execution; + +import java.time.Duration; +import java.time.Instant; +import java.time.LocalDateTime; +import java.util.Optional; +import java.util.concurrent.atomic.AtomicLong; + +import org.eclipse.daanse.olap.api.CacheCommand; +import org.eclipse.daanse.olap.api.Context; +import org.eclipse.daanse.olap.api.ISegmentCacheManager; +import org.eclipse.daanse.olap.api.QueryTiming; +import org.eclipse.daanse.olap.api.Statement; +import org.eclipse.daanse.olap.api.connection.Connection; +import org.eclipse.daanse.olap.api.exception.OlapRuntimeException; +import org.eclipse.daanse.olap.api.execution.Execution; +import org.eclipse.daanse.olap.api.execution.ExecutionContext; +import org.eclipse.daanse.olap.api.execution.ExecutionMetadata; +import org.eclipse.daanse.olap.api.monitor.event.ConnectionEventCommon; +import org.eclipse.daanse.olap.api.monitor.event.EventCommon; +import org.eclipse.daanse.olap.api.monitor.event.ExecutionEndEvent; +import org.eclipse.daanse.olap.api.monitor.event.ExecutionEventCommon; +import org.eclipse.daanse.olap.api.monitor.event.ExecutionPhaseEvent; +import org.eclipse.daanse.olap.api.monitor.event.ExecutionStartEvent; +import org.eclipse.daanse.olap.api.monitor.event.MdxStatementEventCommon; +import org.eclipse.daanse.olap.api.monitor.event.ServertEventCommon; +import org.eclipse.daanse.olap.api.query.component.Query; +import org.eclipse.daanse.olap.common.MemoryLimitExceededException; +import org.eclipse.daanse.olap.common.QueryCanceledException; +import org.eclipse.daanse.olap.common.QueryTimingImpl; +import org.eclipse.daanse.olap.common.Util; +import org.eclipse.daanse.olap.core.AbstractBasicContext; + +/** + * Execution context. + * + * + * Loosely corresponds to a CellSet. A given statement may be executed several + * times over its lifetime, but at most one execution can be going on at a time. + * + * + * @author jhyde + */ +public class ExecutionImpl implements Execution { + /** + * Used for MDX logging, allows for a MDX Statement UID. + */ + private static final AtomicLong SEQ = new AtomicLong(); + + private final StatementImpl statement; + + /** + * ExecutionContext for ScopedValue-based context propagation. This provides the + * bridge to the new ExecutionContext system. + */ + private final ExecutionContext executionContext; + + private State state = State.FRESH; + + /** + * This is a lock object to sync on when changing the {@link #state} variable. + */ + private final Object stateLock = new Object(); + + /** + * If not null, this query was notified that it might cause an OutOfMemoryError. + */ + private String outOfMemoryMsg; + + private LocalDateTime startTime; + private Optional duration; + private final QueryTimingImpl queryTiming = new QueryTimingImpl(); + private int phase; + private int cellCacheHitCount; + private int cellCacheMissCount; + private int cellCachePendingCount; + private int expCacheHitCount; + private int expCacheMissCount; + + /** + * Execution id, global within this JVM instance. + */ + private final long id; + + public static final ExecutionImpl NONE = new ExecutionImpl(null, Optional.empty()); + + private final Execution parent; + + public ExecutionImpl(Statement statement, Optional duration) { + Execution parentExec = null; + ExecutionContext parentContext = null; + // Skip ExecutionContext during static initialization (when statement is null for NONE) + // Use currentOrNull() as we need to handle the case where no context is bound + if (statement != null) { + ExecutionContext currentContext = ExecutionContext.currentOrNull(); + if (currentContext != null) { + parentExec = currentContext.getExecution(); + if (parentExec != null) { + parentContext = parentExec.asContext(); + } + } + } + this.parent = parentExec; + this.id = SEQ.getAndIncrement(); + this.statement = (StatementImpl) statement; + this.duration = duration; + + // Initialize ExecutionContext + if (parentContext != null) { + // Child context - inherits timeout from parent + this.executionContext = parentContext.createChild(ExecutionMetadata.empty(), Optional.empty()); + } else { + // Root context - create with execution metadata + ExecutionMetadata rootMetadata = ExecutionMetadata.of("ExecutionImpl", "Query Execution", null, 0); + this.executionContext = ExecutionContext.root(duration, rootMetadata); + } + + // Set bidirectional reference for compatibility with legacy code + this.executionContext.setExecution(this); + } + + /** + * Marks the start of an Execution instance. It is called by + * {@link Statement#start(ExecutionImpl)} automatically. Users don't need to + * call this method. + */ + public void start() { + assert this.state == State.FRESH; + this.startTime = LocalDateTime.now(); + this.state = State.RUNNING; + this.queryTiming.init(this.statement.getProfileHandler() != null); + fireExecutionStartEvent(); + } + + private String getMdx() { + final Query query = statement.query; + return query != null ? Util.unparse(query) : null; + } + + public void tracePhase(int hitCount, int missCount, int pendingCount) { + final Connection connection = statement.getDaanseConnection(); + final Context context = connection.getContext(); + final int hitCountInc = hitCount - this.cellCacheHitCount; + final int missCountInc = missCount - this.cellCacheMissCount; + final int pendingCountInc = pendingCount - this.cellCachePendingCount; + ExecutionPhaseEvent executionPhaseEvent = new ExecutionPhaseEvent( + new ExecutionEventCommon(new MdxStatementEventCommon(new ConnectionEventCommon( + new ServertEventCommon(EventCommon.ofNow(), context.getName()), connection.getId()), + statement.getId()), id), + phase, hitCountInc, missCountInc, pendingCountInc); + + context.getMonitor().accept(executionPhaseEvent); +// new ExecutionPhaseEvent( System.currentTimeMillis(), context.getName(), connection +// .getId(), statement.getId(), id, phase, hitCountInc, missCountInc, pendingCountInc ) + ++phase; + this.cellCacheHitCount = hitCount; + this.cellCacheMissCount = missCount; + this.cellCachePendingCount = pendingCount; + } + + /** + * Cancels the execution instance. + */ + public void cancel() { + synchronized (stateLock) { + this.state = State.CANCELED; + this.cancelSqlStatements(); + if (parent != null) { + // parent.cancel(); + } + fireExecutionEndEvent(); + } + } + + /** + * This method will change the state of this execution to {@link State#ERROR} + * and will set the message to display. Cleanup of the resources used by this + * execution instance will be performed in the background later on. + * + * @param msg The message to display to the user, describing the problem + * encountered with the memory space. + */ + public final void setOutOfMemory(String msg) { + synchronized (stateLock) { + assert msg != null; + this.outOfMemoryMsg = msg; + this.state = State.ERROR; + } + } + + /** + * Checks the state of this Execution and throws an exception if something is + * wrong. This method should be called by the user thread. + * + * It won't throw anything if the query has successfully completed. + * + * @throws OlapRuntimeException The exception encountered. + */ + public synchronized void checkCancelOrTimeout() throws OlapRuntimeException { + if (parent != null) { + parent.checkCancelOrTimeout(); + } + boolean needInterrupt = false; + switch (this.state) { + case CANCELED: + try { + if (Thread.interrupted()) { + // Checking the state of the thread will clear the + // interrupted flag so we can send an event out. + // After that, we make sure that we set it again + // so the thread state remains consistent. + needInterrupt = true; + } + fireExecutionEndEvent(); + } finally { + if (needInterrupt) { + Thread.currentThread().interrupt(); + } + } + throw new QueryCanceledException(); + case RUNNING: + case TIMEOUT: + if (duration.isPresent()) { + long currTime = System.currentTimeMillis(); +// if ( currTime > timeoutTimeMillis ) { +// this.state = State.TIMEOUT; +// fireExecutionEndEvent(); +// throw new InvalidArgumentException(MessageFormat.format(QueryTimeout, timeoutIntervalMillis / 1000 )); +// } + } + break; + case ERROR: + try { + if (Thread.interrupted()) { + // Checking the state of the thread will clear the + // interrupted flag so we can send an event out. + // After that, we make sure that we set it again + // so the thread state remains consistent. + needInterrupt = true; + } + fireExecutionEndEvent(); + } finally { + if (needInterrupt) { + Thread.currentThread().interrupt(); + } + } + throw new MemoryLimitExceededException(outOfMemoryMsg); + } + } + + /** + * Returns whether this execution is currently in a failed state and will throw + * an exception as soon as the next check is performed using + * {@link ExecutionImpl#checkCancelOrTimeout()}. + * + * @return True or false, depending on the timeout state. + */ + public boolean isCancelOrTimeout() { + if (parent != null && parent.isCancelOrTimeout()) { + return true; + } + synchronized (stateLock) { + if (state == State.CANCELED || state == State.ERROR || state == State.TIMEOUT + || (state == State.RUNNING && duration.isPresent() + && Duration.between(LocalDateTime.now(), startTime).compareTo(duration.get()) > 0)) { + return true; + } + return false; + } + } + + /** + * Tells whether this execution is done executing. + */ + public boolean isDone() { + synchronized (stateLock) { + switch (this.state) { + case CANCELED: + case DONE: + case ERROR: + case TIMEOUT: + return true; + default: + return false; + } + } + } + + /** + * Called by the RolapResultShepherd when the execution needs to clean all of + * its resources for whatever reasons, typically when an exception has occurred + * or the execution has ended. Any currently running SQL statements will be + * canceled. It should only be called if + * {@link ExecutionImpl#isCancelOrTimeout()} returns true. + * + * + * This method doesn't need to be called by a user. It will be called internally + * by Mondrian when the system is ready to clean the remaining resources. + * + * + * To check if this execution is failed, use + * {@link ExecutionImpl#isCancelOrTimeout()} instead. + */ + public void cancelSqlStatements() { + if (parent != null) { + parent.cancelSqlStatements(); + } + // Delegate to ExecutionContext which now handles statement cancellation + executionContext.cancel(); + // Also cleanup the segment registrations from the index. + unregisterSegmentRequests(); + } + + /** + * Called when query execution has completed. Once query execution has ended, it + * is not possible to cancel or timeout the query until it starts executing + * again. + */ + public void end() { + synchronized (stateLock) { + queryTiming.done(); + if (this.state == State.FRESH || this.state == State.RUNNING) { + this.state = State.DONE; + } + // Unregister all segments + unregisterSegmentRequests(); + // Fire up a monitor event. + fireExecutionEndEvent(); + } + } + + /** + * Calls into the SegmentCacheManager and unregisters all the registrations made + * for this execution on segments form the index. + */ + public void unregisterSegmentRequests() { + // We also have to cancel all requests for the current segments. + final ExecutionContext currentContext = executionContext; + AbstractBasicContext abc = (AbstractBasicContext) statement.getConnection().getContext(); + final ISegmentCacheManager mgr = abc.getAggregationManager().getCacheMgr(null); + mgr.execute(new CacheCommand() { + @Override + public Void call() throws Exception { + mgr.getIndexRegistry().cancelExecutionSegments(ExecutionImpl.this); + return null; + } + + @Override + public ExecutionContext getExecutionContext() { + return currentContext; + } + }); + } + + public final LocalDateTime getStartTime() { + return startTime; + } + + public Statement getDaanseStatement() { + return statement; + } + + public final QueryTiming getQueryTiming() { + return queryTiming; + } + + public final long getId() { + return id; + } + + public final Duration getElapsedMillis() { + return Duration.between(LocalDateTime.now(), startTime); + } + + private void fireExecutionEndEvent() { + final Connection connection = statement.getDaanseConnection(); + final Context context = connection.getContext(); + + ExecutionEndEvent endEvent = new ExecutionEndEvent(new ExecutionEventCommon( + + new MdxStatementEventCommon(new ConnectionEventCommon(new ServertEventCommon( + new EventCommon( + Instant.ofEpochMilli(Duration.between(LocalDateTime.now(), this.startTime).toMillis())), + context.getName()), connection.getId()), this.statement.getId()), + this.id), phase, state, cellCacheHitCount, cellCacheMissCount, cellCachePendingCount, expCacheHitCount, + expCacheMissCount); + context.getMonitor().accept(endEvent); + } + + private void fireExecutionStartEvent() { + final Connection connection = statement.getDaanseConnection(); + final Context context = connection.getContext(); + + ExecutionStartEvent executionStartEvent = new ExecutionStartEvent(new ExecutionEventCommon( + + new MdxStatementEventCommon(new ConnectionEventCommon(new ServertEventCommon( + new EventCommon( + Instant.ofEpochMilli(Duration.between(LocalDateTime.now(), this.startTime).toMillis())), + context.getName()), connection.getId()), statement.getId()), + id), getMdx()); + context.getMonitor().accept(executionStartEvent); + } + + public void setCellCacheHitCount(int cellCacheHitCount) { + this.cellCacheHitCount = cellCacheHitCount; + } + + public void setCellCacheMissCount(int cellCacheMissCount) { + this.cellCacheMissCount = cellCacheMissCount; + } + + public void setCellCachePendingCount(int cellCachePendingCount) { + this.cellCachePendingCount = cellCachePendingCount; + } + + public void setExpCacheCounts(int hitCount, int missCount) { + this.expCacheHitCount = hitCount; + this.expCacheMissCount = missCount; + } + + public int getExpCacheHitCount() { + return expCacheHitCount; + } + + public int getExpCacheMissCount() { + return expCacheMissCount; + } + + /** + * Returns the ExecutionContext for ScopedValue-based context propagation. This + * bridges the legacy Execution interface with the new ExecutionContext system. + * + * @return the ExecutionContext representation of this execution + */ + @Override + public ExecutionContext asContext() { + return executionContext; + } +} diff --git a/common/src/main/java/org/eclipse/daanse/olap/server/StatementImpl.java b/common/src/main/java/org/eclipse/daanse/olap/execution/StatementImpl.java similarity index 97% rename from common/src/main/java/org/eclipse/daanse/olap/server/StatementImpl.java rename to common/src/main/java/org/eclipse/daanse/olap/execution/StatementImpl.java index 97d2d1f..7f8dee7 100644 --- a/common/src/main/java/org/eclipse/daanse/olap/server/StatementImpl.java +++ b/common/src/main/java/org/eclipse/daanse/olap/execution/StatementImpl.java @@ -23,16 +23,16 @@ * Stefan Bischof (bipolis.org) - initial */ -package org.eclipse.daanse.olap.server; +package org.eclipse.daanse.olap.execution; import java.sql.SQLException; import java.util.concurrent.atomic.AtomicLong; -import org.eclipse.daanse.olap.api.Execution; -import org.eclipse.daanse.olap.api.ProfileHandler; import org.eclipse.daanse.olap.api.CatalogReader; +import org.eclipse.daanse.olap.api.ProfileHandler; import org.eclipse.daanse.olap.api.Statement; import org.eclipse.daanse.olap.api.element.Catalog; +import org.eclipse.daanse.olap.api.execution.Execution; import org.eclipse.daanse.olap.api.query.component.Query; /** diff --git a/common/src/main/java/org/eclipse/daanse/olap/execution/package-info.java b/common/src/main/java/org/eclipse/daanse/olap/execution/package-info.java new file mode 100644 index 0000000..eaf7d7a --- /dev/null +++ b/common/src/main/java/org/eclipse/daanse/olap/execution/package-info.java @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2025 Contributors to the Eclipse Foundation. + * + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * SmartCity Jena - initial + * Stefan Bischof (bipolis.org) - initial + */ +/** + * Execution context management using JDK 25 ScopedValue for thread-safe context propagation. + * + *

This package provides the ExecutionContext class that replaces the ThreadLocal-based + * Locus system with modern ScopedValue-based context management. + */ +@org.osgi.annotation.bundle.Export +@org.osgi.annotation.versioning.Version("1.0.0") +package org.eclipse.daanse.olap.execution; diff --git a/common/src/main/java/org/eclipse/daanse/olap/fun/FunUtil.java b/common/src/main/java/org/eclipse/daanse/olap/fun/FunUtil.java index 2c36c47..f4593f2 100644 --- a/common/src/main/java/org/eclipse/daanse/olap/fun/FunUtil.java +++ b/common/src/main/java/org/eclipse/daanse/olap/fun/FunUtil.java @@ -43,7 +43,6 @@ import org.eclipse.daanse.olap.api.CatalogReader; import org.eclipse.daanse.olap.api.DataType; import org.eclipse.daanse.olap.api.Evaluator; -import org.eclipse.daanse.olap.api.Execution; import org.eclipse.daanse.olap.api.MatchType; import org.eclipse.daanse.olap.api.Segment; import org.eclipse.daanse.olap.api.Validator; @@ -61,6 +60,7 @@ import org.eclipse.daanse.olap.api.element.MetaData; import org.eclipse.daanse.olap.api.element.OlapElement; import org.eclipse.daanse.olap.api.exception.OlapRuntimeException; +import org.eclipse.daanse.olap.api.execution.Execution; import org.eclipse.daanse.olap.api.function.FunctionDefinition; import org.eclipse.daanse.olap.api.function.FunctionMetaData; import org.eclipse.daanse.olap.api.query.component.DimensionExpression; @@ -75,23 +75,22 @@ import org.eclipse.daanse.olap.api.type.TupleType; import org.eclipse.daanse.olap.api.type.Type; import org.eclipse.daanse.olap.calc.base.type.tuplebase.UnaryTupleList; -import org.eclipse.daanse.olap.element.AbstractProperty; import org.eclipse.daanse.olap.common.ResultStyleException; import org.eclipse.daanse.olap.common.Util; +import org.eclipse.daanse.olap.element.AbstractProperty; +import org.eclipse.daanse.olap.exceptions.CousinHierarchyMismatchException; +import org.eclipse.daanse.olap.exceptions.MdxChildObjectNotFoundException; +import org.eclipse.daanse.olap.fun.sort.OrderKey; +import org.eclipse.daanse.olap.fun.sort.Sorter; import org.eclipse.daanse.olap.function.def.hierarchy.member.HierarchyCurrentMemberFunDef; import org.eclipse.daanse.olap.function.def.parentheses.ParenthesesFunDef; import org.eclipse.daanse.olap.function.def.set.SetFunDef; import org.eclipse.daanse.olap.impl.IdentifierParser.Builder; import org.eclipse.daanse.olap.query.component.HierarchyExpressionImpl; -import org.eclipse.daanse.olap.util.type.TypeUtil; -import org.eclipse.daanse.olap.exceptions.CousinHierarchyMismatchException; -import org.eclipse.daanse.olap.exceptions.MdxChildObjectNotFoundException; -import org.eclipse.daanse.olap.fun.sort.OrderKey; -import org.eclipse.daanse.olap.fun.sort.Sorter; - import org.eclipse.daanse.olap.util.CancellationChecker; import org.eclipse.daanse.olap.util.ConcatenableList; import org.eclipse.daanse.olap.util.IdentifierParser; +import org.eclipse.daanse.olap.util.type.TypeUtil; /** * {@code FunUtil} contains a set of methods useful within the {@code mondrian.olap.fun} package. diff --git a/common/src/main/java/org/eclipse/daanse/olap/fun/sort/Sorter.java b/common/src/main/java/org/eclipse/daanse/olap/fun/sort/Sorter.java index 2da855e..2e19536 100644 --- a/common/src/main/java/org/eclipse/daanse/olap/fun/sort/Sorter.java +++ b/common/src/main/java/org/eclipse/daanse/olap/fun/sort/Sorter.java @@ -27,8 +27,8 @@ package org.eclipse.daanse.olap.fun.sort; +import static org.eclipse.daanse.olap.common.Util.DOUBLE_NULL; import static org.eclipse.daanse.olap.common.Util.newInternal; -import static org.eclipse.daanse.olap.fun.FunUtil.DOUBLE_NULL; import java.util.AbstractList; import java.util.ArrayList; @@ -44,24 +44,23 @@ import java.util.stream.Stream; import org.eclipse.daanse.olap.api.Evaluator; -import org.eclipse.daanse.olap.api.Execution; import org.eclipse.daanse.olap.api.calc.Calc; import org.eclipse.daanse.olap.api.calc.todo.TupleCursor; import org.eclipse.daanse.olap.api.calc.todo.TupleIterable; import org.eclipse.daanse.olap.api.calc.todo.TupleList; import org.eclipse.daanse.olap.api.element.LimitedMember; import org.eclipse.daanse.olap.api.element.Member; +import org.eclipse.daanse.olap.api.execution.Execution; import org.eclipse.daanse.olap.api.type.ScalarType; import org.eclipse.daanse.olap.calc.base.type.tuplebase.DelegatingTupleList; import org.eclipse.daanse.olap.calc.base.type.tuplebase.TupleCollections; import org.eclipse.daanse.olap.common.SystemWideProperties; import org.eclipse.daanse.olap.common.Util; import org.eclipse.daanse.olap.function.def.member.memberorderkey.MemberOrderKeyCalc; +import org.eclipse.daanse.olap.util.CancellationChecker; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.eclipse.daanse.olap.util.CancellationChecker; - @SuppressWarnings( "squid:S4274" ) public class Sorter { diff --git a/common/src/main/java/org/eclipse/daanse/olap/fun/sort/TupleExpMemoComparator.java b/common/src/main/java/org/eclipse/daanse/olap/fun/sort/TupleExpMemoComparator.java index dcf7cb7..cf88694 100644 --- a/common/src/main/java/org/eclipse/daanse/olap/fun/sort/TupleExpMemoComparator.java +++ b/common/src/main/java/org/eclipse/daanse/olap/fun/sort/TupleExpMemoComparator.java @@ -40,12 +40,11 @@ import org.eclipse.daanse.olap.api.element.Member; import org.eclipse.daanse.olap.api.exception.CellRequestQuantumExceededException; import org.eclipse.daanse.olap.common.Util; +import org.eclipse.daanse.olap.util.CancellationChecker; import com.github.benmanes.caffeine.cache.Cache; import com.github.benmanes.caffeine.cache.Caffeine; -import org.eclipse.daanse.olap.util.CancellationChecker; - /** * Supports comparison of tuples, caching results such that .compare calls involving the same tuple do not result in * redundant evaluation. diff --git a/common/src/main/java/org/eclipse/daanse/olap/function/def/AbstractFunctionDefinition.java b/common/src/main/java/org/eclipse/daanse/olap/function/def/AbstractFunctionDefinition.java index 637ceac..0cf656e 100644 --- a/common/src/main/java/org/eclipse/daanse/olap/function/def/AbstractFunctionDefinition.java +++ b/common/src/main/java/org/eclipse/daanse/olap/function/def/AbstractFunctionDefinition.java @@ -37,8 +37,6 @@ import org.eclipse.daanse.olap.api.function.FunctionMetaData; import org.eclipse.daanse.olap.api.query.component.Expression; import org.eclipse.daanse.olap.api.type.Type; -import org.eclipse.daanse.olap.fun.FunUtil; -import org.eclipse.daanse.olap.function.core.FunctionMetaDataR; import org.eclipse.daanse.olap.function.core.FunctionPrinter; import org.eclipse.daanse.olap.query.component.ResolvedFunCallImpl; import org.eclipse.daanse.olap.util.type.TypeUtil; diff --git a/common/src/main/java/org/eclipse/daanse/olap/function/def/crossjoin/BaseListCalc.java b/common/src/main/java/org/eclipse/daanse/olap/function/def/crossjoin/BaseListCalc.java index 3231027..ce4d35e 100644 --- a/common/src/main/java/org/eclipse/daanse/olap/function/def/crossjoin/BaseListCalc.java +++ b/common/src/main/java/org/eclipse/daanse/olap/function/def/crossjoin/BaseListCalc.java @@ -13,13 +13,13 @@ */ package org.eclipse.daanse.olap.function.def.crossjoin; +import org.eclipse.daanse.olap.api.CatalogReader; import org.eclipse.daanse.olap.api.Evaluator; import org.eclipse.daanse.olap.api.NativeEvaluator; import org.eclipse.daanse.olap.api.calc.Calc; import org.eclipse.daanse.olap.api.calc.ResultStyle; import org.eclipse.daanse.olap.api.calc.todo.TupleList; import org.eclipse.daanse.olap.api.calc.todo.TupleListCalc; -import org.eclipse.daanse.olap.api.CatalogReader; import org.eclipse.daanse.olap.api.query.component.ResolvedFunCall; import org.eclipse.daanse.olap.calc.base.type.tuplebase.AbstractProfilingNestedTupleListCalc; import org.eclipse.daanse.olap.calc.base.type.tuplebase.TupleCollections; diff --git a/common/src/main/java/org/eclipse/daanse/olap/function/def/crossjoin/CrossJoinFunDef.java b/common/src/main/java/org/eclipse/daanse/olap/function/def/crossjoin/CrossJoinFunDef.java index 906c64b..f0373d9 100644 --- a/common/src/main/java/org/eclipse/daanse/olap/function/def/crossjoin/CrossJoinFunDef.java +++ b/common/src/main/java/org/eclipse/daanse/olap/function/def/crossjoin/CrossJoinFunDef.java @@ -20,10 +20,9 @@ import java.util.Map; import java.util.Set; -import org.eclipse.daanse.olap.api.Evaluator; -import org.eclipse.daanse.olap.api.Execution; import org.eclipse.daanse.olap.api.CatalogReader; import org.eclipse.daanse.olap.api.ConfigConstants; +import org.eclipse.daanse.olap.api.Evaluator; import org.eclipse.daanse.olap.api.Validator; import org.eclipse.daanse.olap.api.calc.Calc; import org.eclipse.daanse.olap.api.calc.ResultStyle; @@ -34,6 +33,8 @@ import org.eclipse.daanse.olap.api.calc.todo.TupleListCalc; import org.eclipse.daanse.olap.api.element.Hierarchy; import org.eclipse.daanse.olap.api.element.Member; +import org.eclipse.daanse.olap.api.execution.Execution; +import org.eclipse.daanse.olap.api.execution.ExecutionContext; import org.eclipse.daanse.olap.api.function.FunctionMetaData; import org.eclipse.daanse.olap.api.query.component.Expression; import org.eclipse.daanse.olap.api.query.component.Formula; @@ -50,15 +51,12 @@ import org.eclipse.daanse.olap.fun.FunUtil; import org.eclipse.daanse.olap.fun.MemberExtractingVisitor; import org.eclipse.daanse.olap.function.def.AbstractFunctionDefinition; -import org.eclipse.daanse.olap.function.def.set.SetListCalc; import org.eclipse.daanse.olap.function.def.set.ExprIterCalc; - +import org.eclipse.daanse.olap.function.def.set.SetListCalc; +import org.eclipse.daanse.olap.util.CancellationChecker; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.eclipse.daanse.olap.server.LocusImpl; -import org.eclipse.daanse.olap.util.CancellationChecker; - public class CrossJoinFunDef extends AbstractFunctionDefinition { private static final Logger LOGGER = LoggerFactory.getLogger(CrossJoinFunDef.class); @@ -390,7 +388,7 @@ private static void cartesianProductRecurse(int i, List lists, List { diff --git a/common/src/main/java/org/eclipse/daanse/olap/function/def/udf/currentdatestring/CurrentDateStringCalc.java b/common/src/main/java/org/eclipse/daanse/olap/function/def/udf/currentdatestring/CurrentDateStringCalc.java index 516961e..de42c31 100644 --- a/common/src/main/java/org/eclipse/daanse/olap/function/def/udf/currentdatestring/CurrentDateStringCalc.java +++ b/common/src/main/java/org/eclipse/daanse/olap/function/def/udf/currentdatestring/CurrentDateStringCalc.java @@ -20,7 +20,6 @@ import org.eclipse.daanse.olap.api.calc.StringCalc; import org.eclipse.daanse.olap.api.type.Type; import org.eclipse.daanse.olap.calc.base.nested.AbstractProfilingNestedStringCalc; - import org.eclipse.daanse.olap.util.Format; public class CurrentDateStringCalc extends AbstractProfilingNestedStringCalc { diff --git a/common/src/main/java/org/eclipse/daanse/olap/function/def/vba/instr/InStrFunDef.java b/common/src/main/java/org/eclipse/daanse/olap/function/def/vba/instr/InStrFunDef.java index 1756087..03ef56a 100644 --- a/common/src/main/java/org/eclipse/daanse/olap/function/def/vba/instr/InStrFunDef.java +++ b/common/src/main/java/org/eclipse/daanse/olap/function/def/vba/instr/InStrFunDef.java @@ -14,7 +14,6 @@ package org.eclipse.daanse.olap.function.def.vba.instr; import org.eclipse.daanse.olap.api.calc.Calc; -import org.eclipse.daanse.olap.api.calc.DateTimeCalc; import org.eclipse.daanse.olap.api.calc.IntegerCalc; import org.eclipse.daanse.olap.api.calc.StringCalc; import org.eclipse.daanse.olap.api.calc.compiler.ExpressionCompiler; diff --git a/common/src/main/java/org/eclipse/daanse/olap/function/def/vba/integer/IntCalc.java b/common/src/main/java/org/eclipse/daanse/olap/function/def/vba/integer/IntCalc.java index 241a490..35cc157 100644 --- a/common/src/main/java/org/eclipse/daanse/olap/function/def/vba/integer/IntCalc.java +++ b/common/src/main/java/org/eclipse/daanse/olap/function/def/vba/integer/IntCalc.java @@ -21,7 +21,6 @@ import org.eclipse.daanse.olap.api.Evaluator; import org.eclipse.daanse.olap.api.calc.Calc; import org.eclipse.daanse.olap.api.type.Type; -import org.eclipse.daanse.olap.calc.base.nested.AbstractProfilingNestedBooleanCalc; import org.eclipse.daanse.olap.calc.base.nested.AbstractProfilingNestedIntegerCalc; import org.eclipse.daanse.olap.common.InvalidArgumentException; diff --git a/common/src/main/java/org/eclipse/daanse/olap/function/def/vba/nper/NPerCalc.java b/common/src/main/java/org/eclipse/daanse/olap/function/def/vba/nper/NPerCalc.java index c13b825..30bb4f7 100644 --- a/common/src/main/java/org/eclipse/daanse/olap/function/def/vba/nper/NPerCalc.java +++ b/common/src/main/java/org/eclipse/daanse/olap/function/def/vba/nper/NPerCalc.java @@ -13,16 +13,11 @@ */ package org.eclipse.daanse.olap.function.def.vba.nper; -import java.util.Calendar; -import java.util.Date; - import org.eclipse.daanse.olap.api.Evaluator; import org.eclipse.daanse.olap.api.calc.BooleanCalc; -import org.eclipse.daanse.olap.api.calc.DateTimeCalc; import org.eclipse.daanse.olap.api.calc.DoubleCalc; import org.eclipse.daanse.olap.api.type.Type; import org.eclipse.daanse.olap.calc.base.nested.AbstractProfilingNestedDoubleCalc; -import org.eclipse.daanse.olap.calc.base.nested.AbstractProfilingNestedIntegerCalc; public class NPerCalc extends AbstractProfilingNestedDoubleCalc { diff --git a/common/src/main/java/org/eclipse/daanse/olap/function/def/vba/nper/NPerFunDef.java b/common/src/main/java/org/eclipse/daanse/olap/function/def/vba/nper/NPerFunDef.java index a07ac02..17b8e4a 100644 --- a/common/src/main/java/org/eclipse/daanse/olap/function/def/vba/nper/NPerFunDef.java +++ b/common/src/main/java/org/eclipse/daanse/olap/function/def/vba/nper/NPerFunDef.java @@ -17,7 +17,6 @@ import org.eclipse.daanse.olap.api.DataType; import org.eclipse.daanse.olap.api.calc.BooleanCalc; import org.eclipse.daanse.olap.api.calc.Calc; -import org.eclipse.daanse.olap.api.calc.DateTimeCalc; import org.eclipse.daanse.olap.api.calc.DoubleCalc; import org.eclipse.daanse.olap.api.calc.compiler.ExpressionCompiler; import org.eclipse.daanse.olap.api.function.FunctionMetaData; @@ -25,7 +24,6 @@ import org.eclipse.daanse.olap.function.core.FunctionMetaDataR; import org.eclipse.daanse.olap.function.core.FunctionParameterR; import org.eclipse.daanse.olap.function.def.AbstractFunctionDefinition; -import org.eclipse.daanse.olap.function.def.vba.pmt.PmtCalc; public class NPerFunDef extends AbstractFunctionDefinition { diff --git a/common/src/main/java/org/eclipse/daanse/olap/function/def/vba/typename/TypeNameCalc.java b/common/src/main/java/org/eclipse/daanse/olap/function/def/vba/typename/TypeNameCalc.java index d0459fd..ae1d06c 100644 --- a/common/src/main/java/org/eclipse/daanse/olap/function/def/vba/typename/TypeNameCalc.java +++ b/common/src/main/java/org/eclipse/daanse/olap/function/def/vba/typename/TypeNameCalc.java @@ -16,7 +16,6 @@ import org.eclipse.daanse.olap.api.Evaluator; import org.eclipse.daanse.olap.api.calc.Calc; import org.eclipse.daanse.olap.api.type.Type; -import org.eclipse.daanse.olap.calc.base.nested.AbstractProfilingNestedBooleanCalc; import org.eclipse.daanse.olap.calc.base.nested.AbstractProfilingNestedStringCalc; public class TypeNameCalc extends AbstractProfilingNestedStringCalc { diff --git a/common/src/main/java/org/eclipse/daanse/olap/impl/ArrayMap.java b/common/src/main/java/org/eclipse/daanse/olap/impl/ArrayMap.java index 35f07bb..d46bad0 100644 --- a/common/src/main/java/org/eclipse/daanse/olap/impl/ArrayMap.java +++ b/common/src/main/java/org/eclipse/daanse/olap/impl/ArrayMap.java @@ -41,7 +41,6 @@ import java.util.Objects; import java.util.Set; - import org.eclipse.daanse.olap.util.Pair; /** diff --git a/common/src/main/java/org/eclipse/daanse/olap/impl/CellSetAxisImpl.java b/common/src/main/java/org/eclipse/daanse/olap/impl/CellSetAxisImpl.java index 2d3af02..0e860a9 100644 --- a/common/src/main/java/org/eclipse/daanse/olap/impl/CellSetAxisImpl.java +++ b/common/src/main/java/org/eclipse/daanse/olap/impl/CellSetAxisImpl.java @@ -17,6 +17,8 @@ import java.util.List; import java.util.ListIterator; +import org.eclipse.daanse.olap.api.Statement; +import org.eclipse.daanse.olap.api.execution.ExecutionContext; import org.eclipse.daanse.olap.api.query.component.AxisOrdinal; import org.eclipse.daanse.olap.api.query.component.QueryAxis; import org.eclipse.daanse.olap.api.result.Axis; @@ -25,8 +27,8 @@ import org.eclipse.daanse.olap.api.result.CellSetAxisMetaData; import org.eclipse.daanse.olap.api.result.IAxis; import org.eclipse.daanse.olap.api.result.Position; - -import org.eclipse.daanse.olap.server.LocusImpl; +import org.eclipse.daanse.olap.common.ExecuteDurationUtil; +import org.eclipse.daanse.olap.execution.ExecutionImpl; public class CellSetAxisImpl implements CellSetAxis { @@ -77,14 +79,14 @@ public Position get(final int index) { @Override public int size() { - return LocusImpl.execute( - cellSet.getStatement().getConnection(), - "Getting List.size", new LocusImpl.Action() { - @Override - public Integer execute() { - return axis.getTupleList().size(); - } - }); + // Create a new ExecutionImpl for getting size (similar to LocusImpl.execute(connection, ...)) + final Statement statement = cellSet.getStatement().getConnection().getInternalStatement(); + final ExecutionImpl execution = new ExecutionImpl(statement, + ExecuteDurationUtil.executeDurationValue(cellSet.getStatement().getConnection().getContext())); + + return ExecutionContext.where(execution.asContext(), () -> { + return axis.getTupleList().size(); + }); } }; diff --git a/common/src/main/java/org/eclipse/daanse/olap/impl/CellSetImpl.java b/common/src/main/java/org/eclipse/daanse/olap/impl/CellSetImpl.java index 8c469b0..87a0059 100644 --- a/common/src/main/java/org/eclipse/daanse/olap/impl/CellSetImpl.java +++ b/common/src/main/java/org/eclipse/daanse/olap/impl/CellSetImpl.java @@ -29,10 +29,9 @@ import org.eclipse.daanse.olap.api.result.CellSetMetaData; import org.eclipse.daanse.olap.api.result.Result; import org.eclipse.daanse.olap.common.ExecuteDurationUtil; +import org.eclipse.daanse.olap.execution.ExecutionImpl; import org.eclipse.daanse.olap.query.component.QueryAxisImpl; -import org.eclipse.daanse.olap.server.ExecutionImpl; - public class CellSetImpl extends ExecutionImpl implements CellSet { private StatementImpl statement; diff --git a/common/src/main/java/org/eclipse/daanse/olap/impl/StatementImpl.java b/common/src/main/java/org/eclipse/daanse/olap/impl/StatementImpl.java index 8de5aee..4035176 100644 --- a/common/src/main/java/org/eclipse/daanse/olap/impl/StatementImpl.java +++ b/common/src/main/java/org/eclipse/daanse/olap/impl/StatementImpl.java @@ -22,12 +22,13 @@ import org.eclipse.daanse.olap.api.ConfigConstants; import org.eclipse.daanse.olap.api.Context; -import org.eclipse.daanse.olap.api.element.DrillThroughAction; import org.eclipse.daanse.olap.api.Statement; import org.eclipse.daanse.olap.api.calc.ResultStyle; import org.eclipse.daanse.olap.api.connection.Connection; +import org.eclipse.daanse.olap.api.element.DrillThroughAction; import org.eclipse.daanse.olap.api.element.OlapElement; import org.eclipse.daanse.olap.api.exception.OlapRuntimeException; +import org.eclipse.daanse.olap.api.execution.ExecutionContext; import org.eclipse.daanse.olap.api.query.component.DrillThrough; import org.eclipse.daanse.olap.api.query.component.Explain; import org.eclipse.daanse.olap.api.query.component.Query; @@ -35,12 +36,13 @@ import org.eclipse.daanse.olap.api.result.Cell; import org.eclipse.daanse.olap.api.result.CellSet; import org.eclipse.daanse.olap.api.result.Result; -import org.eclipse.daanse.olap.common.QueryCanceledException; -import org.eclipse.daanse.olap.common.QueryTimeoutException; +import org.eclipse.daanse.olap.api.execution.QueryCanceledException; +import org.eclipse.daanse.olap.api.execution.QueryTimeoutException; +import org.eclipse.daanse.olap.common.ExecuteDurationUtil; import org.eclipse.daanse.olap.connection.ConnectionBase; -import org.eclipse.daanse.olap.server.LocusImpl; +import org.eclipse.daanse.olap.execution.ExecutionImpl; -public class StatementImpl extends org.eclipse.daanse.olap.server.StatementImpl implements Statement { +public class StatementImpl extends org.eclipse.daanse.olap.execution.StatementImpl implements Statement { private Connection connection; private boolean closed; @@ -206,23 +208,20 @@ private CellSet executeOlapQueryInternal(Query query) { private Query parseQuery(String mdx) { try { - return LocusImpl.execute( - connection, - "Parsing query", - new LocusImpl.Action() { - @Override - public Query execute() - { - final Query query = - (Query) ((ConnectionBase)connection).parseStatement( - StatementImpl.this, - mdx, - context.getFunctionService(), - false); - return query; - - } - }); + // Create a new ExecutionImpl for parsing (similar to LocusImpl.execute(connection, ...)) + final Statement statement = connection.getInternalStatement(); + final ExecutionImpl execution = new ExecutionImpl(statement, + ExecuteDurationUtil.executeDurationValue(connection.getContext())); + + return ExecutionContext.where(execution.asContext(), () -> { + final Query query = + (Query) ((ConnectionBase)connection).parseStatement( + StatementImpl.this, + mdx, + context.getFunctionService(), + false); + return query; + }); } catch (OlapRuntimeException e) { throw new RuntimeException( "daanse gave exception while parsing query", e); diff --git a/common/src/main/java/org/eclipse/daanse/olap/query/base/MdxToQueryConverter.java b/common/src/main/java/org/eclipse/daanse/olap/query/base/MdxToQueryConverter.java index 22bc42d..e3bf478 100644 --- a/common/src/main/java/org/eclipse/daanse/olap/query/base/MdxToQueryConverter.java +++ b/common/src/main/java/org/eclipse/daanse/olap/query/base/MdxToQueryConverter.java @@ -48,6 +48,9 @@ import org.eclipse.daanse.mdx.model.api.select.CreateSetBodyClause; import org.eclipse.daanse.mdx.model.api.select.MemberPropertyDefinition; import org.eclipse.daanse.mdx.model.api.select.SelectCellPropertyListClause; +import org.eclipse.daanse.mdx.model.api.select.SelectCubeClause; +import org.eclipse.daanse.mdx.model.api.select.SelectCubeClauseName; +import org.eclipse.daanse.mdx.model.api.select.SelectCubeClauseSubStatement; import org.eclipse.daanse.mdx.model.api.select.SelectDimensionPropertyListClause; import org.eclipse.daanse.mdx.model.api.select.SelectQueryAsteriskClause; import org.eclipse.daanse.mdx.model.api.select.SelectQueryAxesClause; @@ -55,9 +58,6 @@ import org.eclipse.daanse.mdx.model.api.select.SelectQueryClause; import org.eclipse.daanse.mdx.model.api.select.SelectQueryEmptyClause; import org.eclipse.daanse.mdx.model.api.select.SelectSlicerAxisClause; -import org.eclipse.daanse.mdx.model.api.select.SelectCubeClause; -import org.eclipse.daanse.mdx.model.api.select.SelectCubeClauseName; -import org.eclipse.daanse.mdx.model.api.select.SelectCubeClauseSubStatement; import org.eclipse.daanse.mdx.model.api.select.SelectWithClause; import org.eclipse.daanse.olap.api.NameSegment; import org.eclipse.daanse.olap.api.Quoting; diff --git a/common/src/main/java/org/eclipse/daanse/olap/query/base/QueryProviderImpl.java b/common/src/main/java/org/eclipse/daanse/olap/query/base/QueryProviderImpl.java index 34a0573..f3e0eb3 100644 --- a/common/src/main/java/org/eclipse/daanse/olap/query/base/QueryProviderImpl.java +++ b/common/src/main/java/org/eclipse/daanse/olap/query/base/QueryProviderImpl.java @@ -14,12 +14,12 @@ package org.eclipse.daanse.olap.query.base; import static org.eclipse.daanse.olap.query.base.MdxToQueryConverter.convertColumns; +import static org.eclipse.daanse.olap.query.base.MdxToQueryConverter.convertCubeClause; import static org.eclipse.daanse.olap.query.base.MdxToQueryConverter.convertFormulaList; import static org.eclipse.daanse.olap.query.base.MdxToQueryConverter.convertName; import static org.eclipse.daanse.olap.query.base.MdxToQueryConverter.convertParameterList; import static org.eclipse.daanse.olap.query.base.MdxToQueryConverter.convertQueryAxis; import static org.eclipse.daanse.olap.query.base.MdxToQueryConverter.convertQueryAxisList; -import static org.eclipse.daanse.olap.query.base.MdxToQueryConverter.convertCubeClause; import static org.eclipse.daanse.olap.query.base.MdxToQueryConverter.getExpressionByCompoundId; import java.util.ArrayList; diff --git a/common/src/main/java/org/eclipse/daanse/olap/query/component/DrillThroughImpl.java b/common/src/main/java/org/eclipse/daanse/olap/query/component/DrillThroughImpl.java index 0a91095..f9c1e83 100644 --- a/common/src/main/java/org/eclipse/daanse/olap/query/component/DrillThroughImpl.java +++ b/common/src/main/java/org/eclipse/daanse/olap/query/component/DrillThroughImpl.java @@ -30,8 +30,8 @@ import java.util.Collections; import java.util.List; -import org.eclipse.daanse.olap.api.DataType; import org.eclipse.daanse.olap.api.CatalogReader; +import org.eclipse.daanse.olap.api.DataType; import org.eclipse.daanse.olap.api.element.OlapElement; import org.eclipse.daanse.olap.api.query.component.DrillThrough; import org.eclipse.daanse.olap.api.query.component.Expression; diff --git a/common/src/main/java/org/eclipse/daanse/olap/query/component/FormulaImpl.java b/common/src/main/java/org/eclipse/daanse/olap/query/component/FormulaImpl.java index 7df28a2..a249348 100644 --- a/common/src/main/java/org/eclipse/daanse/olap/query/component/FormulaImpl.java +++ b/common/src/main/java/org/eclipse/daanse/olap/query/component/FormulaImpl.java @@ -60,10 +60,10 @@ import org.eclipse.daanse.olap.api.type.NumericType; import org.eclipse.daanse.olap.api.type.Type; import org.eclipse.daanse.olap.common.AbstractQueryPart; -import org.eclipse.daanse.olap.element.SetBase; import org.eclipse.daanse.olap.common.StandardProperty; import org.eclipse.daanse.olap.common.Util; import org.eclipse.daanse.olap.element.OlapMetaData; +import org.eclipse.daanse.olap.element.SetBase; import org.eclipse.daanse.olap.exceptions.MdxMemberExpIsSetException; import org.eclipse.daanse.olap.util.type.TypeUtil; diff --git a/common/src/main/java/org/eclipse/daanse/olap/query/component/MemberExpressionImpl.java b/common/src/main/java/org/eclipse/daanse/olap/query/component/MemberExpressionImpl.java index fcdf5d7..5827d8e 100644 --- a/common/src/main/java/org/eclipse/daanse/olap/query/component/MemberExpressionImpl.java +++ b/common/src/main/java/org/eclipse/daanse/olap/query/component/MemberExpressionImpl.java @@ -27,7 +27,6 @@ import org.eclipse.daanse.olap.api.DataType; import org.eclipse.daanse.olap.api.Validator; -import org.eclipse.daanse.olap.api.calc.Calc; import org.eclipse.daanse.olap.api.calc.MemberCalc; import org.eclipse.daanse.olap.api.calc.compiler.ExpressionCompiler; import org.eclipse.daanse.olap.api.element.Member; diff --git a/common/src/main/java/org/eclipse/daanse/olap/query/component/ParameterExpressionImpl.java b/common/src/main/java/org/eclipse/daanse/olap/query/component/ParameterExpressionImpl.java index 7719de0..5dc5b13 100644 --- a/common/src/main/java/org/eclipse/daanse/olap/query/component/ParameterExpressionImpl.java +++ b/common/src/main/java/org/eclipse/daanse/olap/query/component/ParameterExpressionImpl.java @@ -28,9 +28,9 @@ import java.io.PrintWriter; import java.util.List; +import org.eclipse.daanse.olap.api.CatalogReader; import org.eclipse.daanse.olap.api.DataType; import org.eclipse.daanse.olap.api.Parameter; -import org.eclipse.daanse.olap.api.CatalogReader; import org.eclipse.daanse.olap.api.Validator; import org.eclipse.daanse.olap.api.calc.Calc; import org.eclipse.daanse.olap.api.calc.compiler.CompilableParameter; diff --git a/common/src/main/java/org/eclipse/daanse/olap/query/component/QueryImpl.java b/common/src/main/java/org/eclipse/daanse/olap/query/component/QueryImpl.java index 3970e95..411da4b 100644 --- a/common/src/main/java/org/eclipse/daanse/olap/query/component/QueryImpl.java +++ b/common/src/main/java/org/eclipse/daanse/olap/query/component/QueryImpl.java @@ -78,6 +78,7 @@ import org.eclipse.daanse.olap.api.element.NamedSet; import org.eclipse.daanse.olap.api.element.OlapElement; import org.eclipse.daanse.olap.api.exception.OlapRuntimeException; +import org.eclipse.daanse.olap.api.execution.ExecutionContext; import org.eclipse.daanse.olap.api.function.FunctionDefinition; import org.eclipse.daanse.olap.api.function.FunctionService; import org.eclipse.daanse.olap.api.query.component.AxisOrdinal; @@ -119,10 +120,9 @@ import org.eclipse.daanse.olap.exceptions.MdxAxisShowSubtotalsNotSupportedException; import org.eclipse.daanse.olap.exceptions.ParameterIsNotModifiableException; import org.eclipse.daanse.olap.exceptions.UnknownParameterException; +import org.eclipse.daanse.olap.execution.ExecutionImpl; import org.eclipse.daanse.olap.function.def.parameter.ParameterFunDef; import org.eclipse.daanse.olap.impl.IdentifierParser; -import org.eclipse.daanse.olap.server.ExecutionImpl; -import org.eclipse.daanse.olap.server.LocusImpl; import org.eclipse.daanse.olap.util.ArrayStack; import org.eclipse.daanse.olap.util.type.TypeUtil; @@ -964,18 +964,11 @@ public void setParameter(final String parameterName, final Object value) { throw new ParameterIsNotModifiableException( parameterName, param.getScope().name()); } - final Object value2 = - LocusImpl.execute( - new ExecutionImpl(statement, ExecuteDurationUtil.executeDurationValue(getConnection().getContext())), - "Query.quickParse", - new LocusImpl.Action() { - @Override - public Object execute() { - return quickParse( - parameterName, param.getType(), value, QueryImpl.this); - } - } - ); + final ExecutionImpl execution = new ExecutionImpl(statement, + ExecuteDurationUtil.executeDurationValue(getConnection().getContext())); + final Object value2 = ExecutionContext.where(execution.asContext(), () -> { + return quickParse(parameterName, param.getType(), value, QueryImpl.this); + }); param.setValue(value2); } diff --git a/common/src/main/java/org/eclipse/daanse/olap/server/ExecutionImpl.java b/common/src/main/java/org/eclipse/daanse/olap/server/ExecutionImpl.java deleted file mode 100644 index d41fc0d..0000000 --- a/common/src/main/java/org/eclipse/daanse/olap/server/ExecutionImpl.java +++ /dev/null @@ -1,489 +0,0 @@ -/* - * This software is subject to the terms of the Eclipse Public License v1.0 - * Agreement, available at the following URL: - * http://www.eclipse.org/legal/epl-v10.html. - * You must accept the terms of that agreement to use this software. - * - * Copyright (C) 2002-2005 Julian Hyde - * Copyright (C) 2005-2021 Hitachi Vantara and others - * All Rights Reserved. - * - * ---- All changes after Fork in 2023 ------------------------ - * - * Project: Eclipse daanse - * - * Copyright (c) 2023 Contributors to the Eclipse Foundation. - * - * This program and the accompanying materials are made - * available under the terms of the Eclipse Public License 2.0 - * which is available at https://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors after Fork in 2023: - * SmartCity Jena - initial - */ - -package org.eclipse.daanse.olap.server; - -import java.time.Duration; -import java.time.Instant; -import java.time.LocalDateTime; -import java.util.HashMap; -import java.util.Iterator; -import java.util.Map; -import java.util.Map.Entry; -import java.util.Optional; -import java.util.concurrent.atomic.AtomicLong; - -import org.eclipse.daanse.olap.api.CacheCommand; -import org.eclipse.daanse.olap.api.Context; -import org.eclipse.daanse.olap.api.Execution; -import org.eclipse.daanse.olap.api.ISegmentCacheManager; -import org.eclipse.daanse.olap.api.Locus; -import org.eclipse.daanse.olap.api.QueryTiming; -import org.eclipse.daanse.olap.api.Statement; -import org.eclipse.daanse.olap.api.connection.Connection; -import org.eclipse.daanse.olap.api.exception.OlapRuntimeException; -import org.eclipse.daanse.olap.api.monitor.event.ConnectionEventCommon; -import org.eclipse.daanse.olap.api.monitor.event.EventCommon; -import org.eclipse.daanse.olap.api.monitor.event.ExecutionEndEvent; -import org.eclipse.daanse.olap.api.monitor.event.ExecutionEventCommon; -import org.eclipse.daanse.olap.api.monitor.event.ExecutionPhaseEvent; -import org.eclipse.daanse.olap.api.monitor.event.ExecutionStartEvent; -import org.eclipse.daanse.olap.api.monitor.event.MdxStatementEventCommon; -import org.eclipse.daanse.olap.api.monitor.event.ServertEventCommon; -import org.eclipse.daanse.olap.api.query.component.Query; -import org.eclipse.daanse.olap.common.MemoryLimitExceededException; -import org.eclipse.daanse.olap.common.QueryCanceledException; -import org.eclipse.daanse.olap.common.QueryTimingImpl; -import org.eclipse.daanse.olap.common.Util; -import org.eclipse.daanse.olap.core.AbstractBasicContext; - - -/** - * Execution context. - * - * - * Loosely corresponds to a CellSet. A given statement may be executed several times over its lifetime, but at most one - * execution can be going on at a time. - * - * - * @author jhyde - */ -public class ExecutionImpl implements Execution{ - /** - * Used for MDX logging, allows for a MDX Statement UID. - */ - private static final AtomicLong SEQ = new AtomicLong(); - - private final StatementImpl statement; - - /** - * Holds a collection of the SqlStatements which were used by this execution instance. All operations on the map must - * be synchronized on it. - */ - private final Map statements = new HashMap<>(); - - private State state = State.FRESH; - - /** - * Lock monitor for SQL statements. All operations on {@link ExecutionImpl#statements} need to be synchronized on this. - */ - private final Object sqlStateLock = new Object(); - - /** - * This is a lock object to sync on when changing the {@link #state} variable. - */ - private final Object stateLock = new Object(); - - /** - * If not null, this query was notified that it might cause an OutOfMemoryError. - */ - private String outOfMemoryMsg; - - private LocalDateTime startTime; - private Optional duration; - private final QueryTimingImpl queryTiming = new QueryTimingImpl(); - private int phase; - private int cellCacheHitCount; - private int cellCacheMissCount; - private int cellCachePendingCount; - private int expCacheHitCount; - private int expCacheMissCount; - - /** - * Execution id, global within this JVM instance. - */ - private final long id; - - public static final ExecutionImpl NONE = new ExecutionImpl( null, Optional.empty() ); - - - private final Execution parent; - - public ExecutionImpl(Statement statement, Optional duration ) { - Execution parentExec = null; - if ( !LocusImpl.isEmpty() ) { - parentExec = LocusImpl.peek().getExecution(); - } - this.parent = parentExec; - this.id = SEQ.getAndIncrement(); - this.statement = (StatementImpl) statement; - this.duration = duration; - } - - - - /** - * Marks the start of an Execution instance. It is called by {@link Statement#start(ExecutionImpl)} automatically. Users - * don't need to call this method. - */ - public void start() { - assert this.state == State.FRESH; - this.startTime = LocalDateTime.now(); - this.state = State.RUNNING; - this.queryTiming.init( this.statement.getProfileHandler() != null ); - fireExecutionStartEvent(); - } - - private String getMdx() { - final Query query = statement.query; - return query != null ? Util.unparse( query ) : null; - } - - public void tracePhase( int hitCount, int missCount, int pendingCount ) { - final Connection connection = statement.getDaanseConnection(); - final Context context = connection.getContext(); - final int hitCountInc = hitCount - this.cellCacheHitCount; - final int missCountInc = missCount - this.cellCacheMissCount; - final int pendingCountInc = pendingCount - this.cellCachePendingCount; - ExecutionPhaseEvent executionPhaseEvent=new ExecutionPhaseEvent(new ExecutionEventCommon( - new MdxStatementEventCommon( - new ConnectionEventCommon( - new ServertEventCommon( - EventCommon.ofNow(), context.getName()),connection - .getId()), statement.getId()), id), phase, hitCountInc, missCountInc, pendingCountInc); - - context.getMonitor().accept(executionPhaseEvent); -// new ExecutionPhaseEvent( System.currentTimeMillis(), context.getName(), connection -// .getId(), statement.getId(), id, phase, hitCountInc, missCountInc, pendingCountInc ) - ++phase; - this.cellCacheHitCount = hitCount; - this.cellCacheMissCount = missCount; - this.cellCachePendingCount = pendingCount; - } - - /** - * Cancels the execution instance. - */ - public void cancel() { - synchronized ( stateLock ) { - this.state = State.CANCELED; - this.cancelSqlStatements(); - if ( parent != null ) { - //parent.cancel(); - } - fireExecutionEndEvent(); - } - } - - /** - * This method will change the state of this execution to {@link State#ERROR} and will set the message to display. - * Cleanup of the resources used by this execution instance will be performed in the background later on. - * - * @param msg - * The message to display to the user, describing the problem encountered with the memory space. - */ - public final void setOutOfMemory( String msg ) { - synchronized ( stateLock ) { - assert msg != null; - this.outOfMemoryMsg = msg; - this.state = State.ERROR; - } - } - - /** - * Checks the state of this Execution and throws an exception if something is wrong. This method should be called by - * the user thread. - * - * It won't throw anything if the query has successfully completed. - * - * @throws OlapRuntimeException - * The exception encountered. - */ - public synchronized void checkCancelOrTimeout() throws OlapRuntimeException { - if ( parent != null ) { - parent.checkCancelOrTimeout(); - } - boolean needInterrupt = false; - switch ( this.state ) { - case CANCELED: - try { - if ( Thread.interrupted() ) { - // Checking the state of the thread will clear the - // interrupted flag so we can send an event out. - // After that, we make sure that we set it again - // so the thread state remains consistent. - needInterrupt = true; - } - fireExecutionEndEvent(); - } finally { - if ( needInterrupt ) { - Thread.currentThread().interrupt(); - } - } - throw new QueryCanceledException(); - case RUNNING: - case TIMEOUT: - if ( duration.isPresent() ) { - long currTime = System.currentTimeMillis(); -// if ( currTime > timeoutTimeMillis ) { -// this.state = State.TIMEOUT; -// fireExecutionEndEvent(); -// throw new InvalidArgumentException(MessageFormat.format(QueryTimeout, timeoutIntervalMillis / 1000 )); -// } - } - break; - case ERROR: - try { - if ( Thread.interrupted() ) { - // Checking the state of the thread will clear the - // interrupted flag so we can send an event out. - // After that, we make sure that we set it again - // so the thread state remains consistent. - needInterrupt = true; - } - fireExecutionEndEvent(); - } finally { - if ( needInterrupt ) { - Thread.currentThread().interrupt(); - } - } - throw new MemoryLimitExceededException( outOfMemoryMsg ); - } - } - - /** - * Returns whether this execution is currently in a failed state and will throw an exception as soon as the next check - * is performed using {@link ExecutionImpl#checkCancelOrTimeout()}. - * - * @return True or false, depending on the timeout state. - */ - public boolean isCancelOrTimeout() { - if ( parent != null && parent.isCancelOrTimeout() ) { - return true; - } - synchronized ( stateLock ) { - if ( state == State.CANCELED || state == State.ERROR || state == State.TIMEOUT || ( state == State.RUNNING - && duration.isPresent() && Duration.between(LocalDateTime.now(), startTime).compareTo(duration.get()) > 0 ) ) { - return true; - } - return false; - } - } - - /** - * Tells whether this execution is done executing. - */ - public boolean isDone() { - synchronized ( stateLock ) { - switch ( this.state ) { - case CANCELED: - case DONE: - case ERROR: - case TIMEOUT: - return true; - default: - return false; - } - } - } - - /** - * Called by the RolapResultShepherd when the execution needs to clean all of its resources for whatever reasons, - * typically when an exception has occurred or the execution has ended. Any currently running SQL statements will be - * canceled. It should only be called if {@link ExecutionImpl#isCancelOrTimeout()} returns true. - * - * - * This method doesn't need to be called by a user. It will be called internally by Mondrian when the system is ready - * to clean the remaining resources. - * - * - * To check if this execution is failed, use {@link ExecutionImpl#isCancelOrTimeout()} instead. - */ - public void cancelSqlStatements() { - if ( parent != null ) { - parent.cancelSqlStatements(); - } - synchronized ( sqlStateLock ) { - for ( Iterator> iterator = statements.entrySet().iterator(); iterator - .hasNext(); ) { - // Remove entry from the map before trying to cancel the - // statement, so that if the cancel throws, we will not try to - // cancel again. It's possible that we will try to cancel the - // other statements later. - final Entry entry = iterator.next(); - final java.sql.Statement statement1 = entry.getValue(); - iterator.remove(); - // We only want to cancel the statement, but we can't close it. - // Some drivers will not notice the interruption flag on their - // own thread before a considerable time has passed. If we were - // using a pooling layer, calling close() would make the - // underlying connection available again, despite the first - // statement still being processed. Some drivers will fail - // there. It is therefore important to close and release the - // resources on the proper thread, namely, the thread which - // runs the actual statement. - Util.cancelStatement( statement1 ); - } - // Also cleanup the segment registrations from the index. - unregisterSegmentRequests(); - } - } - - /** - * Called when query execution has completed. Once query execution has ended, it is not possible to cancel or timeout - * the query until it starts executing again. - */ - public void end() { - synchronized ( stateLock ) { - queryTiming.done(); - if ( this.state == State.FRESH || this.state == State.RUNNING ) { - this.state = State.DONE; - } - // Clear pointer to pending SQL statements - statements.clear(); - // Unregister all segments - unregisterSegmentRequests(); - // Fire up a monitor event. - fireExecutionEndEvent(); - } - } - - /** - * Calls into the SegmentCacheManager and unregisters all the registrations made for this execution on segments form - * the index. - */ - public void unregisterSegmentRequests() { - // We also have to cancel all requests for the current segments. - final LocusImpl locus = new LocusImpl( this, "Execution.unregisterSegmentRequests", "cleaning up segment registrations" ); - AbstractBasicContext abc = (AbstractBasicContext) locus.getContext(); - final ISegmentCacheManager mgr = abc.getAggregationManager().getCacheMgr(null); - mgr.execute( new CacheCommand() { - @Override - public Void call() throws Exception { - mgr.getIndexRegistry().cancelExecutionSegments( ExecutionImpl.this ); - return null; - } - - @Override - public Locus getLocus() { - return locus; - } - } ); - } - - public final LocalDateTime getStartTime() { - return startTime; - } - - public Statement getDaanseStatement() { - return statement; - } - - public final QueryTiming getQueryTiming() { - return queryTiming; - } - - public final long getId() { - return id; - } - - public final Duration getElapsedMillis() { - return Duration.between(LocalDateTime.now(), startTime); - } - - /** - * This method is typically called by SqlStatement at construction time. It ties all Statement objects to a particular - * Execution instance so that we can audit, monitor and gracefully cancel an execution. - * - * @param statement - * The statement used by this execution. - */ - public void registerStatement( Locus locus, java.sql.Statement statement ) { - synchronized ( sqlStateLock ) { - synchronized ( stateLock ) { - if ( state == State.FRESH ) { - start(); - } - if ( state == State.RUNNING ) { - this.statements.put( locus, statement ); - } - } - } - } - - private void fireExecutionEndEvent() { - final Connection connection = statement.getDaanseConnection(); - final Context context = connection.getContext(); - - ExecutionEndEvent endEvent = new ExecutionEndEvent( - new ExecutionEventCommon( - - new MdxStatementEventCommon( - new ConnectionEventCommon( - new ServertEventCommon( - new EventCommon(Instant.ofEpochMilli( Duration.between(LocalDateTime.now(), this.startTime).toMillis())), context.getName()), connection.getId()), - this.statement.getId()), this.id), - phase, state, cellCacheHitCount, cellCacheMissCount, cellCachePendingCount, expCacheHitCount, - expCacheMissCount); - context.getMonitor().accept(endEvent); -// new ExecutionEndEvent( , context.getName(), connection.getId(), -// , this.id, this.phase, this.state, this.cellCacheHitCount, this.cellCacheMissCount, -// this.cellCachePendingCount, expCacheHitCount, expCacheMissCount ) - } - - private void fireExecutionStartEvent() { - final Connection connection = statement.getDaanseConnection(); - final Context context = connection.getContext(); - - - ExecutionStartEvent executionStartEvent = new ExecutionStartEvent(new ExecutionEventCommon( - - new MdxStatementEventCommon(new ConnectionEventCommon( - new ServertEventCommon(new EventCommon(Instant.ofEpochMilli( Duration.between(LocalDateTime.now(), this.startTime).toMillis())), context.getName()), connection.getId()), - statement.getId()), - id), getMdx()); - context.getMonitor().accept(executionStartEvent); -// new ExecutionStartEvent( startTimeMillis, context.getName(), connection.getId(), -// statement.getId(), id, getMdx() ) - } - - public void setCellCacheHitCount( int cellCacheHitCount ) { - this.cellCacheHitCount = cellCacheHitCount; - } - - public void setCellCacheMissCount( int cellCacheMissCount ) { - this.cellCacheMissCount = cellCacheMissCount; - } - - public void setCellCachePendingCount( int cellCachePendingCount ) { - this.cellCachePendingCount = cellCachePendingCount; - } - - public void setExpCacheCounts( int hitCount, int missCount ) { - this.expCacheHitCount = hitCount; - this.expCacheMissCount = missCount; - } - - - - public int getExpCacheHitCount() { - return expCacheHitCount; - } - - public int getExpCacheMissCount() { - return expCacheMissCount; - } -} diff --git a/common/src/main/java/org/eclipse/daanse/olap/server/LocusImpl.java b/common/src/main/java/org/eclipse/daanse/olap/server/LocusImpl.java deleted file mode 100644 index c8dde9e..0000000 --- a/common/src/main/java/org/eclipse/daanse/olap/server/LocusImpl.java +++ /dev/null @@ -1,136 +0,0 @@ -/* - * This software is subject to the terms of the Eclipse Public License v1.0 - * Agreement, available at the following URL: - * http://www.eclipse.org/legal/epl-v10.html. - * You must accept the terms of that agreement to use this software. - * - * Copyright (c) 2002-2020 Hitachi Vantara.. All rights reserved. - * - * ---- All changes after Fork in 2023 ------------------------ - * - * Project: Eclipse daanse - * - * Copyright (c) 2023 Contributors to the Eclipse Foundation. - * - * This program and the accompanying materials are made - * available under the terms of the Eclipse Public License 2.0 - * which is available at https://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors after Fork in 2023: - * SmartCity Jena - initial - */ - -package org.eclipse.daanse.olap.server; - -import org.eclipse.daanse.olap.api.Context; -import org.eclipse.daanse.olap.api.Execution; -import org.eclipse.daanse.olap.api.Locus; -import org.eclipse.daanse.olap.api.Statement; -import org.eclipse.daanse.olap.api.connection.Connection; -import org.eclipse.daanse.olap.common.ExecuteDurationUtil; - -import org.eclipse.daanse.olap.util.ArrayStack; - -//TODO: https://docs.oracle.com/en/java/javase/21/docs/api/java.base/java/lang/ScopedValue.html -//TODO: https://openjdk.org/jeps/462 -/** - * Point of execution from which a service is invoked. - */ -public class LocusImpl implements Locus { - private final Execution execution; - public final String message; - public final String component; - - private static final ThreadLocal> THREAD_LOCAL = - ThreadLocal.withInitial(ArrayStack::new); - - /** - * Creates a Locus. - * - * @param execution Execution context - * @param component Description of a the component executing the query, - * generally a method name, e.g. "SqlTupleReader.readTuples" - * @param message Description of the purpose of this statement, to be - * printed if there is an error - */ - public LocusImpl( - Execution execution, - String component, - String message) - { - if (execution == null) { - throw new IllegalArgumentException("execution should not be null"); - } - - this.execution = execution; - this.component = component; - this.message = message; - } - - public static void pop(Locus locus) { - final Locus pop = THREAD_LOCAL.get().pop(); - if (locus != pop) { - throw new IllegalArgumentException("locus should be equals pop"); - } - } - - public static void push(Locus locus) { - THREAD_LOCAL.get().push(locus); - } - - public static Locus peek() { - return THREAD_LOCAL.get().peek(); - } - - public static boolean isEmpty() { - return THREAD_LOCAL.get().isEmpty(); - } - - public static T execute( - Connection connection, - String component, - Action action) - { - final Statement statement = connection.getInternalStatement(); - final ExecutionImpl execution = new ExecutionImpl(statement, - ExecuteDurationUtil.executeDurationValue(connection.getContext())); - return execute(execution, component, action); - } - - public static void remove() { - THREAD_LOCAL.remove(); - } - - public static T execute( - Execution execution, - String component, - Action action) - { - final Locus locus = - new LocusImpl( - execution, - component, - null); - LocusImpl.push(locus); - try { - return action.execute(); - } finally { - LocusImpl.pop(locus); - } - } - - public final Context getContext() { - return getExecution().getDaanseStatement().getDaanseConnection().getContext(); - } - - @Override - public Execution getExecution() { - return execution; - } - - public interface Action { - T execute(); - } -} diff --git a/common/src/main/java/org/eclipse/daanse/olap/server/package-info.java b/common/src/main/java/org/eclipse/daanse/olap/server/package-info.java deleted file mode 100644 index 4b0220d..0000000 --- a/common/src/main/java/org/eclipse/daanse/olap/server/package-info.java +++ /dev/null @@ -1,17 +0,0 @@ -/* -* Copyright (c) 2023 Contributors to the Eclipse Foundation. -* -* This program and the accompanying materials are made -* available under the terms of the Eclipse Public License 2.0 -* which is available at https://www.eclipse.org/legal/epl-2.0/ -* -* SPDX-License-Identifier: EPL-2.0 -* -* Contributors: -* SmartCity Jena - initial -* Stefan Bischof (bipolis.org) - initial -*/ -//TODO: RM EXPORT -@org.osgi.annotation.bundle.Export -@org.osgi.annotation.versioning.Version("0.0.1") -package org.eclipse.daanse.olap.server; \ No newline at end of file diff --git a/common/src/main/java/org/eclipse/daanse/olap/server/package.html b/common/src/main/java/org/eclipse/daanse/olap/server/package.html deleted file mode 100644 index 396ddd5..0000000 --- a/common/src/main/java/org/eclipse/daanse/olap/server/package.html +++ /dev/null @@ -1,13 +0,0 @@ - - - - title - - -Augments the Mondrian engine with server functionality. - -Whereas the embedded engine is configured, started and managed by -the container, a server has its own services such as repository, -authentication, management of sessions and statements. - - diff --git a/common/src/main/java/org/eclipse/daanse/olap/util/CancellationChecker.java b/common/src/main/java/org/eclipse/daanse/olap/util/CancellationChecker.java index 906f096..4edc3c1 100644 --- a/common/src/main/java/org/eclipse/daanse/olap/util/CancellationChecker.java +++ b/common/src/main/java/org/eclipse/daanse/olap/util/CancellationChecker.java @@ -27,7 +27,7 @@ package org.eclipse.daanse.olap.util; import org.eclipse.daanse.olap.api.ConfigConstants; -import org.eclipse.daanse.olap.api.Execution; +import org.eclipse.daanse.olap.api.execution.Execution; /** * Encapsulates cancel and timeouts checks diff --git a/common/src/main/java/org/eclipse/daanse/olap/util/IdentifierParser.java b/common/src/main/java/org/eclipse/daanse/olap/util/IdentifierParser.java index b3a911e..069c2e3 100644 --- a/common/src/main/java/org/eclipse/daanse/olap/util/IdentifierParser.java +++ b/common/src/main/java/org/eclipse/daanse/olap/util/IdentifierParser.java @@ -39,9 +39,9 @@ import java.util.Collections; import java.util.List; -import org.eclipse.daanse.olap.api.DataType; import org.eclipse.daanse.olap.api.CatalogReader; import org.eclipse.daanse.olap.api.ConfigConstants; +import org.eclipse.daanse.olap.api.DataType; import org.eclipse.daanse.olap.api.Segment; import org.eclipse.daanse.olap.api.calc.todo.TupleList; import org.eclipse.daanse.olap.api.element.Cube; diff --git a/common/src/main/java/org/eclipse/daanse/olap/util/UtilCompatibleJdk16.java b/common/src/main/java/org/eclipse/daanse/olap/util/UtilCompatibleJdk16.java index de691ac..9d39a00 100644 --- a/common/src/main/java/org/eclipse/daanse/olap/util/UtilCompatibleJdk16.java +++ b/common/src/main/java/org/eclipse/daanse/olap/util/UtilCompatibleJdk16.java @@ -50,7 +50,7 @@ public class UtilCompatibleJdk16 implements UtilCompatible { private static final Logger LOGGER = LoggerFactory.getLogger(Util.class); private final static String executionStatementCleanupException = - "An exception was encountered while trying to cleanup an execution context. A statement failed to cancel gracefully. Locus was : \"{0}\"."; + "An exception was encountered while trying to cleanup an execution context. A statement failed to cancel gracefully. ExecutionContext was : \"{0}\"."; @Override public void cancelStatement(Statement stmt) { diff --git a/common/src/test/java/org/eclipse/daanse/olap/fun/sort/SorterTest.java b/common/src/test/java/org/eclipse/daanse/olap/fun/sort/SorterTest.java index 45fde13..6ce09e2 100644 --- a/common/src/test/java/org/eclipse/daanse/olap/fun/sort/SorterTest.java +++ b/common/src/test/java/org/eclipse/daanse/olap/fun/sort/SorterTest.java @@ -54,7 +54,7 @@ import org.eclipse.daanse.olap.connection.ConnectionBase; import org.eclipse.daanse.olap.function.def.member.memberorderkey.MemberOrderKeyCalc; import org.eclipse.daanse.olap.query.component.QueryImpl; -import org.eclipse.daanse.olap.server.ExecutionImpl; +import org.eclipse.daanse.olap.execution.ExecutionImpl; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; diff --git a/common/src/test/java/org/eclipse/daanse/olap/function/def/crossjoin/CrossJoinTest.java b/common/src/test/java/org/eclipse/daanse/olap/function/def/crossjoin/CrossJoinTest.java index 9ef6f19..5a4c19b 100644 --- a/common/src/test/java/org/eclipse/daanse/olap/function/def/crossjoin/CrossJoinTest.java +++ b/common/src/test/java/org/eclipse/daanse/olap/function/def/crossjoin/CrossJoinTest.java @@ -63,8 +63,8 @@ import org.eclipse.daanse.olap.common.SystemWideProperties; import org.eclipse.daanse.olap.function.core.FunctionParameterR; import org.eclipse.daanse.olap.query.component.ResolvedFunCallImpl; -import org.eclipse.daanse.olap.server.ExecutionImpl; -import org.eclipse.daanse.olap.server.LocusImpl; +import org.eclipse.daanse.olap.api.execution.ExecutionContext; +import org.eclipse.daanse.olap.execution.ExecutionImpl; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -137,9 +137,10 @@ void testListTupleListTupleIterCalc() { when(rolapConnection.getContext()).thenReturn(context); when(statement.getDaanseConnection()).thenReturn(rolapConnection); when(excMock.getDaanseStatement()).thenReturn(statement); + ExecutionContext executionContext = mock(ExecutionContext.class); + when(excMock.asContext()).thenReturn(executionContext); CrossJoinIterCalc calc = new CrossJoinIterCalc( getResolvedFunCall(), null, crossJoinFunDef.getCtag() ); - doTupleTupleIterTest( calc, excMock ); } @@ -155,14 +156,10 @@ private void doTupleTupleIterTest( String e3 = "{[k, l], [m, n]}"; assertEquals( e3, s3 ); - String s = LocusImpl.execute( - execution, "CrossJoinTest", new LocusImpl.Action() { - @Override - public String execute() { - TupleIterable iterable = calc.makeIterable( l4, l3 ); - return CrossJoinTest.this.toString( iterable ); - } - } ); + String s = ExecutionContext.where(execution.asContext(), () -> { + TupleIterable iterable = calc.makeIterable( l4, l3 ); + return CrossJoinTest.this.toString( iterable ); + }); String e = "{[U, V, k, l], [U, V, m, n], [W, X, k, l], " + "[W, X, m, n], [Y, Z, k, l], [Y, Z, m, n]}"; @@ -181,22 +178,18 @@ private static TupleList getGenderMembers( Result genders ) { private Integer crossJoinIterCalcIterate( final TupleList list1, final TupleList list2, final ExecutionImpl execution ) { - return LocusImpl.execute( - execution, "CrossJoinTest", new LocusImpl.Action() { - @Override - public Integer execute() { - TupleIterable iterable = - new CrossJoinIterCalc( - getResolvedFunCall(), null, crossJoinFunDef.getCtag() ).makeIterable( list1, list2 ); - TupleCursor tupleCursor = iterable.tupleCursor(); - // total count of all iterations - int counter = 0; - while ( tupleCursor.forward() ) { - counter++; - } - return Integer.valueOf( counter ); - } - } ); + return ExecutionContext.where(execution.asContext(), () -> { + TupleIterable iterable = + new CrossJoinIterCalc( + getResolvedFunCall(), null, crossJoinFunDef.getCtag() ).makeIterable( list1, list2 ); + TupleCursor tupleCursor = iterable.tupleCursor(); + // total count of all iterations + int counter = 0; + while ( tupleCursor.forward() ) { + counter++; + } + return Integer.valueOf( counter ); + }); } //////////////////////////////////////////////////////////////////////// diff --git a/common/src/test/java/org/eclipse/daanse/olap/util/CancellationCheckerTest.java b/common/src/test/java/org/eclipse/daanse/olap/util/CancellationCheckerTest.java index ab89142..8c9ee4d 100644 --- a/common/src/test/java/org/eclipse/daanse/olap/util/CancellationCheckerTest.java +++ b/common/src/test/java/org/eclipse/daanse/olap/util/CancellationCheckerTest.java @@ -34,7 +34,7 @@ import org.eclipse.daanse.olap.api.Statement; import org.eclipse.daanse.olap.api.connection.Connection; import org.eclipse.daanse.olap.common.SystemWideProperties; -import org.eclipse.daanse.olap.server.ExecutionImpl; +import org.eclipse.daanse.olap.execution.ExecutionImpl; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.Test; diff --git a/common/test.bndrun b/common/test.bndrun index fa4053b..c847d18 100644 --- a/common/test.bndrun +++ b/common/test.bndrun @@ -43,7 +43,7 @@ -runfw: org.apache.felix.framework --runee: JavaSE-21 +-runee: JavaSE-25 -runrequires: \ bnd.identity;id='${project.artifactId}-tests',\ @@ -53,14 +53,14 @@ -runbundles: \ assertj-core;version='[3.26.0,3.26.1)',\ com.github.ben-manes.caffeine;version='[3.1.2,3.1.3)',\ - junit-jupiter-api;version='[5.10.2,5.10.3)',\ - junit-jupiter-engine;version='[5.10.2,5.10.3)',\ - junit-jupiter-params;version='[5.10.2,5.10.3)',\ - junit-platform-commons;version='[1.10.2,1.10.3)',\ - junit-platform-engine;version='[1.10.2,1.10.3)',\ - junit-platform-launcher;version='[1.10.2,1.10.3)',\ - net.bytebuddy.byte-buddy;version='[1.14.16,1.14.17)',\ - net.bytebuddy.byte-buddy-agent;version='[1.14.11,1.14.12)',\ + junit-jupiter-api;version='[5.12.2,5.12.3)',\ + junit-jupiter-engine;version='[5.12.2,5.12.3)',\ + junit-jupiter-params;version='[5.12.2,5.12.3)',\ + junit-platform-commons;version='[1.12.2,1.12.3)',\ + junit-platform-engine;version='[1.12.2,1.12.3)',\ + junit-platform-launcher;version='[1.12.2,1.12.3)',\ + net.bytebuddy.byte-buddy;version='[1.17.5,1.17.6)',\ + net.bytebuddy.byte-buddy-agent;version='[1.17.5,1.17.6)',\ org.apache.felix.scr;version='[2.2.10,2.2.11)',\ org.eclipse.daanse.jdbc.db.dialect.api;version='[0.0.1,0.0.2)',\ org.eclipse.daanse.mdx.model.api;version='[0.0.1,0.0.2)',\ @@ -69,8 +69,8 @@ org.eclipse.daanse.olap.common;version='[0.0.1,0.0.2)',\ org.eclipse.daanse.olap.common-tests;version='[0.0.1,0.0.2)',\ org.eclipse.daanse.sql.guard.api;version='[0.0.1,0.0.2)',\ - org.mockito.junit-jupiter;version='[5.10.0,5.10.1)',\ - org.mockito.mockito-core;version='[5.10.0,5.10.1)',\ + org.mockito.junit-jupiter;version='[5.18.0,5.18.1)',\ + org.mockito.mockito-core;version='[5.18.0,5.18.1)',\ org.objenesis;version='[3.3.0,3.3.1)',\ org.opentest4j;version='[1.3.0,1.3.1)',\ org.osgi.service.component;version='[1.5.1,1.5.2)',\ diff --git a/format/src/test/java/org/eclipse/daanse/olap/format/FormatterCreateContextTest.java b/format/src/test/java/org/eclipse/daanse/olap/format/FormatterCreateContextTest.java index 76c2db7..36fcb8a 100644 --- a/format/src/test/java/org/eclipse/daanse/olap/format/FormatterCreateContextTest.java +++ b/format/src/test/java/org/eclipse/daanse/olap/format/FormatterCreateContextTest.java @@ -23,7 +23,6 @@ import static org.assertj.core.api.Assertions.assertThat; - import org.junit.jupiter.api.Test; class FormatterCreateContextTest { diff --git a/pom.xml b/pom.xml index cccc029..f75d28a 100644 --- a/pom.xml +++ b/pom.xml @@ -19,39 +19,25 @@ org.eclipse.daanse org.eclipse.daanse.pom.parent - 0.0.4 + 0.0.5-SNAPSHOT org.eclipse.daanse.olap ${revision} pom Eclipse Daanse OLAP Processing Engine - Comprehensive OLAP (Online Analytical Processing) engine providing multidimensional data processing, cube operations, advanced query execution, intelligent caching, and aggregation management. Includes complete API framework for hierarchical navigation, measure calculations, access control, and XMLA protocol integration for enterprise analytical applications. + Comprehensive OLAP (Online Analytical Processing) engine + providing multidimensional data processing, cube operations, advanced query + execution, intelligent caching, and aggregation management. Includes + complete API framework for hierarchical navigation, measure calculations, + access control, and XMLA protocol integration for enterprise analytical + applications. 0.0.1-SNAPSHOT 2.0.9 3.1.2 - - 5.10.0 - 21 - 21 - 21 - - - Central Portal Snapshots - central-portal-snapshots - https://central.sonatype.com/repository/maven-snapshots/ - - false - - - true - - - - api common @@ -62,23 +48,12 @@ - - org.slf4j - slf4j-api - ${slf4j.version} - compile - - - org.mockito - mockito-core - ${mockito.version} - test - - - org.mockito - mockito-junit-jupiter - ${mockito.version} - test - + + org.slf4j + slf4j-api + ${slf4j.version} + compile + + diff --git a/spi/src/main/java/org/eclipse/daanse/olap/spi/StatisticsProvider.java b/spi/src/main/java/org/eclipse/daanse/olap/spi/StatisticsProvider.java index b022cd3..3256891 100644 --- a/spi/src/main/java/org/eclipse/daanse/olap/spi/StatisticsProvider.java +++ b/spi/src/main/java/org/eclipse/daanse/olap/spi/StatisticsProvider.java @@ -27,7 +27,7 @@ import org.eclipse.daanse.jdbc.db.dialect.api.Dialect; import org.eclipse.daanse.olap.api.Context; -import org.eclipse.daanse.olap.server.ExecutionImpl; +import org.eclipse.daanse.olap.execution.ExecutionImpl; /** * Provides estimates of the number of rows in a database. diff --git a/xmla/bridge/src/main/java/org/eclipse/daanse/olap/xmla/bridge/ActionService.java b/xmla/bridge/src/main/java/org/eclipse/daanse/olap/xmla/bridge/ActionService.java index cf50dff..9aa6bfd 100644 --- a/xmla/bridge/src/main/java/org/eclipse/daanse/olap/xmla/bridge/ActionService.java +++ b/xmla/bridge/src/main/java/org/eclipse/daanse/olap/xmla/bridge/ActionService.java @@ -18,7 +18,6 @@ import org.eclipse.daanse.olap.api.element.Catalog; import org.eclipse.daanse.xmla.api.RequestMetaData; -import org.eclipse.daanse.xmla.api.UserRolePrincipal; import org.eclipse.daanse.xmla.api.common.enums.ActionTypeEnum; import org.eclipse.daanse.xmla.api.common.enums.CoordinateTypeEnum; import org.eclipse.daanse.xmla.api.common.enums.CubeSourceEnum; diff --git a/xmla/bridge/src/main/java/org/eclipse/daanse/olap/xmla/bridge/ActionServiceImpl.java b/xmla/bridge/src/main/java/org/eclipse/daanse/olap/xmla/bridge/ActionServiceImpl.java index 4562bcc..694c688 100644 --- a/xmla/bridge/src/main/java/org/eclipse/daanse/olap/xmla/bridge/ActionServiceImpl.java +++ b/xmla/bridge/src/main/java/org/eclipse/daanse/olap/xmla/bridge/ActionServiceImpl.java @@ -29,7 +29,6 @@ import org.eclipse.daanse.olap.api.element.Cube; import org.eclipse.daanse.olap.api.element.DrillThroughAction; import org.eclipse.daanse.xmla.api.RequestMetaData; -import org.eclipse.daanse.xmla.api.UserRolePrincipal; import org.eclipse.daanse.xmla.api.common.enums.ActionTypeEnum; import org.eclipse.daanse.xmla.api.common.enums.CoordinateTypeEnum; import org.eclipse.daanse.xmla.api.common.enums.CubeSourceEnum; diff --git a/xmla/bridge/src/main/java/org/eclipse/daanse/olap/xmla/bridge/discover/DelegatingDiscoverService.java b/xmla/bridge/src/main/java/org/eclipse/daanse/olap/xmla/bridge/discover/DelegatingDiscoverService.java index 18ae438..e4c02b8 100644 --- a/xmla/bridge/src/main/java/org/eclipse/daanse/olap/xmla/bridge/discover/DelegatingDiscoverService.java +++ b/xmla/bridge/src/main/java/org/eclipse/daanse/olap/xmla/bridge/discover/DelegatingDiscoverService.java @@ -19,7 +19,6 @@ import org.eclipse.daanse.olap.xmla.bridge.ContextGroupXmlaServiceConfig; import org.eclipse.daanse.olap.xmla.bridge.ContextListSupplyer; import org.eclipse.daanse.xmla.api.RequestMetaData; -import org.eclipse.daanse.xmla.api.UserRolePrincipal; import org.eclipse.daanse.xmla.api.discover.DiscoverService; import org.eclipse.daanse.xmla.api.discover.dbschema.catalogs.DbSchemaCatalogsRequest; import org.eclipse.daanse.xmla.api.discover.dbschema.catalogs.DbSchemaCatalogsResponseRow; diff --git a/xmla/bridge/src/main/java/org/eclipse/daanse/olap/xmla/bridge/discover/MDSchemaDiscoverService.java b/xmla/bridge/src/main/java/org/eclipse/daanse/olap/xmla/bridge/discover/MDSchemaDiscoverService.java index 169212e..c0d2fde 100644 --- a/xmla/bridge/src/main/java/org/eclipse/daanse/olap/xmla/bridge/discover/MDSchemaDiscoverService.java +++ b/xmla/bridge/src/main/java/org/eclipse/daanse/olap/xmla/bridge/discover/MDSchemaDiscoverService.java @@ -34,7 +34,6 @@ import org.eclipse.daanse.olap.api.element.Catalog; import org.eclipse.daanse.olap.xmla.bridge.ActionService; import org.eclipse.daanse.olap.xmla.bridge.ContextListSupplyer; -import org.eclipse.daanse.olap.xmla.bridge.session.SessionServiceImpl; import org.eclipse.daanse.xmla.api.RequestMetaData; import org.eclipse.daanse.xmla.api.common.enums.ActionTypeEnum; import org.eclipse.daanse.xmla.api.common.enums.CoordinateTypeEnum; diff --git a/xmla/bridge/src/main/java/org/eclipse/daanse/olap/xmla/bridge/discover/OtherDiscoverService.java b/xmla/bridge/src/main/java/org/eclipse/daanse/olap/xmla/bridge/discover/OtherDiscoverService.java index 5cec438..8cf49e2 100644 --- a/xmla/bridge/src/main/java/org/eclipse/daanse/olap/xmla/bridge/discover/OtherDiscoverService.java +++ b/xmla/bridge/src/main/java/org/eclipse/daanse/olap/xmla/bridge/discover/OtherDiscoverService.java @@ -29,10 +29,8 @@ import org.eclipse.daanse.olap.api.element.Catalog; import org.eclipse.daanse.olap.xmla.bridge.ContextGroupXmlaServiceConfig; import org.eclipse.daanse.olap.xmla.bridge.ContextListSupplyer; -import org.eclipse.daanse.olap.xmla.bridge.RoleUtils; import org.eclipse.daanse.xmla.api.PropertyDefinition; import org.eclipse.daanse.xmla.api.RequestMetaData; -import org.eclipse.daanse.xmla.api.UserRolePrincipal; import org.eclipse.daanse.xmla.api.XmlaConstants; import org.eclipse.daanse.xmla.api.annotation.Enumerator; import org.eclipse.daanse.xmla.api.annotation.Operation; diff --git a/xmla/bridge/test.bndrun b/xmla/bridge/test.bndrun index 9768b98..617e5fa 100644 --- a/xmla/bridge/test.bndrun +++ b/xmla/bridge/test.bndrun @@ -43,7 +43,7 @@ -runfw: org.apache.felix.framework --runee: JavaSE-21 +-runee: JavaSE-25 -runrequires: \ bnd.identity;id='${project.artifactId}-tests',\ @@ -53,14 +53,14 @@ -runbundles: \ assertj-core;version='[3.26.0,3.26.1)',\ com.github.ben-manes.caffeine;version='[3.1.2,3.1.3)',\ - junit-jupiter-api;version='[5.10.2,5.10.3)',\ - junit-jupiter-engine;version='[5.10.2,5.10.3)',\ - junit-jupiter-params;version='[5.10.2,5.10.3)',\ - junit-platform-commons;version='[1.10.2,1.10.3)',\ - junit-platform-engine;version='[1.10.2,1.10.3)',\ - junit-platform-launcher;version='[1.10.2,1.10.3)',\ - net.bytebuddy.byte-buddy;version='[1.14.16,1.14.17)',\ - net.bytebuddy.byte-buddy-agent;version='[1.14.11,1.14.12)',\ + junit-jupiter-api;version='[5.12.2,5.12.3)',\ + junit-jupiter-engine;version='[5.12.2,5.12.3)',\ + junit-jupiter-params;version='[5.12.2,5.12.3)',\ + junit-platform-commons;version='[1.12.2,1.12.3)',\ + junit-platform-engine;version='[1.12.2,1.12.3)',\ + junit-platform-launcher;version='[1.12.2,1.12.3)',\ + net.bytebuddy.byte-buddy;version='[1.17.5,1.17.6)',\ + net.bytebuddy.byte-buddy-agent;version='[1.17.5,1.17.6)',\ org.apache.felix.configadmin;version='[1.9.26,1.9.27)',\ org.apache.felix.scr;version='[2.2.10,2.2.11)',\ org.eclipse.daanse.jdbc.db.dialect.api;version='[0.0.1,0.0.2)',\ @@ -74,8 +74,8 @@ org.eclipse.daanse.sql.guard.api;version='[0.0.1,0.0.2)',\ org.eclipse.daanse.xmla.api;version='[0.0.1,0.0.2)',\ org.eclipse.daanse.xmla.model.record;version='[0.0.1,0.0.2)',\ - org.mockito.junit-jupiter;version='[5.10.0,5.10.1)',\ - org.mockito.mockito-core;version='[5.10.0,5.10.1)',\ + org.mockito.junit-jupiter;version='[5.18.0,5.18.1)',\ + org.mockito.mockito-core;version='[5.18.0,5.18.1)',\ org.objenesis;version='[3.3.0,3.3.1)',\ org.opentest4j;version='[1.3.0,1.3.1)',\ org.osgi.service.component;version='[1.5.1,1.5.2)',\