1/*-
2 * See the file LICENSE for redistribution information.
3 *
4 * Copyright (c) 2009 Oracle.  All rights reserved.
5 *
6 */
7using System;
8using System.Collections.Generic;
9using System.Text;
10using BerkeleyDB.Internal;
11
12namespace BerkeleyDB {
13    /// <summary>
14    /// Represents errors that occur during Berkley DB operations.
15    /// </summary>
16    public class DatabaseException : Exception {
17        /// <summary>
18        /// The underlying error code from the Berkeley DB C library.
19        /// </summary>
20        public int ErrorCode;
21
22        /// <summary>
23        /// Throw an exception which corresponds to the specified Berkeley DB
24        /// error code.
25        /// </summary>
26        /// <param name="err">The Berkeley DB error code</param>
27        public static void ThrowException(int err) {
28            switch (err) {
29                case 0:
30                    return;
31                case ErrorCodes.DB_NOTFOUND:
32                    throw new NotFoundException();
33                case ErrorCodes.DB_BUFFER_SMALL:
34                    throw new MemoryException();
35                case ErrorCodes.DB_FOREIGN_CONFLICT:
36                    throw new ForeignConflictException();
37                case ErrorCodes.DB_KEYEMPTY:
38                    throw new KeyEmptyException();
39                case ErrorCodes.DB_KEYEXIST:
40                    throw new KeyExistException();
41                case ErrorCodes.DB_LOCK_DEADLOCK:
42                    throw new DeadlockException();
43                case ErrorCodes.DB_LOCK_NOTGRANTED:
44                    throw new LockNotGrantedException();
45                case ErrorCodes.DB_LOG_BUFFER_FULL:
46                    throw new FullLogBufferException();
47                case ErrorCodes.DB_OLD_VERSION:
48                    throw new OldVersionException();
49                case ErrorCodes.DB_PAGE_NOTFOUND:
50                    throw new PageNotFoundException();
51                case ErrorCodes.DB_REP_DUPMASTER:
52                case ErrorCodes.DB_REP_HOLDELECTION:
53                case ErrorCodes.DB_REP_IGNORE:
54                case ErrorCodes.DB_REP_ISPERM:
55                case ErrorCodes.DB_REP_JOIN_FAILURE:
56                case ErrorCodes.DB_REP_NEWSITE:
57                case ErrorCodes.DB_REP_NOTPERM:
58                    return;
59                case ErrorCodes.DB_REP_LEASE_EXPIRED:
60                    throw new LeaseExpiredException();
61                case ErrorCodes.DB_RUNRECOVERY:
62                    throw new RunRecoveryException();
63                case ErrorCodes.DB_SECONDARY_BAD:
64                    throw new BadSecondaryException();
65                case ErrorCodes.DB_VERIFY_BAD:
66                    throw new VerificationException();
67                case ErrorCodes.DB_VERSION_MISMATCH:
68                    throw new VersionMismatchException();
69                default:
70                    throw new DatabaseException(err);
71            }
72        }
73
74        /// <summary>
75        /// Create a new DatabaseException, encapsulating a specific error code.
76        /// </summary>
77        /// <param name="err">The error code to encapsulate.</param>
78        public DatabaseException(int err)
79            : base(libdb_csharp.db_strerror(err)) {
80            ErrorCode = err;
81        }
82    }
83
84    /// <summary>
85    /// A secondary index has been corrupted. This is likely the result of an
86    /// application operating on related databases without first associating
87    /// them.
88    /// </summary>
89    public class BadSecondaryException : DatabaseException {
90        /// <summary>
91        /// Initialize a new instance of the BadSecondaryException
92        /// </summary>
93        public BadSecondaryException() : base(ErrorCodes.DB_SECONDARY_BAD) { }
94    }
95
96    /// <summary>
97    ///
98    /// </summary>
99    public class ForeignConflictException : DatabaseException {
100        /// <summary>
101        /// Initialize a new instance of the ForeignConflictException
102        /// </summary>
103        public ForeignConflictException()
104            : base(ErrorCodes.DB_FOREIGN_CONFLICT) { }
105    }
106
107    /// <summary>
108    /// In-memory logs are configured and no more log buffer space is available.
109    /// </summary>
110    public class FullLogBufferException : DatabaseException {
111        /// <summary>
112        /// Initialize a new instance of the FullLogBufferException
113        /// </summary>
114        public FullLogBufferException()
115            : base(ErrorCodes.DB_LOG_BUFFER_FULL) { }
116    }
117
118    /// <summary>
119    /// The requested key/data pair logically exists but was never explicitly
120    /// created by the application, or that the requested key/data pair was
121    /// deleted and never re-created. In addition, the Queue access method will
122    /// throw a KeyEmptyException for records that were created as part of a
123    /// transaction that was later aborted and never re-created.
124    /// </summary>
125    /// <remarks>
126    /// The Recno and Queue access methods will automatically create key/data
127    /// pairs under some circumstances.
128    /// </remarks>
129    public class KeyEmptyException : DatabaseException {
130        /// <summary>
131        /// Initialize a new instance of the KeyEmptyException
132        /// </summary>
133        public KeyEmptyException() : base(ErrorCodes.DB_KEYEMPTY) { }
134    }
135
136    /// <summary>
137    /// A key/data pair was inserted into the database using
138    /// <see cref="Database.PutNoOverwrite"/> and the key already
139    /// exists in the database, or using
140    /// <see cref="BTreeDatabase.PutNoDuplicate"/> or
141    /// <see cref="HashDatabase.PutNoDuplicate"/> and the key/data
142    /// pair already exists in the database.
143    /// </summary>
144    public class KeyExistException : DatabaseException {
145        /// <summary>
146        /// Initialize a new instance of the KeyExistException
147        /// </summary>
148        public KeyExistException() : base(ErrorCodes.DB_KEYEXIST) { }
149    }
150
151    /// <summary>
152    /// When multiple threads of control are modifying the database, there is
153    /// normally the potential for deadlock. In Berkeley DB, deadlock is
154    /// signified by a DeadlockException thrown from the Berkeley DB function.
155    /// Whenever a Berkeley DB function throws a DeadlockException, the
156    /// enclosing transaction should be aborted.
157    /// </summary>
158    public class DeadlockException : DatabaseException {
159        /// <summary>
160        /// Initialize a new instance of the DeadlockException
161        /// </summary>
162        public DeadlockException() : base(ErrorCodes.DB_LOCK_DEADLOCK) { }
163    }
164
165    /// <summary>
166    /// The site's replication master lease has expired.
167    /// </summary>
168    public class LeaseExpiredException : DatabaseException {
169        /// <summary>
170        /// Initialize a new instance of the LeaseExpiredException
171        /// </summary>
172        public LeaseExpiredException()
173            : base(ErrorCodes.DB_REP_LEASE_EXPIRED) { }
174    }
175
176    /// <summary>
177    /// If <see cref="DatabaseEnvironmentConfig.TimeNotGranted"/> is true,
178    /// database calls timing out based on lock or transaction timeout values
179    /// will throw a LockNotGrantedException, instead of a DeadlockException.
180    /// </summary>
181    public class LockNotGrantedException : DatabaseException {
182        /// <summary>
183        /// Initialize a new instance of the LockNotGrantedException
184        /// </summary>
185        public LockNotGrantedException()
186            : base(ErrorCodes.DB_LOCK_NOTGRANTED) { }
187    }
188
189    internal class MemoryException : DatabaseException {
190        /// <summary>
191        /// Initialize a new instance of the MemoryException
192        /// </summary>
193        internal MemoryException() : base(ErrorCodes.DB_BUFFER_SMALL) { }
194    }
195
196    /// <summary>
197    /// The requested key/data pair did not exist in the database or that
198    /// start-of- or end-of-file has been reached by a cursor.
199    /// </summary>
200    public class NotFoundException : DatabaseException {
201        /// <summary>
202        /// Initialize a new instance of the NotFoundException
203        /// </summary>
204        public NotFoundException() : base(ErrorCodes.DB_NOTFOUND) { }
205    }
206
207    /// <summary>
208    /// This version of Berkeley DB is unable to upgrade a given database.
209    /// </summary>
210    public class OldVersionException : DatabaseException {
211        /// <summary>
212        /// Initialize a new instance of the OldVersionException
213        /// </summary>
214        public OldVersionException() : base(ErrorCodes.DB_OLD_VERSION) { }
215    }
216
217    /// <summary>
218    ///
219    /// </summary>
220    public class PageNotFoundException : DatabaseException {
221        /// <summary>
222        ///
223        /// </summary>
224        public PageNotFoundException() : base(ErrorCodes.DB_PAGE_NOTFOUND) { }
225    }
226
227    /// <summary>
228    /// Berkeley DB has encountered an error it considers fatal to an entire
229    /// environment. Once a RunRecoveryException has been thrown by any
230    /// interface, it will be returned from all subsequent Berkeley DB calls
231    /// made by any threads of control participating in the environment.
232    /// </summary>
233    /// <remarks>
234    /// An example of this type of fatal error is a corrupted database page. The
235    /// only way to recover from this type of error is to have all threads of
236    /// control exit the Berkeley DB environment, run recovery of the
237    /// environment, and re-enter Berkeley DB. (It is not strictly necessary
238    /// that the processes exit, although that is the only way to recover system
239    /// resources, such as file descriptors and memory, allocated by
240    /// Berkeley DB.)
241    /// </remarks>
242    public class RunRecoveryException : DatabaseException {
243        /// <summary>
244        /// Initialize a new instance of the RunRecoveryException
245        /// </summary>
246        public RunRecoveryException() : base(ErrorCodes.DB_RUNRECOVERY) { }
247    }
248
249    /// <summary>
250    /// Thrown by <see cref="Database.Verify"/> if a database is
251    /// corrupted, and by <see cref="Database.Salvage"/> if all
252    /// key/data pairs in the file may not have been successfully output.
253    /// </summary>
254    public class VerificationException : DatabaseException {
255        /// <summary>
256        /// Initialize a new instance of the VerificationException
257        /// </summary>
258        public VerificationException() : base(ErrorCodes.DB_VERIFY_BAD) { }
259    }
260
261    /// <summary>
262    /// The version of the Berkeley DB library doesn't match the version that
263    /// created the database environment.
264    /// </summary>
265    public class VersionMismatchException : DatabaseException {
266        /// <summary>
267        /// Initialize a new instance of the VersionMismatchException
268        /// </summary>
269        public VersionMismatchException()
270            : base(ErrorCodes.DB_VERSION_MISMATCH) { }
271    }
272}
273