1 /* 2 * See the file LICENSE for redistribution information. 3 * 4 * Copyright (c) 2002, 2014 Oracle and/or its affiliates. All rights reserved. 5 * 6 */ 7 8 package com.sleepycat.je; 9 10 import com.sleepycat.je.txn.Locker; 11 12 /** 13 * Indicates that a failure has occurred that impacts the current operation 14 * and/or transaction. For failures that impact the environment as a whole, 15 * see {@link EnvironmentFailureException}. For an overview of all exceptions 16 * thrown by JE, see {@link DatabaseException}. 17 * 18 * <p>If an explicit transaction applies to a method which threw this 19 * exception, the exception may indicate that {@link Transaction#abort} must be 20 * called, depending on the nature of the failure. A transaction is applicable 21 * to a method call in two cases.</p> 22 * <ol> 23 * <li>When an explicit (non-null) {@code Transaction} instance is specified. 24 * This applies when the {@code Transaction} is passed as a parameter to the 25 * method that throws the exception, or when the {@code Transaction} is passed 26 * to {@link Database#openCursor} and a {@code Cursor} method throws the 27 * exception. 28 * </li> 29 * <li>When a per-thread {@code Transaction} applies to the method that throws 30 * the exception. Per-thread transactions apply when using {@link 31 * com.sleepycat.collections persistent collections} with {@link 32 * com.sleepycat.collections.CurrentTransaction} or {@link 33 * com.sleepycat.collections.TransactionRunner}, or when using XA transactions 34 * with {@link XAEnvironment}. 35 * </li> 36 * </ol> 37 * 38 * <p>When a transaction is applicable to a method call, the application should 39 * catch {@code OperationFailureException} and then call {@link 40 * Transaction#isValid}. If {@code false} is returned, all {@code Cursor} 41 * instances that were created with the transaction must be closed and then 42 * {@link Transaction#abort} must be called. Also note that {@link 43 * Transaction#isValid} may be called at any time, not just during exception 44 * handling.</p> 45 * 46 * <p>The use of the {@link Transaction#isValid} method allows JE to determine 47 * dynamically whether the failure requires an abort or not, and allows for 48 * this determination to change in future releases. Over time, internal 49 * improvements to error handling may allow more error conditions to be handled 50 * without invalidating the {@code Transaction}.</p> 51 * 52 * <p>The specific handling that is necessary for an {@code 53 * OperationFailureException} depends on the specific subclass thrown. See the 54 * javadoc for each method for information on which methods throw which {@code 55 * OperationFailureException}s and why.</p> 56 * 57 * <p>If {@link Transaction#abort} is not called after an {@code 58 * OperationFailureException} invalidates the {@code Transaction}, all 59 * subsequent method calls using the {@code Transaction} will throw the same 60 * exception. This provides more than one opportunity to catch and handle the 61 * specific exception subclass that caused the failure.</p> 62 * 63 * <p>{@code OperationFailureException} is also thrown by methods where no 64 * transaction applies. In most cases the action required to handle the 65 * exception is the same as with a transaction, although of course no abort is 66 * necessary.</p> 67 * 68 * <p>However, please be aware that for some operations on a non-transactional 69 * {@code Database} or {@code EntityStore}, an {@code 70 * OperationFailureException} may cause data corruption. For example, see 71 * {@link SecondaryReferenceException}.</p> 72 * 73 * <p>There are two groups of operation failure subclasses worth noting since 74 * they apply to many methods: read operation failures and write operation 75 * failures. These are described below.</p> 76 * 77 * <a name="readFailures"><h3>Read Operation Failures</h3></a> 78 * 79 * <p>Read operations are all those performed by the {@code get} family of 80 * methods, for example, {@link Database#get Database.get}, {@link 81 * Cursor#getNext Cursor.getNext}, {@link com.sleepycat.persist.EntityIndex#get 82 * EntityIndex.get}, {@link com.sleepycat.persist.EntityCursor#next 83 * EntityCursor.next}, {@link com.sleepycat.collections.StoredMap#get 84 * StoredMap.get}, and {@link ForwardCursor#getNext ForwardCursor.getNext}. 85 * These methods may cause the following operation 86 * failures.</p> 87 * 88 * <ul> 89 * <li>{@link OperationFailureException} is the superclass of all read 90 * operation failures.</li> 91 * <ul> 92 * <li>{@link LockConflictException} is thrown if a lock conflict prevents 93 * the operation from completing. A read operation may be blocked by another 94 * locker (transaction or non-transactional cursor) that holds a write lock 95 * on the record.</li> 96 * 97 * <ul> 98 * <li>{@link com.sleepycat.je.rep.LockPreemptedException} is a subclass 99 * of {@code LockConflictException} that is thrown in a replicated 100 * environment on the Replica node, when the Master node has changed a 101 * record that was previously locked by the reading transaction or 102 * cursor.</li> 103 * </ul> 104 * 105 * <li>{@link SecondaryIntegrityException} is thrown if a primary-secondary 106 * relationship integrity problem is detected while reading a primary 107 * database record via a secondary index.</li> 108 * 109 * <li>{@link com.sleepycat.je.rep.DatabasePreemptedException} is thrown in a 110 * replicated environment on the Replica node, when the Master node has 111 * truncated, removed or renamed the database.</li> 112 * 113 * <li>Other {@link OperationFailureException} subclasses may be thrown if 114 * such an exception was thrown earlier and caused the transaction to be 115 * invalidated.</li> 116 * </ul> 117 * </ul> 118 * 119 * <a name="writeFailures"><h3>Write Operation Failures</h3></a> 120 * 121 * <p>Write operations are all those performed by the {@code put} and {@code 122 * delete} families of methods, for example, {@link Database#put Database.put}, 123 * {@link Cursor#delete Cursor.delete}, {@link 124 * com.sleepycat.persist.PrimaryIndex#put PrimaryIndex.put}, {@link 125 * com.sleepycat.persist.EntityCursor#delete EntityCursor.delete} and {@link 126 * com.sleepycat.collections.StoredMap#put StoredMap.put}. These methods may 127 * cause the following operation failures, although certain failures are only 128 * caused by {@code put} methods and others only by {@code delete} methods, as 129 * noted below.</p> 130 * 131 * <ul> 132 * <li>{@link OperationFailureException} is the superclass of all write 133 * operation failures.</li> 134 * 135 * <ul> 136 * <li>{@link LockConflictException} is thrown if a lock conflict prevents 137 * the operation from completing. A write operation may be blocked by 138 * another locker (transaction or non-transactional cursor) that holds a read 139 * or write lock on the record.</li> 140 * 141 * <li>{@link SecondaryConstraintException} is the superclass of all 142 * exceptions thrown when a write operation fails because of a secondary 143 * constraint.</li> 144 * 145 * <ul> 146 * <li>{@link ForeignConstraintException} is thrown when an attempt to 147 * write a primary database record would insert a secondary record with a 148 * key that does not exist in a foreign key database, when the secondary 149 * key is configured as a foreign key. This exception is only thrown by 150 * {@code put} methods.</li> 151 * 152 * <li>{@link UniqueConstraintException} is thrown when an attempt to write 153 * a primary database record would insert a secondary record with a 154 * duplicate key, for secondaries that represent one-to-one and one-to-many 155 * relationships. This exception is only thrown by {@code put} 156 * methods.</li> 157 * 158 * <li>{@link DeleteConstraintException} is thrown when an attempt is made 159 * to delete a key from a foreign key database, when that key is referenced 160 * by a secondary database, and the secondary is configured to cause an 161 * abort in this situation. This exception is only thrown by {@code 162 * delete} methods.</li> 163 * </ul> 164 * 165 * <li>{@link SecondaryIntegrityException} is thrown if a primary-secondary 166 * relationship integrity problem is detected while writing a record in a 167 * primary database that has one or more secondary indices. 168 * 169 * <li>{@link com.sleepycat.je.rep.DatabasePreemptedException} is thrown in a 170 * replicated environment on a Replica node, when the Master node has 171 * truncated, removed or renamed the database.</li> 172 * 173 * <li>{@link com.sleepycat.je.rep.ReplicaWriteException} is always thrown in 174 * a replicated environment on a Replica node, since write operations are not 175 * allowed on a Replica.</li> 176 * 177 * <li>Other {@link OperationFailureException} subclasses may be thrown if 178 * such an exception was thrown earlier and caused the transaction to be 179 * invalidated.</li> 180 * </ul> 181 * </ul> 182 * 183 * @since 4.0 184 */ 185 public abstract class OperationFailureException extends DatabaseException { 186 187 private static final long serialVersionUID = 1; 188 189 /** 190 * For internal use only. 191 * @hidden 192 */ OperationFailureException(Locker locker, boolean abortOnly, String message, Throwable cause)193 public OperationFailureException(Locker locker, 194 boolean abortOnly, 195 String message, 196 Throwable cause) { 197 super(message, cause); 198 if (abortOnly) { 199 assert locker != null; 200 locker.setOnlyAbortable(this); 201 } 202 } 203 204 /** 205 * For internal use only. 206 * @hidden 207 * Only for use by bind/collection/persist exception subclasses. 208 */ OperationFailureException(String message)209 public OperationFailureException(String message) { 210 this(null /*locker*/, false /*abortOnly*/, message, null /*cause*/); 211 } 212 213 /** 214 * For internal use only. 215 * @hidden 216 * Only for use by wrapSelf methods. 217 */ OperationFailureException(String message, OperationFailureException cause)218 protected OperationFailureException(String message, 219 OperationFailureException cause) { 220 super(message, cause); 221 } 222 223 /** 224 * For internal use only. 225 * @hidden 226 * Must be implemented by every concrete subclass to return an instance of 227 * its own class, constructed with the given msg and this exception as 228 * parameters, e.g.: return new MyClass(msg, this); 229 */ wrapSelf(String msg)230 public abstract OperationFailureException wrapSelf(String msg); 231 } 232