You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@iotdb.apache.org by ro...@apache.org on 2022/01/10 11:09:46 UTC

[iotdb] branch master updated: [IOTDB-2284] Trigger: Multiple triggers can be registered on the same timeseries (#4745)

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

rong 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 618a913  [IOTDB-2284] Trigger: Multiple triggers can be registered on the same timeseries (#4745)
618a913 is described below

commit 618a913d350378141a5c9098809a2361be143478
Author: Steve Yurong Su <ro...@apache.org>
AuthorDate: Mon Jan 10 19:09:17 2022 +0800

    [IOTDB-2284] Trigger: Multiple triggers can be registered on the same timeseries (#4745)
---
 .../db/integration/IoTDBTriggerManagementIT.java   | 40 +++++++++++++++-
 .../service/TriggerRegistrationService.java        | 54 +++++++++++++---------
 2 files changed, 71 insertions(+), 23 deletions(-)

diff --git a/integration/src/test/java/org/apache/iotdb/db/integration/IoTDBTriggerManagementIT.java b/integration/src/test/java/org/apache/iotdb/db/integration/IoTDBTriggerManagementIT.java
index a7ee180..c58159b 100644
--- a/integration/src/test/java/org/apache/iotdb/db/integration/IoTDBTriggerManagementIT.java
+++ b/integration/src/test/java/org/apache/iotdb/db/integration/IoTDBTriggerManagementIT.java
@@ -195,7 +195,7 @@ public class IoTDBTriggerManagementIT {
       statement.execute(
           "create trigger trigger_1 before insert on root.vehicle.d1.s1 as 'org.apache.iotdb.db.engine.trigger.example.Accumulator'");
       statement.execute(
-          "create trigger trigger_1 after insert on root.vehicle.d1.s1 as 'org.apache.iotdb.db.engine.trigger.example.Accumulator'");
+          "create trigger trigger_1 after insert on root.vehicle.d1.s2 as 'org.apache.iotdb.db.engine.trigger.example.Accumulator'");
     } catch (SQLException throwable) {
       assertTrue(
           throwable
@@ -206,6 +206,41 @@ public class IoTDBTriggerManagementIT {
   }
 
   @Test
+  public void testRegisterOnSameTimeseries() {
+    try (Connection connection =
+            DriverManager.getConnection(
+                Config.IOTDB_URL_PREFIX + "127.0.0.1:6667/", "root", "root");
+        Statement statement = connection.createStatement()) {
+      statement.execute(
+          "create trigger trigger_1 before insert on root.vehicle.d1.s1 as 'org.apache.iotdb.db.engine.trigger.example.Accumulator'");
+
+      try {
+        statement.execute(
+            "create trigger trigger_2 before insert on root.vehicle.d1.s1 as 'org.apache.iotdb.db.engine.trigger.example.Accumulator'");
+      } catch (SQLException throwable) {
+        assertTrue(
+            throwable
+                .getMessage()
+                .contains(
+                    "because a trigger trigger_1(org.apache.iotdb.db.engine.trigger.example.Accumulator) has already been registered on the timeseries root.vehicle.d1.s1"));
+      }
+
+      try {
+        statement.execute(
+            "create trigger trigger_3 after insert on root.vehicle.d1.s1 as 'org.apache.iotdb.db.engine.trigger.example.Accumulator'");
+      } catch (SQLException throwable) {
+        assertTrue(
+            throwable
+                .getMessage()
+                .contains(
+                    "because a trigger trigger_1(org.apache.iotdb.db.engine.trigger.example.Accumulator) has already been registered on the timeseries root.vehicle.d1.s1"));
+      }
+    } catch (SQLException throwable) {
+      fail(throwable.getMessage());
+    }
+  }
+
+  @Test
   public void testRegisterTriggersWithSameNameButDifferentClasses() {
     try (Connection connection =
             DriverManager.getConnection(
@@ -457,15 +492,16 @@ public class IoTDBTriggerManagementIT {
       assertFalse(trigger2Info.isStopped());
 
       statement.execute("drop trigger trigger_2");
+      statement.execute("drop trigger trigger_1");
       statement.execute(
           "create trigger trigger_2 after insert on root.vehicle.d1.s3 as 'org.apache.iotdb.db.engine.trigger.example.Counter'");
-      statement.execute("drop trigger trigger_1");
       statement.execute(
           "create trigger trigger_1 before insert on root.vehicle.d1.s4 as 'org.apache.iotdb.db.engine.trigger.example.Accumulator' with ('k5'='v5')");
       statement.execute("stop trigger trigger_2");
       statement.execute(
           "create trigger trigger_3 before insert on root.vehicle.d1.s2 as 'org.apache.iotdb.db.engine.trigger.example.Accumulator'");
     } catch (Exception e) {
+      e.printStackTrace();
       fail(e.getMessage());
     }
 
diff --git a/server/src/main/java/org/apache/iotdb/db/engine/trigger/service/TriggerRegistrationService.java b/server/src/main/java/org/apache/iotdb/db/engine/trigger/service/TriggerRegistrationService.java
index ad3e34a..5973fce 100644
--- a/server/src/main/java/org/apache/iotdb/db/engine/trigger/service/TriggerRegistrationService.java
+++ b/server/src/main/java/org/apache/iotdb/db/engine/trigger/service/TriggerRegistrationService.java
@@ -73,6 +73,8 @@ public class TriggerRegistrationService implements IService {
 
   private static final Logger LOGGER = LoggerFactory.getLogger(TriggerRegistrationService.class);
 
+  private static final IoTDBConfig CONFIG = IoTDBDescriptor.getInstance().getConfig();
+
   private static final String LOG_FILE_DIR =
       IoTDBDescriptor.getInstance().getConfig().getSystemDir()
           + File.separator
@@ -85,8 +87,6 @@ public class TriggerRegistrationService implements IService {
 
   private final ConcurrentHashMap<String, TriggerExecutor> executors;
 
-  private static IoTDBConfig config = IoTDBDescriptor.getInstance().getConfig();
-
   private TriggerLogWriter logWriter;
 
   private TriggerRegistrationService() {
@@ -95,30 +95,42 @@ public class TriggerRegistrationService implements IService {
 
   public synchronized void register(CreateTriggerPlan plan)
       throws TriggerManagementException, TriggerExecutionException {
-    checkIfRegistered(plan);
     IMeasurementMNode measurementMNode = tryGetMeasurementMNode(plan);
+    checkIfRegistered(plan, measurementMNode);
     tryAppendRegistrationLog(plan);
     doRegister(plan, measurementMNode);
   }
 
-  private void checkIfRegistered(CreateTriggerPlan plan) throws TriggerManagementException {
-    TriggerExecutor executor = executors.get(plan.getTriggerName());
-    if (executor == null) {
-      return;
+  private void checkIfRegistered(CreateTriggerPlan plan, IMeasurementMNode measurementMNode)
+      throws TriggerManagementException {
+    TriggerExecutor executor = measurementMNode.getTriggerExecutor();
+    if (executor != null) {
+      TriggerRegistrationInformation information = executor.getRegistrationInformation();
+      throw new TriggerManagementException(
+          String.format(
+              "Failed to register trigger %s(%s), because a trigger %s(%s) has already been registered on the timeseries %s.",
+              plan.getTriggerName(),
+              plan.getClassName(),
+              information.getTriggerName(),
+              information.getClassName(),
+              measurementMNode.getFullPath()));
     }
 
-    TriggerRegistrationInformation information = executor.getRegistrationInformation();
-    throw new TriggerManagementException(
-        information.getClassName().equals(plan.getClassName())
-            ? String.format(
-                "Failed to register trigger %s(%s), because a trigger with the same trigger name and the class name has already been registered.",
-                plan.getTriggerName(), plan.getClassName())
-            : String.format(
-                "Failed to register trigger %s(%s), because a trigger %s(%s) with the same trigger name but a different class name has already been registered.",
-                plan.getTriggerName(),
-                plan.getClassName(),
-                information.getTriggerName(),
-                information.getClassName()));
+    executor = executors.get(plan.getTriggerName());
+    if (executor != null) {
+      TriggerRegistrationInformation information = executor.getRegistrationInformation();
+      throw new TriggerManagementException(
+          information.getClassName().equals(plan.getClassName())
+              ? String.format(
+                  "Failed to register trigger %s(%s), because a trigger with the same trigger name and the class name has already been registered.",
+                  plan.getTriggerName(), plan.getClassName())
+              : String.format(
+                  "Failed to register trigger %s(%s), because a trigger %s(%s) with the same trigger name but a different class name has already been registered.",
+                  plan.getTriggerName(),
+                  plan.getClassName(),
+                  information.getTriggerName(),
+                  information.getClassName()));
+    }
   }
 
   private IMeasurementMNode tryGetMeasurementMNode(CreateTriggerPlan plan)
@@ -160,7 +172,7 @@ public class TriggerRegistrationService implements IService {
     measurementMNode.setTriggerExecutor(executor);
 
     // update id table
-    if (config.isEnableIDTable()) {
+    if (CONFIG.isEnableIDTable()) {
       try {
         IDTable idTable =
             IDTableManager.getInstance().getIDTable(plan.getFullPath().getDevicePath());
@@ -214,7 +226,7 @@ public class TriggerRegistrationService implements IService {
         .deregister(executor.getRegistrationInformation().getClassName());
 
     // update id table
-    if (config.isEnableIDTable()) {
+    if (CONFIG.isEnableIDTable()) {
       try {
         PartialPath fullPath = executor.getMeasurementMNode().getPartialPath();
         IDTable idTable = IDTableManager.getInstance().getIDTable(fullPath.getDevicePath());