This is an automated email from the ASF dual-hosted git repository.
tkalkirill pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/ignite-3.git
The following commit(s) were added to refs/heads/main by this push:
new df6a3b5b6b IGNITE-18571 Fix busyLock usage in
AbstractPageMemoryTableStorage and related (#1545)
df6a3b5b6b is described below
commit df6a3b5b6b13f308a430f2b21eff1c896dd3f386
Author: Kirill Tkalenko <[email protected]>
AuthorDate: Wed Jan 18 17:49:20 2023 +0300
IGNITE-18571 Fix busyLock usage in AbstractPageMemoryTableStorage and
related (#1545)
---
.../pagememory/AbstractPageMemoryTableStorage.java | 140 ++++---
.../PersistentPageMemoryStorageEngine.java | 2 +-
.../PersistentPageMemoryTableStorage.java | 10 +-
.../pagememory/VolatilePageMemoryTableStorage.java | 2 +-
.../index/hash/PageMemoryHashIndexStorage.java | 154 +++-----
.../index/sorted/PageMemorySortedIndexStorage.java | 237 +++++------
.../mv/AbstractPageMemoryMvPartitionStorage.java | 432 ++++++++++-----------
.../mv/PersistentPageMemoryMvPartitionStorage.java | 171 +++-----
.../mv/VolatilePageMemoryMvPartitionStorage.java | 95 +----
9 files changed, 531 insertions(+), 712 deletions(-)
diff --git
a/modules/storage-page-memory/src/main/java/org/apache/ignite/internal/storage/pagememory/AbstractPageMemoryTableStorage.java
b/modules/storage-page-memory/src/main/java/org/apache/ignite/internal/storage/pagememory/AbstractPageMemoryTableStorage.java
index 0c6759bb88..ce3625e62d 100644
---
a/modules/storage-page-memory/src/main/java/org/apache/ignite/internal/storage/pagememory/AbstractPageMemoryTableStorage.java
+++
b/modules/storage-page-memory/src/main/java/org/apache/ignite/internal/storage/pagememory/AbstractPageMemoryTableStorage.java
@@ -18,6 +18,7 @@
package org.apache.ignite.internal.storage.pagememory;
import static java.util.concurrent.CompletableFuture.completedFuture;
+import static org.apache.ignite.internal.util.IgniteUtils.inBusyLock;
import java.util.ArrayList;
import java.util.List;
@@ -25,19 +26,21 @@ import java.util.UUID;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
+import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicReferenceArray;
+import java.util.function.Supplier;
import org.apache.ignite.internal.pagememory.DataRegion;
import org.apache.ignite.internal.pagememory.PageMemory;
import org.apache.ignite.internal.schema.configuration.TableConfiguration;
import org.apache.ignite.internal.schema.configuration.TableView;
import org.apache.ignite.internal.schema.configuration.TablesConfiguration;
-import org.apache.ignite.internal.storage.MvPartitionStorage;
import org.apache.ignite.internal.storage.StorageException;
import org.apache.ignite.internal.storage.engine.MvTableStorage;
import org.apache.ignite.internal.storage.index.HashIndexStorage;
import org.apache.ignite.internal.storage.index.SortedIndexStorage;
import
org.apache.ignite.internal.storage.pagememory.mv.AbstractPageMemoryMvPartitionStorage;
import org.apache.ignite.internal.tostring.S;
+import org.apache.ignite.internal.util.IgniteSpinBusyLock;
import org.apache.ignite.internal.util.IgniteUtils;
import org.jetbrains.annotations.Nullable;
@@ -47,14 +50,17 @@ import org.jetbrains.annotations.Nullable;
public abstract class AbstractPageMemoryTableStorage implements MvTableStorage
{
protected final TableConfiguration tableCfg;
- protected TablesConfiguration tablesConfiguration;
-
- protected volatile boolean started;
+ protected final TablesConfiguration tablesCfg;
protected volatile
AtomicReferenceArray<AbstractPageMemoryMvPartitionStorage> mvPartitions;
protected final ConcurrentMap<Integer, CompletableFuture<Void>>
partitionIdDestroyFutureMap = new ConcurrentHashMap<>();
+ private final IgniteSpinBusyLock busyLock = new IgniteSpinBusyLock();
+
+ /** Prevents double stopping of the component. */
+ private final AtomicBoolean stopGuard = new AtomicBoolean();
+
/**
* Constructor.
*
@@ -62,7 +68,7 @@ public abstract class AbstractPageMemoryTableStorage
implements MvTableStorage {
*/
protected AbstractPageMemoryTableStorage(TableConfiguration tableCfg,
TablesConfiguration tablesCfg) {
this.tableCfg = tableCfg;
- tablesConfiguration = tablesCfg;
+ this.tablesCfg = tablesCfg;
}
@Override
@@ -72,7 +78,7 @@ public abstract class AbstractPageMemoryTableStorage
implements MvTableStorage {
@Override
public TablesConfiguration tablesConfiguration() {
- return tablesConfiguration;
+ return tablesCfg;
}
/**
@@ -82,16 +88,22 @@ public abstract class AbstractPageMemoryTableStorage
implements MvTableStorage {
@Override
public void start() throws StorageException {
- TableView tableView = tableCfg.value();
+ busy(() -> {
+ TableView tableView = tableCfg.value();
- mvPartitions = new AtomicReferenceArray<>(tableView.partitions());
+ mvPartitions = new AtomicReferenceArray<>(tableView.partitions());
- started = true;
+ return null;
+ });
}
@Override
public void stop() throws StorageException {
- started = false;
+ if (!stopGuard.compareAndSet(false, true)) {
+ return;
+ }
+
+ busyLock.block();
List<AutoCloseable> closeables = new ArrayList<>();
@@ -112,7 +124,11 @@ public abstract class AbstractPageMemoryTableStorage
implements MvTableStorage {
@Override
public CompletableFuture<Void> destroy() {
- started = false;
+ if (!stopGuard.compareAndSet(false, true)) {
+ return completedFuture(null);
+ }
+
+ busyLock.block();
List<CompletableFuture<Void>> destroyFutures = new ArrayList<>();
@@ -167,25 +183,29 @@ public abstract class AbstractPageMemoryTableStorage
implements MvTableStorage {
@Override
public AbstractPageMemoryMvPartitionStorage getOrCreateMvPartition(int
partitionId) throws StorageException {
- AbstractPageMemoryMvPartitionStorage partition =
getMvPartition(partitionId);
+ return busy(() -> {
+ AbstractPageMemoryMvPartitionStorage partition =
getMvPartitionBusy(partitionId);
- if (partition != null) {
- return partition;
- }
+ if (partition != null) {
+ return partition;
+ }
- partition = createMvPartitionStorage(partitionId);
+ partition = createMvPartitionStorage(partitionId);
- partition.start();
+ partition.start();
- mvPartitions.set(partitionId, partition);
+ mvPartitions.set(partitionId, partition);
- return partition;
+ return partition;
+ });
}
@Override
public @Nullable AbstractPageMemoryMvPartitionStorage getMvPartition(int
partitionId) {
- assert started : "Storage has not started yet";
+ return busy(() -> getMvPartitionBusy(partitionId));
+ }
+ private @Nullable AbstractPageMemoryMvPartitionStorage
getMvPartitionBusy(int partitionId) {
checkPartitionId(partitionId);
return mvPartitions.get(partitionId);
@@ -193,60 +213,64 @@ public abstract class AbstractPageMemoryTableStorage
implements MvTableStorage {
@Override
public CompletableFuture<Void> destroyPartition(int partitionId) {
- assert started : "Storage has not started yet";
-
- checkPartitionId(partitionId);
+ return busy(() -> {
+ checkPartitionId(partitionId);
- CompletableFuture<Void> destroyPartitionFuture = new
CompletableFuture<>();
+ CompletableFuture<Void> destroyPartitionFuture = new
CompletableFuture<>();
- CompletableFuture<Void> previousDestroyPartitionFuture =
partitionIdDestroyFutureMap.putIfAbsent(
- partitionId,
- destroyPartitionFuture
- );
+ CompletableFuture<Void> previousDestroyPartitionFuture =
partitionIdDestroyFutureMap.putIfAbsent(
+ partitionId,
+ destroyPartitionFuture
+ );
- if (previousDestroyPartitionFuture != null) {
- return previousDestroyPartitionFuture;
- }
-
- MvPartitionStorage partition = mvPartitions.getAndSet(partitionId,
null);
+ if (previousDestroyPartitionFuture != null) {
+ return previousDestroyPartitionFuture;
+ }
- if (partition != null) {
- destroyMvPartitionStorage((AbstractPageMemoryMvPartitionStorage)
partition).whenComplete((unused, throwable) -> {
- partitionIdDestroyFutureMap.remove(partitionId);
+ AbstractPageMemoryMvPartitionStorage partition =
mvPartitions.getAndSet(partitionId, null);
- if (throwable != null) {
- destroyPartitionFuture.completeExceptionally(throwable);
- } else {
- destroyPartitionFuture.complete(null);
- }
- });
- } else {
- partitionIdDestroyFutureMap.remove(partitionId).complete(null);
- }
+ if (partition != null) {
+ destroyMvPartitionStorage(partition).whenComplete((unused,
throwable) -> {
+ partitionIdDestroyFutureMap.remove(partitionId);
+
+ if (throwable != null) {
+
destroyPartitionFuture.completeExceptionally(throwable);
+ } else {
+ destroyPartitionFuture.complete(null);
+ }
+ });
+ } else {
+ partitionIdDestroyFutureMap.remove(partitionId).complete(null);
+ }
- return destroyPartitionFuture;
+ return destroyPartitionFuture;
+ });
}
@Override
public SortedIndexStorage getOrCreateSortedIndex(int partitionId, UUID
indexId) {
- AbstractPageMemoryMvPartitionStorage partitionStorage =
getMvPartition(partitionId);
+ return busy(() -> {
+ AbstractPageMemoryMvPartitionStorage partitionStorage =
getMvPartitionBusy(partitionId);
- if (partitionStorage == null) {
- throw new StorageException(String.format("Partition ID %d does not
exist", partitionId));
- }
+ if (partitionStorage == null) {
+ throw new StorageException(String.format("Partition ID %d does
not exist", partitionId));
+ }
- return partitionStorage.getOrCreateSortedIndex(indexId);
+ return partitionStorage.getOrCreateSortedIndex(indexId);
+ });
}
@Override
public HashIndexStorage getOrCreateHashIndex(int partitionId, UUID
indexId) {
- AbstractPageMemoryMvPartitionStorage partitionStorage =
getMvPartition(partitionId);
+ return busy(() -> {
+ AbstractPageMemoryMvPartitionStorage partitionStorage =
getMvPartitionBusy(partitionId);
- if (partitionStorage == null) {
- throw new StorageException(String.format("Partition ID %d does not
exist", partitionId));
- }
+ if (partitionStorage == null) {
+ throw new StorageException(String.format("Partition ID %d does
not exist", partitionId));
+ }
- return partitionStorage.getOrCreateHashIndex(indexId);
+ return partitionStorage.getOrCreateHashIndex(indexId);
+ });
}
@Override
@@ -276,4 +300,8 @@ public abstract class AbstractPageMemoryTableStorage
implements MvTableStorage {
));
}
}
+
+ private <V> V busy(Supplier<V> supplier) {
+ return inBusyLock(busyLock, supplier);
+ }
}
diff --git
a/modules/storage-page-memory/src/main/java/org/apache/ignite/internal/storage/pagememory/PersistentPageMemoryStorageEngine.java
b/modules/storage-page-memory/src/main/java/org/apache/ignite/internal/storage/pagememory/PersistentPageMemoryStorageEngine.java
index 79a5e81019..3c6a644d82 100644
---
a/modules/storage-page-memory/src/main/java/org/apache/ignite/internal/storage/pagememory/PersistentPageMemoryStorageEngine.java
+++
b/modules/storage-page-memory/src/main/java/org/apache/ignite/internal/storage/pagememory/PersistentPageMemoryStorageEngine.java
@@ -189,7 +189,7 @@ public class PersistentPageMemoryStorageEngine implements
StorageEngine {
throws StorageException {
PersistentPageMemoryDataStorageView dataStorageView =
(PersistentPageMemoryDataStorageView) tableCfg.dataStorage().value();
- return new PersistentPageMemoryTableStorage(this, tableCfg,
regions.get(dataStorageView.dataRegion()), tablesCfg);
+ return new PersistentPageMemoryTableStorage(tableCfg, tablesCfg, this,
regions.get(dataStorageView.dataRegion()));
}
/**
diff --git
a/modules/storage-page-memory/src/main/java/org/apache/ignite/internal/storage/pagememory/PersistentPageMemoryTableStorage.java
b/modules/storage-page-memory/src/main/java/org/apache/ignite/internal/storage/pagememory/PersistentPageMemoryTableStorage.java
index 2162a7bc56..e0c0fb59f0 100644
---
a/modules/storage-page-memory/src/main/java/org/apache/ignite/internal/storage/pagememory/PersistentPageMemoryTableStorage.java
+++
b/modules/storage-page-memory/src/main/java/org/apache/ignite/internal/storage/pagememory/PersistentPageMemoryTableStorage.java
@@ -61,15 +61,15 @@ public class PersistentPageMemoryTableStorage extends
AbstractPageMemoryTableSto
/**
* Constructor.
*
- * @param engine Storage engine instance.
* @param tableCfg Table configuration.
+ * @param engine Storage engine instance.
* @param dataRegion Data region for the table.
*/
public PersistentPageMemoryTableStorage(
- PersistentPageMemoryStorageEngine engine,
TableConfiguration tableCfg,
- PersistentPageMemoryDataRegion dataRegion,
- TablesConfiguration tablesCfg
+ TablesConfiguration tablesCfg,
+ PersistentPageMemoryStorageEngine engine,
+ PersistentPageMemoryDataRegion dataRegion
) {
super(tableCfg, tablesCfg);
@@ -156,7 +156,7 @@ public class PersistentPageMemoryTableStorage extends
AbstractPageMemoryTableSto
indexColumnsFreeList,
versionChainTree,
indexMetaTree,
- tablesConfiguration
+ tablesCfg
);
} catch (IgniteInternalCheckedException e) {
throw new StorageException(
diff --git
a/modules/storage-page-memory/src/main/java/org/apache/ignite/internal/storage/pagememory/VolatilePageMemoryTableStorage.java
b/modules/storage-page-memory/src/main/java/org/apache/ignite/internal/storage/pagememory/VolatilePageMemoryTableStorage.java
index 6110f22cd4..fb6cf5f178 100644
---
a/modules/storage-page-memory/src/main/java/org/apache/ignite/internal/storage/pagememory/VolatilePageMemoryTableStorage.java
+++
b/modules/storage-page-memory/src/main/java/org/apache/ignite/internal/storage/pagememory/VolatilePageMemoryTableStorage.java
@@ -72,7 +72,7 @@ public class VolatilePageMemoryTableStorage extends
AbstractPageMemoryTableStora
return new VolatilePageMemoryMvPartitionStorage(
this,
- tablesConfiguration,
+ tablesCfg,
partitionId,
versionChainTree,
indexMetaTree,
diff --git
a/modules/storage-page-memory/src/main/java/org/apache/ignite/internal/storage/pagememory/index/hash/PageMemoryHashIndexStorage.java
b/modules/storage-page-memory/src/main/java/org/apache/ignite/internal/storage/pagememory/index/hash/PageMemoryHashIndexStorage.java
index cc2e3e2c26..fe2422f229 100644
---
a/modules/storage-page-memory/src/main/java/org/apache/ignite/internal/storage/pagememory/index/hash/PageMemoryHashIndexStorage.java
+++
b/modules/storage-page-memory/src/main/java/org/apache/ignite/internal/storage/pagememory/index/hash/PageMemoryHashIndexStorage.java
@@ -17,8 +17,8 @@
package org.apache.ignite.internal.storage.pagememory.index.hash;
-import java.lang.invoke.MethodHandles;
-import java.lang.invoke.VarHandle;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.function.Supplier;
import org.apache.ignite.internal.schema.BinaryTuple;
import org.apache.ignite.internal.storage.RowId;
import org.apache.ignite.internal.storage.StorageClosedException;
@@ -36,16 +36,6 @@ import org.apache.ignite.lang.IgniteInternalCheckedException;
* Implementation of Hash index storage using Page Memory.
*/
public class PageMemoryHashIndexStorage implements HashIndexStorage {
- private static final VarHandle CLOSED;
-
- static {
- try {
- CLOSED =
MethodHandles.lookup().findVarHandle(PageMemoryHashIndexStorage.class,
"closed", boolean.class);
- } catch (ReflectiveOperationException e) {
- throw new ExceptionInInitializerError(e);
- }
- }
-
/** Index descriptor. */
private final HashIndexDescriptor descriptor;
@@ -65,11 +55,10 @@ public class PageMemoryHashIndexStorage implements
HashIndexStorage {
private final RowId highestRowId;
/** Busy lock for synchronous closing. */
- private final IgniteSpinBusyLock closeBusyLock = new IgniteSpinBusyLock();
+ private final IgniteSpinBusyLock busyLock = new IgniteSpinBusyLock();
- /** To avoid double closure. */
- @SuppressWarnings("unused")
- private volatile boolean closed;
+ /** Prevents double stopping of the component. */
+ private final AtomicBoolean stopGuard = new AtomicBoolean();
/**
* Constructor.
@@ -97,100 +86,76 @@ public class PageMemoryHashIndexStorage implements
HashIndexStorage {
@Override
public Cursor<RowId> get(BinaryTuple key) throws StorageException {
- if (!closeBusyLock.enterBusy()) {
- throwStorageClosedException();
- }
-
- try {
- IndexColumns indexColumns = new IndexColumns(partitionId,
key.byteBuffer());
-
- HashIndexRow lowerBound = new HashIndexRow(indexColumns,
lowestRowId);
- HashIndexRow upperBound = new HashIndexRow(indexColumns,
highestRowId);
+ return busy(() -> {
+ try {
+ IndexColumns indexColumns = new IndexColumns(partitionId,
key.byteBuffer());
- Cursor<HashIndexRow> cursor = hashIndexTree.find(lowerBound,
upperBound);
+ HashIndexRow lowerBound = new HashIndexRow(indexColumns,
lowestRowId);
+ HashIndexRow upperBound = new HashIndexRow(indexColumns,
highestRowId);
- return new Cursor<>() {
- @Override
- public void close() {
- cursor.close();
- }
-
- @Override
- public boolean hasNext() {
- if (!closeBusyLock.enterBusy()) {
- throwStorageClosedException();
- }
+ Cursor<HashIndexRow> cursor = hashIndexTree.find(lowerBound,
upperBound);
- try {
- return cursor.hasNext();
- } finally {
- closeBusyLock.leaveBusy();
+ return new Cursor<RowId>() {
+ @Override
+ public void close() {
+ cursor.close();
}
- }
- @Override
- public RowId next() {
- if (!closeBusyLock.enterBusy()) {
- throwStorageClosedException();
+ @Override
+ public boolean hasNext() {
+ return busy(cursor::hasNext);
}
- try {
- return cursor.next().rowId();
- } finally {
- closeBusyLock.leaveBusy();
+ @Override
+ public RowId next() {
+ return busy(() -> cursor.next().rowId());
}
- }
- };
- } catch (IgniteInternalCheckedException e) {
- throw new StorageException("Failed to create scan cursor", e);
- } finally {
- closeBusyLock.leaveBusy();
- }
+ };
+ } catch (IgniteInternalCheckedException e) {
+ throw new StorageException("Failed to create scan cursor", e);
+ }
+ });
}
@Override
public void put(IndexRow row) throws StorageException {
- if (!closeBusyLock.enterBusy()) {
- throwStorageClosedException();
- }
+ busy(() -> {
+ try {
+ IndexColumns indexColumns = new IndexColumns(partitionId,
row.indexColumns().byteBuffer());
- try {
- IndexColumns indexColumns = new IndexColumns(partitionId,
row.indexColumns().byteBuffer());
+ HashIndexRow hashIndexRow = new HashIndexRow(indexColumns,
row.rowId());
- HashIndexRow hashIndexRow = new HashIndexRow(indexColumns,
row.rowId());
+ var insert = new InsertHashIndexRowInvokeClosure(hashIndexRow,
freeList, hashIndexTree.inlineSize());
- var insert = new InsertHashIndexRowInvokeClosure(hashIndexRow,
freeList, hashIndexTree.inlineSize());
+ hashIndexTree.invoke(hashIndexRow, null, insert);
- hashIndexTree.invoke(hashIndexRow, null, insert);
- } catch (IgniteInternalCheckedException e) {
- throw new StorageException("Failed to put value into index", e);
- } finally {
- closeBusyLock.leaveBusy();
- }
+ return null;
+ } catch (IgniteInternalCheckedException e) {
+ throw new StorageException("Failed to put value into index",
e);
+ }
+ });
}
@Override
public void remove(IndexRow row) throws StorageException {
- if (!closeBusyLock.enterBusy()) {
- throwStorageClosedException();
- }
+ busy(() -> {
+ try {
+ IndexColumns indexColumns = new IndexColumns(partitionId,
row.indexColumns().byteBuffer());
- try {
- IndexColumns indexColumns = new IndexColumns(partitionId,
row.indexColumns().byteBuffer());
+ HashIndexRow hashIndexRow = new HashIndexRow(indexColumns,
row.rowId());
- HashIndexRow hashIndexRow = new HashIndexRow(indexColumns,
row.rowId());
+ var remove = new RemoveHashIndexRowInvokeClosure(hashIndexRow,
freeList);
- var remove = new RemoveHashIndexRowInvokeClosure(hashIndexRow,
freeList);
+ hashIndexTree.invoke(hashIndexRow, null, remove);
- hashIndexTree.invoke(hashIndexRow, null, remove);
+ // Performs actual deletion from freeList if necessary.
+ remove.afterCompletion();
- // Performs actual deletion from freeList if necessary.
- remove.afterCompletion();
- } catch (IgniteInternalCheckedException e) {
- throw new StorageException("Failed to remove value from index", e);
- } finally {
- closeBusyLock.leaveBusy();
- }
+ return null;
+ } catch (IgniteInternalCheckedException e) {
+ throw new StorageException("Failed to remove value from
index", e);
+ }
+ });
}
@Override
@@ -203,19 +168,24 @@ public class PageMemoryHashIndexStorage implements
HashIndexStorage {
* Closes the hash index storage.
*/
public void close() {
- if (!CLOSED.compareAndSet(this, false, true)) {
+ if (!stopGuard.compareAndSet(false, true)) {
return;
}
- closeBusyLock.block();
+ busyLock.block();
hashIndexTree.close();
}
- /**
- * Throws an exception that the storage is already closed.
- */
- private void throwStorageClosedException() {
- throw new StorageClosedException();
+ private <V> V busy(Supplier<V> supplier) {
+ if (!busyLock.enterBusy()) {
+ throw new StorageClosedException();
+ }
+
+ try {
+ return supplier.get();
+ } finally {
+ busyLock.leaveBusy();
+ }
}
}
diff --git
a/modules/storage-page-memory/src/main/java/org/apache/ignite/internal/storage/pagememory/index/sorted/PageMemorySortedIndexStorage.java
b/modules/storage-page-memory/src/main/java/org/apache/ignite/internal/storage/pagememory/index/sorted/PageMemorySortedIndexStorage.java
index 5c2c639e5f..46c730d8a3 100644
---
a/modules/storage-page-memory/src/main/java/org/apache/ignite/internal/storage/pagememory/index/sorted/PageMemorySortedIndexStorage.java
+++
b/modules/storage-page-memory/src/main/java/org/apache/ignite/internal/storage/pagememory/index/sorted/PageMemorySortedIndexStorage.java
@@ -17,11 +17,11 @@
package org.apache.ignite.internal.storage.pagememory.index.sorted;
-import java.lang.invoke.MethodHandles;
-import java.lang.invoke.VarHandle;
import java.nio.ByteBuffer;
import java.util.NoSuchElementException;
+import java.util.concurrent.atomic.AtomicBoolean;
import java.util.function.Function;
+import java.util.function.Supplier;
import org.apache.ignite.internal.binarytuple.BinaryTupleCommon;
import org.apache.ignite.internal.schema.BinaryTuple;
import org.apache.ignite.internal.schema.BinaryTuplePrefix;
@@ -44,16 +44,6 @@ import org.jetbrains.annotations.Nullable;
* Implementation of Sorted index storage using Page Memory.
*/
public class PageMemorySortedIndexStorage implements SortedIndexStorage {
- private static final VarHandle CLOSED;
-
- static {
- try {
- CLOSED =
MethodHandles.lookup().findVarHandle(PageMemorySortedIndexStorage.class,
"closed", boolean.class);
- } catch (ReflectiveOperationException e) {
- throw new ExceptionInInitializerError(e);
- }
- }
-
/** Index descriptor. */
private final SortedIndexDescriptor descriptor;
@@ -73,11 +63,10 @@ public class PageMemorySortedIndexStorage implements
SortedIndexStorage {
private final RowId highestRowId;
/** Busy lock for synchronous closing. */
- private final IgniteSpinBusyLock closeBusyLock = new IgniteSpinBusyLock();
+ private final IgniteSpinBusyLock busyLock = new IgniteSpinBusyLock();
- /** To avoid double closure. */
- @SuppressWarnings("unused")
- private volatile boolean closed;
+ /** Prevents double stopping of the component. */
+ private final AtomicBoolean stopGuard = new AtomicBoolean();
/**
* Constructor.
@@ -105,71 +94,59 @@ public class PageMemorySortedIndexStorage implements
SortedIndexStorage {
@Override
public Cursor<RowId> get(BinaryTuple key) throws StorageException {
- if (!closeBusyLock.enterBusy()) {
- throwStorageClosedException();
- }
-
- try {
- SortedIndexRowKey lowerBound = toSortedIndexRow(key, lowestRowId);
+ return busy(() -> {
+ try {
+ SortedIndexRowKey lowerBound = toSortedIndexRow(key,
lowestRowId);
- SortedIndexRowKey upperBound = toSortedIndexRow(key, highestRowId);
+ SortedIndexRowKey upperBound = toSortedIndexRow(key,
highestRowId);
- return convertCursor(sortedIndexTree.find(lowerBound, upperBound),
SortedIndexRow::rowId);
- } catch (IgniteInternalCheckedException e) {
- throw new StorageException("Failed to create scan cursor", e);
- } finally {
- closeBusyLock.leaveBusy();
- }
+ return convertCursor(sortedIndexTree.find(lowerBound,
upperBound), SortedIndexRow::rowId);
+ } catch (IgniteInternalCheckedException e) {
+ throw new StorageException("Failed to create scan cursor", e);
+ }
+ });
}
@Override
public void put(IndexRow row) {
- if (!closeBusyLock.enterBusy()) {
- throwStorageClosedException();
- }
+ busy(() -> {
+ try {
+ SortedIndexRow sortedIndexRow =
toSortedIndexRow(row.indexColumns(), row.rowId());
- try {
- SortedIndexRow sortedIndexRow =
toSortedIndexRow(row.indexColumns(), row.rowId());
+ var insert = new
InsertSortedIndexRowInvokeClosure(sortedIndexRow, freeList,
sortedIndexTree.inlineSize());
- var insert = new InsertSortedIndexRowInvokeClosure(sortedIndexRow,
freeList, sortedIndexTree.inlineSize());
+ sortedIndexTree.invoke(sortedIndexRow, null, insert);
- sortedIndexTree.invoke(sortedIndexRow, null, insert);
- } catch (IgniteInternalCheckedException e) {
- throw new StorageException("Failed to put value into index", e);
- } finally {
- closeBusyLock.leaveBusy();
- }
+ return null;
+ } catch (IgniteInternalCheckedException e) {
+ throw new StorageException("Failed to put value into index",
e);
+ }
+ });
}
@Override
public void remove(IndexRow row) {
- if (!closeBusyLock.enterBusy()) {
- throwStorageClosedException();
- }
+ busy(() -> {
+ try {
+ SortedIndexRow sortedIndexRow =
toSortedIndexRow(row.indexColumns(), row.rowId());
- try {
- SortedIndexRow sortedIndexRow =
toSortedIndexRow(row.indexColumns(), row.rowId());
+ var remove = new
RemoveSortedIndexRowInvokeClosure(sortedIndexRow, freeList);
- var remove = new RemoveSortedIndexRowInvokeClosure(sortedIndexRow,
freeList);
+ sortedIndexTree.invoke(sortedIndexRow, null, remove);
- sortedIndexTree.invoke(sortedIndexRow, null, remove);
+ // Performs actual deletion from freeList if necessary.
+ remove.afterCompletion();
- // Performs actual deletion from freeList if necessary.
- remove.afterCompletion();
- } catch (IgniteInternalCheckedException e) {
- throw new StorageException("Failed to remove value from index", e);
- } finally {
- closeBusyLock.leaveBusy();
- }
+ return null;
+ } catch (IgniteInternalCheckedException e) {
+ throw new StorageException("Failed to remove value from
index", e);
+ }
+ });
}
@Override
public PeekCursor<IndexRow> scan(@Nullable BinaryTuplePrefix lowerBound,
@Nullable BinaryTuplePrefix upperBound, int flags) {
- if (!closeBusyLock.enterBusy()) {
- throwStorageClosedException();
- }
-
- try {
+ return busy(() -> {
boolean includeLower = (flags & GREATER_OR_EQUAL) != 0;
boolean includeUpper = (flags & LESS_OR_EQUAL) != 0;
@@ -178,13 +155,10 @@ public class PageMemorySortedIndexStorage implements
SortedIndexStorage {
SortedIndexRowKey upper = createBound(upperBound, includeUpper);
return new ScanCursor(lower, upper);
- } finally {
- closeBusyLock.leaveBusy();
- }
+ });
}
- @Nullable
- private SortedIndexRowKey createBound(@Nullable BinaryTuplePrefix bound,
boolean setEqualityFlag) {
+ private @Nullable SortedIndexRowKey createBound(@Nullable
BinaryTuplePrefix bound, boolean setEqualityFlag) {
if (bound == null) {
return null;
}
@@ -215,22 +189,15 @@ public class PageMemorySortedIndexStorage implements
SortedIndexStorage {
* Closes the sorted index storage.
*/
public void close() {
- if (!CLOSED.compareAndSet(this, false, true)) {
+ if (!stopGuard.compareAndSet(false, true)) {
return;
}
- closeBusyLock.block();
+ busyLock.block();
sortedIndexTree.close();
}
- /**
- * Throws an exception that the storage is already closed.
- */
- private void throwStorageClosedException() {
- throw new StorageClosedException();
- }
-
/**
* Returns a new cursor that converts elements to another type, and also
throws {@link StorageClosedException} on
* {@link Cursor#hasNext()} and {@link Cursor#next()} when the sorted
index storage is {@link #close()}.
@@ -247,28 +214,12 @@ public class PageMemorySortedIndexStorage implements
SortedIndexStorage {
@Override
public boolean hasNext() {
- if (!closeBusyLock.enterBusy()) {
- throwStorageClosedException();
- }
-
- try {
- return cursor.hasNext();
- } finally {
- closeBusyLock.leaveBusy();
- }
+ return busy(cursor::hasNext);
}
@Override
public R next() {
- if (!closeBusyLock.enterBusy()) {
- throwStorageClosedException();
- }
-
- try {
- return mapper.apply(cursor.next());
- } finally {
- closeBusyLock.leaveBusy();
- }
+ return busy(() -> mapper.apply(cursor.next()));
}
};
}
@@ -298,73 +249,67 @@ public class PageMemorySortedIndexStorage implements
SortedIndexStorage {
@Override
public boolean hasNext() {
- if (!closeBusyLock.enterBusy()) {
- throwStorageClosedException();
- }
-
- try {
- advanceIfNeeded();
+ return busy(() -> {
+ try {
+ advanceIfNeeded();
- return hasNext;
- } catch (IgniteInternalCheckedException e) {
- throw new StorageException("Error while advancing the cursor",
e);
- } finally {
- closeBusyLock.leaveBusy();
- }
+ return hasNext;
+ } catch (IgniteInternalCheckedException e) {
+ throw new StorageException("Error while advancing the
cursor", e);
+ }
+ });
}
@Override
public IndexRow next() {
- if (!closeBusyLock.enterBusy()) {
- throwStorageClosedException();
- }
-
- try {
- advanceIfNeeded();
+ return busy(() -> {
+ try {
+ advanceIfNeeded();
- boolean hasNext = this.hasNext;
+ boolean hasNext = this.hasNext;
- if (!hasNext) {
- throw new NoSuchElementException();
- }
+ if (!hasNext) {
+ throw new NoSuchElementException();
+ }
- this.hasNext = null;
+ this.hasNext = null;
- return toIndexRowImpl(treeRow);
- } catch (IgniteInternalCheckedException e) {
- throw new StorageException("Error while advancing the cursor",
e);
- } finally {
- closeBusyLock.leaveBusy();
- }
+ return toIndexRowImpl(treeRow);
+ } catch (IgniteInternalCheckedException e) {
+ throw new StorageException("Error while advancing the
cursor", e);
+ }
+ });
}
@Override
public @Nullable IndexRow peek() {
- if (hasNext != null) {
- if (hasNext) {
- return toIndexRowImpl(treeRow);
+ return busy(() -> {
+ if (hasNext != null) {
+ if (hasNext) {
+ return toIndexRowImpl(treeRow);
+ }
+
+ return null;
}
- return null;
- }
+ try {
+ SortedIndexRow nextTreeRow;
- try {
- SortedIndexRow nextTreeRow;
+ if (treeRow == null) {
+ nextTreeRow = lower == null ?
sortedIndexTree.findFirst() : sortedIndexTree.findNext(lower, true);
+ } else {
+ nextTreeRow = sortedIndexTree.findNext(treeRow, false);
+ }
- if (treeRow == null) {
- nextTreeRow = lower == null ? sortedIndexTree.findFirst()
: sortedIndexTree.findNext(lower, true);
- } else {
- nextTreeRow = sortedIndexTree.findNext(treeRow, false);
- }
+ if (nextTreeRow == null || (upper != null &&
compareRows(nextTreeRow, upper) >= 0)) {
+ return null;
+ }
- if (nextTreeRow == null || (upper != null &&
compareRows(nextTreeRow, upper) >= 0)) {
- return null;
+ return toIndexRowImpl(nextTreeRow);
+ } catch (IgniteInternalCheckedException e) {
+ throw new StorageException("Error when peeking next
element", e);
}
-
- return toIndexRowImpl(nextTreeRow);
- } catch (IgniteInternalCheckedException e) {
- throw new StorageException("Error when peeking next element",
e);
- }
+ });
}
private void advanceIfNeeded() throws IgniteInternalCheckedException {
@@ -396,4 +341,16 @@ public class PageMemorySortedIndexStorage implements
SortedIndexStorage {
);
}
}
+
+ private <V> V busy(Supplier<V> supplier) {
+ if (!busyLock.enterBusy()) {
+ throw new StorageClosedException();
+ }
+
+ try {
+ return supplier.get();
+ } finally {
+ busyLock.leaveBusy();
+ }
+ }
}
diff --git
a/modules/storage-page-memory/src/main/java/org/apache/ignite/internal/storage/pagememory/mv/AbstractPageMemoryMvPartitionStorage.java
b/modules/storage-page-memory/src/main/java/org/apache/ignite/internal/storage/pagememory/mv/AbstractPageMemoryMvPartitionStorage.java
index 7df72b562b..5496706fd4 100644
---
a/modules/storage-page-memory/src/main/java/org/apache/ignite/internal/storage/pagememory/mv/AbstractPageMemoryMvPartitionStorage.java
+++
b/modules/storage-page-memory/src/main/java/org/apache/ignite/internal/storage/pagememory/mv/AbstractPageMemoryMvPartitionStorage.java
@@ -20,18 +20,17 @@ package org.apache.ignite.internal.storage.pagememory.mv;
import static
org.apache.ignite.internal.configuration.util.ConfigurationUtil.getByInternalId;
import static org.apache.ignite.internal.pagememory.util.PageIdUtils.NULL_LINK;
-import java.lang.invoke.MethodHandles;
-import java.lang.invoke.VarHandle;
import java.nio.ByteBuffer;
-import java.util.Iterator;
+import java.util.ArrayList;
+import java.util.List;
import java.util.NoSuchElementException;
-import java.util.Objects;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
+import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicLong;
import java.util.function.Predicate;
-import java.util.stream.Stream;
+import java.util.function.Supplier;
import org.apache.ignite.configuration.NamedListView;
import org.apache.ignite.internal.hlc.HybridTimestamp;
import org.apache.ignite.internal.pagememory.PageIdAllocator;
@@ -64,8 +63,8 @@ import
org.apache.ignite.internal.storage.pagememory.index.meta.IndexMetaTree;
import
org.apache.ignite.internal.storage.pagememory.index.sorted.PageMemorySortedIndexStorage;
import
org.apache.ignite.internal.storage.pagememory.index.sorted.SortedIndexTree;
import org.apache.ignite.internal.util.Cursor;
-import org.apache.ignite.internal.util.CursorUtils;
import org.apache.ignite.internal.util.IgniteSpinBusyLock;
+import org.apache.ignite.internal.util.IgniteUtils;
import org.apache.ignite.lang.IgniteInternalCheckedException;
import org.jetbrains.annotations.Nullable;
@@ -77,16 +76,6 @@ public abstract class AbstractPageMemoryMvPartitionStorage
implements MvPartitio
private static final Predicate<HybridTimestamp> ALWAYS_LOAD_VALUE =
timestamp -> true;
- protected static final VarHandle STARTED;
-
- static {
- try {
- STARTED =
MethodHandles.lookup().findVarHandle(AbstractPageMemoryMvPartitionStorage.class,
"started", boolean.class);
- } catch (ReflectiveOperationException e) {
- throw new ExceptionInInitializerError(e);
- }
- }
-
protected final int partitionId;
protected final int groupId;
@@ -101,8 +90,6 @@ public abstract class AbstractPageMemoryMvPartitionStorage
implements MvPartitio
protected final IndexMetaTree indexMetaTree;
- private final TablesConfiguration tablesConfiguration;
-
protected final DataPageReader rowVersionDataPageReader;
protected final ConcurrentMap<UUID, PageMemoryHashIndexStorage>
hashIndexes = new ConcurrentHashMap<>();
@@ -110,11 +97,10 @@ public abstract class AbstractPageMemoryMvPartitionStorage
implements MvPartitio
protected final ConcurrentMap<UUID, PageMemorySortedIndexStorage>
sortedIndexes = new ConcurrentHashMap<>();
/** Busy lock for synchronous closing. */
- protected final IgniteSpinBusyLock closeBusyLock = new
IgniteSpinBusyLock();
+ protected final IgniteSpinBusyLock busyLock = new IgniteSpinBusyLock();
- /** To avoid double closure. */
- @SuppressWarnings("unused")
- private volatile boolean started;
+ /** Prevents double stopping of the component. */
+ protected final AtomicBoolean stopGuard = new AtomicBoolean();
/**
* Constructor.
@@ -144,8 +130,6 @@ public abstract class AbstractPageMemoryMvPartitionStorage
implements MvPartitio
this.versionChainTree = versionChainTree;
this.indexMetaTree = indexMetaTree;
- tablesConfiguration = tablesCfg;
-
PageMemory pageMemory = tableStorage.dataRegion().pageMemory();
groupId = tableStorage.configuration().value().tableId();
@@ -157,35 +141,31 @@ public abstract class
AbstractPageMemoryMvPartitionStorage implements MvPartitio
* Starts a partition by initializing its internal structures.
*/
public void start() {
- if (!closeBusyLock.enterBusy()) {
- throwStorageClosedException();
- }
+ busy(() -> {
+ try (Cursor<IndexMeta> cursor = indexMetaTree.find(null, null)) {
+ NamedListView<TableIndexView> indexesCfgView =
tableStorage.tablesConfiguration().indexes().value();
- try (Cursor<IndexMeta> cursor = indexMetaTree.find(null, null)) {
- NamedListView<TableIndexView> indexesCfgView =
tablesConfiguration.indexes().value();
+ while (cursor.hasNext()) {
+ IndexMeta indexMeta = cursor.next();
- while (cursor.hasNext()) {
- IndexMeta indexMeta = cursor.next();
+ TableIndexView indexCfgView =
getByInternalId(indexesCfgView, indexMeta.id());
- TableIndexView indexCfgView = getByInternalId(indexesCfgView,
indexMeta.id());
+ if (indexCfgView instanceof HashIndexView) {
+ createOrRestoreHashIndex(indexMeta);
+ } else if (indexCfgView instanceof SortedIndexView) {
+ createOrRestoreSortedIndex(indexMeta);
+ } else {
+ assert indexCfgView == null;
- if (indexCfgView instanceof HashIndexView) {
- createOrRestoreHashIndex(indexMeta);
- } else if (indexCfgView instanceof SortedIndexView) {
- createOrRestoreSortedIndex(indexMeta);
- } else {
- assert indexCfgView == null;
-
- //TODO: IGNITE-17626 Drop the index synchronously.
+ //TODO: IGNITE-17626 Drop the index synchronously.
+ }
}
- }
- } catch (Exception e) {
- throw new StorageException("Failed to process SQL indexes during
the partition start", e);
- } finally {
- closeBusyLock.leaveBusy();
- }
- started = true;
+ return null;
+ } catch (Exception e) {
+ throw new StorageException("Failed to process SQL indexes
during the partition start", e);
+ }
+ });
}
/**
@@ -201,15 +181,7 @@ public abstract class AbstractPageMemoryMvPartitionStorage
implements MvPartitio
* @param indexId Index UUID.
*/
public PageMemoryHashIndexStorage getOrCreateHashIndex(UUID indexId) {
- if (!closeBusyLock.enterBusy()) {
- throwStorageClosedException();
- }
-
- try {
- return hashIndexes.computeIfAbsent(indexId, uuid ->
createOrRestoreHashIndex(new IndexMeta(indexId, 0L)));
- } finally {
- closeBusyLock.leaveBusy();
- }
+ return busy(() -> hashIndexes.computeIfAbsent(indexId, uuid ->
createOrRestoreHashIndex(new IndexMeta(indexId, 0L))));
}
/**
@@ -218,19 +190,11 @@ public abstract class
AbstractPageMemoryMvPartitionStorage implements MvPartitio
* @param indexId Index UUID.
*/
public PageMemorySortedIndexStorage getOrCreateSortedIndex(UUID indexId) {
- if (!closeBusyLock.enterBusy()) {
- throwStorageClosedException();
- }
-
- try {
- return sortedIndexes.computeIfAbsent(indexId, uuid ->
createOrRestoreSortedIndex(new IndexMeta(indexId, 0L)));
- } finally {
- closeBusyLock.leaveBusy();
- }
+ return busy(() -> sortedIndexes.computeIfAbsent(indexId, uuid ->
createOrRestoreSortedIndex(new IndexMeta(indexId, 0L))));
}
private PageMemoryHashIndexStorage createOrRestoreHashIndex(IndexMeta
indexMeta) {
- var indexDescriptor = new HashIndexDescriptor(indexMeta.id(),
tablesConfiguration.value());
+ var indexDescriptor = new HashIndexDescriptor(indexMeta.id(),
tableStorage.tablesConfiguration().value());
try {
PageMemory pageMemory = tableStorage.dataRegion().pageMemory();
@@ -269,7 +233,7 @@ public abstract class AbstractPageMemoryMvPartitionStorage
implements MvPartitio
}
private PageMemorySortedIndexStorage createOrRestoreSortedIndex(IndexMeta
indexMeta) {
- var indexDescriptor = new SortedIndexDescriptor(indexMeta.id(),
tablesConfiguration.value());
+ var indexDescriptor = new SortedIndexDescriptor(indexMeta.id(),
tableStorage.tablesConfiguration().value());
try {
PageMemory pageMemory = tableStorage.dataRegion().pageMemory();
@@ -309,11 +273,7 @@ public abstract class AbstractPageMemoryMvPartitionStorage
implements MvPartitio
@Override
public ReadResult read(RowId rowId, HybridTimestamp timestamp) throws
StorageException {
- if (!closeBusyLock.enterBusy()) {
- throwStorageClosedException();
- }
-
- try {
+ return busy(() -> {
if (rowId.partitionId() != partitionId) {
throw new IllegalArgumentException(
String.format("RowId partition [%d] is not equal to
storage partition [%d].", rowId.partitionId(), partitionId));
@@ -330,9 +290,7 @@ public abstract class AbstractPageMemoryMvPartitionStorage
implements MvPartitio
} else {
return findRowVersionByTimestamp(versionChain, timestamp);
}
- } finally {
- closeBusyLock.leaveBusy();
- }
+ });
}
private boolean lookingForLatestVersion(HybridTimestamp timestamp) {
@@ -530,11 +488,7 @@ public abstract class AbstractPageMemoryMvPartitionStorage
implements MvPartitio
throws TxIdMismatchException, StorageException {
assert rowId.partitionId() == partitionId : rowId;
- if (!closeBusyLock.enterBusy()) {
- throwStorageClosedException();
- }
-
- try {
+ return busy(() -> {
VersionChain currentChain = findVersionChain(rowId);
if (currentChain == null) {
@@ -571,20 +525,14 @@ public abstract class
AbstractPageMemoryMvPartitionStorage implements MvPartitio
updateVersionChain(chainReplacement);
return res;
- } finally {
- closeBusyLock.leaveBusy();
- }
+ });
}
@Override
public @Nullable BinaryRow abortWrite(RowId rowId) throws StorageException
{
assert rowId.partitionId() == partitionId : rowId;
- if (!closeBusyLock.enterBusy()) {
- throwStorageClosedException();
- }
-
- try {
+ return busy(() -> {
VersionChain currentVersionChain = findVersionChain(rowId);
if (currentVersionChain == null ||
currentVersionChain.transactionId() == null) {
@@ -611,9 +559,7 @@ public abstract class AbstractPageMemoryMvPartitionStorage
implements MvPartitio
}
return rowVersionToBinaryRow(latestVersion);
- } finally {
- closeBusyLock.leaveBusy();
- }
+ });
}
private void removeVersionChain(VersionChain currentVersionChain) {
@@ -628,16 +574,12 @@ public abstract class
AbstractPageMemoryMvPartitionStorage implements MvPartitio
public void commitWrite(RowId rowId, HybridTimestamp timestamp) throws
StorageException {
assert rowId.partitionId() == partitionId : rowId;
- if (!closeBusyLock.enterBusy()) {
- throwStorageClosedException();
- }
-
- try {
+ busy(() -> {
VersionChain currentVersionChain = findVersionChain(rowId);
if (currentVersionChain == null ||
currentVersionChain.transactionId() == null) {
// Row doesn't exist or the chain doesn't contain an
uncommitted write intent.
- return;
+ return null;
}
long chainLink = currentVersionChain.headLink();
@@ -659,9 +601,9 @@ public abstract class AbstractPageMemoryMvPartitionStorage
implements MvPartitio
} catch (IgniteInternalCheckedException e) {
throw new StorageException("Cannot update transaction ID", e);
}
- } finally {
- closeBusyLock.leaveBusy();
- }
+
+ return null;
+ });
}
private void removeRowVersion(RowVersion currentVersion) {
@@ -684,11 +626,7 @@ public abstract class AbstractPageMemoryMvPartitionStorage
implements MvPartitio
public void addWriteCommitted(RowId rowId, @Nullable BinaryRow row,
HybridTimestamp commitTimestamp) throws StorageException {
assert rowId.partitionId() == partitionId : rowId;
- if (!closeBusyLock.enterBusy()) {
- throwStorageClosedException();
- }
-
- try {
+ busy(() -> {
VersionChain currentChain = findVersionChain(rowId);
if (currentChain != null && currentChain.isUncommitted()) {
@@ -703,9 +641,9 @@ public abstract class AbstractPageMemoryMvPartitionStorage
implements MvPartitio
VersionChain chainReplacement =
VersionChain.createCommitted(rowId, newVersion.link(), newVersion.nextLink());
updateVersionChain(chainReplacement);
- } finally {
- closeBusyLock.leaveBusy();
- }
+
+ return null;
+ });
}
private RowVersion insertCommittedRowVersion(@Nullable BinaryRow row,
HybridTimestamp commitTimestamp, long nextPartitionlessLink) {
@@ -720,47 +658,7 @@ public abstract class AbstractPageMemoryMvPartitionStorage
implements MvPartitio
@Override
public Cursor<ReadResult> scanVersions(RowId rowId) throws
StorageException {
- if (!closeBusyLock.enterBusy()) {
- throwStorageClosedException();
- }
-
- try {
- VersionChain versionChain = versionChainTree.findOne(new
VersionChainKey(rowId));
-
- if (versionChain == null) {
- return CursorUtils.emptyCursor();
- }
-
- RowVersion head = readRowVersion(versionChain.headLink(),
ALWAYS_LOAD_VALUE);
-
- Iterator<ReadResult> iterator = Stream.iterate(
- head,
- Objects::nonNull,
- rowVersion -> {
- if (!closeBusyLock.enterBusy()) {
- throwStorageClosedException();
- }
-
- try {
- if (!rowVersion.hasNextLink()) {
- return null;
- }
-
- return
readRowVersion(rowVersion.nextLink(), ALWAYS_LOAD_VALUE);
- } finally {
- closeBusyLock.leaveBusy();
- }
- }
- )
- .map(rowVersion ->
rowVersionToResultNotFillingLastCommittedTs(versionChain, rowVersion))
- .iterator();
-
- return Cursor.fromBareIterator(iterator);
- } catch (IgniteInternalCheckedException e) {
- throw new StorageException(e);
- } finally {
- closeBusyLock.leaveBusy();
- }
+ return busy(() -> new ScanVersionsCursor(rowId));
}
private static ReadResult
rowVersionToResultNotFillingLastCommittedTs(VersionChain versionChain,
RowVersion rowVersion) {
@@ -782,11 +680,7 @@ public abstract class AbstractPageMemoryMvPartitionStorage
implements MvPartitio
@Override
public PartitionTimestampCursor scan(HybridTimestamp timestamp) throws
StorageException {
- if (!closeBusyLock.enterBusy()) {
- throwStorageClosedException();
- }
-
- try {
+ return busy(() -> {
Cursor<VersionChain> treeCursor;
try {
@@ -800,39 +694,29 @@ public abstract class
AbstractPageMemoryMvPartitionStorage implements MvPartitio
} else {
return new TimestampCursor(treeCursor, timestamp);
}
- } finally {
- closeBusyLock.leaveBusy();
- }
+ });
}
@Override
public @Nullable RowId closestRowId(RowId lowerBound) throws
StorageException {
- if (!closeBusyLock.enterBusy()) {
- throwStorageClosedException();
- }
-
- try (Cursor<VersionChain> cursor = versionChainTree.find(new
VersionChainKey(lowerBound), null)) {
- return cursor.hasNext() ? cursor.next().rowId() : null;
- } catch (Exception e) {
- throw new StorageException("Error occurred while trying to read a
row id", e);
- } finally {
- closeBusyLock.leaveBusy();
- }
+ return busy(() -> {
+ try (Cursor<VersionChain> cursor = versionChainTree.find(new
VersionChainKey(lowerBound), null)) {
+ return cursor.hasNext() ? cursor.next().rowId() : null;
+ } catch (Exception e) {
+ throw new StorageException("Error occurred while trying to
read a row id", e);
+ }
+ });
}
@Override
public long rowsCount() {
- if (!closeBusyLock.enterBusy()) {
- throwStorageClosedException();
- }
-
- try {
- return versionChainTree.size();
- } catch (IgniteInternalCheckedException e) {
- throw new StorageException("Error occurred while fetching the
size.", e);
- } finally {
- closeBusyLock.leaveBusy();
- }
+ return busy(() -> {
+ try {
+ return versionChainTree.size();
+ } catch (IgniteInternalCheckedException e) {
+ throw new StorageException("Error occurred while fetching the
size.", e);
+ }
+ });
}
private abstract class BasePartitionTimestampCursor implements
PartitionTimestampCursor {
@@ -850,17 +734,19 @@ public abstract class
AbstractPageMemoryMvPartitionStorage implements MvPartitio
@Override
public final ReadResult next() {
- if (!hasNext()) {
- throw new NoSuchElementException("The cursor is exhausted");
- }
+ return busy(() -> {
+ if (!hasNext()) {
+ throw new NoSuchElementException("The cursor is
exhausted");
+ }
- assert nextRead != null;
+ assert nextRead != null;
- ReadResult res = nextRead;
+ ReadResult res = nextRead;
- nextRead = null;
+ nextRead = null;
- return res;
+ return res;
+ });
}
@Override
@@ -870,11 +756,7 @@ public abstract class AbstractPageMemoryMvPartitionStorage
implements MvPartitio
@Override
public @Nullable BinaryRow committed(HybridTimestamp timestamp) {
- if (!closeBusyLock.enterBusy()) {
- throwStorageClosedException();
- }
-
- try {
+ return busy(() -> {
if (currentChain == null) {
throw new IllegalStateException();
}
@@ -887,9 +769,7 @@ public abstract class AbstractPageMemoryMvPartitionStorage
implements MvPartitio
// We don't check if row conforms the key filter here, because
we've already checked it.
return result.binaryRow();
- } finally {
- closeBusyLock.leaveBusy();
- }
+ });
}
}
@@ -910,22 +790,18 @@ public abstract class
AbstractPageMemoryMvPartitionStorage implements MvPartitio
@Override
public boolean hasNext() {
- if (nextRead != null) {
- return true;
- }
-
- if (iterationExhausted) {
- return false;
- }
-
- currentChain = null;
+ return busy(() -> {
+ if (nextRead != null) {
+ return true;
+ }
- while (true) {
- if (!closeBusyLock.enterBusy()) {
- throwStorageClosedException();
+ if (iterationExhausted) {
+ return false;
}
- try {
+ currentChain = null;
+
+ while (true) {
if (!treeCursor.hasNext()) {
iterationExhausted = true;
@@ -943,10 +819,8 @@ public abstract class AbstractPageMemoryMvPartitionStorage
implements MvPartitio
currentChain = chain;
return true;
- } finally {
- closeBusyLock.leaveBusy();
}
- }
+ });
}
}
@@ -964,20 +838,16 @@ public abstract class
AbstractPageMemoryMvPartitionStorage implements MvPartitio
@Override
public boolean hasNext() {
- if (nextRead != null) {
- return true;
- }
-
- if (iterationExhausted) {
- return false;
- }
+ return busy(() -> {
+ if (nextRead != null) {
+ return true;
+ }
- while (true) {
- if (!closeBusyLock.enterBusy()) {
- throwStorageClosedException();
+ if (iterationExhausted) {
+ return false;
}
- try {
+ while (true) {
if (!treeCursor.hasNext()) {
iterationExhausted = true;
return false;
@@ -994,17 +864,127 @@ public abstract class
AbstractPageMemoryMvPartitionStorage implements MvPartitio
currentChain = chain;
return true;
- } finally {
- closeBusyLock.leaveBusy();
}
+ });
+ }
+ }
+
+ private class ScanVersionsCursor implements Cursor<ReadResult> {
+ final RowId rowId;
+
+ @Nullable
+ private Boolean hasNext;
+
+ @Nullable
+ private VersionChain versionChain;
+
+ @Nullable
+ private RowVersion rowVersion;
+
+ private ScanVersionsCursor(RowId rowId) {
+ this.rowId = rowId;
+ }
+
+ @Override
+ public void close() {
+ // No-op.
+ }
+
+ @Override
+ public boolean hasNext() {
+ return busy(() -> {
+ advanceIfNeeded();
+
+ return hasNext;
+ });
+ }
+
+ @Override
+ public ReadResult next() {
+ return busy(() -> {
+ advanceIfNeeded();
+
+ if (!hasNext) {
+ throw new NoSuchElementException();
+ }
+
+ hasNext = null;
+
+ return
rowVersionToResultNotFillingLastCommittedTs(versionChain, rowVersion);
+ });
+ }
+
+ private void advanceIfNeeded() {
+ if (hasNext != null) {
+ return;
+ }
+
+ if (versionChain == null) {
+ try {
+ versionChain = versionChainTree.findOne(new
VersionChainKey(rowId));
+ } catch (IgniteInternalCheckedException e) {
+ throw new StorageException(e);
+ }
+
+ rowVersion = versionChain == null ? null :
readRowVersion(versionChain.headLink(), ALWAYS_LOAD_VALUE);
+ } else {
+ rowVersion = !rowVersion.hasNextLink() ? null :
readRowVersion(rowVersion.nextLink(), ALWAYS_LOAD_VALUE);
}
+
+ hasNext = rowVersion != null;
+ }
+ }
+
+ @Override
+ public void close() {
+ if (!stopGuard.compareAndSet(false, true)) {
+ return;
+ }
+
+ busyLock.block();
+
+ try {
+ IgniteUtils.closeAll(getResourcesToClose());
+ } catch (Exception e) {
+ throw new StorageException(e);
}
}
/**
- * Throws an exception that the storage is already closed.
+ * Returns resources that should be closed on {@link #close()}.
*/
- protected void throwStorageClosedException() {
- throw new StorageClosedException();
+ protected List<AutoCloseable> getResourcesToClose() {
+ List<AutoCloseable> resources = new ArrayList<>();
+
+ resources.add(versionChainTree::close);
+ resources.add(indexMetaTree::close);
+
+ hashIndexes.values().forEach(index -> resources.add(index::close));
+ sortedIndexes.values().forEach(index -> resources.add(index::close));
+
+ resources.add(hashIndexes::clear);
+ resources.add(sortedIndexes::clear);
+
+ return resources;
+ }
+
+ /**
+ * Performs a supplier using a {@link #busyLock}.
+ *
+ * @param <V> Type of the returned value.
+ * @param supplier Supplier.
+ * @return Value.
+ * @throws StorageClosedException If the storage is closed.
+ */
+ protected <V> V busy(Supplier<V> supplier) {
+ if (!busyLock.enterBusy()) {
+ throw new StorageClosedException();
+ }
+
+ try {
+ return supplier.get();
+ } finally {
+ busyLock.leaveBusy();
+ }
}
}
diff --git
a/modules/storage-page-memory/src/main/java/org/apache/ignite/internal/storage/pagememory/mv/PersistentPageMemoryMvPartitionStorage.java
b/modules/storage-page-memory/src/main/java/org/apache/ignite/internal/storage/pagememory/mv/PersistentPageMemoryMvPartitionStorage.java
index 2bc5eba659..6576debc83 100644
---
a/modules/storage-page-memory/src/main/java/org/apache/ignite/internal/storage/pagememory/mv/PersistentPageMemoryMvPartitionStorage.java
+++
b/modules/storage-page-memory/src/main/java/org/apache/ignite/internal/storage/pagememory/mv/PersistentPageMemoryMvPartitionStorage.java
@@ -17,6 +17,7 @@
package org.apache.ignite.internal.storage.pagememory.mv;
+import java.util.List;
import java.util.UUID;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Executor;
@@ -45,7 +46,6 @@ import
org.apache.ignite.internal.storage.pagememory.index.meta.IndexMetaTree;
import
org.apache.ignite.internal.storage.pagememory.index.sorted.PageMemorySortedIndexStorage;
import org.apache.ignite.internal.util.ByteUtils;
import org.apache.ignite.lang.IgniteInternalCheckedException;
-import org.apache.ignite.lang.IgniteInternalException;
import org.jetbrains.annotations.Nullable;
/**
@@ -132,11 +132,7 @@ public class PersistentPageMemoryMvPartitionStorage
extends AbstractPageMemoryMv
@Override
public <V> V runConsistently(WriteClosure<V> closure) throws
StorageException {
- if (!closeBusyLock.enterBusy()) {
- throwStorageClosedException();
- }
-
- try {
+ return busy(() -> {
checkpointTimeoutLock.checkpointReadLock();
try {
@@ -144,18 +140,12 @@ public class PersistentPageMemoryMvPartitionStorage
extends AbstractPageMemoryMv
} finally {
checkpointTimeoutLock.checkpointReadUnlock();
}
- } finally {
- closeBusyLock.leaveBusy();
- }
+ });
}
@Override
public CompletableFuture<Void> flush() {
- if (!closeBusyLock.enterBusy()) {
- throwStorageClosedException();
- }
-
- try {
+ return busy(() -> {
CheckpointProgress lastCheckpoint =
checkpointManager.lastCheckpointProgress();
CheckpointProgress scheduledCheckpoint;
@@ -172,115 +162,93 @@ public class PersistentPageMemoryMvPartitionStorage
extends AbstractPageMemoryMv
}
return
scheduledCheckpoint.futureFor(CheckpointState.FINISHED).thenApply(res -> null);
- } finally {
- closeBusyLock.leaveBusy();
- }
+ });
}
@Override
public long lastAppliedIndex() {
- if (!closeBusyLock.enterBusy()) {
- throwStorageClosedException();
- }
-
- try {
- return meta.lastAppliedIndex();
- } finally {
- closeBusyLock.leaveBusy();
- }
+ return busy(meta::lastAppliedIndex);
}
@Override
public long lastAppliedTerm() {
- if (!closeBusyLock.enterBusy()) {
- throwStorageClosedException();
- }
-
- try {
- return meta.lastAppliedTerm();
- } finally {
- closeBusyLock.leaveBusy();
- }
+ return busy(meta::lastAppliedTerm);
}
@Override
public void lastApplied(long lastAppliedIndex, long lastAppliedTerm)
throws StorageException {
- assert checkpointTimeoutLock.checkpointLockIsHeldByThread();
+ busy(() -> {
+ assert checkpointTimeoutLock.checkpointLockIsHeldByThread();
+
+ CheckpointProgress lastCheckpoint =
checkpointManager.lastCheckpointProgress();
- CheckpointProgress lastCheckpoint =
checkpointManager.lastCheckpointProgress();
+ UUID lastCheckpointId = lastCheckpoint == null ? null :
lastCheckpoint.id();
- UUID lastCheckpointId = lastCheckpoint == null ? null :
lastCheckpoint.id();
+ meta.lastApplied(lastCheckpointId, lastAppliedIndex,
lastAppliedTerm);
- meta.lastApplied(lastCheckpointId, lastAppliedIndex, lastAppliedTerm);
+ return null;
+ });
}
@Override
public long persistedIndex() {
- if (!closeBusyLock.enterBusy()) {
- throwStorageClosedException();
- }
-
- try {
- return persistedIndex;
- } finally {
- closeBusyLock.leaveBusy();
- }
+ return busy(() -> persistedIndex);
}
@Override
@Nullable
public RaftGroupConfiguration committedGroupConfiguration() {
- if (!closeBusyLock.enterBusy()) {
- throwStorageClosedException();
- }
-
- try {
- replicationProtocolGroupConfigReadWriteLock.readLock().lock();
-
+ return busy(() -> {
try {
- long configFirstPageId =
meta.lastReplicationProtocolGroupConfigFirstPageId();
+ replicationProtocolGroupConfigReadWriteLock.readLock().lock();
- if (configFirstPageId == BlobStorage.NO_PAGE_ID) {
- return null;
- }
+ try {
+ long configFirstPageId =
meta.lastReplicationProtocolGroupConfigFirstPageId();
- byte[] bytes =
blobStorage.readBlob(meta.lastReplicationProtocolGroupConfigFirstPageId());
+ if (configFirstPageId == BlobStorage.NO_PAGE_ID) {
+ return null;
+ }
- return replicationProtocolGroupConfigFromBytes(bytes);
- } finally {
-
replicationProtocolGroupConfigReadWriteLock.readLock().unlock();
+ byte[] bytes =
blobStorage.readBlob(meta.lastReplicationProtocolGroupConfigFirstPageId());
+
+ return replicationProtocolGroupConfigFromBytes(bytes);
+ } finally {
+
replicationProtocolGroupConfigReadWriteLock.readLock().unlock();
+ }
+ } catch (IgniteInternalCheckedException e) {
+ throw new StorageException("Failed to read group config,
groupId=" + groupId + ", partitionId=" + partitionId, e);
}
- } catch (IgniteInternalCheckedException e) {
- throw new IgniteInternalException("Failed to read group config,
groupId=" + groupId + ", partitionId=" + partitionId, e);
- } finally {
- closeBusyLock.leaveBusy();
- }
+ });
}
@Override
public void committedGroupConfiguration(RaftGroupConfiguration config) {
- assert checkpointTimeoutLock.checkpointLockIsHeldByThread();
+ busy(() -> {
+ assert checkpointTimeoutLock.checkpointLockIsHeldByThread();
- CheckpointProgress lastCheckpoint =
checkpointManager.lastCheckpointProgress();
- UUID lastCheckpointId = lastCheckpoint == null ? null :
lastCheckpoint.id();
+ CheckpointProgress lastCheckpoint =
checkpointManager.lastCheckpointProgress();
+ UUID lastCheckpointId = lastCheckpoint == null ? null :
lastCheckpoint.id();
- byte[] groupConfigBytes =
replicationProtocolGroupConfigToBytes(config);
+ byte[] groupConfigBytes =
replicationProtocolGroupConfigToBytes(config);
- replicationProtocolGroupConfigReadWriteLock.writeLock().lock();
+ replicationProtocolGroupConfigReadWriteLock.writeLock().lock();
- try {
- if (meta.lastReplicationProtocolGroupConfigFirstPageId() ==
BlobStorage.NO_PAGE_ID) {
- long configPageId = blobStorage.addBlob(groupConfigBytes);
+ try {
+ if (meta.lastReplicationProtocolGroupConfigFirstPageId() ==
BlobStorage.NO_PAGE_ID) {
+ long configPageId = blobStorage.addBlob(groupConfigBytes);
-
meta.lastReplicationProtocolGroupConfigFirstPageId(lastCheckpointId,
configPageId);
- } else {
-
blobStorage.updateBlob(meta.lastReplicationProtocolGroupConfigFirstPageId(),
groupConfigBytes);
+
meta.lastReplicationProtocolGroupConfigFirstPageId(lastCheckpointId,
configPageId);
+ } else {
+
blobStorage.updateBlob(meta.lastReplicationProtocolGroupConfigFirstPageId(),
groupConfigBytes);
+ }
+ } catch (IgniteInternalCheckedException e) {
+ throw new StorageException("Cannot save committed group
configuration, groupId=" + groupId + ", partitionId=" + groupId, e);
+ } finally {
+
replicationProtocolGroupConfigReadWriteLock.writeLock().unlock();
}
- } catch (IgniteInternalCheckedException e) {
- throw new StorageException("Cannot save committed group
configuration, groupId=" + groupId + ", partitionId=" + groupId, e);
- } finally {
- replicationProtocolGroupConfigReadWriteLock.writeLock().unlock();
- }
+
+ return null;
+ });
}
@Nullable
@@ -307,33 +275,16 @@ public class PersistentPageMemoryMvPartitionStorage
extends AbstractPageMemoryMv
}
@Override
- public void close() {
- if (!STARTED.compareAndSet(this, true, false)) {
- return;
- }
-
- closeBusyLock.block();
-
- checkpointManager.removeCheckpointListener(checkpointListener);
+ protected List<AutoCloseable> getResourcesToClose() {
+ List<AutoCloseable> resourcesToClose = super.getResourcesToClose();
- rowVersionFreeList.close();
- indexFreeList.close();
+ resourcesToClose.add(() ->
checkpointManager.removeCheckpointListener(checkpointListener));
- versionChainTree.close();
- indexMetaTree.close();
-
- blobStorage.close();
-
- for (PageMemoryHashIndexStorage hashIndexStorage :
hashIndexes.values()) {
- hashIndexStorage.close();
- }
-
- for (PageMemorySortedIndexStorage sortedIndexStorage :
sortedIndexes.values()) {
- sortedIndexStorage.close();
- }
+ resourcesToClose.add(rowVersionFreeList::close);
+ resourcesToClose.add(indexFreeList::close);
+ resourcesToClose.add(blobStorage::close);
- hashIndexes.clear();
- sortedIndexes.clear();
+ return resourcesToClose;
}
/**
@@ -352,7 +303,7 @@ public class PersistentPageMemoryMvPartitionStorage extends
AbstractPageMemoryMv
try {
rowVersionFreeList.saveMetadata();
} catch (IgniteInternalCheckedException e) {
- throw new IgniteInternalException("Failed to save
RowVersionFreeList metadata", e);
+ throw new StorageException("Failed to save
RowVersionFreeList metadata", e);
}
});
@@ -360,7 +311,7 @@ public class PersistentPageMemoryMvPartitionStorage extends
AbstractPageMemoryMv
try {
indexFreeList.saveMetadata();
} catch (IgniteInternalCheckedException e) {
- throw new IgniteInternalException("Failed to save
IndexColumnsFreeList metadata", e);
+ throw new StorageException("Failed to save
IndexColumnsFreeList metadata", e);
}
});
}
diff --git
a/modules/storage-page-memory/src/main/java/org/apache/ignite/internal/storage/pagememory/mv/VolatilePageMemoryMvPartitionStorage.java
b/modules/storage-page-memory/src/main/java/org/apache/ignite/internal/storage/pagememory/mv/VolatilePageMemoryMvPartitionStorage.java
index 4eabeb9faf..0c7fc0b5bd 100644
---
a/modules/storage-page-memory/src/main/java/org/apache/ignite/internal/storage/pagememory/mv/VolatilePageMemoryMvPartitionStorage.java
+++
b/modules/storage-page-memory/src/main/java/org/apache/ignite/internal/storage/pagememory/mv/VolatilePageMemoryMvPartitionStorage.java
@@ -17,6 +17,8 @@
package org.apache.ignite.internal.storage.pagememory.mv;
+import static java.util.concurrent.CompletableFuture.completedFuture;
+
import java.util.concurrent.CompletableFuture;
import java.util.function.Predicate;
import org.apache.ignite.internal.hlc.HybridTimestamp;
@@ -28,9 +30,7 @@ import org.apache.ignite.internal.storage.MvPartitionStorage;
import org.apache.ignite.internal.storage.RaftGroupConfiguration;
import org.apache.ignite.internal.storage.StorageException;
import
org.apache.ignite.internal.storage.pagememory.VolatilePageMemoryTableStorage;
-import
org.apache.ignite.internal.storage.pagememory.index.hash.PageMemoryHashIndexStorage;
import org.apache.ignite.internal.storage.pagememory.index.meta.IndexMetaTree;
-import
org.apache.ignite.internal.storage.pagememory.index.sorted.PageMemorySortedIndexStorage;
import org.apache.ignite.lang.IgniteInternalCheckedException;
import org.apache.ignite.lang.IgniteInternalException;
import org.jetbrains.annotations.Nullable;
@@ -85,86 +85,42 @@ public class VolatilePageMemoryMvPartitionStorage extends
AbstractPageMemoryMvPa
@Override
public <V> V runConsistently(WriteClosure<V> closure) throws
StorageException {
- if (!closeBusyLock.enterBusy()) {
- throwStorageClosedException();
- }
-
- try {
- return closure.execute();
- } finally {
- closeBusyLock.leaveBusy();
- }
+ return busy(closure::execute);
}
@Override
public CompletableFuture<Void> flush() {
- if (!closeBusyLock.enterBusy()) {
- throwStorageClosedException();
- }
-
- try {
- return CompletableFuture.completedFuture(null);
- } finally {
- closeBusyLock.leaveBusy();
- }
+ return busy(() -> completedFuture(null));
}
@Override
public long lastAppliedIndex() {
- if (!closeBusyLock.enterBusy()) {
- throwStorageClosedException();
- }
-
- try {
- return lastAppliedIndex;
- } finally {
- closeBusyLock.leaveBusy();
- }
+ return busy(() -> lastAppliedIndex);
}
@Override
public long lastAppliedTerm() {
- if (!closeBusyLock.enterBusy()) {
- throwStorageClosedException();
- }
-
- try {
- return lastAppliedTerm;
- } finally {
- closeBusyLock.leaveBusy();
- }
+ return busy(() -> lastAppliedTerm);
}
@Override
public void lastApplied(long lastAppliedIndex, long lastAppliedTerm)
throws StorageException {
- this.lastAppliedIndex = lastAppliedIndex;
- this.lastAppliedTerm = lastAppliedTerm;
+ busy(() -> {
+ this.lastAppliedIndex = lastAppliedIndex;
+ this.lastAppliedTerm = lastAppliedTerm;
+
+ return null;
+ });
}
@Override
public long persistedIndex() {
- if (!closeBusyLock.enterBusy()) {
- throwStorageClosedException();
- }
-
- try {
- return lastAppliedIndex;
- } finally {
- closeBusyLock.leaveBusy();
- }
+ return busy(() -> lastAppliedIndex);
}
@Override
public @Nullable RaftGroupConfiguration committedGroupConfiguration() {
- if (!closeBusyLock.enterBusy()) {
- throwStorageClosedException();
- }
-
- try {
- return groupConfig;
- } finally {
- closeBusyLock.leaveBusy();
- }
+ return busy(() -> groupConfig);
}
@Override
@@ -172,29 +128,6 @@ public class VolatilePageMemoryMvPartitionStorage extends
AbstractPageMemoryMvPa
this.groupConfig = config;
}
- @Override
- public void close() {
- if (!STARTED.compareAndSet(this, true, false)) {
- return;
- }
-
- closeBusyLock.block();
-
- versionChainTree.close();
- indexMetaTree.close();
-
- for (PageMemoryHashIndexStorage hashIndexStorage :
hashIndexes.values()) {
- hashIndexStorage.close();
- }
-
- for (PageMemorySortedIndexStorage sortedIndexStorage :
sortedIndexes.values()) {
- sortedIndexStorage.close();
- }
-
- hashIndexes.clear();
- sortedIndexes.clear();
- }
-
/**
* Destroys internal structures backing this partition.
*