diff --git a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/utils/datastructure/AlignedTVList.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/utils/datastructure/AlignedTVList.java index 9e3a556710cc9..591c91a664000 100644 --- a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/utils/datastructure/AlignedTVList.java +++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/utils/datastructure/AlignedTVList.java @@ -539,7 +539,13 @@ public List getTsDataTypes() { } @Override - public int delete(long lowerBound, long upperBound) { + /* + * Must be synchronized with sort() on the same TVList instance: a query may sort + * this list in place (sort() is synchronized), and a concurrent delete would + * otherwise read the half-rebuilt indices and throw IndexOutOfBoundsException + * or delete wrong rows. + */ + public synchronized int delete(long lowerBound, long upperBound) { int deletedNumber = 0; for (int i = 0; i < dataTypes.size(); i++) { deletedNumber += delete(lowerBound, upperBound, i).left; @@ -550,12 +556,17 @@ public int delete(long lowerBound, long upperBound) { /** * Delete points in a specific column. * + *

Must be synchronized with {@link #sort()} on the same TVList instance: a query may sort this + * list in place ({@code sort()} is synchronized), and a concurrent delete would otherwise read + * the half-rebuilt {@code indices} and throw IndexOutOfBoundsException or delete wrong rows. + * * @param lowerBound deletion lower bound * @param upperBound deletion upper bound * @param columnIndex column index to be deleted * @return Delete info pair. Left: deletedNumber int; right: ifDeleteColumn boolean */ - public Pair delete(long lowerBound, long upperBound, int columnIndex) { + public synchronized Pair delete( + long lowerBound, long upperBound, int columnIndex) { if (columnIndex >= values.size()) { return new Pair<>(0, false); } @@ -577,7 +588,13 @@ public Pair delete(long lowerBound, long upperBound, int colum return new Pair<>(deletedNumber, deleteColumn); } - public void deleteColumn(int columnIndex) { + /* + * Must be synchronized with sort() on the same TVList instance: a query may sort + * this list in place (sort() is synchronized), and a concurrent delete would + * otherwise read the half-rebuilt indices and throw IndexOutOfBoundsException + * or delete wrong rows. + */ + public synchronized void deleteColumn(int columnIndex) { if (bitMaps == null) { List> localBitMaps = new ArrayList<>(dataTypes.size()); for (int j = 0; j < dataTypes.size(); j++) { diff --git a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/utils/datastructure/TVList.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/utils/datastructure/TVList.java index d21ecc83e0f1b..220ca87a9a8a3 100644 --- a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/utils/datastructure/TVList.java +++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/utils/datastructure/TVList.java @@ -558,7 +558,13 @@ public TVList clone(long version) { return clone(); } - public int delete(long lowerBound, long upperBound) { + /* + * Must be synchronized with sort() on the same TVList instance: a query may sort + * this list in place (sort() is synchronized), and a concurrent delete would + * otherwise read the half-rebuilt indices and throw IndexOutOfBoundsException + * or delete wrong rows. + */ + public synchronized int delete(long lowerBound, long upperBound) { int deletedNumber = 0; long maxTime = Long.MIN_VALUE; long minTime = Long.MAX_VALUE;