1 /*
2    bdb2d is BerkeleyDB for D language
3    It is part of unDE project (http://unde.su)
4 
5    Copyright (C) 2009-2014 Nikolay (unDEFER) Krivchenkov <undefer@gmail.com>
6 
7    This program is free software: you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation, either version 3 of the License, or
10    (at your option) any later version.
11 
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16 
17    You should have received a copy of the GNU General Public License
18    along with this program.  If not, see <http://www.gnu.org/licenses/>.
19 */
20 
21 module berkeleydb.dbexception;
22 
23 import berkeleydb.c;
24 import berkeleydb.dbenv;
25 import berkeleydb.dbt;
26 import std.conv;
27 
28 /* 
29  * This method fully coming from macroses DB_RETOK_*
30  * from db/src/dbinc/db_int.in
31  */
32 package auto DbRetCodeToException(string Func)(int ret, DbEnv dbenv = null, Dbt *dbt = null,
33         db_lockop_t op = 0, db_lockmode_t mode = 0, const (DB_LOCK) *lock = null, int index = 0)
34 {
35 	switch(ret)
36 	{
37 		case 0:
38 
39 		static if(Func == "std")
40 		{
41 			return;
42 		}	
43 		else static if(Func == "Dbc.del" 
44 				|| Func == "Db.del")
45 		{
46 		case DB_KEYEMPTY:
47 		case DB_NOTFOUND:
48 			return ret;
49 		}
50 		else static if(Func == "Dbc.get" 
51 				|| Func == "Db.get" 
52 				|| Func == "exists")
53 		{
54 		case DB_KEYEMPTY:
55 		case DB_NOTFOUND:
56 			return ret;
57 		}
58 		else static if(Func == "Dbc.put")
59 		{
60 		case DB_KEYEXIST:
61 		case DB_NOTFOUND:
62 			return ret;
63 		}
64 		else static if(Func == "Db.put")
65 		{
66 		case DB_KEYEXIST:
67 			return ret;
68 		}
69 		else static if(Func == "DbLogc.get")
70 		{
71 		case DB_NOTFOUND:
72 			return ret;
73 		}
74 		else static if(Func == "DbMpoolfile.get")
75 		{
76 		case DB_PAGE_NOTFOUND:
77 			return ret;
78 		}
79 		else static if(Func == "rep_process_message")
80 		{
81 		case DB_REP_IGNORE:
82 		case DB_REP_ISPERM:
83 		case DB_REP_NEWMASTER:
84 		case DB_REP_NEWSITE:
85 		case DB_REP_NOTPERM:
86 		case DB_REP_WOULDROLLBACK:
87 			return ret;
88 		}
89 		else static if(Func == "repmgr_localsite")
90 		{
91 		case DB_NOTFOUND:
92 			return ret;
93 		}
94 		else static if(Func == "repmgr_start")
95 		{
96 		case DB_REP_IGNORE:
97 			return ret;
98 		}
99 		else static if(Func == "txn_applied")
100 		{
101 		case DB_NOTFOUND:
102 		case DB_TIMEOUT:
103 		case DB_KEYEMPTY:
104 			return ret;
105 		}
106 		else
107 		{
108 			static assert(0, "Bad func name for DbRetCodeToException");
109 		}
110 
111         case DB_LOCK_DEADLOCK:
112             throw new DbDeadlockException("BerkeleyDB error", ret, dbenv);
113 
114         case DB_LOCK_NOTGRANTED:
115             throw new DbLockNotGrantedException("BerkeleyDB error", ret, dbenv,
116                     op, mode, dbt, lock, index);
117 
118         case DB_REP_HANDLE_DEAD:
119             throw new DbRepHandleDeadException("BerkeleyDB error", ret, dbenv);
120 
121         case DB_RUNRECOVERY:
122             throw new DbRunRecoveryException("BerkeleyDB error", ret, dbenv);
123 
124 		static if(Func == "Dbc.get" 
125 				|| Func == "Db.get" 
126 				|| Func == "DbLogc.get")
127 		{
128         case DB_BUFFER_SMALL:
129             if (dbt is null)
130             {
131                 throw new DbException("BerkeleyDB error", ret, dbenv);
132             }
133             else if (dbt.flags & DB_DBT_USERMEM && dbt.size > dbt.ulen)
134             {
135                 throw new DbMemoryException("BerkeleyDB error", ret, dbenv, dbt);
136             }
137             else
138             {
139                 return ret;
140             }
141         }
142 
143 		default:
144 			throw new DbException("BerkeleyDB error", ret, dbenv);
145 	}
146 }
147 
148 package auto DbRetCodeToException()(int ret, DbEnv dbenv = null, Dbt *dbt = null,
149         db_lockop_t op = 0, db_lockmode_t mode = 0, const (DB_LOCK) *lock = null, int index = 0)
150 {
151 	DbRetCodeToException!"std"(ret, dbenv, dbt, op, mode, lock, index);
152 }
153 
154 class DbException : Exception
155 {
156 	int dberrno;
157 	DbEnv dbenv;
158 
159 	package this(string msg_prefix, int errno, DbEnv env, string file = __FILE__, size_t line = __LINE__)
160 	{
161 		dberrno = errno;
162 		dbenv = env;
163 
164 		char *strerror = db_strerror(dberrno);
165 		super(msg_prefix~": "~to!string(strerror), file, line);
166 	}
167 }
168 
169 class DbWrongUsingException : Exception
170 {
171 	package this(string msg, string file = __FILE__, size_t line = __LINE__)
172 	{
173 		super(msg, file, line);
174 	}
175 }
176 
177 
178 class DbDeadlockException : DbException
179 {
180 	package this(string msg_prefix, int errno, DbEnv env, string file = __FILE__, size_t line = __LINE__)
181 	{
182 		super(msg_prefix, errno, env, file, line);
183 	}
184 }
185 
186 class DbLockNotGrantedException : DbException
187 {
188     db_lockop_t op;
189     db_lockmode_t mode;
190     const (Dbt) *obj;
191     const (DB_LOCK) *lock;
192     int index;
193 	package this(string msg_prefix, int errno, DbEnv env, 
194             db_lockop_t _op, db_lockmode_t _mode, const (Dbt) *_obj, const (DB_LOCK) *_lock, int _index,
195             string file = __FILE__, size_t line = __LINE__)
196 	{
197         op = _op;
198         mode = _mode;
199         obj = _obj;
200         lock = _lock;
201         index = _index;
202 		super(msg_prefix, errno, env, file, line);
203 	}
204 }
205 
206 class DbMemoryException : DbException
207 {
208 	Dbt *dbt;
209 	package this(string msg_prefix, int errno, DbEnv env, Dbt *t, string file = __FILE__, size_t line = __LINE__)
210 	{
211 		dbt = t;
212 		super(msg_prefix, errno, env, file, line);
213 	}
214 }
215 
216 class DbRepHandleDeadException : DbException
217 {
218 	package this(string msg_prefix, int errno, DbEnv env, string file = __FILE__, size_t line = __LINE__)
219 	{
220 		super(msg_prefix, errno, env, file, line);
221 	}
222 }
223 
224 class DbRunRecoveryException : DbException
225 {
226 	package this(string msg_prefix, int errno, DbEnv env, string file = __FILE__, size_t line = __LINE__)
227 	{
228 		super(msg_prefix, errno, env, file, line);
229 	}
230 }
231