IGNITE-8920 - Fixed transaction hanging on Runtime exceptions during commit. - Unified StorageException and PersistentStorageIOException. - BPlus tree behavior is overridable in tests. - Refactored AccountTransferAmountTest to make it possible to develop any transaction failover based on it. - Fixes #4432.
Signed-off-by: Dmitriy Pavlov <dpav...@apache.org> Project: http://git-wip-us.apache.org/repos/asf/ignite/repo Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/dde936ac Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/dde936ac Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/dde936ac Branch: refs/heads/ignite-9273 Commit: dde936ace5eb0618edc360ca05006d76e810add8 Parents: 0020e41 Author: Pavel Kovalenko <jokse...@gmail.com> Authored: Wed Aug 22 17:24:27 2018 +0300 Committer: Dmitriy Pavlov <dpav...@apache.org> Committed: Wed Aug 22 17:24:27 2018 +0300 ---------------------------------------------------------------------- .../ignite/internal/NodeStoppingException.java | 2 +- .../pagemem/wal/IgniteWriteAheadLogManager.java | 1 + .../internal/pagemem/wal/StorageException.java | 53 -- .../processors/cache/GridCacheMapEntry.java | 2 +- .../cache/IgniteCacheOffheapManagerImpl.java | 4 +- .../GridDistributedTxRemoteAdapter.java | 43 +- .../distributed/dht/GridDhtTxFinishFuture.java | 5 +- .../dht/atomic/GridDhtAtomicCache.java | 2 +- .../GridCacheDatabaseSharedManager.java | 18 +- .../persistence/GridCacheOffheapManager.java | 1 - .../cache/persistence/StorageException.java | 53 ++ .../cache/persistence/file/FilePageStore.java | 48 +- .../persistence/file/FilePageStoreManager.java | 23 +- .../file/PersistentStorageIOException.java | 47 -- .../persistence/metastorage/MetaStorage.java | 2 +- .../cache/persistence/pagemem/PageMemoryEx.java | 2 +- .../persistence/pagemem/PageMemoryImpl.java | 2 +- .../cache/persistence/tree/BPlusTree.java | 111 ++-- .../tree/CorruptedTreeException.java | 38 ++ .../tree/util/PageHandlerWrapper.java | 36 ++ .../wal/FileWriteAheadLogManager.java | 2 +- .../wal/FsyncModeFileWriteAheadLogManager.java | 2 +- .../cache/transactions/IgniteTxAdapter.java | 37 +- .../transactions/IgniteTxLocalAdapter.java | 59 +- .../resources/META-INF/classnames.properties | 2 +- .../failure/AccountTransferTransactionTest.java | 331 ----------- .../IgnitePdsCorruptedStoreTest.java | 1 - .../db/wal/IgniteWalFormatFileFailoverTest.java | 2 +- .../persistence/pagemem/NoOpWALManager.java | 2 +- .../AbstractTransactionIntergrityTest.java | 595 +++++++++++++++++++ ...IntegrityWithPrimaryIndexCorruptionTest.java | 238 ++++++++ ...ctionIntegrityWithSystemWorkerDeathTest.java | 106 ++++ .../ignite/testsuites/IgniteBasicTestSuite.java | 5 +- .../IgniteBasicWithPersistenceTestSuite.java | 5 +- .../testsuites/IgniteCacheTestSuite6.java | 4 +- .../testsuites/IgniteCacheTestSuite7.java | 6 +- 36 files changed, 1265 insertions(+), 625 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/ignite/blob/dde936ac/modules/core/src/main/java/org/apache/ignite/internal/NodeStoppingException.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/internal/NodeStoppingException.java b/modules/core/src/main/java/org/apache/ignite/internal/NodeStoppingException.java index cc39b14..75447a1 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/NodeStoppingException.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/NodeStoppingException.java @@ -22,7 +22,7 @@ import org.apache.ignite.IgniteCheckedException; /** * */ -public class NodeStoppingException extends IgniteCheckedException implements InvalidEnvironmentException { +public class NodeStoppingException extends IgniteCheckedException { /** */ private static final long serialVersionUID = 0L; http://git-wip-us.apache.org/repos/asf/ignite/blob/dde936ac/modules/core/src/main/java/org/apache/ignite/internal/pagemem/wal/IgniteWriteAheadLogManager.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/internal/pagemem/wal/IgniteWriteAheadLogManager.java b/modules/core/src/main/java/org/apache/ignite/internal/pagemem/wal/IgniteWriteAheadLogManager.java index a43fd0d..b5282ff 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/pagemem/wal/IgniteWriteAheadLogManager.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/pagemem/wal/IgniteWriteAheadLogManager.java @@ -21,6 +21,7 @@ import org.apache.ignite.IgniteCheckedException; import org.apache.ignite.IgniteException; import org.apache.ignite.internal.pagemem.wal.record.WALRecord; import org.apache.ignite.internal.processors.cache.GridCacheSharedManager; +import org.apache.ignite.internal.processors.cache.persistence.StorageException; import org.apache.ignite.internal.processors.cluster.IgniteChangeGlobalStateSupport; /** http://git-wip-us.apache.org/repos/asf/ignite/blob/dde936ac/modules/core/src/main/java/org/apache/ignite/internal/pagemem/wal/StorageException.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/internal/pagemem/wal/StorageException.java b/modules/core/src/main/java/org/apache/ignite/internal/pagemem/wal/StorageException.java deleted file mode 100644 index debc391..0000000 --- a/modules/core/src/main/java/org/apache/ignite/internal/pagemem/wal/StorageException.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * 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.ignite.internal.pagemem.wal; - -import java.io.IOException; -import org.apache.ignite.IgniteCheckedException; -import org.apache.ignite.internal.InvalidEnvironmentException; -import org.jetbrains.annotations.NotNull; - -/** - * Exception is needed to distinguish WAL manager & page store critical I/O errors. - */ -public class StorageException extends IgniteCheckedException implements InvalidEnvironmentException { - /** */ - private static final long serialVersionUID = 0L; - - /** - * @param msg Error message. - * @param cause Error cause. - */ - public StorageException(String msg, @NotNull IOException cause) { - super(msg, cause); - } - - /** - * @param e Cause exception. - */ - public StorageException(IOException e) { - super(e); - } - - /** - * @param msg Error message - */ - public StorageException(String msg) { - super(msg); - } -} http://git-wip-us.apache.org/repos/asf/ignite/blob/dde936ac/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheMapEntry.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheMapEntry.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheMapEntry.java index 53c3945..a1722db 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheMapEntry.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheMapEntry.java @@ -37,7 +37,7 @@ import org.apache.ignite.cache.eviction.EvictableEntry; import org.apache.ignite.internal.NodeStoppingException; import org.apache.ignite.internal.UnregisteredBinaryTypeException; import org.apache.ignite.internal.UnregisteredClassException; -import org.apache.ignite.internal.pagemem.wal.StorageException; +import org.apache.ignite.internal.processors.cache.persistence.StorageException; import org.apache.ignite.internal.pagemem.wal.WALPointer; import org.apache.ignite.internal.pagemem.wal.record.DataEntry; import org.apache.ignite.internal.pagemem.wal.record.DataRecord; http://git-wip-us.apache.org/repos/asf/ignite/blob/dde936ac/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/IgniteCacheOffheapManagerImpl.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/IgniteCacheOffheapManagerImpl.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/IgniteCacheOffheapManagerImpl.java index 5482b3a..a8ad32d 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/IgniteCacheOffheapManagerImpl.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/IgniteCacheOffheapManagerImpl.java @@ -1584,7 +1584,7 @@ public class IgniteCacheOffheapManagerImpl implements IgniteCacheOffheapManager rowStore.removeRow(row.link()); } catch (IgniteCheckedException e) { - U.error(log, "Fail remove row [link=" + row.link() + "]"); + U.error(log, "Failed to remove row [link=" + row.link() + "]"); IgniteCheckedException ex = exception.get(); @@ -1597,7 +1597,7 @@ public class IgniteCacheOffheapManagerImpl implements IgniteCacheOffheapManager }); if (exception.get() != null) - throw new IgniteCheckedException("Fail destroy store", exception.get()); + throw new IgniteCheckedException("Failed to destroy store", exception.get()); } /** {@inheritDoc} */ http://git-wip-us.apache.org/repos/asf/ignite/blob/dde936ac/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/GridDistributedTxRemoteAdapter.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/GridDistributedTxRemoteAdapter.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/GridDistributedTxRemoteAdapter.java index 1b9b3a8..c1293fc 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/GridDistributedTxRemoteAdapter.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/GridDistributedTxRemoteAdapter.java @@ -29,9 +29,11 @@ import java.util.UUID; import java.util.concurrent.atomic.AtomicIntegerFieldUpdater; import java.util.stream.Collectors; import org.apache.ignite.IgniteCheckedException; -import org.apache.ignite.internal.InvalidEnvironmentException; +import org.apache.ignite.failure.FailureContext; +import org.apache.ignite.failure.FailureType; import org.apache.ignite.internal.IgniteInternalFuture; -import org.apache.ignite.internal.pagemem.wal.StorageException; +import org.apache.ignite.internal.InvalidEnvironmentException; +import org.apache.ignite.internal.NodeStoppingException; import org.apache.ignite.internal.pagemem.wal.WALPointer; import org.apache.ignite.internal.pagemem.wal.record.DataEntry; import org.apache.ignite.internal.pagemem.wal.record.DataRecord; @@ -49,6 +51,7 @@ import org.apache.ignite.internal.processors.cache.GridCacheSharedContext; import org.apache.ignite.internal.processors.cache.GridCacheUpdateTxResult; import org.apache.ignite.internal.processors.cache.KeyCacheObject; import org.apache.ignite.internal.processors.cache.distributed.near.GridNearCacheEntry; +import org.apache.ignite.internal.processors.cache.persistence.StorageException; import org.apache.ignite.internal.processors.cache.transactions.IgniteInternalTx; import org.apache.ignite.internal.processors.cache.transactions.IgniteTxAdapter; import org.apache.ignite.internal.processors.cache.transactions.IgniteTxEntry; @@ -744,26 +747,46 @@ public abstract class GridDistributedTxRemoteAdapter extends IgniteTxAdapter } } catch (Throwable ex) { - boolean hasIOIssue = X.hasCause(ex, InvalidEnvironmentException.class); + boolean isNodeStopping = X.hasCause(ex, NodeStoppingException.class); + boolean hasInvalidEnvironmentIssue = X.hasCause(ex, InvalidEnvironmentException.class); // In case of error, we still make the best effort to commit, // as there is no way to rollback at this point. err = new IgniteTxHeuristicCheckedException("Commit produced a runtime exception " + "(all transaction entries will be invalidated): " + CU.txString(this), ex); - if (hasIOIssue) { + if (isNodeStopping) { U.warn(log, "Failed to commit transaction, node is stopping [tx=" + this + ", err=" + ex + ']'); } + else if (hasInvalidEnvironmentIssue) { + U.warn(log, "Failed to commit transaction, node is in invalid state and will be stopped [tx=" + this + + ", err=" + ex + ']'); + } else U.error(log, "Commit failed.", err); - uncommit(hasIOIssue); - state(UNKNOWN); + if (hasInvalidEnvironmentIssue) + cctx.kernalContext().failure().process(new FailureContext(FailureType.CRITICAL_ERROR, ex)); + else if (!isNodeStopping) { // Skip fair uncommit in case of node stopping or invalidation. + try { + // Courtesy to minimize damage. + uncommit(); + } + catch (Throwable ex1) { + U.error(log, "Failed to uncommit transaction: " + this, ex1); + + if (ex1 instanceof Error) + throw ex1; + } + } + if (ex instanceof Error) - throw (Error)ex; + throw (Error) ex; + + throw err; } } @@ -792,12 +815,6 @@ public abstract class GridDistributedTxRemoteAdapter extends IgniteTxAdapter } } - if (err != null) { - state(UNKNOWN); - - throw err; - } - cctx.tm().commitTx(this); state(COMMITTED); http://git-wip-us.apache.org/repos/asf/ignite/blob/dde936ac/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtTxFinishFuture.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtTxFinishFuture.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtTxFinishFuture.java index 0ed8419..2f36053 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtTxFinishFuture.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtTxFinishFuture.java @@ -30,6 +30,7 @@ import org.apache.ignite.internal.InvalidEnvironmentException; import org.apache.ignite.internal.IgniteDiagnosticAware; import org.apache.ignite.internal.IgniteDiagnosticPrepareContext; import org.apache.ignite.internal.IgniteInternalFuture; +import org.apache.ignite.internal.NodeStoppingException; import org.apache.ignite.internal.cluster.ClusterTopologyCheckedException; import org.apache.ignite.internal.processors.cache.GridCacheCompoundIdentityFuture; import org.apache.ignite.internal.processors.cache.GridCacheFuture; @@ -168,7 +169,7 @@ public final class GridDhtTxFinishFuture<K, V> extends GridCacheCompoundIdentity if (ERR_UPD.compareAndSet(this, null, e)) { tx.setRollbackOnly(); - if (X.hasCause(e, InvalidEnvironmentException.class)) + if (X.hasCause(e, InvalidEnvironmentException.class, NodeStoppingException.class)) onComplete(); else finish(false); @@ -225,7 +226,7 @@ public final class GridDhtTxFinishFuture<K, V> extends GridCacheCompoundIdentity if (this.tx.onePhaseCommit() && (this.tx.state() == COMMITTING)) { try { - boolean hasInvalidEnvironmentIssue = X.hasCause(err, InvalidEnvironmentException.class); + boolean hasInvalidEnvironmentIssue = X.hasCause(err, InvalidEnvironmentException.class, NodeStoppingException.class); this.tx.tmFinish(err == null, hasInvalidEnvironmentIssue, false); } http://git-wip-us.apache.org/repos/asf/ignite/blob/dde936ac/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/atomic/GridDhtAtomicCache.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/atomic/GridDhtAtomicCache.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/atomic/GridDhtAtomicCache.java index fbb4359..2e77b52 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/atomic/GridDhtAtomicCache.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/atomic/GridDhtAtomicCache.java @@ -41,7 +41,7 @@ import org.apache.ignite.internal.UnregisteredBinaryTypeException; import org.apache.ignite.internal.UnregisteredClassException; import org.apache.ignite.internal.cluster.ClusterTopologyCheckedException; import org.apache.ignite.internal.mem.IgniteOutOfMemoryException; -import org.apache.ignite.internal.pagemem.wal.StorageException; +import org.apache.ignite.internal.processors.cache.persistence.StorageException; import org.apache.ignite.internal.processors.affinity.AffinityAssignment; import org.apache.ignite.internal.processors.affinity.AffinityTopologyVersion; import org.apache.ignite.internal.processors.cache.CacheEntryPredicate; http://git-wip-us.apache.org/repos/asf/ignite/blob/dde936ac/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/GridCacheDatabaseSharedManager.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/GridCacheDatabaseSharedManager.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/GridCacheDatabaseSharedManager.java index ce914e4..f955231 100755 --- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/GridCacheDatabaseSharedManager.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/GridCacheDatabaseSharedManager.java @@ -88,7 +88,6 @@ import org.apache.ignite.internal.pagemem.PageMemory; import org.apache.ignite.internal.pagemem.PageUtils; import org.apache.ignite.internal.pagemem.store.IgnitePageStoreManager; import org.apache.ignite.internal.pagemem.store.PageStore; -import org.apache.ignite.internal.pagemem.wal.StorageException; import org.apache.ignite.internal.pagemem.wal.WALIterator; import org.apache.ignite.internal.pagemem.wal.WALPointer; import org.apache.ignite.internal.pagemem.wal.record.CacheState; @@ -119,7 +118,6 @@ import org.apache.ignite.internal.processors.cache.persistence.file.FileIO; import org.apache.ignite.internal.processors.cache.persistence.file.FileIOFactory; import org.apache.ignite.internal.processors.cache.persistence.file.FilePageStore; import org.apache.ignite.internal.processors.cache.persistence.file.FilePageStoreManager; -import org.apache.ignite.internal.processors.cache.persistence.file.PersistentStorageIOException; import org.apache.ignite.internal.processors.cache.persistence.metastorage.MetaStorage; import org.apache.ignite.internal.processors.cache.persistence.metastorage.MetastorageLifecycleListener; import org.apache.ignite.internal.processors.cache.persistence.pagemem.CheckpointMetricsTracker; @@ -604,7 +602,7 @@ public class GridCacheDatabaseSharedManager extends IgniteCacheDatabaseSharedMan Files.delete(endFile); } catch (IOException e) { - throw new PersistentStorageIOException("Failed to delete stale checkpoint files: " + cpEntry, e); + throw new StorageException("Failed to delete stale checkpoint files: " + cpEntry, e); } } @@ -855,7 +853,7 @@ public class GridCacheDatabaseSharedManager extends IgniteCacheDatabaseSharedMan notifyMetastorageReadyForReadWrite(); } catch (IgniteCheckedException e) { - if (X.hasCause(e, StorageException.class, PersistentStorageIOException.class, IOException.class)) + if (X.hasCause(e, StorageException.class, IOException.class)) cctx.kernalContext().failure().process(new FailureContext(FailureType.CRITICAL_ERROR, e)); throw e; @@ -901,7 +899,7 @@ public class GridCacheDatabaseSharedManager extends IgniteCacheDatabaseSharedMan Files.move(Paths.get(cpDir.getAbsolutePath(), tmpFileName), Paths.get(cpDir.getAbsolutePath(), fileName)); } catch (IOException e) { - throw new PersistentStorageIOException("Failed to write node start marker: " + ptr, e); + throw new StorageException("Failed to write node start marker: " + ptr, e); } } @@ -944,12 +942,12 @@ public class GridCacheDatabaseSharedManager extends IgniteCacheDatabaseSharedMan buf.clear(); } catch (IOException e) { - throw new PersistentStorageIOException("Failed to read node started marker file: " + f.getAbsolutePath(), e); + throw new StorageException("Failed to read node started marker file: " + f.getAbsolutePath(), e); } } } catch (IOException e) { - throw new PersistentStorageIOException("Failed to retreive node started files.", e); + throw new StorageException("Failed to retreive node started files.", e); } // Sort start markers by file timestamp. @@ -2620,9 +2618,9 @@ public class GridCacheDatabaseSharedManager extends IgniteCacheDatabaseSharedMan * @param entryBuf Checkpoint entry buffer to write. * @param cp Checkpoint entry. * @param type Checkpoint entry type. - * @throws PersistentStorageIOException If failed to write checkpoint entry. + * @throws StorageException If failed to write checkpoint entry. */ - public void writeCheckpointEntry(ByteBuffer entryBuf, CheckpointEntry cp, CheckpointEntryType type) throws PersistentStorageIOException { + public void writeCheckpointEntry(ByteBuffer entryBuf, CheckpointEntry cp, CheckpointEntryType type) throws StorageException { String fileName = checkpointFileName(cp, type); String tmpFileName = fileName + FILE_TMP_SUFFIX; @@ -2642,7 +2640,7 @@ public class GridCacheDatabaseSharedManager extends IgniteCacheDatabaseSharedMan Files.move(Paths.get(cpDir.getAbsolutePath(), tmpFileName), Paths.get(cpDir.getAbsolutePath(), fileName)); } catch (IOException e) { - throw new PersistentStorageIOException("Failed to write checkpoint entry [ptr=" + cp.checkpointMark() + throw new StorageException("Failed to write checkpoint entry [ptr=" + cp.checkpointMark() + ", cpTs=" + cp.timestamp() + ", cpId=" + cp.checkpointId() + ", type=" + type + "]", e); http://git-wip-us.apache.org/repos/asf/ignite/blob/dde936ac/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/GridCacheOffheapManager.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/GridCacheOffheapManager.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/GridCacheOffheapManager.java index 62aadb2..826f619 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/GridCacheOffheapManager.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/GridCacheOffheapManager.java @@ -35,7 +35,6 @@ import org.apache.ignite.internal.pagemem.PageIdUtils; import org.apache.ignite.internal.pagemem.PageMemory; import org.apache.ignite.internal.pagemem.PageSupport; import org.apache.ignite.internal.pagemem.wal.IgniteWriteAheadLogManager; -import org.apache.ignite.internal.pagemem.wal.StorageException; import org.apache.ignite.internal.pagemem.wal.WALIterator; import org.apache.ignite.internal.pagemem.wal.WALPointer; import org.apache.ignite.internal.pagemem.wal.record.DataEntry; http://git-wip-us.apache.org/repos/asf/ignite/blob/dde936ac/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/StorageException.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/StorageException.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/StorageException.java new file mode 100644 index 0000000..509dee6 --- /dev/null +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/StorageException.java @@ -0,0 +1,53 @@ +/* + * 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.ignite.internal.processors.cache.persistence; + +import java.io.IOException; +import org.apache.ignite.IgniteCheckedException; +import org.apache.ignite.internal.InvalidEnvironmentException; +import org.jetbrains.annotations.NotNull; + +/** + * Exception is needed to distinguish WAL manager & page store critical I/O errors. + */ +public class StorageException extends IgniteCheckedException implements InvalidEnvironmentException { + /** */ + private static final long serialVersionUID = 0L; + + /** + * @param msg Error message. + * @param cause Error cause. + */ + public StorageException(String msg, @NotNull IOException cause) { + super(msg, cause); + } + + /** + * @param e Cause exception. + */ + public StorageException(IOException e) { + super(e); + } + + /** + * @param msg Error message + */ + public StorageException(String msg) { + super(msg); + } +} http://git-wip-us.apache.org/repos/asf/ignite/blob/dde936ac/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/file/FilePageStore.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/file/FilePageStore.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/file/FilePageStore.java index c4f90e5..cc4f27b 100755 --- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/file/FilePageStore.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/file/FilePageStore.java @@ -33,6 +33,7 @@ import org.apache.ignite.configuration.DataStorageConfiguration; import org.apache.ignite.internal.pagemem.PageIdUtils; import org.apache.ignite.internal.pagemem.store.PageStore; import org.apache.ignite.internal.processors.cache.persistence.AllocatedPageTracker; +import org.apache.ignite.internal.processors.cache.persistence.StorageException; import org.apache.ignite.internal.processors.cache.persistence.tree.io.PageIO; import org.apache.ignite.internal.processors.cache.persistence.wal.crc.IgniteDataIntegrityViolationException; import org.apache.ignite.internal.processors.cache.persistence.wal.crc.PureJavaCrc32; @@ -182,7 +183,7 @@ public class FilePageStore implements PageStore { * Checks that file store has correct header and size. * * @return Next available position in the file to store a data. - * @throws IOException If check is failed. + * @throws IOException If check has failed. */ private long checkFile(FileIO fileIO) throws IOException { ByteBuffer hdr = ByteBuffer.allocate(headerSize()).order(ByteOrder.LITTLE_ENDIAN); @@ -233,10 +234,10 @@ public class FilePageStore implements PageStore { } /** - * @param cleanFile {@code True} to delete file. - * @throws PersistentStorageIOException If failed. + * @param delete {@code True} to delete file. + * @throws StorageException If failed in case of underlying I/O exception. */ - public void stop(boolean cleanFile) throws PersistentStorageIOException { + public void stop(boolean delete) throws StorageException { lock.writeLock().lock(); try { @@ -249,11 +250,12 @@ public class FilePageStore implements PageStore { fileIO = null; - if (cleanFile) + if (delete) Files.delete(cfgFile.toPath()); } catch (IOException e) { - throw new PersistentStorageIOException(e); + throw new StorageException("Failed to stop serving partition file [file=" + cfgFile.getPath() + + ", delete=" + delete + "]", e); } finally { lock.writeLock().unlock(); @@ -264,9 +266,9 @@ public class FilePageStore implements PageStore { * Truncates and deletes partition file. * * @param tag New partition tag. - * @throws PersistentStorageIOException If failed + * @throws StorageException If failed in case of underlying I/O exception. */ - public void truncate(int tag) throws PersistentStorageIOException { + public void truncate(int tag) throws StorageException { init(); lock.writeLock().lock(); @@ -283,7 +285,7 @@ public class FilePageStore implements PageStore { Files.delete(cfgFile.toPath()); } catch (IOException e) { - throw new PersistentStorageIOException("Failed to delete partition file: " + cfgFile.getPath(), e); + throw new StorageException("Failed to truncate partition file [file=" + cfgFile.getPath() + "]", e); } finally { allocatedTracker.updateTotalAllocatedPages(-1L * allocated.get() / pageSize); @@ -311,9 +313,9 @@ public class FilePageStore implements PageStore { } /** - * + * @throws StorageException If failed in case of underlying I/O exception. */ - public void finishRecover() throws PersistentStorageIOException { + public void finishRecover() throws StorageException { lock.writeLock().lock(); try { @@ -332,7 +334,7 @@ public class FilePageStore implements PageStore { recover = false; } catch (IOException e) { - throw new PersistentStorageIOException("Failed to finish recover", e); + throw new StorageException("Failed to finish recover partition file [file=" + cfgFile.getAbsolutePath() + "]", e); } finally { lock.writeLock().unlock(); @@ -386,7 +388,7 @@ public class FilePageStore implements PageStore { PageIO.setCrc(pageBuf, savedCrc32); } catch (IOException e) { - throw new PersistentStorageIOException("Read error", e); + throw new StorageException("Failed to read page [file=" + cfgFile.getAbsolutePath() + ", pageId=" + pageId + "]", e); } } @@ -400,14 +402,14 @@ public class FilePageStore implements PageStore { readWithFailover(buf, 0); } catch (IOException e) { - throw new PersistentStorageIOException("Read error", e); + throw new StorageException("Failed to read header [file=" + cfgFile.getAbsolutePath() + "]", e); } } /** - * @throws PersistentStorageIOException If failed to initialize store file. + * @throws StorageException If failed to initialize store file. */ - private void init() throws PersistentStorageIOException { + private void init() throws StorageException { if (!inited) { lock.writeLock().lock(); @@ -415,7 +417,7 @@ public class FilePageStore implements PageStore { if (!inited) { FileIO fileIO = null; - PersistentStorageIOException err = null; + StorageException err = null; long newSize; @@ -449,8 +451,8 @@ public class FilePageStore implements PageStore { inited = true; } catch (IOException e) { - err = new PersistentStorageIOException( - "Failed to initialize partition file: " + cfgFile.getName(), e); + err = new StorageException( + "Failed to initialize partition file: " + cfgFile.getAbsolutePath(), e); throw err; } @@ -608,8 +610,8 @@ public class FilePageStore implements PageStore { } } - throw new PersistentStorageIOException("Failed to write the page to the file store [pageId=" + pageId - + ", file=" + cfgFile.getAbsolutePath() + ']', e); + throw new StorageException("Failed to write page [file=" + cfgFile.getAbsolutePath() + + ", pageId=" + pageId + ", tag=" + tag + "]", e); } } } @@ -635,7 +637,7 @@ public class FilePageStore implements PageStore { } /** {@inheritDoc} */ - @Override public void sync() throws IgniteCheckedException { + @Override public void sync() throws StorageException { lock.writeLock().lock(); try { @@ -647,7 +649,7 @@ public class FilePageStore implements PageStore { fileIO.force(); } catch (IOException e) { - throw new PersistentStorageIOException("Sync error", e); + throw new StorageException("Failed to fsync partition file [file=" + cfgFile.getAbsolutePath() + "]", e); } finally { lock.writeLock().unlock(); http://git-wip-us.apache.org/repos/asf/ignite/blob/dde936ac/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/file/FilePageStoreManager.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/file/FilePageStoreManager.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/file/FilePageStoreManager.java index 3d23d53..c72b0bf 100755 --- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/file/FilePageStoreManager.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/file/FilePageStoreManager.java @@ -55,6 +55,7 @@ import org.apache.ignite.internal.processors.cache.GridCacheSharedManagerAdapter import org.apache.ignite.internal.processors.cache.StoredCacheData; import org.apache.ignite.internal.processors.cache.persistence.AllocatedPageTracker; import org.apache.ignite.internal.processors.cache.persistence.DataRegionMetricsImpl; +import org.apache.ignite.internal.processors.cache.persistence.StorageException; import org.apache.ignite.internal.processors.cache.persistence.filename.PdsFolderSettings; import org.apache.ignite.internal.processors.cache.persistence.metastorage.MetaStorage; import org.apache.ignite.internal.processors.cache.persistence.snapshot.IgniteCacheSnapshotManager; @@ -270,7 +271,7 @@ public class FilePageStoreManager extends GridCacheSharedManagerAdapter implemen partStore.finishRecover(); } } - catch (PersistentStorageIOException e) { + catch (StorageException e) { cctx.kernalContext().failure().process(new FailureContext(FailureType.CRITICAL_ERROR, e)); throw e; @@ -278,8 +279,7 @@ public class FilePageStoreManager extends GridCacheSharedManagerAdapter implemen } /** {@inheritDoc} */ - @Override public void initializeForCache(CacheGroupDescriptor grpDesc, StoredCacheData cacheData) - throws IgniteCheckedException { + @Override public void initializeForCache(CacheGroupDescriptor grpDesc, StoredCacheData cacheData) throws IgniteCheckedException { int grpId = grpDesc.groupId(); if (!idxCacheStores.containsKey(grpId)) { @@ -292,8 +292,7 @@ public class FilePageStoreManager extends GridCacheSharedManagerAdapter implemen } /** {@inheritDoc} */ - @Override public void initializeForMetastorage() - throws IgniteCheckedException { + @Override public void initializeForMetastorage() throws IgniteCheckedException { int grpId = MetaStorage.METASTORAGE_CACHE_ID; if (!idxCacheStores.containsKey(grpId)) { @@ -399,7 +398,7 @@ public class FilePageStoreManager extends GridCacheSharedManagerAdapter implemen try { store.read(pageId, pageBuf, keepCrc); } - catch (PersistentStorageIOException e) { + catch (StorageException e) { cctx.kernalContext().failure().process(new FailureContext(FailureType.CRITICAL_ERROR, e)); throw e; @@ -420,7 +419,7 @@ public class FilePageStoreManager extends GridCacheSharedManagerAdapter implemen try { store.readHeader(buf); } - catch (PersistentStorageIOException e) { + catch (StorageException e) { cctx.kernalContext().failure().process(new FailureContext(FailureType.CRITICAL_ERROR, e)); throw e; @@ -456,7 +455,7 @@ public class FilePageStoreManager extends GridCacheSharedManagerAdapter implemen try { store.write(pageId, pageBuf, tag, calculateCrc); } - catch (PersistentStorageIOException e) { + catch (StorageException e) { cctx.kernalContext().failure().process(new FailureContext(FailureType.CRITICAL_ERROR, e)); throw e; @@ -542,7 +541,7 @@ public class FilePageStoreManager extends GridCacheSharedManagerAdapter implemen return new CacheStoreHolder(idxStore, partStores); } - catch (PersistentStorageIOException e) { + catch (StorageException e) { cctx.kernalContext().failure().process(new FailureContext(FailureType.CRITICAL_ERROR, e)); throw e; @@ -634,7 +633,7 @@ public class FilePageStoreManager extends GridCacheSharedManagerAdapter implemen try { getStore(grpId, partId).sync(); } - catch (PersistentStorageIOException e) { + catch (StorageException e) { cctx.kernalContext().failure().process(new FailureContext(FailureType.CRITICAL_ERROR, e)); throw e; @@ -646,7 +645,7 @@ public class FilePageStoreManager extends GridCacheSharedManagerAdapter implemen try { getStore(grpId, partId).ensure(); } - catch (PersistentStorageIOException e) { + catch (StorageException e) { cctx.kernalContext().failure().process(new FailureContext(FailureType.CRITICAL_ERROR, e)); throw e; @@ -664,7 +663,7 @@ public class FilePageStoreManager extends GridCacheSharedManagerAdapter implemen return PageIdUtils.pageId(partId, flags, (int)pageIdx); } - catch (PersistentStorageIOException e) { + catch (StorageException e) { cctx.kernalContext().failure().process(new FailureContext(FailureType.CRITICAL_ERROR, e)); throw e; http://git-wip-us.apache.org/repos/asf/ignite/blob/dde936ac/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/file/PersistentStorageIOException.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/file/PersistentStorageIOException.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/file/PersistentStorageIOException.java deleted file mode 100644 index 7b3c303..0000000 --- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/file/PersistentStorageIOException.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * 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.ignite.internal.processors.cache.persistence.file; - -import java.io.IOException; -import org.apache.ignite.IgniteCheckedException; - -/** - * Exception is needed to distinguish persistent storage I/O errors. - */ -public class PersistentStorageIOException extends IgniteCheckedException { - /** */ - private static final long serialVersionUID = 0L; - - /** - * Create an instance of exception. - * - * @param cause Error cause. - */ - public PersistentStorageIOException(IOException cause) { - super(cause); - } - - /** - * Create an instance of exception. - * - * @param msg Error message. - * @param cause Error cause. - */ - public PersistentStorageIOException(String msg, IOException cause) { - super(msg, cause); - } -} http://git-wip-us.apache.org/repos/asf/ignite/blob/dde936ac/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/metastorage/MetaStorage.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/metastorage/MetaStorage.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/metastorage/MetaStorage.java index 4a2549b..c0fba73 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/metastorage/MetaStorage.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/metastorage/MetaStorage.java @@ -29,7 +29,7 @@ import org.apache.ignite.internal.pagemem.FullPageId; import org.apache.ignite.internal.pagemem.PageIdUtils; import org.apache.ignite.internal.pagemem.PageMemory; import org.apache.ignite.internal.pagemem.wal.IgniteWriteAheadLogManager; -import org.apache.ignite.internal.pagemem.wal.StorageException; +import org.apache.ignite.internal.processors.cache.persistence.StorageException; import org.apache.ignite.internal.pagemem.wal.WALPointer; import org.apache.ignite.internal.pagemem.wal.record.MetastoreDataRecord; import org.apache.ignite.internal.pagemem.wal.record.delta.MetaPageInitRecord; http://git-wip-us.apache.org/repos/asf/ignite/blob/dde936ac/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/pagemem/PageMemoryEx.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/pagemem/PageMemoryEx.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/pagemem/PageMemoryEx.java index ed0d304..af204dd 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/pagemem/PageMemoryEx.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/pagemem/PageMemoryEx.java @@ -23,7 +23,7 @@ import org.apache.ignite.IgniteException; import org.apache.ignite.internal.IgniteInternalFuture; import org.apache.ignite.internal.pagemem.FullPageId; import org.apache.ignite.internal.pagemem.PageMemory; -import org.apache.ignite.internal.pagemem.wal.StorageException; +import org.apache.ignite.internal.processors.cache.persistence.StorageException; import org.apache.ignite.internal.util.GridMultiCollectionWrapper; import org.jetbrains.annotations.Nullable; http://git-wip-us.apache.org/repos/asf/ignite/blob/dde936ac/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/pagemem/PageMemoryImpl.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/pagemem/PageMemoryImpl.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/pagemem/PageMemoryImpl.java index 1524150..75cc036 100755 --- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/pagemem/PageMemoryImpl.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/pagemem/PageMemoryImpl.java @@ -52,7 +52,7 @@ import org.apache.ignite.internal.pagemem.PageIdUtils; import org.apache.ignite.internal.pagemem.PageUtils; import org.apache.ignite.internal.pagemem.store.IgnitePageStoreManager; import org.apache.ignite.internal.pagemem.wal.IgniteWriteAheadLogManager; -import org.apache.ignite.internal.pagemem.wal.StorageException; +import org.apache.ignite.internal.processors.cache.persistence.StorageException; import org.apache.ignite.internal.pagemem.wal.WALIterator; import org.apache.ignite.internal.pagemem.wal.WALPointer; import org.apache.ignite.internal.pagemem.wal.record.CheckpointRecord; http://git-wip-us.apache.org/repos/asf/ignite/blob/dde936ac/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/tree/BPlusTree.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/tree/BPlusTree.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/tree/BPlusTree.java index 141b94f..8a63a00 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/tree/BPlusTree.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/tree/BPlusTree.java @@ -57,6 +57,7 @@ import org.apache.ignite.internal.processors.cache.persistence.tree.reuse.LongLi import org.apache.ignite.internal.processors.cache.persistence.tree.reuse.ReuseBag; import org.apache.ignite.internal.processors.cache.persistence.tree.reuse.ReuseList; import org.apache.ignite.internal.processors.cache.persistence.tree.util.PageHandler; +import org.apache.ignite.internal.processors.cache.persistence.tree.util.PageHandlerWrapper; import org.apache.ignite.internal.processors.failure.FailureProcessor; import org.apache.ignite.internal.util.GridArrays; import org.apache.ignite.internal.util.GridLongList; @@ -90,6 +91,9 @@ public abstract class BPlusTree<L, T extends L> extends DataStructure implements /** */ private static final Object[] EMPTY = {}; + /** Wrapper for tree pages operations. Noop by default. Override for test purposes. */ + public static volatile PageHandlerWrapper<Result> pageHndWrapper = (tree, hnd) -> hnd; + /** */ private static volatile boolean interrupted; @@ -228,7 +232,7 @@ public abstract class BPlusTree<L, T extends L> extends DataStructure implements }; /** */ - private final GetPageHandler<Get> askNeighbor = new AskNeighbor(); + private final PageHandler<Get, Result> askNeighbor; /** * @@ -259,12 +263,12 @@ public abstract class BPlusTree<L, T extends L> extends DataStructure implements } /** */ - private final GetPageHandler<Get> search = new Search(); + private final PageHandler<Get, Result> search; /** * */ - private class Search extends GetPageHandler<Get> { + public class Search extends GetPageHandler<Get> { /** {@inheritDoc} */ @Override public Result run0(long pageId, long page, long pageAddr, BPlusIO<L> io, Get g, int lvl) throws IgniteCheckedException { @@ -348,12 +352,12 @@ public abstract class BPlusTree<L, T extends L> extends DataStructure implements } /** */ - private final GetPageHandler<Put> replace = new Replace(); + private final PageHandler<Put, Result> replace; /** * */ - private class Replace extends GetPageHandler<Put> { + public class Replace extends GetPageHandler<Put> { /** {@inheritDoc} */ @SuppressWarnings("unchecked") @Override public Result run0(long pageId, long page, long pageAddr, BPlusIO<L> io, Put p, int lvl) @@ -410,12 +414,12 @@ public abstract class BPlusTree<L, T extends L> extends DataStructure implements } /** */ - private final GetPageHandler<Put> insert = new Insert(); + private final PageHandler<Put, Result> insert; /** * */ - private class Insert extends GetPageHandler<Put> { + public class Insert extends GetPageHandler<Put> { /** {@inheritDoc} */ @Override public Result run0(long pageId, long page, long pageAddr, BPlusIO<L> io, Put p, int lvl) throws IgniteCheckedException { @@ -459,7 +463,7 @@ public abstract class BPlusTree<L, T extends L> extends DataStructure implements } /** */ - private final GetPageHandler<Remove> rmvFromLeaf = new RemoveFromLeaf(); + private final PageHandler<Remove, Result> rmvFromLeaf; /** * @@ -534,7 +538,7 @@ public abstract class BPlusTree<L, T extends L> extends DataStructure implements } /** */ - private final GetPageHandler<Remove> lockBackAndRmvFromLeaf = new LockBackAndRmvFromLeaf(); + private final PageHandler<Remove, Result> lockBackAndRmvFromLeaf; /** * @@ -559,7 +563,7 @@ public abstract class BPlusTree<L, T extends L> extends DataStructure implements } /** */ - private final GetPageHandler<Remove> lockBackAndTail = new LockBackAndTail(); + private final PageHandler<Remove, Result> lockBackAndTail; /** * @@ -583,7 +587,7 @@ public abstract class BPlusTree<L, T extends L> extends DataStructure implements } /** */ - private final GetPageHandler<Remove> lockTailForward = new LockTailForward(); + private final PageHandler<Remove, Result> lockTailForward; /** * @@ -599,7 +603,7 @@ public abstract class BPlusTree<L, T extends L> extends DataStructure implements } /** */ - private final GetPageHandler<Remove> lockTail = new LockTail(); + private final PageHandler<Remove, Result> lockTail; /** * @@ -784,6 +788,17 @@ public abstract class BPlusTree<L, T extends L> extends DataStructure implements this.reuseList = reuseList; this.globalRmvId = globalRmvId; this.failureProcessor = failureProcessor; + + // Initialize page handlers. + askNeighbor = (PageHandler<Get, Result>) pageHndWrapper.wrap(this, new AskNeighbor()); + search = (PageHandler<Get, Result>) pageHndWrapper.wrap(this, new Search()); + lockTail = (PageHandler<Remove, Result>) pageHndWrapper.wrap(this, new LockTail()); + lockTailForward = (PageHandler<Remove, Result>) pageHndWrapper.wrap(this, new LockTailForward()); + lockBackAndTail = (PageHandler<Remove, Result>) pageHndWrapper.wrap(this, new LockBackAndTail()); + lockBackAndRmvFromLeaf = (PageHandler<Remove, Result>) pageHndWrapper.wrap(this, new LockBackAndRmvFromLeaf()); + rmvFromLeaf = (PageHandler<Remove, Result>) pageHndWrapper.wrap(this, new RemoveFromLeaf()); + insert = (PageHandler<Put, Result>) pageHndWrapper.wrap(this, new Insert()); + replace = (PageHandler<Put, Result>) pageHndWrapper.wrap(this, new Replace()); } /** @@ -981,11 +996,8 @@ public abstract class BPlusTree<L, T extends L> extends DataStructure implements catch (IgniteCheckedException e) { throw new IgniteCheckedException("Runtime failure on bounds: [lower=" + lower + ", upper=" + upper + "]", e); } - catch (RuntimeException e) { - throw new IgniteException("Runtime failure on bounds: [lower=" + lower + ", upper=" + upper + "]", e); - } - catch (AssertionError e) { - throw new AssertionError("Assertion error on bounds: [lower=" + lower + ", upper=" + upper + "]", e); + catch (RuntimeException | AssertionError e) { + throw new CorruptedTreeException("Runtime failure on bounds: [lower=" + lower + ", upper=" + upper + "]", e); } finally { checkDestroyed(); @@ -1033,11 +1045,8 @@ public abstract class BPlusTree<L, T extends L> extends DataStructure implements catch (IgniteCheckedException e) { throw new IgniteCheckedException("Runtime failure on first row lookup", e); } - catch (RuntimeException e) { - throw new IgniteException("Runtime failure on first row lookup", e); - } - catch (AssertionError e) { - throw new AssertionError("Assertion error on first row lookup", e); + catch (RuntimeException | AssertionError e) { + throw new CorruptedTreeException("Runtime failure on first row lookup", e); } finally { checkDestroyed(); @@ -1058,12 +1067,9 @@ public abstract class BPlusTree<L, T extends L> extends DataStructure implements catch (IgniteCheckedException e) { throw new IgniteCheckedException("Runtime failure on last row lookup", e); } - catch (RuntimeException e) { + catch (RuntimeException | AssertionError e) { throw new IgniteException("Runtime failure on last row lookup", e); } - catch (AssertionError e) { - throw new AssertionError("Assertion error on last row lookup", e); - } finally { checkDestroyed(); } @@ -1089,11 +1095,8 @@ public abstract class BPlusTree<L, T extends L> extends DataStructure implements catch (IgniteCheckedException e) { throw new IgniteCheckedException("Runtime failure on lookup row: " + row, e); } - catch (RuntimeException e) { - throw new IgniteException("Runtime failure on lookup row: " + row, e); - } - catch (AssertionError e) { - throw new AssertionError("Assertion error on lookup row: " + row, e); + catch (RuntimeException | AssertionError e) { + throw new CorruptedTreeException("Runtime failure on lookup row: " + row, e); } finally { checkDestroyed(); @@ -1653,11 +1656,8 @@ public abstract class BPlusTree<L, T extends L> extends DataStructure implements catch (IgniteCheckedException e) { throw new IgniteCheckedException("Runtime failure on search row: " + row, e); } - catch (RuntimeException e) { - throw new IgniteException("Runtime failure on search row: " + row, e); - } - catch (AssertionError e) { - throw new AssertionError("Assertion error on search row: " + row, e); + catch (RuntimeException | AssertionError e) { + throw new CorruptedTreeException("Runtime failure on search row: " + row, e); } finally { x.releaseAll(); @@ -1813,11 +1813,8 @@ public abstract class BPlusTree<L, T extends L> extends DataStructure implements catch (IgniteCheckedException e) { throw new IgniteCheckedException("Runtime failure on search row: " + row, e); } - catch (RuntimeException e) { - throw new IgniteException("Runtime failure on search row: " + row, e); - } - catch (AssertionError e) { - throw new AssertionError("Assertion error on search row: " + row, e); + catch (RuntimeException | AssertionError e) { + throw new CorruptedTreeException("Runtime failure on search row: " + row, e); } finally { r.releaseAll(); @@ -2132,11 +2129,8 @@ public abstract class BPlusTree<L, T extends L> extends DataStructure implements catch (IgniteCheckedException e) { throw new IgniteCheckedException("Runtime failure on row: " + row, e); } - catch (RuntimeException e) { - throw new IgniteException("Runtime failure on row: " + row, e); - } - catch (AssertionError e) { - throw new AssertionError("Assertion error on row: " + row, e); + catch (RuntimeException | AssertionError e) { + throw new CorruptedTreeException("Runtime failure on row: " + row, e); } finally { checkDestroyed(); @@ -2427,7 +2421,7 @@ public abstract class BPlusTree<L, T extends L> extends DataStructure implements /** * Get operation. */ - private abstract class Get { + public abstract class Get { /** */ long rmvId; @@ -2542,7 +2536,7 @@ public abstract class BPlusTree<L, T extends L> extends DataStructure implements * @param lvl Level. * @return {@code true} If we can release the given page. */ - boolean canRelease(long pageId, int lvl) { + public boolean canRelease(long pageId, int lvl) { return pageId != 0L; } @@ -2592,6 +2586,13 @@ public abstract class BPlusTree<L, T extends L> extends DataStructure implements lockRetriesCnt--; } + + /** + * @return Operation row. + */ + public L row() { + return row; + } } /** @@ -2665,11 +2666,13 @@ public abstract class BPlusTree<L, T extends L> extends DataStructure implements /** * Put operation. */ - private final class Put extends Get { + public final class Put extends Get { /** Mark of NULL value of page id. It means valid value can't be equal this value. */ private static final long NULL_PAGE_ID = 0L; + /** Mark of NULL value of page. */ private static final long NULL_PAGE = 0L; + /** Mark of NULL value of page address. */ private static final long NULL_PAGE_ADDRESS = 0L; @@ -2754,7 +2757,7 @@ public abstract class BPlusTree<L, T extends L> extends DataStructure implements } /** {@inheritDoc} */ - @Override boolean canRelease(long pageId, int lvl) { + @Override public boolean canRelease(long pageId, int lvl) { return pageId != NULL_PAGE_ID && tailId != pageId; } @@ -3013,7 +3016,7 @@ public abstract class BPlusTree<L, T extends L> extends DataStructure implements /** * Invoke operation. */ - private final class Invoke extends Get { + public final class Invoke extends Get { /** */ Object x; @@ -3151,7 +3154,7 @@ public abstract class BPlusTree<L, T extends L> extends DataStructure implements } /** {@inheritDoc} */ - @Override boolean canRelease(long pageId, int lvl) { + @Override public boolean canRelease(long pageId, int lvl) { if (pageId == 0L) return false; @@ -4128,7 +4131,7 @@ public abstract class BPlusTree<L, T extends L> extends DataStructure implements } /** {@inheritDoc} */ - @Override boolean canRelease(long pageId, int lvl) { + @Override public boolean canRelease(long pageId, int lvl) { return pageId != 0L && !isTail(pageId, lvl); } @@ -4902,7 +4905,7 @@ public abstract class BPlusTree<L, T extends L> extends DataStructure implements /** * Operation result. */ - enum Result { + public enum Result { /** */ GO_DOWN, http://git-wip-us.apache.org/repos/asf/ignite/blob/dde936ac/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/tree/CorruptedTreeException.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/tree/CorruptedTreeException.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/tree/CorruptedTreeException.java new file mode 100644 index 0000000..a6bfb1f --- /dev/null +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/tree/CorruptedTreeException.java @@ -0,0 +1,38 @@ +/* + * 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.ignite.internal.processors.cache.persistence.tree; + +import org.apache.ignite.IgniteCheckedException; +import org.apache.ignite.internal.InvalidEnvironmentException; +import org.jetbrains.annotations.Nullable; + +/** + * Exception to distinguish {@link BPlusTree} tree broken invariants. + */ +public class CorruptedTreeException extends IgniteCheckedException implements InvalidEnvironmentException { + /** */ + private static final long serialVersionUID = 0L; + + /** + * @param msg Message. + * @param cause Cause. + */ + public CorruptedTreeException(String msg, @Nullable Throwable cause) { + super(msg, cause); + } +} http://git-wip-us.apache.org/repos/asf/ignite/blob/dde936ac/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/tree/util/PageHandlerWrapper.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/tree/util/PageHandlerWrapper.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/tree/util/PageHandlerWrapper.java new file mode 100644 index 0000000..495eba0 --- /dev/null +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/tree/util/PageHandlerWrapper.java @@ -0,0 +1,36 @@ +/* + * 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.ignite.internal.processors.cache.persistence.tree.util; + +import org.apache.ignite.internal.processors.cache.persistence.tree.BPlusTree; + +/** + * Wrapper factory for {@link PageHandler} instances. + * + * @param <R> Result type of actual {@link PageHandler} class. + */ +public interface PageHandlerWrapper<R> { + /** + * Wraps given {@code hnd}. + * + * @param tree Instance of {@link BPlusTree} where given {@code} is used. + * @param hnd Page handler to wrap. + * @return Wrapped version of given {@code hnd}. + */ + public PageHandler<?, R> wrap(BPlusTree<?, ?> tree, PageHandler<?, R> hnd); +} http://git-wip-us.apache.org/repos/asf/ignite/blob/dde936ac/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/wal/FileWriteAheadLogManager.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/wal/FileWriteAheadLogManager.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/wal/FileWriteAheadLogManager.java index e3f5a52..0525384 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/wal/FileWriteAheadLogManager.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/wal/FileWriteAheadLogManager.java @@ -77,7 +77,7 @@ import org.apache.ignite.internal.IgniteInternalFuture; import org.apache.ignite.internal.IgniteInterruptedCheckedException; import org.apache.ignite.internal.managers.eventstorage.GridEventStorageManager; import org.apache.ignite.internal.pagemem.wal.IgniteWriteAheadLogManager; -import org.apache.ignite.internal.pagemem.wal.StorageException; +import org.apache.ignite.internal.processors.cache.persistence.StorageException; import org.apache.ignite.internal.pagemem.wal.WALIterator; import org.apache.ignite.internal.pagemem.wal.WALPointer; import org.apache.ignite.internal.pagemem.wal.record.CheckpointRecord; http://git-wip-us.apache.org/repos/asf/ignite/blob/dde936ac/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/wal/FsyncModeFileWriteAheadLogManager.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/wal/FsyncModeFileWriteAheadLogManager.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/wal/FsyncModeFileWriteAheadLogManager.java index c8224a5..4797f81 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/wal/FsyncModeFileWriteAheadLogManager.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/wal/FsyncModeFileWriteAheadLogManager.java @@ -73,7 +73,7 @@ import org.apache.ignite.internal.IgniteInternalFuture; import org.apache.ignite.internal.IgniteInterruptedCheckedException; import org.apache.ignite.internal.managers.eventstorage.GridEventStorageManager; import org.apache.ignite.internal.pagemem.wal.IgniteWriteAheadLogManager; -import org.apache.ignite.internal.pagemem.wal.StorageException; +import org.apache.ignite.internal.processors.cache.persistence.StorageException; import org.apache.ignite.internal.pagemem.wal.WALIterator; import org.apache.ignite.internal.pagemem.wal.WALPointer; import org.apache.ignite.internal.pagemem.wal.record.MarshalledRecord; http://git-wip-us.apache.org/repos/asf/ignite/blob/dde936ac/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteTxAdapter.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteTxAdapter.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteTxAdapter.java index e97b31c..bdd0c53 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteTxAdapter.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteTxAdapter.java @@ -445,36 +445,27 @@ public abstract class IgniteTxAdapter extends GridMetadataAwareAdapter implement /** * Uncommits transaction by invalidating all of its entries. Courtesy to minimize inconsistency. - * - * @param nodeStopping {@code True} if tx was cancelled during node stop. */ @SuppressWarnings({"CatchGenericClass"}) - protected void uncommit(boolean nodeStopping) { - try { - if (!nodeStopping) { - for (IgniteTxEntry e : writeMap().values()) { - try { - GridCacheEntryEx entry = e.cached(); - - if (e.op() != NOOP) - entry.invalidate(xidVer); - } - catch (Throwable t) { - U.error(log, "Failed to invalidate transaction entries while reverting a commit.", t); + protected void uncommit() { + for (IgniteTxEntry e : writeMap().values()) { + try { + GridCacheEntryEx entry = e.cached(); - if (t instanceof Error) - throw (Error)t; + if (e.op() != NOOP) + entry.invalidate(xidVer); + } + catch (Throwable t) { + U.error(log, "Failed to invalidate transaction entries while reverting a commit.", t); - break; - } - } + if (t instanceof Error) + throw (Error)t; - cctx.tm().uncommitTx(this); + break; } } - catch (Exception ex) { - U.error(log, "Failed to do uncommit.", ex); - } + + cctx.tm().uncommitTx(this); } /** {@inheritDoc} */ http://git-wip-us.apache.org/repos/asf/ignite/blob/dde936ac/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteTxLocalAdapter.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteTxLocalAdapter.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteTxLocalAdapter.java index 0f590ff..e6c656e 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteTxLocalAdapter.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/transactions/IgniteTxLocalAdapter.java @@ -30,9 +30,12 @@ import javax.cache.expiry.ExpiryPolicy; import javax.cache.processor.EntryProcessor; import org.apache.ignite.IgniteCheckedException; import org.apache.ignite.cache.CacheWriteSynchronizationMode; +import org.apache.ignite.failure.FailureContext; +import org.apache.ignite.failure.FailureType; import org.apache.ignite.internal.InvalidEnvironmentException; import org.apache.ignite.internal.IgniteInternalFuture; -import org.apache.ignite.internal.pagemem.wal.StorageException; +import org.apache.ignite.internal.NodeStoppingException; +import org.apache.ignite.internal.processors.cache.persistence.StorageException; import org.apache.ignite.internal.pagemem.wal.WALPointer; import org.apache.ignite.internal.pagemem.wal.record.DataEntry; import org.apache.ignite.internal.pagemem.wal.record.DataRecord; @@ -46,7 +49,6 @@ import org.apache.ignite.internal.processors.cache.GridCacheContext; import org.apache.ignite.internal.processors.cache.GridCacheEntryEx; import org.apache.ignite.internal.processors.cache.GridCacheEntryRemovedException; import org.apache.ignite.internal.processors.cache.GridCacheFilterFailedException; -import org.apache.ignite.internal.processors.cache.GridCacheIndexUpdateException; import org.apache.ignite.internal.processors.cache.GridCacheMvccCandidate; import org.apache.ignite.internal.processors.cache.GridCacheOperation; import org.apache.ignite.internal.processors.cache.GridCacheReturn; @@ -834,39 +836,34 @@ public abstract class IgniteTxLocalAdapter extends IgniteTxAdapter implements Ig // Need to remove version from committed list. cctx.tm().removeCommittedTx(this); - if (X.hasCause(ex, GridCacheIndexUpdateException.class) && cacheCtx.cache().isMongoDataCache()) { - if (log.isDebugEnabled()) - log.debug("Failed to update mongo document index (transaction entry will " + - "be ignored): " + txEntry); + boolean isNodeStopping = X.hasCause(ex, NodeStoppingException.class); + boolean hasInvalidEnvironmentIssue = X.hasCause(ex, InvalidEnvironmentException.class); - // Set operation to NOOP. - txEntry.op(NOOP); + IgniteCheckedException err = new IgniteTxHeuristicCheckedException("Failed to locally write to cache " + + "(all transaction entries will be invalidated, however there was a window when " + + "entries for this transaction were visible to others): " + this, ex); - errorWhenCommitting(); - - throw ex; + if (isNodeStopping) { + U.warn(log, "Failed to commit transaction, node is stopping [tx=" + this + + ", err=" + ex + ']'); } - else { - boolean hasInvalidEnvironmentIssue = X.hasCause(ex, InvalidEnvironmentException.class); - - IgniteCheckedException err = new IgniteTxHeuristicCheckedException("Failed to locally write to cache " + - "(all transaction entries will be invalidated, however there was a window when " + - "entries for this transaction were visible to others): " + this, ex); - - if (hasInvalidEnvironmentIssue) { - U.warn(log, "Failed to commit transaction, node is stopping " + - "[tx=" + this + ", err=" + ex + ']'); - } - else - U.error(log, "Heuristic transaction failure.", err); + else if (hasInvalidEnvironmentIssue) { + U.warn(log, "Failed to commit transaction, node is in invalid state and will be stopped [tx=" + this + + ", err=" + ex + ']'); + } + else + U.error(log, "Commit failed.", err); - COMMIT_ERR_UPD.compareAndSet(this, null, err); + COMMIT_ERR_UPD.compareAndSet(this, null, err); - state(UNKNOWN); + state(UNKNOWN); + if (hasInvalidEnvironmentIssue) + cctx.kernalContext().failure().process(new FailureContext(FailureType.CRITICAL_ERROR, ex)); + else if (!isNodeStopping) { // Skip fair uncommit in case of node stopping or invalidation. try { // Courtesy to minimize damage. - uncommit(hasInvalidEnvironmentIssue); + uncommit(); } catch (Throwable ex1) { U.error(log, "Failed to uncommit transaction: " + this, ex1); @@ -874,12 +871,12 @@ public abstract class IgniteTxLocalAdapter extends IgniteTxAdapter implements Ig if (ex1 instanceof Error) throw ex1; } + } - if (ex instanceof Error) - throw ex; + if (ex instanceof Error) + throw ex; - throw err; - } + throw err; } } http://git-wip-us.apache.org/repos/asf/ignite/blob/dde936ac/modules/core/src/main/resources/META-INF/classnames.properties ---------------------------------------------------------------------- diff --git a/modules/core/src/main/resources/META-INF/classnames.properties b/modules/core/src/main/resources/META-INF/classnames.properties index 27934ad..c105421 100644 --- a/modules/core/src/main/resources/META-INF/classnames.properties +++ b/modules/core/src/main/resources/META-INF/classnames.properties @@ -390,7 +390,7 @@ org.apache.ignite.internal.managers.loadbalancer.GridLoadBalancerManager$1 org.apache.ignite.internal.marshaller.optimized.OptimizedFieldType org.apache.ignite.internal.mem.IgniteOutOfMemoryException org.apache.ignite.internal.pagemem.impl.PageMemoryNoStoreImpl$Segment -org.apache.ignite.internal.pagemem.wal.StorageException +org.apache.ignite.internal.processors.cache.persistence.StorageException org.apache.ignite.internal.pagemem.wal.WALIterator org.apache.ignite.internal.pagemem.wal.WALPointer org.apache.ignite.internal.pagemem.wal.record.ExchangeRecord$Type