This is an automated email from the ASF dual-hosted git repository.

xiangweiwei pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/iotdb.git


The following commit(s) were added to refs/heads/master by this push:
     new cc83ab87f3 [IOTDB-5449] Allow query scheduler to receive more tasks 
(#8957)
cc83ab87f3 is described below

commit cc83ab87f3b98343179a7c291c371b24a18ecf72
Author: Xiangwei Wei <[email protected]>
AuthorDate: Mon Feb 6 15:07:15 2023 +0800

    [IOTDB-5449] Allow query scheduler to receive more tasks (#8957)
---
 .../db/mpp/execution/schedule/DriverScheduler.java | 41 ++++++++---
 .../schedule/queue/IndexedBlockingQueue.java       | 11 ++-
 .../queue/IndexedBlockingReserveQueue.java         | 81 ++++++++++++++++++++++
 .../multilevelqueue/MultilevelPriorityQueue.java   |  4 +-
 .../schedule/queue/L1PriorityQueueTest.java        | 24 -------
 .../schedule/queue/L2PriorityQueueTest.java        | 24 -------
 6 files changed, 118 insertions(+), 67 deletions(-)

diff --git 
a/server/src/main/java/org/apache/iotdb/db/mpp/execution/schedule/DriverScheduler.java
 
b/server/src/main/java/org/apache/iotdb/db/mpp/execution/schedule/DriverScheduler.java
index fb0fb7bf0c..7188717d20 100644
--- 
a/server/src/main/java/org/apache/iotdb/db/mpp/execution/schedule/DriverScheduler.java
+++ 
b/server/src/main/java/org/apache/iotdb/db/mpp/execution/schedule/DriverScheduler.java
@@ -29,6 +29,7 @@ import org.apache.iotdb.db.mpp.execution.driver.IDriver;
 import org.apache.iotdb.db.mpp.execution.exchange.IMPPDataExchangeManager;
 import org.apache.iotdb.db.mpp.execution.exchange.MPPDataExchangeService;
 import org.apache.iotdb.db.mpp.execution.schedule.queue.IndexedBlockingQueue;
+import 
org.apache.iotdb.db.mpp.execution.schedule.queue.IndexedBlockingReserveQueue;
 import org.apache.iotdb.db.mpp.execution.schedule.queue.L1PriorityQueue;
 import 
org.apache.iotdb.db.mpp.execution.schedule.queue.multilevelqueue.DriverTaskHandle;
 import 
org.apache.iotdb.db.mpp.execution.schedule.queue.multilevelqueue.MultilevelPriorityQueue;
@@ -68,7 +69,7 @@ public class DriverScheduler implements IDriverScheduler, 
IService {
     return InstanceHolder.instance;
   }
 
-  private final IndexedBlockingQueue<DriverTask> readyQueue;
+  private final IndexedBlockingReserveQueue<DriverTask> readyQueue;
   private final IndexedBlockingQueue<DriverTask> timeoutQueue;
   private final Set<DriverTask> blockedTasks;
   private final Map<QueryId, Map<FragmentInstanceId, Set<DriverTask>>> 
queryMap;
@@ -77,10 +78,11 @@ public class DriverScheduler implements IDriverScheduler, 
IService {
   private final AtomicInteger nextDriverTaskHandleId = new AtomicInteger(0);
   private IMPPDataExchangeManager blockManager;
 
-  private static final int MAX_CAPACITY =
+  private static final int QUERY_MAX_CAPACITY =
       
IoTDBDescriptor.getInstance().getConfig().getMaxAllowedConcurrentQueries();
   private static final int WORKER_THREAD_NUM =
       IoTDBDescriptor.getInstance().getConfig().getQueryThreadCount();
+  private static final int TASK_MAX_CAPACITY = QUERY_MAX_CAPACITY * 
WORKER_THREAD_NUM * 2;
   private static final long QUERY_TIMEOUT_MS =
       IoTDBDescriptor.getInstance().getConfig().getQueryTimeoutThreshold();
   private final ThreadGroup workerGroups;
@@ -88,9 +90,10 @@ public class DriverScheduler implements IDriverScheduler, 
IService {
 
   private DriverScheduler() {
     this.readyQueue =
-        new MultilevelPriorityQueue(LEVEL_TIME_MULTIPLIER, MAX_CAPACITY, new 
DriverTask());
+        new MultilevelPriorityQueue(LEVEL_TIME_MULTIPLIER, TASK_MAX_CAPACITY, 
new DriverTask());
     this.timeoutQueue =
-        new L1PriorityQueue<>(MAX_CAPACITY, new 
DriverTask.TimeoutComparator(), new DriverTask());
+        new L1PriorityQueue<>(
+            QUERY_MAX_CAPACITY, new DriverTask.TimeoutComparator(), new 
DriverTask());
     this.queryMap = new ConcurrentHashMap<>();
     this.blockedTasks = Collections.synchronizedSet(new HashSet<>());
     this.scheduler = new Scheduler();
@@ -254,12 +257,30 @@ public class DriverScheduler implements IDriverScheduler, 
IService {
   private void clearDriverTask(DriverTask task) {
     try (SetThreadName driverTaskName =
         new SetThreadName(task.getDriver().getDriverTaskId().getFullId())) {
-      if (task.getStatus() != DriverTaskStatus.FINISHED) {
-        task.setStatus(DriverTaskStatus.ABORTED);
+      DriverTaskStatus status = task.getStatus();
+      switch (status) {
+          // If it has been aborted, return directly
+        case ABORTED:
+          return;
+        case READY:
+          task.setStatus(DriverTaskStatus.ABORTED);
+          readyQueue.remove(task.getDriverTaskId());
+          break;
+        case BLOCKED:
+          task.setStatus(DriverTaskStatus.ABORTED);
+          blockedTasks.remove(task);
+          readyQueue.decreaseReservedSize();
+          break;
+        case RUNNING:
+          task.setStatus(DriverTaskStatus.ABORTED);
+          readyQueue.decreaseReservedSize();
+          break;
+        case FINISHED:
+          readyQueue.decreaseReservedSize();
+          break;
       }
-      readyQueue.remove(task.getDriverTaskId());
+
       timeoutQueue.remove(task.getDriverTaskId());
-      blockedTasks.remove(task);
       Map<FragmentInstanceId, Set<DriverTask>> queryRelatedTasks =
           queryMap.get(task.getDriverTaskId().getQueryId());
       if (queryRelatedTasks != null) {
@@ -361,7 +382,7 @@ public class DriverScheduler implements IDriverScheduler, 
IService {
             BLOCK_QUEUED_TIME, System.nanoTime() - 
task.getLastEnterBlockQueueTime());
         task.setLastEnterReadyQueueTime(System.nanoTime());
         task.resetLevelScheduledTime();
-        readyQueue.push(task);
+        readyQueue.repush(task);
         blockedTasks.remove(task);
       } finally {
         task.unlock();
@@ -395,7 +416,7 @@ public class DriverScheduler implements IDriverScheduler, 
IService {
         task.updateSchedulePriority(context);
         task.setStatus(DriverTaskStatus.READY);
         task.setLastEnterReadyQueueTime(System.nanoTime());
-        readyQueue.push(task);
+        readyQueue.repush(task);
       } finally {
         task.unlock();
       }
diff --git 
a/server/src/main/java/org/apache/iotdb/db/mpp/execution/schedule/queue/IndexedBlockingQueue.java
 
b/server/src/main/java/org/apache/iotdb/db/mpp/execution/schedule/queue/IndexedBlockingQueue.java
index 1498bbbc30..6fdcbb0392 100644
--- 
a/server/src/main/java/org/apache/iotdb/db/mpp/execution/schedule/queue/IndexedBlockingQueue.java
+++ 
b/server/src/main/java/org/apache/iotdb/db/mpp/execution/schedule/queue/IndexedBlockingQueue.java
@@ -37,9 +37,9 @@ import com.google.common.base.Preconditions;
  */
 public abstract class IndexedBlockingQueue<E extends IDIndexedAccessible> {
 
-  private final int MAX_CAPACITY;
-  private final E queryHolder;
-  private int size;
+  protected final int MAX_CAPACITY;
+  protected final E queryHolder;
+  protected int size;
 
   /**
    * Init the queue with a max capacity. The queryHolder is just a simple 
reused object in query to
@@ -85,10 +85,7 @@ public abstract class IndexedBlockingQueue<E extends 
IDIndexedAccessible> {
     if (element == null) {
       throw new NullPointerException("pushed element is null");
     }
-    Preconditions.checkState(
-        !contains(element),
-        "The queue has already contained the element: " + 
element.getDriverTaskId());
-    Preconditions.checkState(size < MAX_CAPACITY, "The queue is full");
+    Preconditions.checkState(size < MAX_CAPACITY, "The system can't allow more 
queries.");
     pushToQueue(element);
     size++;
     this.notifyAll();
diff --git 
a/server/src/main/java/org/apache/iotdb/db/mpp/execution/schedule/queue/IndexedBlockingReserveQueue.java
 
b/server/src/main/java/org/apache/iotdb/db/mpp/execution/schedule/queue/IndexedBlockingReserveQueue.java
new file mode 100644
index 0000000000..ba14fe9f82
--- /dev/null
+++ 
b/server/src/main/java/org/apache/iotdb/db/mpp/execution/schedule/queue/IndexedBlockingReserveQueue.java
@@ -0,0 +1,81 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.iotdb.db.mpp.execution.schedule.queue;
+
+import com.google.common.base.Preconditions;
+
+/**
+ * This class is different from <class>IndexedBlockingQueue</class> in that it 
will reserve space
+ * for polled element in case it will be pushed again.
+ */
+public abstract class IndexedBlockingReserveQueue<E extends 
IDIndexedAccessible>
+    extends IndexedBlockingQueue<E> {
+
+  // To avoid some elements can't join the queue again that are polled out for 
running or blocked
+  private int reservedSize;
+
+  public IndexedBlockingReserveQueue(int maxCapacity, E queryHolder) {
+    super(maxCapacity, queryHolder);
+  }
+
+  /**
+   * Get and remove the first element of the queue. Reserve space for this 
polled element.
+   *
+   * @return the queue head element.
+   */
+  public synchronized E poll() throws InterruptedException {
+    while (isEmpty()) {
+      this.wait();
+    }
+    E output = pollFirst();
+    size--;
+    reservedSize++;
+    return output;
+  }
+
+  public synchronized void push(E element) {
+    if (element == null) {
+      throw new NullPointerException("pushed element is null");
+    }
+    Preconditions.checkState(
+        size + reservedSize < MAX_CAPACITY, "The system can't allow more query 
tasks.");
+    pushToQueue(element);
+    size++;
+    this.notifyAll();
+  }
+
+  /** RePush an element which is polled out for running or blocked before to 
the queue. */
+  public synchronized void repush(E element) {
+    if (element == null) {
+      throw new NullPointerException("pushed element is null");
+    }
+    pushToQueue(element);
+    reservedSize--;
+    size++;
+    this.notifyAll();
+  }
+
+  /**
+   * For task that is not in readyQueue when it's cleared, it won't be added 
into the queue again.
+   */
+  public synchronized void decreaseReservedSize() {
+    this.reservedSize--;
+  }
+}
diff --git 
a/server/src/main/java/org/apache/iotdb/db/mpp/execution/schedule/queue/multilevelqueue/MultilevelPriorityQueue.java
 
b/server/src/main/java/org/apache/iotdb/db/mpp/execution/schedule/queue/multilevelqueue/MultilevelPriorityQueue.java
index 97ecf3927e..2c5bc41fa1 100644
--- 
a/server/src/main/java/org/apache/iotdb/db/mpp/execution/schedule/queue/multilevelqueue/MultilevelPriorityQueue.java
+++ 
b/server/src/main/java/org/apache/iotdb/db/mpp/execution/schedule/queue/multilevelqueue/MultilevelPriorityQueue.java
@@ -19,7 +19,7 @@
 
 package org.apache.iotdb.db.mpp.execution.schedule.queue.multilevelqueue;
 
-import org.apache.iotdb.db.mpp.execution.schedule.queue.IndexedBlockingQueue;
+import 
org.apache.iotdb.db.mpp.execution.schedule.queue.IndexedBlockingReserveQueue;
 import org.apache.iotdb.db.mpp.execution.schedule.task.DriverTask;
 
 import java.util.PriorityQueue;
@@ -34,7 +34,7 @@ import static java.util.concurrent.TimeUnit.SECONDS;
  * This class is inspired by Trino <a
  * 
href="https://github.com/trinodb/trino/blob/master/core/trino-main/src/main/java/io/trino/execution/executor/MultilevelSplitQueue.java";>...</a>
  */
-public class MultilevelPriorityQueue extends IndexedBlockingQueue<DriverTask> {
+public class MultilevelPriorityQueue extends 
IndexedBlockingReserveQueue<DriverTask> {
   /** Scheduled time threshold of TASK in each level */
   static final int[] LEVEL_THRESHOLD_SECONDS = {0, 1, 10, 60, 300};
 
diff --git 
a/server/src/test/java/org/apache/iotdb/db/mpp/execution/schedule/queue/L1PriorityQueueTest.java
 
b/server/src/test/java/org/apache/iotdb/db/mpp/execution/schedule/queue/L1PriorityQueueTest.java
index 5d36688454..418ca48fe5 100644
--- 
a/server/src/test/java/org/apache/iotdb/db/mpp/execution/schedule/queue/L1PriorityQueueTest.java
+++ 
b/server/src/test/java/org/apache/iotdb/db/mpp/execution/schedule/queue/L1PriorityQueueTest.java
@@ -108,30 +108,6 @@ public class L1PriorityQueueTest {
     Assert.assertEquals(0, queue.size());
   }
 
-  @Test
-  public void testPushSameElement() {
-    IndexedBlockingQueue<QueueElement> queue =
-        new L1PriorityQueue<>(
-            10,
-            (o1, o2) -> {
-              if (o1.equals(o2)) {
-                return 0;
-              }
-              return Integer.compare(o1.getValue(), o2.getValue());
-            },
-            new QueueElement(new QueueElement.QueueElementID(0), 0));
-    QueueElement e1 = new QueueElement(new QueueElement.QueueElementID(1), 10);
-    queue.push(e1);
-    Assert.assertEquals(1, queue.size());
-    QueueElement e1e = new QueueElement(new QueueElement.QueueElementID(1), 5);
-    try {
-      queue.push(e1e);
-      Assert.fail();
-    } catch (IllegalStateException e) {
-      Assert.assertTrue(e.getMessage().contains("has already contained"));
-    }
-  }
-
   @Test
   public void testRemoveElement() {
     IndexedBlockingQueue<QueueElement> queue =
diff --git 
a/server/src/test/java/org/apache/iotdb/db/mpp/execution/schedule/queue/L2PriorityQueueTest.java
 
b/server/src/test/java/org/apache/iotdb/db/mpp/execution/schedule/queue/L2PriorityQueueTest.java
index 2c762e7736..9acf787151 100644
--- 
a/server/src/test/java/org/apache/iotdb/db/mpp/execution/schedule/queue/L2PriorityQueueTest.java
+++ 
b/server/src/test/java/org/apache/iotdb/db/mpp/execution/schedule/queue/L2PriorityQueueTest.java
@@ -123,30 +123,6 @@ public class L2PriorityQueueTest {
     Assert.assertEquals(0, queue.size());
   }
 
-  @Test
-  public void testPushSameElement() {
-    IndexedBlockingQueue<QueueElement> queue =
-        new L2PriorityQueue<>(
-            10,
-            (o1, o2) -> {
-              if (o1.equals(o2)) {
-                return 0;
-              }
-              return Integer.compare(o1.getValue(), o2.getValue());
-            },
-            new QueueElement(new QueueElement.QueueElementID(0), 0));
-    QueueElement e1 = new QueueElement(new QueueElement.QueueElementID(1), 10);
-    queue.push(e1);
-    Assert.assertEquals(1, queue.size());
-    QueueElement e1e = new QueueElement(new QueueElement.QueueElementID(1), 5);
-    try {
-      queue.push(e1e);
-      fail();
-    } catch (IllegalStateException e) {
-      Assert.assertTrue(e.getMessage().contains("has already contained"));
-    }
-  }
-
   @Test
   public void testRemoveElement() {
     IndexedBlockingQueue<QueueElement> queue =

Reply via email to