1 /*-
2  * Copyright (c) 1997, 2020 Oracle and/or its affiliates.  All rights reserved.
3  *
4  * See the file LICENSE for license information.
5  *
6  * $Id$
7  */
8 
9 #include "db_config.h"
10 
11 #include "db_int.h"
12 
13 #include "db_cxx.h"
14 #include "dbinc/cxx_int.h"
15 
16 #include "dbinc/db_page.h"
17 #include "dbinc/db_am.h"
18 #include "dbinc/log.h"
19 #include "dbinc_auto/common_ext.h"
20 #include "dbinc_auto/log_ext.h"
21 
22 #ifdef HAVE_CXX_STDHEADERS
23 using std::cerr;
24 #endif
25 
26 // Helper macros for simple methods that pass through to the
27 // underlying C method.  They may return an error or raise an exception.
28 // These macros expect that input _argspec is an argument
29 // list element (e.g., "char *arg") and that _arglist is the arguments
30 // that should be passed through to the C method (e.g., "(dbenv, arg)")
31 //
32 #define	DBENV_METHOD_ERR(_name, _argspec, _arglist, _on_err)	  \
33 int DbEnv::_name _argspec					  \
34 {								  \
35 	DB_ENV *dbenv = unwrap(this);				  \
36 	int ret;						  \
37 								  \
38 	if ((ret = dbenv->_name _arglist) != 0)	{		  \
39 		_on_err;					  \
40 	}							  \
41 	return (ret);						  \
42 }
43 
44 #define	DBENV_METHOD(_name, _argspec, _arglist)			  \
45 	DBENV_METHOD_ERR(_name, _argspec, _arglist,		  \
46 	DB_ERROR(this, "DbEnv::" # _name, ret, error_policy()))
47 
48 #define	DBENV_METHOD_QUIET(_name, _argspec, _arglist)		  \
49 int DbEnv::_name _argspec					  \
50 {								  \
51 	DB_ENV *dbenv = unwrap(this);				  \
52 								  \
53 	return (dbenv->_name _arglist);				  \
54 }
55 
56 #define	DBENV_METHOD_VOID(_name, _argspec, _arglist)		  \
57 void DbEnv::_name _argspec					  \
58 {								  \
59 	DB_ENV *dbenv = unwrap(this);				  \
60 								  \
61 	dbenv->_name _arglist;					  \
62 }
63 
64 // The reason for a static variable is that some structures
65 // (like Dbts) have no connection to any Db or DbEnv, so when
66 // errors occur in their methods, we must have some reasonable
67 // way to determine whether to throw or return errors.
68 //
69 // This variable is taken from flags whenever a DbEnv is constructed.
70 // Normally there is only one DbEnv per program, and even if not,
71 // there is typically a single policy of throwing or returning.
72 //
73 static int last_known_error_policy = ON_ERROR_UNKNOWN;
74 
75 // These 'glue' function are declared as extern "C" so they will
76 // be compatible with picky compilers that do not allow mixing
77 // of function pointers to 'C' functions with function pointers
78 // to C++ functions.
79 //
80 extern "C"
_feedback_intercept_c(DB_ENV * dbenv,int opcode,int pct)81 void _feedback_intercept_c(DB_ENV *dbenv, int opcode, int pct)
82 {
83 	DbEnv::_feedback_intercept(dbenv, opcode, pct);
84 }
85 
86 extern "C"
_paniccall_intercept_c(DB_ENV * dbenv,int errval)87 void _paniccall_intercept_c(DB_ENV *dbenv, int errval)
88 {
89 	DbEnv::_paniccall_intercept(dbenv, errval);
90 }
91 
92 extern "C"
_partial_rep_intercept_c(DB_ENV * dbenv,const char * name,int * result,u_int32_t flags)93 int _partial_rep_intercept_c(DB_ENV *dbenv,
94     const char *name, int *result, u_int32_t flags)
95 {
96 	return (DbEnv::_partial_rep_intercept(dbenv, name, result, flags));
97 }
98 
99 extern "C"
_event_func_intercept_c(DB_ENV * dbenv,u_int32_t event,void * event_info)100 void _event_func_intercept_c(DB_ENV *dbenv, u_int32_t event, void *event_info)
101 {
102 	DbEnv::_event_func_intercept(dbenv, event, event_info);
103 }
104 
105 extern "C"
_stream_error_function_c(const DB_ENV * dbenv,const char * prefix,const char * message)106 void _stream_error_function_c(const DB_ENV *dbenv,
107     const char *prefix, const char *message)
108 {
109 	DbEnv::_stream_error_function(dbenv, prefix, message);
110 }
111 
112 extern "C"
_stream_message_function_c(const DB_ENV * dbenv,const char * prefix,const char * message)113 void _stream_message_function_c(const DB_ENV *dbenv,
114     const char *prefix, const char *message)
115 {
116 	DbEnv::_stream_message_function(dbenv, prefix, message);
117 }
118 
119 extern "C"
_app_dispatch_intercept_c(DB_ENV * dbenv,DBT * dbt,DB_LSN * lsn,db_recops op)120 int _app_dispatch_intercept_c(DB_ENV *dbenv, DBT *dbt, DB_LSN *lsn, db_recops op)
121 {
122 	return (DbEnv::_app_dispatch_intercept(dbenv, dbt, lsn, op));
123 }
124 
125 extern "C"
_rep_send_intercept_c(DB_ENV * dbenv,const DBT * cntrl,const DBT * data,const DB_LSN * lsn,int id,u_int32_t flags)126 int _rep_send_intercept_c(DB_ENV *dbenv, const DBT *cntrl, const DBT *data,
127     const DB_LSN *lsn, int id, u_int32_t flags)
128 {
129 	return (DbEnv::_rep_send_intercept(dbenv,
130 	    cntrl, data, lsn, id, flags));
131 }
132 
133 extern "C"
_repmgr_set_socket_intercept_c(DB_ENV * dbenv,DB_REPMGR_SOCKET socket,int * result,u_int32_t flags)134 int _repmgr_set_socket_intercept_c(DB_ENV *dbenv, DB_REPMGR_SOCKET socket,
135 	int *result, u_int32_t flags)
136 {
137 	return DbEnv::_repmgr_set_socket_intercept(dbenv, socket, result, flags);
138 }
139 
140 extern "C"
_message_dispatch_intercept_c(DB_ENV * dbenv,DB_CHANNEL * channel,DBT * request,u_int32_t nrequest,u_int32_t cb_flags)141 void _message_dispatch_intercept_c(DB_ENV *dbenv, DB_CHANNEL *channel,
142     DBT *request, u_int32_t nrequest, u_int32_t cb_flags)
143 {
144 	DbEnv::_message_dispatch_intercept(dbenv, channel, request, nrequest,
145 	    cb_flags);
146 }
147 
148 extern "C"
_isalive_intercept_c(DB_ENV * dbenv,pid_t pid,db_threadid_t thrid,u_int32_t flags)149 int _isalive_intercept_c(
150     DB_ENV *dbenv, pid_t pid, db_threadid_t thrid, u_int32_t flags)
151 {
152 	return (DbEnv::_isalive_intercept(dbenv, pid, thrid, flags));
153 }
154 
155 extern "C"
_thread_id_intercept_c(DB_ENV * dbenv,pid_t * pidp,db_threadid_t * thridp)156 void _thread_id_intercept_c(DB_ENV *dbenv, pid_t *pidp, db_threadid_t *thridp)
157 {
158 	DbEnv::_thread_id_intercept(dbenv, pidp, thridp);
159 }
160 
161 extern "C"
_thread_id_string_intercept_c(DB_ENV * dbenv,pid_t pid,db_threadid_t thrid,char * buf)162 char *_thread_id_string_intercept_c(DB_ENV *dbenv, pid_t pid,
163     db_threadid_t thrid, char *buf)
164 {
165 	return (DbEnv::_thread_id_string_intercept(dbenv, pid, thrid, buf));
166 }
167 
168 extern "C"
_backup_close_intercept_c(DB_ENV * dbenv,const char * dbname,void * handle)169 int _backup_close_intercept_c(DB_ENV *dbenv, const char *dbname, void *handle)
170 {
171 	return (DbEnv::_backup_close_intercept(dbenv, dbname, handle));
172 }
173 
174 extern "C"
_backup_open_intercept_c(DB_ENV * dbenv,const char * dbname,const char * target,void ** handle)175 int _backup_open_intercept_c(DB_ENV *dbenv,
176     const char *dbname, const char *target, void **handle)
177 {
178 	return (DbEnv::_backup_open_intercept(dbenv, dbname, target, handle));
179 }
180 
181 extern "C"
_backup_write_intercept_c(DB_ENV * dbenv,u_int32_t off_gbytes,u_int32_t off_bytes,u_int32_t size,u_int8_t * buf,void * handle)182 int _backup_write_intercept_c(DB_ENV *dbenv, u_int32_t off_gbytes,
183     u_int32_t off_bytes, u_int32_t size, u_int8_t *buf, void *handle)
184 {
185 	return (DbEnv::_backup_write_intercept(
186 		dbenv, off_gbytes, off_bytes, size, buf, handle));
187 }
188 
_feedback_intercept(DB_ENV * dbenv,int opcode,int pct)189 void DbEnv::_feedback_intercept(DB_ENV *dbenv, int opcode, int pct)
190 {
191 	DbEnv *cxxenv = DbEnv::get_DbEnv(dbenv);
192 	if (cxxenv == 0) {
193 		DB_ERROR(0,
194 		    "DbEnv::feedback_callback", EINVAL, ON_ERROR_UNKNOWN);
195 		return;
196 	}
197 	if (cxxenv->feedback_callback_ == 0) {
198 		DB_ERROR(DbEnv::get_DbEnv(dbenv),
199 		    "DbEnv::feedback_callback", EINVAL, cxxenv->error_policy());
200 		return;
201 	}
202 	(*cxxenv->feedback_callback_)(cxxenv, opcode, pct);
203 }
204 
_paniccall_intercept(DB_ENV * dbenv,int errval)205 void DbEnv::_paniccall_intercept(DB_ENV *dbenv, int errval)
206 {
207 	DbEnv *cxxenv = DbEnv::get_DbEnv(dbenv);
208 	if (cxxenv == 0) {
209 		DB_ERROR(0,
210 		    "DbEnv::paniccall_callback", EINVAL, ON_ERROR_UNKNOWN);
211 		return;
212 	}
213 	if (cxxenv->paniccall_callback_ == 0) {
214 		DB_ERROR(cxxenv, "DbEnv::paniccall_callback", EINVAL,
215 		    cxxenv->error_policy());
216 		return;
217 	}
218 	(*cxxenv->paniccall_callback_)(cxxenv, errval);
219 }
220 
_partial_rep_intercept(DB_ENV * dbenv,const char * name,int * result,u_int32_t flags)221 int DbEnv::_partial_rep_intercept(DB_ENV *dbenv,
222     const char *name, int *result, u_int32_t flags)
223 {
224 	DbEnv *cxxenv = DbEnv::get_DbEnv(dbenv);
225 	if (cxxenv == 0) {
226 		DB_ERROR(0,
227 		    "DbEnv::partial_rep_callback", EINVAL, ON_ERROR_UNKNOWN);
228 		return (EINVAL);
229 	}
230 	return ((*cxxenv->partial_rep_callback_)(cxxenv, name, result, flags));
231 }
232 
_event_func_intercept(DB_ENV * dbenv,u_int32_t event,void * event_info)233 void DbEnv::_event_func_intercept(
234     DB_ENV *dbenv, u_int32_t event, void *event_info)
235 {
236 	DbEnv *cxxenv = DbEnv::get_DbEnv(dbenv);
237 	if (cxxenv == 0) {
238 		DB_ERROR(0,
239 		    "DbEnv::event_func_callback", EINVAL, ON_ERROR_UNKNOWN);
240 		return;
241 	}
242 	if (cxxenv->event_func_callback_ == 0) {
243 		DB_ERROR(cxxenv, "DbEnv::event_func_callback", EINVAL,
244 		    cxxenv->error_policy());
245 		return;
246 	}
247 	(*cxxenv->event_func_callback_)(cxxenv, event, event_info);
248 }
249 
_app_dispatch_intercept(DB_ENV * dbenv,DBT * dbt,DB_LSN * lsn,db_recops op)250 int DbEnv::_app_dispatch_intercept(DB_ENV *dbenv, DBT *dbt, DB_LSN *lsn,
251     db_recops op)
252 {
253 	DbEnv *cxxenv = DbEnv::get_DbEnv(dbenv);
254 	if (cxxenv == 0) {
255 		DB_ERROR(DbEnv::get_DbEnv(dbenv),
256 		    "DbEnv::app_dispatch_callback", EINVAL, ON_ERROR_UNKNOWN);
257 		return (EINVAL);
258 	}
259 	if (cxxenv->app_dispatch_callback_ == 0) {
260 		DB_ERROR(DbEnv::get_DbEnv(dbenv),
261 		    "DbEnv::app_dispatch_callback", EINVAL,
262 		    cxxenv->error_policy());
263 		return (EINVAL);
264 	}
265 	Dbt *cxxdbt = (Dbt *)dbt;
266 	DbLsn *cxxlsn = (DbLsn *)lsn;
267 	return ((*cxxenv->app_dispatch_callback_)(cxxenv, cxxdbt, cxxlsn, op));
268 }
269 
_isalive_intercept(DB_ENV * dbenv,pid_t pid,db_threadid_t thrid,u_int32_t flags)270 int DbEnv::_isalive_intercept(
271     DB_ENV *dbenv, pid_t pid, db_threadid_t thrid, u_int32_t flags)
272 {
273 	DbEnv *cxxenv = DbEnv::get_DbEnv(dbenv);
274 	if (cxxenv == 0) {
275 		DB_ERROR(DbEnv::get_DbEnv(dbenv),
276 			"DbEnv::isalive_callback", EINVAL, ON_ERROR_UNKNOWN);
277 		return (0);
278 	}
279 	return ((*cxxenv->isalive_callback_)(cxxenv, pid, thrid, flags));
280 }
281 
_repmgr_set_socket_intercept(DB_ENV * dbenv,DB_REPMGR_SOCKET socket,int * result,u_int32_t flags)282 int DbEnv::_repmgr_set_socket_intercept(DB_ENV *dbenv,
283 	DB_REPMGR_SOCKET socket, int *result, u_int32_t flags)
284 {
285 	DbEnv *cxxenv = DbEnv::get_DbEnv(dbenv);
286 	if (cxxenv == 0) {
287 		DB_ERROR(DbEnv::get_DbEnv(dbenv),
288 		    "DbEnv::repmgr_set_socket_callback", EINVAL,
289 		    ON_ERROR_UNKNOWN);
290 		return (EINVAL);
291 	} else {
292 		return ((*cxxenv->repmgr_set_socket_callback_)(cxxenv,
293 			socket, result, flags));
294 	}
295 }
296 
_message_dispatch_intercept(DB_ENV * dbenv,DB_CHANNEL * dbchannel,DBT * request,u_int32_t nrequest,u_int32_t cb_flags)297 void DbEnv::_message_dispatch_intercept(DB_ENV *dbenv, DB_CHANNEL *dbchannel,
298     DBT *request, u_int32_t nrequest, u_int32_t cb_flags)
299 {
300 	DbEnv *cxxenv = DbEnv::get_DbEnv(dbenv);
301 	if (cxxenv == 0)
302 		DB_ERROR(DbEnv::get_DbEnv(dbenv),
303 		    "DbEnv::message_dispatch_callback", EINVAL,
304 		    ON_ERROR_UNKNOWN);
305 	else {
306 		DbChannel *cxxchannel = (DbChannel *)dbchannel;
307 		Dbt *cxxdbt = (Dbt *)request;
308 		((*cxxenv->message_dispatch_callback_)(cxxenv, cxxchannel,
309 		    cxxdbt, nrequest, cb_flags));
310 	}
311 }
312 
_rep_send_intercept(DB_ENV * dbenv,const DBT * cntrl,const DBT * data,const DB_LSN * lsn,int id,u_int32_t flags)313 int DbEnv::_rep_send_intercept(DB_ENV *dbenv, const DBT *cntrl, const DBT *data,
314     const DB_LSN *lsn, int id, u_int32_t flags)
315 {
316 	DbEnv *cxxenv = DbEnv::get_DbEnv(dbenv);
317 	if (cxxenv == 0) {
318 		DB_ERROR(DbEnv::get_DbEnv(dbenv),
319 			"DbEnv::rep_send_callback", EINVAL, ON_ERROR_UNKNOWN);
320 		return (EINVAL);
321 	}
322 	const Dbt *cxxcntrl = (const Dbt *)cntrl;
323 	const DbLsn *cxxlsn = (const DbLsn *)lsn;
324 	Dbt *cxxdata = (Dbt *)data;
325 	return ((*cxxenv->rep_send_callback_)(cxxenv,
326 	    cxxcntrl, cxxdata, cxxlsn, id, flags));
327 }
328 
_thread_id_intercept(DB_ENV * dbenv,pid_t * pidp,db_threadid_t * thridp)329 void DbEnv::_thread_id_intercept(DB_ENV *dbenv,
330     pid_t *pidp, db_threadid_t *thridp)
331 {
332 	DbEnv *cxxenv = DbEnv::get_DbEnv(dbenv);
333 	if (cxxenv == 0) {
334 		DB_ERROR(DbEnv::get_DbEnv(dbenv),
335 			"DbEnv::thread_id_callback", EINVAL, ON_ERROR_UNKNOWN);
336 	} else
337 		cxxenv->thread_id_callback_(cxxenv, pidp, thridp);
338 }
339 
_thread_id_string_intercept(DB_ENV * dbenv,pid_t pid,db_threadid_t thrid,char * buf)340 char *DbEnv::_thread_id_string_intercept(DB_ENV *dbenv,
341     pid_t pid, db_threadid_t thrid, char *buf)
342 {
343 	DbEnv *cxxenv = DbEnv::get_DbEnv(dbenv);
344 	if (cxxenv == 0) {
345 		DB_ERROR(DbEnv::get_DbEnv(dbenv),
346 		    "DbEnv::thread_id_string_callback", EINVAL,
347 		    ON_ERROR_UNKNOWN);
348 		return (NULL);
349 	}
350 	return (cxxenv->thread_id_string_callback_(cxxenv, pid, thrid, buf));
351 }
352 
_backup_close_intercept(DB_ENV * dbenv,const char * dbname,void * handle)353 int DbEnv::_backup_close_intercept(
354     DB_ENV *dbenv, const char *dbname, void *handle)
355 {
356 	DbEnv *cxxenv = DbEnv::get_DbEnv(dbenv);
357 	if (cxxenv == 0) {
358 		DB_ERROR(DbEnv::get_DbEnv(dbenv),
359 		    "DbEnv::backup_close_callback", EINVAL, ON_ERROR_UNKNOWN);
360 		return (EINVAL);
361 	}
362 	if (cxxenv->backup_close_callback_ == 0) {
363 		DB_ERROR(DbEnv::get_DbEnv(dbenv), "DbEnv::backup_close_callback",
364 		    EINVAL, cxxenv->error_policy());
365 		return (EINVAL);
366 	}
367 	return (*cxxenv->backup_close_callback_)(cxxenv, dbname, handle);
368 }
369 
_backup_open_intercept(DB_ENV * dbenv,const char * dbname,const char * target,void ** handle)370 int DbEnv::_backup_open_intercept(DB_ENV *dbenv,
371     const char *dbname, const char *target, void **handle)
372 {
373 	DbEnv *cxxenv = DbEnv::get_DbEnv(dbenv);
374 	if (cxxenv == 0) {
375 		DB_ERROR(DbEnv::get_DbEnv(dbenv),
376 		    "DbEnv::backup_open_callback", EINVAL, ON_ERROR_UNKNOWN);
377 		return (EINVAL);
378 	}
379 	if (cxxenv->backup_open_callback_ == 0) {
380 		DB_ERROR(DbEnv::get_DbEnv(dbenv), "DbEnv::backup_open_callback",
381 		    EINVAL, cxxenv->error_policy());
382 		return (EINVAL);
383 	}
384 	return (*cxxenv->backup_open_callback_)(cxxenv, dbname, target, handle);
385 }
386 
_backup_write_intercept(DB_ENV * dbenv,u_int32_t off_gbytes,u_int32_t off_bytes,u_int32_t size,u_int8_t * buf,void * handle)387 int DbEnv::_backup_write_intercept(DB_ENV *dbenv, u_int32_t off_gbytes,
388     u_int32_t off_bytes, u_int32_t size, u_int8_t *buf, void *handle)
389 {
390 	DbEnv *cxxenv = DbEnv::get_DbEnv(dbenv);
391 	if (cxxenv == 0) {
392 		DB_ERROR(DbEnv::get_DbEnv(dbenv),
393 		    "DbEnv::backup_write_callback", EINVAL, ON_ERROR_UNKNOWN);
394 		return (EINVAL);
395 	}
396 	if (cxxenv->backup_write_callback_ == 0) {
397 		DB_ERROR(DbEnv::get_DbEnv(dbenv), "DbEnv::backup_write_callback",
398 		    EINVAL, cxxenv->error_policy());
399 		return (EINVAL);
400 	}
401 	return (*cxxenv->backup_write_callback_)(
402 	    cxxenv, off_gbytes, off_bytes, size, buf, handle);
403 }
404 
405 // A truism for the DbEnv object is that there is a valid
406 // DB_ENV handle from the constructor until close().
407 // After the close, the DB_ENV handle is invalid and
408 // no operations are permitted on the DbEnv (other than
409 // destructor).  Leaving the DbEnv handle open and not
410 // doing a close is generally considered an error.
411 //
412 // We used to allow DbEnv objects to be closed and reopened.
413 // This implied always keeping a valid DB_ENV object, and
414 // coordinating the open objects between Db/DbEnv turned
415 // out to be overly complicated.  Now we do not allow this.
416 
DbEnv(u_int32_t flags)417 DbEnv::DbEnv(u_int32_t flags)
418 :	imp_(0)
419 ,	slices_(0)
420 ,	construct_error_(0)
421 ,	construct_flags_(flags)
422 ,	internally_managed_(false)
423 ,	error_stream_(0)
424 ,	message_stream_(0)
425 ,	app_dispatch_callback_(0)
426 ,	feedback_callback_(0)
427 ,	paniccall_callback_(0)
428 ,	partial_rep_callback_(0)
429 ,	event_func_callback_(0)
430 ,	rep_send_callback_(0)
431 ,	message_dispatch_callback_(0)
432 {
433 	if ((construct_error_ = initialize(0)) != 0)
434 		DB_ERROR(this, "DbEnv::DbEnv", construct_error_,
435 		    error_policy());
436 }
437 
DbEnv(DB_ENV * dbenv,u_int32_t flags)438 DbEnv::DbEnv(DB_ENV *dbenv, u_int32_t flags)
439 :	imp_(0)
440 ,	slices_(0)
441 ,	construct_error_(0)
442 ,	construct_flags_(flags)
443 ,	internally_managed_(false)
444 ,	error_stream_(0)
445 ,	message_stream_(0)
446 ,	app_dispatch_callback_(0)
447 ,	feedback_callback_(0)
448 ,	paniccall_callback_(0)
449 ,	partial_rep_callback_(0)
450 ,	event_func_callback_(0)
451 ,	rep_send_callback_(0)
452 ,	message_dispatch_callback_(0)
453 {
454 	if ((construct_error_ = initialize(dbenv)) != 0)
455 		DB_ERROR(this, "DbEnv::DbEnv", construct_error_,
456 		    error_policy());
457 }
458 
DbEnv(DB_ENV * dbenv)459 DbEnv::DbEnv(DB_ENV *dbenv)
460 :	imp_(0)
461 ,	slices_(0)
462 ,	construct_error_(0)
463 ,	construct_flags_(0)
464 ,	internally_managed_(true)
465 ,	error_stream_(0)
466 ,	message_stream_(0)
467 ,	app_dispatch_callback_(0)
468 ,	feedback_callback_(0)
469 ,	paniccall_callback_(0)
470 ,	partial_rep_callback_(0)
471 ,	event_func_callback_(0)
472 ,	rep_send_callback_(0)
473 ,	message_dispatch_callback_(0)
474 {
475 	if ((construct_error_ = initialize(dbenv)) != 0)
476 		DB_ERROR(this, "DbEnv::DbEnv", construct_error_,
477 		error_policy());
478 }
479 
480 // If the DB_ENV handle is still open, we close it.  This is to make stack
481 // allocation of DbEnv objects easier so that they are cleaned up in the error
482 // path.  Note that the C layer catches cases where handles are open in the
483 // environment at close time and reports an error.  Applications should call
484 // close explicitly in normal (non-exceptional) cases to check the return
485 // value.
486 //
~DbEnv()487 DbEnv::~DbEnv()
488 {
489 	DB_ENV *dbenv = unwrap(this);
490 
491 	/*
492 	 * Specify DB_FORCESYNC to make sure databases are sync'ed to disk.
493 	 * Users can call DbEnv::close with 0 as real parameter to close all
494 	 * but the last environment object/handle. Doing so can avoid
495 	 * unnecessary database syncs. The last environment object/handle
496 	 * must be closed with DB_FORCESYNC parameter, or be closed via this
497 	 * function.
498 	 */
499 	if (dbenv != NULL) {
500 		/*
501 		 * Do not close environments that are opened and closed
502 		 * internally, such as slice environments.
503 		 */
504 		if (!internally_managed_)
505 			(void)dbenv->close(dbenv, DB_FORCESYNC);
506 		cleanup();
507 	}
508 }
509 
510 // called by destructors before the DB_ENV is destroyed.
cleanup()511 void DbEnv::cleanup()
512 {
513 	int i;
514 
515 	if (slices_ != NULL) {
516 		for (i = 0; slices_[i] != NULL; i++) {
517 			delete slices_[i];
518 		}
519 		delete [] slices_;
520 	}
521 	imp_ = 0;
522 }
523 
close(u_int32_t flags)524 int DbEnv::close(u_int32_t flags)
525 {
526 	int ret;
527 	DB_ENV *dbenv = unwrap(this);
528 
529 	ret = dbenv->close(dbenv, flags);
530 
531 	// after a close (no matter if success or failure),
532 	// the underlying DB_ENV object must not be accessed.
533 	cleanup();
534 
535 	// It's safe to throw an error after the close,
536 	// since our error mechanism does not peer into
537 	// the DB* structures.
538 	//
539 	if (ret != 0)
540 		DB_ERROR(this, "DbEnv::close", ret, error_policy());
541 
542 	return (ret);
543 }
544 
545 DBENV_METHOD(dbremove,
546     (DbTxn *txn, const char *name, const char *subdb, u_int32_t flags),
547     (dbenv, unwrap(txn), name, subdb, flags))
548 DBENV_METHOD(dbrename, (DbTxn *txn, const char *name, const char *subdb,
549     const char *newname, u_int32_t flags),
550     (dbenv, unwrap(txn), name, subdb, newname, flags))
551 
err(int error,const char * format,...)552 void DbEnv::err(int error, const char *format, ...)
553 {
554 	DB_ENV *dbenv = unwrap(this);
555 
556 	DB_REAL_ERR(dbenv, error, DB_ERROR_SET, 1, format);
557 }
558 
559 // Return a tristate value corresponding to whether we should
560 // throw exceptions on errors:
561 //   ON_ERROR_RETURN
562 //   ON_ERROR_THROW
563 //   ON_ERROR_UNKNOWN
564 //
error_policy()565 int DbEnv::error_policy()
566 {
567 	if ((construct_flags_ & DB_CXX_NO_EXCEPTIONS) != 0) {
568 		return (ON_ERROR_RETURN);
569 	}
570 	else {
571 		return (ON_ERROR_THROW);
572 	}
573 }
574 
errx(const char * format,...)575 void DbEnv::errx(const char *format, ...)
576 {
577 	DB_ENV *dbenv = unwrap(this);
578 
579 	DB_REAL_ERR(dbenv, 0, DB_ERROR_NOT_SET, 1, format);
580 }
581 
get_app_private() const582 void *DbEnv::get_app_private() const
583 {
584 	return unwrapConst(this)->app_private;
585 }
586 
587 DBENV_METHOD(failchk, (u_int32_t flags), (dbenv, flags))
588 DBENV_METHOD(fileid_reset, (const char *file, u_int32_t flags),
589     (dbenv, file, flags))
590 DBENV_METHOD(get_home, (const char **homep), (dbenv, homep))
591 DBENV_METHOD(get_open_flags, (u_int32_t *flagsp), (dbenv, flagsp))
592 DBENV_METHOD(get_data_dirs, (const char ***dirspp), (dbenv, dirspp))
593 
is_bigendian()594 bool DbEnv::is_bigendian()
595 {
596 	return unwrap(this)->is_bigendian() ? true : false;
597 }
598 
599 DBENV_METHOD(get_thread_count, (u_int32_t *count), (dbenv, count))
600 DBENV_METHOD(set_thread_count, (u_int32_t count), (dbenv, count))
601 
602 // used internally during constructor
603 // to associate an existing DB_ENV with this DbEnv,
604 // or create a new one.
605 //
initialize(DB_ENV * dbenv)606 int DbEnv::initialize(DB_ENV *dbenv)
607 {
608 	int ret;
609 
610 	last_known_error_policy = error_policy();
611 
612 	if (dbenv == 0) {
613 		// Create a new DB_ENV environment.
614 		if ((ret = ::db_env_create(&dbenv,
615 		    construct_flags_ & ~DB_CXX_NO_EXCEPTIONS)) != 0)
616 			return (ret);
617 	}
618 	imp_ = dbenv;
619 	dbenv->api1_internal = this;	// for DB_ENV* to DbEnv* conversion
620 	return (0);
621 }
622 
623 // lock methods
624 DBENV_METHOD(lock_detect, (u_int32_t flags, u_int32_t atype, int *aborted),
625     (dbenv, flags, atype, aborted))
626 DBENV_METHOD_ERR(lock_get,
627     (u_int32_t locker, u_int32_t flags, Dbt *obj,
628     db_lockmode_t lock_mode, DbLock *lock),
629     (dbenv, locker, flags, obj, lock_mode, &lock->lock_),
630     DbEnv::runtime_error_lock_get(this, "DbEnv::lock_get", ret,
631 				  DB_LOCK_GET, lock_mode, obj, *lock,
632 				  -1, error_policy()))
633 DBENV_METHOD(lock_id, (u_int32_t *idp), (dbenv, idp))
634 DBENV_METHOD(lock_id_free, (u_int32_t id), (dbenv, id))
635 DBENV_METHOD(lock_put, (DbLock *lock), (dbenv, &lock->lock_))
636 DBENV_METHOD(lock_stat, (DB_LOCK_STAT **statp, u_int32_t flags),
637     (dbenv, statp, flags))
638 DBENV_METHOD(lock_stat_print, (u_int32_t flags), (dbenv, flags))
639 DBENV_METHOD_ERR(lock_vec,
640     (u_int32_t locker, u_int32_t flags, DB_LOCKREQ list[],
641     int nlist, DB_LOCKREQ **elist_returned),
642     (dbenv, locker, flags, list, nlist, elist_returned),
643     DbEnv::runtime_error_lock_get(this, "DbEnv::lock_vec", ret,
644 	(*elist_returned)->op, (*elist_returned)->mode,
645 	Dbt::get_Dbt((*elist_returned)->obj), DbLock((*elist_returned)->lock),
646 	(int)((*elist_returned) - list), error_policy()))
647 // log methods
648 DBENV_METHOD(log_archive, (char **list[], u_int32_t flags),
649     (dbenv, list, flags))
650 
log_compare(const DbLsn * lsn0,const DbLsn * lsn1)651 int DbEnv::log_compare(const DbLsn *lsn0, const DbLsn *lsn1)
652 {
653 	return (::log_compare(lsn0, lsn1));
654 }
655 
656 // The following cast implies that DbLogc can be no larger than DB_LOGC
657 DBENV_METHOD(log_cursor, (DbLogc **cursorp, u_int32_t flags),
658     (dbenv, (DB_LOGC **)cursorp, flags))
659 DBENV_METHOD(log_file, (DbLsn *lsn, char *namep, size_t len),
660     (dbenv, lsn, namep, len))
661 DBENV_METHOD(log_flush, (const DbLsn *lsn), (dbenv, lsn))
662 DBENV_METHOD(log_get_config, (u_int32_t which, int *onoffp),
663     (dbenv, which, onoffp))
664 DBENV_METHOD(log_put, (DbLsn *lsn, const Dbt *data, u_int32_t flags),
665     (dbenv, lsn, data, flags))
666 
log_printf(DbTxn * txn,const char * fmt,...)667 int DbEnv::log_printf(DbTxn *txn, const char *fmt, ...)
668 {
669 	DB_ENV *dbenv = unwrap(this);
670 	va_list ap;
671 	int ret;
672 
673 	va_start(ap, fmt);
674 	ret = __log_printf_pp(dbenv, unwrap(txn), fmt, ap);
675 	va_end(ap);
676 
677 	return (ret);
678 }
679 
680 DBENV_METHOD(log_set_config, (u_int32_t which, int onoff),
681     (dbenv, which, onoff))
682 DBENV_METHOD(log_stat, (DB_LOG_STAT **spp, u_int32_t flags),
683     (dbenv, spp, flags))
684 DBENV_METHOD(log_stat_print, (u_int32_t flags), (dbenv, flags))
685 
log_verify(DB_LOG_VERIFY_CONFIG * config)686 int DbEnv::log_verify(DB_LOG_VERIFY_CONFIG *config)
687 {
688 	DB_ENV *dbenv = unwrap(this);
689 
690 	// Simply return the error, don't throw exceptions.
691 	return dbenv->log_verify(dbenv, config);
692 }
693 
694 DBENV_METHOD(lsn_reset, (const char *file, u_int32_t flags),
695     (dbenv, file, flags))
696 
memp_fcreate(DbMpoolFile ** dbmfp,u_int32_t flags)697 int DbEnv::memp_fcreate(DbMpoolFile **dbmfp, u_int32_t flags)
698 {
699 	DB_ENV *dbenv = unwrap(this);
700 	int ret;
701 	DB_MPOOLFILE *mpf;
702 
703 	if (dbenv == NULL)
704 		ret = EINVAL;
705 	else
706 		ret = dbenv->memp_fcreate(dbenv, &mpf, flags);
707 
708 	if (DB_RETOK_STD(ret)) {
709 		*dbmfp = new DbMpoolFile();
710 		(*dbmfp)->imp_ = mpf;
711 	} else
712 		DB_ERROR(this, "DbMpoolFile::f_create", ret, ON_ERROR_UNKNOWN);
713 
714 	return (ret);
715 }
716 
717 DBENV_METHOD(memp_register,
718     (int ftype, pgin_fcn_type pgin_fcn, pgout_fcn_type pgout_fcn),
719     (dbenv, ftype, pgin_fcn, pgout_fcn))
720 
721 // memory pool methods
722 DBENV_METHOD(memp_stat,
723     (DB_MPOOL_STAT **gsp, DB_MPOOL_FSTAT ***fsp, u_int32_t flags),
724     (dbenv, gsp, fsp, flags))
725 DBENV_METHOD(memp_stat_print, (u_int32_t flags), (dbenv, flags))
726 DBENV_METHOD(memp_sync, (DbLsn *sn), (dbenv, sn))
727 DBENV_METHOD(memp_trickle, (int pct, int *nwrotep), (dbenv, pct, nwrotep))
728 
msg(const char * format,...)729 void DbEnv::msg(const char *format, ...)
730 {
731 	DB_ENV *dbenv = unwrap(this);
732 
733 	DB_REAL_MSG(dbenv, format);
734 }
735 
736 // If an error occurred during the constructor, report it now.
737 // Otherwise, call the underlying DB->open method.
738 //
open(const char * db_home,u_int32_t flags,int mode)739 int DbEnv::open(const char *db_home, u_int32_t flags, int mode)
740 {
741 	int ret;
742 	DB_ENV *dbenv = unwrap(this);
743 
744 	if (construct_error_ != 0)
745 		ret = construct_error_;
746 	else
747 		ret = dbenv->open(dbenv, db_home, flags, mode);
748 
749 	if (!DB_RETOK_STD(ret))
750 		DB_ERROR(this, "DbEnv::open", ret, error_policy());
751 
752 	return (ret);
753 }
754 
remove(const char * db_home,u_int32_t flags)755 int DbEnv::remove(const char *db_home, u_int32_t flags)
756 {
757 	int ret;
758 	DB_ENV *dbenv = unwrap(this);
759 
760 	ret = dbenv->remove(dbenv, db_home, flags);
761 
762 	// after a remove (no matter if success or failure),
763 	// the underlying DB_ENV object must not be accessed,
764 	// so we clean up in advance.
765 	//
766 	cleanup();
767 
768 	if (ret != 0)
769 		DB_ERROR(this, "DbEnv::remove", ret, error_policy());
770 
771 	return (ret);
772 }
773 
774 // Report an error associated with the DbEnv.
775 // error_policy is one of:
776 //   ON_ERROR_THROW     throw an error
777 //   ON_ERROR_RETURN    do nothing here, the caller will return an error
778 //   ON_ERROR_UNKNOWN   defer the policy to policy saved in DbEnv::DbEnv
779 //
runtime_error(DbEnv * dbenv,const char * caller,int error,int error_policy)780 void DbEnv::runtime_error(DbEnv *dbenv,
781     const char *caller, int error, int error_policy)
782 {
783 	if (error_policy == ON_ERROR_UNKNOWN)
784 		error_policy = last_known_error_policy;
785 	if (error_policy == ON_ERROR_THROW) {
786 		// Creating and throwing the object in two separate
787 		// statements seems to be necessary for HP compilers.
788 		switch (error) {
789 		case DB_LOCK_DEADLOCK:
790 			{
791 				DbDeadlockException dl_except(caller);
792 				dl_except.set_env(dbenv);
793 				throw dl_except;
794 			}
795 		case DB_LOCK_NOTGRANTED:
796 			{
797 				DbLockNotGrantedException lng_except(caller);
798 				lng_except.set_env(dbenv);
799 				throw lng_except;
800 			}
801 		case DB_REP_HANDLE_DEAD:
802 			{
803 				DbRepHandleDeadException hd_except(caller);
804 				hd_except.set_env(dbenv);
805 				throw hd_except;
806 			}
807 		case DB_RUNRECOVERY:
808 			{
809 				DbRunRecoveryException rr_except(caller);
810 				rr_except.set_env(dbenv);
811 				throw rr_except;
812 			}
813 		default:
814 			{
815 				DbException except(caller, error);
816 				except.set_env(dbenv);
817 				throw except;
818 			}
819 		}
820 	}
821 }
822 
823 // Like DbEnv::runtime_error, but issue a DbMemoryException
824 // based on the fact that this Dbt is not large enough.
runtime_error_dbt(DbEnv * dbenv,const char * caller,Dbt * dbt,int error_policy)825 void DbEnv::runtime_error_dbt(DbEnv *dbenv,
826     const char *caller, Dbt *dbt, int error_policy)
827 {
828 	if (error_policy == ON_ERROR_UNKNOWN)
829 		error_policy = last_known_error_policy;
830 	if (error_policy == ON_ERROR_THROW) {
831 		// Creating and throwing the object in two separate
832 		// statements seems to be necessary for HP compilers.
833 		DbMemoryException except(caller, dbt);
834 		except.set_env(dbenv);
835 		throw except;
836 	}
837 }
838 
839 // Like DbEnv::runtime_error, but issue a DbLockNotGrantedException,
840 // or a regular runtime error.
841 // call regular runtime_error if it
runtime_error_lock_get(DbEnv * dbenv,const char * caller,int error,db_lockop_t op,db_lockmode_t mode,Dbt * obj,DbLock lock,int index,int error_policy)842 void DbEnv::runtime_error_lock_get(DbEnv *dbenv,
843     const char *caller, int error,
844     db_lockop_t op, db_lockmode_t mode, Dbt *obj,
845     DbLock lock, int index, int error_policy)
846 {
847 	if (error != DB_LOCK_NOTGRANTED) {
848 		runtime_error(dbenv, caller, error, error_policy);
849 		return;
850 	}
851 
852 	if (error_policy == ON_ERROR_UNKNOWN)
853 		error_policy = last_known_error_policy;
854 	if (error_policy == ON_ERROR_THROW) {
855 		// Creating and throwing the object in two separate
856 		// statements seems to be necessary for HP compilers.
857 		DbLockNotGrantedException except(caller, op, mode,
858 		    obj, lock, index);
859 		except.set_env(dbenv);
860 		throw except;
861 	}
862 }
863 
_stream_error_function(const DB_ENV * dbenv,const char * prefix,const char * message)864 void DbEnv::_stream_error_function(
865     const DB_ENV *dbenv, const char *prefix, const char *message)
866 {
867 	const DbEnv *cxxenv = DbEnv::get_const_DbEnv(dbenv);
868 	if (cxxenv == 0) {
869 		DB_ERROR(0,
870 		    "DbEnv::stream_error", EINVAL, ON_ERROR_UNKNOWN);
871 		return;
872 	}
873 
874 	if (cxxenv->error_callback_)
875 		cxxenv->error_callback_(cxxenv, prefix, message);
876 	else if (cxxenv->error_stream_) {
877 		// HP compilers need the extra casts, we don't know why.
878 		if (prefix) {
879 			(*cxxenv->error_stream_) << prefix;
880 			(*cxxenv->error_stream_) << (const char *)": ";
881 		}
882 		if (message)
883 			(*cxxenv->error_stream_) << (const char *)message;
884 		(*cxxenv->error_stream_) << (const char *)"\n";
885 	}
886 }
887 
_stream_message_function(const DB_ENV * dbenv,const char * prefix,const char * message)888 void DbEnv::_stream_message_function(
889     const DB_ENV *dbenv, const char *prefix, const char *message)
890 {
891 	const DbEnv *cxxenv = DbEnv::get_const_DbEnv(dbenv);
892 	if (cxxenv == 0) {
893 		DB_ERROR(0,
894 		    "DbEnv::stream_message", EINVAL, ON_ERROR_UNKNOWN);
895 		return;
896 	}
897 
898 	if (cxxenv->message_callback_)
899 		cxxenv->message_callback_(cxxenv, prefix, message);
900 	else if (cxxenv->message_stream_) {
901 		// HP compilers need the extra casts, we don't know why.
902 		if (prefix) {
903 			(*cxxenv->message_stream_) << prefix;
904 			(*cxxenv->message_stream_) << (const char *)": ";
905 		}
906 		if (message)
907 			(*cxxenv->message_stream_) << (const char *)message;
908 		(*cxxenv->message_stream_) << (const char *)"\n";
909 	}
910 }
911 
912 // static method
strerror(int error)913 char *DbEnv::strerror(int error)
914 {
915 	return (db_strerror(error));
916 }
917 
918 // We keep these alphabetical by field name,
919 // for comparison with Java's list.
920 //
921 DBENV_METHOD(get_backup_config, (DB_BACKUP_CONFIG type, u_int32_t *valuep), (dbenv, type, valuep))
922 DBENV_METHOD(set_backup_config, (DB_BACKUP_CONFIG type, u_int32_t value), (dbenv, type, value))
923 DBENV_METHOD(get_blob_dir, (const char **dir), (dbenv, dir))
924 DBENV_METHOD(set_blob_dir, (const char *dir), (dbenv, dir))
925 DBENV_METHOD(get_blob_threshold, (u_int32_t *bytes), (dbenv, bytes))
926 DBENV_METHOD(set_blob_threshold, (u_int32_t bytes, u_int32_t flags), (dbenv, bytes, flags))
927 DBENV_METHOD(set_data_dir, (const char *dir), (dbenv, dir))
928 DBENV_METHOD(get_encrypt_flags, (u_int32_t *flagsp),
929     (dbenv, flagsp))
930 DBENV_METHOD(set_encrypt, (const char *passwd, u_int32_t flags),
931     (dbenv, passwd, flags))
932 DBENV_METHOD_VOID(get_errfile, (FILE **errfilep), (dbenv, errfilep))
933 DBENV_METHOD_VOID(set_errfile, (FILE *errfile), (dbenv, errfile))
934 DBENV_METHOD_VOID(get_errpfx, (const char **errpfxp), (dbenv, errpfxp))
935 DBENV_METHOD_VOID(set_errpfx, (const char *errpfx), (dbenv, errpfx))
936 DBENV_METHOD(get_ext_file_dir, (const char **dir), (dbenv, dir))
937 DBENV_METHOD(set_ext_file_dir, (const char *dir), (dbenv, dir))
938 DBENV_METHOD(get_ext_file_threshold, (u_int32_t *bytes), (dbenv, bytes))
939 DBENV_METHOD(set_ext_file_threshold, (u_int32_t bytes, u_int32_t flags), (dbenv, bytes, flags))
940 DBENV_METHOD(get_intermediate_dir_mode, (const char **modep), (dbenv, modep))
941 DBENV_METHOD(set_intermediate_dir_mode, (const char *mode), (dbenv, mode))
942 DBENV_METHOD(get_lg_bsize, (u_int32_t *bsizep), (dbenv, bsizep))
943 DBENV_METHOD(set_lg_bsize, (u_int32_t bsize), (dbenv, bsize))
944 DBENV_METHOD(get_lg_dir, (const char **dirp), (dbenv, dirp))
945 DBENV_METHOD(set_lg_dir, (const char *dir), (dbenv, dir))
946 DBENV_METHOD(get_lg_filemode, (int *modep), (dbenv, modep))
947 DBENV_METHOD(set_lg_filemode, (int mode), (dbenv, mode))
948 DBENV_METHOD(get_lg_max, (u_int32_t *maxp), (dbenv, maxp))
949 DBENV_METHOD(set_lg_max, (u_int32_t max), (dbenv, max))
950 DBENV_METHOD(get_lg_regionmax, (u_int32_t *regionmaxp), (dbenv, regionmaxp))
951 DBENV_METHOD(set_lg_regionmax, (u_int32_t regionmax), (dbenv, regionmax))
952 DBENV_METHOD(get_lk_conflicts, (const u_int8_t **lk_conflictsp, int *lk_maxp),
953     (dbenv, lk_conflictsp, lk_maxp))
954 DBENV_METHOD(set_lk_conflicts, (u_int8_t *lk_conflicts, int lk_max),
955     (dbenv, lk_conflicts, lk_max))
956 DBENV_METHOD(get_lk_detect, (u_int32_t *detectp), (dbenv, detectp))
957 DBENV_METHOD(set_lk_detect, (u_int32_t detect), (dbenv, detect))
958 DBENV_METHOD(get_lk_max_lockers, (u_int32_t *max_lockersp),
959     (dbenv, max_lockersp))
960 DBENV_METHOD(set_lk_max_lockers, (u_int32_t max_lockers), (dbenv, max_lockers))
961 DBENV_METHOD(get_lk_max_locks, (u_int32_t *max_locksp), (dbenv, max_locksp))
962 DBENV_METHOD(set_lk_max_locks, (u_int32_t max_locks), (dbenv, max_locks))
963 DBENV_METHOD(get_lk_max_objects, (u_int32_t *max_objectsp),
964     (dbenv, max_objectsp))
965 DBENV_METHOD(set_lk_max_objects, (u_int32_t max_objects), (dbenv, max_objects))
966 DBENV_METHOD(get_lk_partitions, (u_int32_t *partitionsp), (dbenv, partitionsp))
967 DBENV_METHOD(set_lk_partitions, (u_int32_t partitions), (dbenv, partitions))
968 DBENV_METHOD(get_lk_priority, (u_int32_t lockerid, u_int32_t *priorityp), (dbenv, lockerid, priorityp))
969 DBENV_METHOD(set_lk_priority, (u_int32_t lockerid, u_int32_t priority), (dbenv, lockerid, priority))
970 DBENV_METHOD(get_lk_tablesize, (u_int32_t *tablesize), (dbenv, tablesize))
971 DBENV_METHOD(set_lk_tablesize, (u_int32_t tablesize), (dbenv, tablesize))
972 DBENV_METHOD(get_memory_init, (DB_MEM_CONFIG type, u_int32_t *count), (dbenv, type, count))
973 DBENV_METHOD(set_memory_init, (DB_MEM_CONFIG type, u_int32_t count), (dbenv, type, count))
974 DBENV_METHOD(get_memory_max, (u_int32_t *gbytes, u_int32_t *bytes), (dbenv, gbytes, bytes))
975 DBENV_METHOD(set_memory_max, (u_int32_t gbytes, u_int32_t bytes), (dbenv, gbytes, bytes))
976 DBENV_METHOD(get_metadata_dir, (const char **dirp), (dbenv, dirp))
977 DBENV_METHOD(set_metadata_dir, (const char *dir), (dbenv, dir))
978 DBENV_METHOD(get_mp_max_openfd, (int *maxopenfdp), (dbenv, maxopenfdp))
979 DBENV_METHOD(set_mp_max_openfd, (int maxopenfd), (dbenv, maxopenfd))
980 DBENV_METHOD(get_mp_max_write, (int *maxwritep, db_timeout_t *maxwrite_sleepp),
981     (dbenv, maxwritep, maxwrite_sleepp))
982 DBENV_METHOD(set_mp_max_write, (int maxwrite, db_timeout_t maxwrite_sleep),
983     (dbenv, maxwrite, maxwrite_sleep))
984 DBENV_METHOD(get_mp_mmapsize, (size_t *mmapsizep), (dbenv, mmapsizep))
985 DBENV_METHOD(set_mp_mmapsize, (size_t mmapsize), (dbenv, mmapsize))
986 DBENV_METHOD(get_mp_pagesize, (u_int32_t *pagesizep), (dbenv, pagesizep))
987 DBENV_METHOD(set_mp_pagesize, (u_int32_t pagesize), (dbenv, pagesize))
988 DBENV_METHOD(get_mp_tablesize, (u_int32_t *tablesizep), (dbenv, tablesizep))
989 DBENV_METHOD(set_mp_tablesize, (u_int32_t tablesize), (dbenv, tablesize))
990 DBENV_METHOD_VOID(get_msgfile, (FILE **msgfilep), (dbenv, msgfilep))
991 DBENV_METHOD_VOID(set_msgfile, (FILE *msgfile), (dbenv, msgfile))
992 DBENV_METHOD_VOID(get_msgpfx, (const char **msgpfxp), (dbenv, msgpfxp))
993 DBENV_METHOD_VOID(set_msgpfx, (const char *msgpfx), (dbenv, msgpfx))
994 DBENV_METHOD(get_region_dir, (const char **dirp), (dbenv, dirp))
995 DBENV_METHOD(set_region_dir, (const char *dir), (dbenv, dir))
996 DBENV_METHOD(get_tmp_dir, (const char **tmp_dirp), (dbenv, tmp_dirp))
997 DBENV_METHOD(set_tmp_dir, (const char *tmp_dir), (dbenv, tmp_dir))
998 DBENV_METHOD(get_tx_max, (u_int32_t *tx_maxp), (dbenv, tx_maxp))
999 DBENV_METHOD(set_tx_max, (u_int32_t tx_max), (dbenv, tx_max))
1000 
1001 DBENV_METHOD(stat_print, (u_int32_t flags), (dbenv, flags))
1002 
1003 DBENV_METHOD_QUIET(get_alloc,
1004     (db_malloc_fcn_type *malloc_fcnp, db_realloc_fcn_type *realloc_fcnp,
1005     db_free_fcn_type *free_fcnp),
1006     (dbenv, malloc_fcnp, realloc_fcnp, free_fcnp))
1007 
1008 DBENV_METHOD_QUIET(set_alloc,
1009     (db_malloc_fcn_type malloc_fcn, db_realloc_fcn_type realloc_fcn,
1010     db_free_fcn_type free_fcn),
1011     (dbenv, malloc_fcn, realloc_fcn, free_fcn))
1012 
set_app_private(void * value)1013 void DbEnv::set_app_private(void *value)
1014 {
1015 	unwrap(this)->app_private = value;
1016 }
1017 
1018 DBENV_METHOD(get_cachesize,
1019     (u_int32_t *gbytesp, u_int32_t *bytesp, int *ncachep),
1020     (dbenv, gbytesp, bytesp, ncachep))
1021 DBENV_METHOD(set_cachesize,
1022     (u_int32_t gbytes, u_int32_t bytes, int ncache),
1023     (dbenv, gbytes, bytes, ncache))
1024 DBENV_METHOD(get_cache_max, (u_int32_t *gbytesp, u_int32_t *bytesp),
1025     (dbenv, gbytesp, bytesp))
1026 DBENV_METHOD(set_cache_max, (u_int32_t gbytes, u_int32_t bytes),
1027     (dbenv, gbytes, bytes))
1028 DBENV_METHOD(get_create_dir, (const char **dirp), (dbenv, dirp))
1029 DBENV_METHOD(set_create_dir, (const char *dir), (dbenv, dir))
1030 
get_slices(DbEnv *** slices)1031 int DbEnv::get_slices(DbEnv ***slices)
1032 {
1033 	DB_ENV **c_slices;
1034 	DB_ENV *dbenv;
1035 	int i, num_slices, ret;
1036 
1037 	if (slices_ != NULL) {
1038 		*slices = slices_;
1039 		return (0);
1040 	}
1041 
1042 	dbenv = unwrap(this);
1043 	ret = dbenv->get_slices(dbenv, &c_slices);
1044 	if (ret == 0) {
1045 		for (num_slices = 0;
1046 			c_slices[num_slices] != NULL; num_slices++);
1047 		if (num_slices == 0) {
1048 			*slices = NULL;
1049 			return (0);
1050 		}
1051 		slices_ = new DbEnv *[num_slices + 1];
1052 		for (i = 0; i < num_slices; i++) {
1053 			slices_[i] = new DbEnv(c_slices[i]);
1054 		}
1055 		slices_[i] = NULL;
1056 		*slices = slices_;
1057 	}
1058 	else
1059 		*slices = NULL;
1060 
1061 	if (!DB_RETOK_STD(ret))
1062 		DB_ERROR(this, "DbEnv::get_slices", ret, error_policy());
1063 	return (ret);
1064 }
1065 
get_slice_count()1066 u_int32_t DbEnv::get_slice_count()
1067 {
1068 	DB_ENV *dbenv;
1069 	u_int32_t count;
1070 	int ret;
1071 
1072 	dbenv = unwrap(this);
1073 	count = 0;
1074 
1075 	ret = dbenv->get_slice_count(dbenv, &count);
1076 	if (!DB_RETOK_STD(ret))
1077 		DB_ERROR(this, "DbEnv::get_slice_count", ret, error_policy());
1078 
1079 	return (count);
1080 }
1081 
get_errcall(void (** argp)(const DbEnv *,const char *,const char *))1082 void DbEnv::get_errcall(void (**argp)(const DbEnv *, const char *, const char *))
1083 {
1084 	if (argp != NULL)
1085 		*argp = error_callback_;
1086 	return;
1087 }
1088 
set_errcall(void (* arg)(const DbEnv *,const char *,const char *))1089 void DbEnv::set_errcall(void (*arg)(const DbEnv *, const char *, const char *))
1090 {
1091 	DB_ENV *dbenv = unwrap(this);
1092 
1093 	error_callback_ = arg;
1094 	error_stream_ = 0;
1095 
1096 	dbenv->set_errcall(dbenv, (arg == 0) ? 0 :
1097 			   _stream_error_function_c);
1098 }
1099 
__DB_STD(ostream)1100 __DB_STD(ostream) *DbEnv::get_error_stream()
1101 {
1102 	return (error_stream_);
1103 }
1104 
set_error_stream(__DB_STD (ostream)* stream)1105 void DbEnv::set_error_stream(__DB_STD(ostream) *stream)
1106 {
1107 	DB_ENV *dbenv = unwrap(this);
1108 
1109 	error_stream_ = stream;
1110 	error_callback_ = 0;
1111 
1112 	dbenv->set_errcall(dbenv, (stream == 0) ? 0 :
1113 			   _stream_error_function_c);
1114 }
1115 
get_feedback(void (** argp)(DbEnv *,int,int))1116 int DbEnv::get_feedback(void (**argp)(DbEnv *, int, int))
1117 {
1118 	if (argp != NULL)
1119 		*argp = feedback_callback_;
1120 	return 0;
1121 }
1122 
set_feedback(void (* arg)(DbEnv *,int,int))1123 int DbEnv::set_feedback(void (*arg)(DbEnv *, int, int))
1124 {
1125 	DB_ENV *dbenv = unwrap(this);
1126 
1127 	feedback_callback_ = arg;
1128 
1129 	return (dbenv->set_feedback(dbenv,
1130 	    arg == 0 ? 0 : _feedback_intercept_c));
1131 }
1132 
1133 DBENV_METHOD(get_flags, (u_int32_t *flagsp), (dbenv, flagsp))
1134 DBENV_METHOD(set_flags, (u_int32_t flags, int onoff), (dbenv, flags, onoff))
1135 
get_msgcall(void (** argp)(const DbEnv *,const char *,const char *))1136 void DbEnv::get_msgcall(void (**argp)(const DbEnv *, const char *, const char *))
1137 {
1138 	if (argp != NULL)
1139 		*argp = message_callback_;
1140 }
1141 
set_msgcall(void (* arg)(const DbEnv *,const char *,const char *))1142 void DbEnv::set_msgcall(void (*arg)(const DbEnv *, const char *, const char *))
1143 {
1144 	DB_ENV *dbenv = unwrap(this);
1145 
1146 	message_callback_ = arg;
1147 	message_stream_ = 0;
1148 
1149 	dbenv->set_msgcall(dbenv, (arg == 0) ? 0 :
1150 	    _stream_message_function_c);
1151 }
1152 
__DB_STD(ostream)1153 __DB_STD(ostream) *DbEnv::get_message_stream()
1154 {
1155 	return (message_stream_);
1156 }
1157 
set_message_stream(__DB_STD (ostream)* stream)1158 void DbEnv::set_message_stream(__DB_STD(ostream) *stream)
1159 {
1160 	DB_ENV *dbenv = unwrap(this);
1161 
1162 	message_stream_ = stream;
1163 	message_callback_ = 0;
1164 
1165 	dbenv->set_msgcall(dbenv, (stream == 0) ? 0 :
1166 			   _stream_message_function_c);
1167 }
1168 
set_paniccall(void (* arg)(DbEnv *,int))1169 int DbEnv::set_paniccall(void (*arg)(DbEnv *, int))
1170 {
1171 	DB_ENV *dbenv = unwrap(this);
1172 
1173 	paniccall_callback_ = arg;
1174 
1175 	return (dbenv->set_paniccall(dbenv,
1176 	    arg == 0 ? 0 : _paniccall_intercept_c));
1177 }
1178 
set_event_notify(void (* arg)(DbEnv *,u_int32_t,void *))1179 int DbEnv::set_event_notify(void (*arg)(DbEnv *, u_int32_t, void *))
1180 {
1181 	DB_ENV *dbenv = unwrap(this);
1182 
1183 	event_func_callback_ = arg;
1184 
1185 	return (dbenv->set_event_notify(dbenv,
1186 	    arg == 0 ? 0 : _event_func_intercept_c));
1187 }
1188 
1189 DBENV_METHOD(get_shm_key, (long *shm_keyp), (dbenv, shm_keyp))
1190 DBENV_METHOD(set_shm_key, (long shm_key), (dbenv, shm_key))
1191 
get_app_dispatch(int (** argp)(DbEnv *,Dbt *,DbLsn *,db_recops))1192 int DbEnv::get_app_dispatch
1193     (int (**argp)(DbEnv *, Dbt *, DbLsn *, db_recops))
1194 {
1195 	if (argp != NULL)
1196 		*argp = app_dispatch_callback_;
1197 	return 0;
1198 }
1199 
set_app_dispatch(int (* arg)(DbEnv *,Dbt *,DbLsn *,db_recops))1200 int DbEnv::set_app_dispatch
1201     (int (*arg)(DbEnv *, Dbt *, DbLsn *, db_recops))
1202 {
1203 	DB_ENV *dbenv = unwrap(this);
1204 	int ret;
1205 
1206 	app_dispatch_callback_ = arg;
1207 	if ((ret = dbenv->set_app_dispatch(dbenv,
1208 	    arg == 0 ? 0 : _app_dispatch_intercept_c)) != 0)
1209 		DB_ERROR(this, "DbEnv::set_app_dispatch", ret, error_policy());
1210 
1211 	return (ret);
1212 }
1213 
get_isalive(int (** argp)(DbEnv *,pid_t,db_threadid_t,u_int32_t))1214 int DbEnv::get_isalive
1215     (int (**argp)(DbEnv *, pid_t, db_threadid_t, u_int32_t))
1216 {
1217 	if (argp != NULL)
1218 		*argp = isalive_callback_;
1219 	return 0;
1220 }
1221 
set_isalive(int (* arg)(DbEnv *,pid_t,db_threadid_t,u_int32_t))1222 int DbEnv::set_isalive
1223     (int (*arg)(DbEnv *, pid_t, db_threadid_t, u_int32_t))
1224 {
1225 	DB_ENV *dbenv = unwrap(this);
1226 	int ret;
1227 
1228 	isalive_callback_ = arg;
1229 	if ((ret = dbenv->set_isalive(dbenv,
1230 	    arg == 0 ? 0 : _isalive_intercept_c)) != 0)
1231 		DB_ERROR(this, "DbEnv::set_isalive", ret, error_policy());
1232 
1233 	return (ret);
1234 }
1235 
1236 DBENV_METHOD(get_tx_timestamp, (time_t *timestamp), (dbenv, timestamp))
1237 DBENV_METHOD(set_tx_timestamp, (time_t *timestamp), (dbenv, timestamp))
1238 DBENV_METHOD(get_verbose, (u_int32_t which, int *onoffp),
1239     (dbenv, which, onoffp))
1240 DBENV_METHOD(set_verbose, (u_int32_t which, int onoff), (dbenv, which, onoff))
1241 
1242 DBENV_METHOD(mutex_alloc,
1243     (u_int32_t flags, db_mutex_t *mutexp), (dbenv, flags, mutexp))
1244 DBENV_METHOD(mutex_free, (db_mutex_t mutex), (dbenv, mutex))
1245 DBENV_METHOD(mutex_get_align, (u_int32_t *argp), (dbenv, argp))
1246 DBENV_METHOD(mutex_get_increment, (u_int32_t *argp), (dbenv, argp))
1247 DBENV_METHOD(mutex_get_init, (u_int32_t *argp), (dbenv, argp))
1248 DBENV_METHOD(mutex_get_max, (u_int32_t *argp), (dbenv, argp))
1249 DBENV_METHOD(mutex_get_tas_spins, (u_int32_t *argp), (dbenv, argp))
1250 DBENV_METHOD(mutex_lock, (db_mutex_t mutex), (dbenv, mutex))
1251 DBENV_METHOD(mutex_set_align, (u_int32_t arg), (dbenv, arg))
1252 DBENV_METHOD(mutex_set_increment, (u_int32_t arg), (dbenv, arg))
1253 DBENV_METHOD(mutex_set_init, (u_int32_t arg), (dbenv, arg))
1254 DBENV_METHOD(mutex_set_max, (u_int32_t arg), (dbenv, arg))
1255 DBENV_METHOD(mutex_set_tas_spins, (u_int32_t arg), (dbenv, arg))
1256 DBENV_METHOD(mutex_stat,
1257     (DB_MUTEX_STAT **statp, u_int32_t flags), (dbenv, statp, flags))
1258 DBENV_METHOD(mutex_stat_print, (u_int32_t flags), (dbenv, flags))
1259 DBENV_METHOD(mutex_unlock, (db_mutex_t mutex), (dbenv, mutex))
1260 
get_thread_id_fn(void (** argp)(DbEnv *,pid_t *,db_threadid_t *))1261 int DbEnv::get_thread_id_fn(void (**argp)(DbEnv *, pid_t *, db_threadid_t *))
1262 {
1263 	if (argp != NULL)
1264 		*argp = thread_id_callback_;
1265 	return 0;
1266 }
1267 
set_thread_id(void (* arg)(DbEnv *,pid_t *,db_threadid_t *))1268 int DbEnv::set_thread_id(void (*arg)(DbEnv *, pid_t *, db_threadid_t *))
1269 {
1270 	DB_ENV *dbenv = unwrap(this);
1271 	int ret;
1272 
1273 	thread_id_callback_ = arg;
1274 	if ((ret = dbenv->set_thread_id(dbenv,
1275 	    arg == 0 ? 0 : _thread_id_intercept_c)) != 0)
1276 		DB_ERROR(this, "DbEnv::set_thread_id", ret, error_policy());
1277 
1278 	return (ret);
1279 }
1280 
get_thread_id_string_fn(char * (** argp)(DbEnv *,pid_t,db_threadid_t,char *))1281 int DbEnv::get_thread_id_string_fn(
1282     char *(**argp)(DbEnv *, pid_t, db_threadid_t, char *))
1283 {
1284 	if (argp != NULL)
1285 		*argp = thread_id_string_callback_;
1286 	return 0;
1287 }
1288 
set_thread_id_string(char * (* arg)(DbEnv *,pid_t,db_threadid_t,char *))1289 int DbEnv::set_thread_id_string(
1290     char *(*arg)(DbEnv *, pid_t, db_threadid_t, char *))
1291 {
1292 	DB_ENV *dbenv = unwrap(this);
1293 	int ret;
1294 
1295 	thread_id_string_callback_ = arg;
1296 	if ((ret = dbenv->set_thread_id_string(dbenv,
1297 	    arg == 0 ? 0 : _thread_id_string_intercept_c)) != 0)
1298 		DB_ERROR(this, "DbEnv::set_thread_id_string", ret,
1299 		    error_policy());
1300 
1301 	return (ret);
1302 }
1303 
get_backup_callbacks(int (** open_funcp)(DbEnv *,const char *,const char *,void **),int (** write_funcp)(DbEnv *,u_int32_t,u_int32_t,u_int32_t,u_int8_t *,void *),int (** close_funcp)(DbEnv *,const char *,void *))1304 int DbEnv::get_backup_callbacks(
1305     int (**open_funcp)(DbEnv *, const char *, const char *, void **),
1306     int (**write_funcp)(DbEnv *, u_int32_t, u_int32_t, u_int32_t, u_int8_t *, void *),
1307     int (**close_funcp)(DbEnv *, const char *, void *))
1308 {
1309 	if (open_funcp != NULL)
1310 		*open_funcp = backup_open_callback_;
1311 	if (write_funcp != NULL)
1312 		*write_funcp = backup_write_callback_;
1313 	if (close_funcp != NULL)
1314 		*close_funcp = backup_close_callback_;
1315 
1316 	return 0;
1317 }
1318 
set_backup_callbacks(int (* open_func)(DbEnv *,const char *,const char *,void **),int (* write_func)(DbEnv *,u_int32_t,u_int32_t,u_int32_t,u_int8_t *,void *),int (* close_func)(DbEnv *,const char *,void *))1319 int DbEnv::set_backup_callbacks(
1320     int (*open_func)(DbEnv *, const char *, const char *, void **),
1321     int (*write_func)(DbEnv *, u_int32_t, u_int32_t, u_int32_t, u_int8_t *, void *),
1322     int (*close_func)(DbEnv *, const char *, void *))
1323 {
1324 	DB_ENV *dbenv = unwrap(this);
1325 	int ret;
1326 
1327 	backup_open_callback_ = open_func;
1328 	backup_write_callback_ = write_func;
1329 	backup_close_callback_ = close_func;
1330 
1331 	if ((ret = dbenv->set_backup_callbacks(dbenv,
1332 	    open_func == 0 ? 0 : _backup_open_intercept_c,
1333 	    write_func == 0 ? 0 : _backup_write_intercept_c,
1334 	    close_func == 0 ? 0 : _backup_close_intercept_c)) != 0)
1335 		DB_ERROR(this, "DbEnv::set_backup_callbacks", ret,
1336 		    error_policy());
1337 
1338 	return (ret);
1339 }
1340 
1341 DBENV_METHOD(add_data_dir, (const char *dir), (dbenv, dir))
1342 
cdsgroup_begin(DbTxn ** tid)1343 int DbEnv::cdsgroup_begin(DbTxn **tid)
1344 {
1345 	DB_ENV *dbenv = unwrap(this);
1346 	DB_TXN *txn;
1347 	int ret;
1348 
1349 	ret = dbenv->cdsgroup_begin(dbenv, &txn);
1350 	if (DB_RETOK_STD(ret))
1351 		*tid = new DbTxn(txn, NULL);
1352 	else
1353 		DB_ERROR(this, "DbEnv::cdsgroup_begin", ret, error_policy());
1354 
1355 	return (ret);
1356 }
1357 
txn_begin(DbTxn * pid,DbTxn ** tid,u_int32_t flags)1358 int DbEnv::txn_begin(DbTxn *pid, DbTxn **tid, u_int32_t flags)
1359 {
1360 	DB_ENV *dbenv = unwrap(this);
1361 	DB_TXN *txn;
1362 	int ret;
1363 
1364 	ret = dbenv->txn_begin(dbenv, unwrap(pid), &txn, flags);
1365 	if (DB_RETOK_STD(ret))
1366 		*tid = new DbTxn(txn, pid);
1367 	else
1368 		DB_ERROR(this, "DbEnv::txn_begin", ret, error_policy());
1369 
1370 	return (ret);
1371 }
1372 
1373 DBENV_METHOD(txn_checkpoint, (u_int32_t kbyte, u_int32_t min, u_int32_t flags),
1374     (dbenv, kbyte, min, flags))
1375 
txn_recover(DbPreplist * preplist,long count,long * retp,u_int32_t flags)1376 int DbEnv::txn_recover(DbPreplist *preplist, long count,
1377     long *retp, u_int32_t flags)
1378 {
1379 	DB_ENV *dbenv = unwrap(this);
1380 	DB_PREPLIST *c_preplist;
1381 	long i;
1382 	int ret;
1383 
1384 	/*
1385 	 * We need to allocate some local storage for the
1386 	 * returned preplist, and that requires us to do
1387 	 * our own argument validation.
1388 	 */
1389 	if (count <= 0)
1390 		ret = EINVAL;
1391 	else
1392 		ret = __os_malloc(dbenv->env, sizeof(DB_PREPLIST) * count,
1393 		    &c_preplist);
1394 
1395 	if (ret != 0) {
1396 		DB_ERROR(this, "DbEnv::txn_recover", ret, error_policy());
1397 		return (ret);
1398 	}
1399 
1400 	if ((ret =
1401 	    dbenv->txn_recover(dbenv, c_preplist, count, retp, flags)) != 0) {
1402 		__os_free(dbenv->env, c_preplist);
1403 		DB_ERROR(this, "DbEnv::txn_recover", ret, error_policy());
1404 		return (ret);
1405 	}
1406 
1407 	for (i = 0; i < *retp; i++) {
1408 		preplist[i].txn = new DbTxn(NULL);
1409 		preplist[i].txn->imp_ = c_preplist[i].txn;
1410 		memcpy(preplist[i].gid, c_preplist[i].gid,
1411 		    sizeof(preplist[i].gid));
1412 	}
1413 
1414 	__os_free(dbenv->env, c_preplist);
1415 
1416 	return (0);
1417 }
1418 
1419 DBENV_METHOD(txn_stat, (DB_TXN_STAT **statp, u_int32_t flags),
1420     (dbenv, statp, flags))
1421 DBENV_METHOD(txn_stat_print, (u_int32_t flags), (dbenv, flags))
1422 
rep_set_transport(int myid,int (* arg)(DbEnv *,const Dbt *,const Dbt *,const DbLsn *,int,u_int32_t))1423 int DbEnv::rep_set_transport(int myid, int (*arg)(DbEnv *,
1424     const Dbt *, const Dbt *, const DbLsn *, int, u_int32_t))
1425 {
1426 	DB_ENV *dbenv = unwrap(this);
1427 	int ret;
1428 
1429 	rep_send_callback_ = arg;
1430 	if ((ret = dbenv->rep_set_transport(dbenv, myid,
1431 	    arg == 0 ? 0 : _rep_send_intercept_c)) != 0)
1432 		DB_ERROR(this, "DbEnv::rep_set_transport", ret, error_policy());
1433 
1434 	return (ret);
1435 }
1436 
1437 DBENV_METHOD(rep_elect, (u_int32_t nsites, u_int32_t nvotes, u_int32_t flags),
1438     (dbenv, nsites, nvotes, flags))
1439 DBENV_METHOD(rep_flush, (), (dbenv))
1440 DBENV_METHOD(rep_get_config, (u_int32_t which, int *onoffp),
1441     (dbenv, which, onoffp))
1442 DBENV_METHOD(rep_get_request, (u_int32_t *min, u_int32_t *max),
1443     (dbenv, min, max))
1444 DBENV_METHOD(rep_set_request, (u_int32_t min, u_int32_t max), (dbenv, min, max))
1445 
rep_process_message(Dbt * control,Dbt * rec,int id,DbLsn * ret_lsnp)1446 int DbEnv::rep_process_message(Dbt *control,
1447     Dbt *rec, int id, DbLsn *ret_lsnp)
1448 {
1449 	DB_ENV *dbenv = unwrap(this);
1450 	int ret;
1451 
1452 	ret = dbenv->rep_process_message(dbenv, control, rec, id, ret_lsnp);
1453 	if (!DB_RETOK_REPPMSG(ret))
1454 		DB_ERROR(this, "DbEnv::rep_process_message", ret,
1455 		    error_policy());
1456 
1457 	return (ret);
1458 }
1459 
1460 DBENV_METHOD(rep_set_config,
1461     (u_int32_t which, int onoff), (dbenv, which, onoff))
1462 DBENV_METHOD(rep_start,
1463     (Dbt *cookie, u_int32_t flags),
1464     (dbenv, (DBT *)cookie, flags))
1465 
1466 DBENV_METHOD(rep_stat, (DB_REP_STAT **statp, u_int32_t flags),
1467     (dbenv, statp, flags))
1468 DBENV_METHOD(rep_stat_print, (u_int32_t flags), (dbenv, flags))
1469 DBENV_METHOD(rep_sync, (u_int32_t flags), (dbenv, flags))
1470 
1471 DBENV_METHOD(rep_get_clockskew, (u_int32_t *fast_clockp, u_int32_t *slow_clockp),
1472     (dbenv, fast_clockp, slow_clockp))
1473 DBENV_METHOD(rep_set_clockskew, (u_int32_t fast_clock, u_int32_t slow_clock),
1474     (dbenv, fast_clock, slow_clock))
1475 DBENV_METHOD(rep_get_limit, (u_int32_t *gbytesp, u_int32_t *bytesp),
1476     (dbenv, gbytesp, bytesp))
1477 DBENV_METHOD(rep_set_limit, (u_int32_t gbytes, u_int32_t bytes),
1478     (dbenv, gbytes, bytes))
1479 
1480 //
1481 // Begin advanced replication API method implementations
1482 DBENV_METHOD(rep_get_nsites, (u_int32_t *n), (dbenv, n))
1483 DBENV_METHOD(rep_set_nsites, (u_int32_t n), (dbenv, n))
1484 DBENV_METHOD(rep_get_priority, (u_int32_t *priority),
1485     (dbenv, priority))
1486 DBENV_METHOD(rep_set_priority, (u_int32_t priority),
1487     (dbenv, priority))
1488 DBENV_METHOD(rep_get_timeout, (int which, db_timeout_t * timeout),
1489     (dbenv, which, timeout))
1490 DBENV_METHOD(rep_set_timeout, (int which, db_timeout_t timeout),
1491     (dbenv, which, timeout))
1492 
rep_set_view(int (* arg)(DbEnv *,const char *,int *,u_int32_t))1493 int DbEnv::rep_set_view(int (*arg)(DbEnv *, const char *, int *, u_int32_t))
1494 {
1495 	DB_ENV *dbenv = unwrap(this);
1496 
1497 	partial_rep_callback_ = arg;
1498 
1499 	return (dbenv->rep_set_view(dbenv,
1500 	    arg == 0 ? 0 : _partial_rep_intercept_c));
1501 }
1502 
1503 DBENV_METHOD(repmgr_get_ack_policy, (int *policy), (dbenv, policy))
1504 DBENV_METHOD(repmgr_set_ack_policy, (int policy), (dbenv, policy))
1505 DBENV_METHOD(repmgr_get_incoming_queue_max,
1506     (u_int32_t *gbytesp, u_int32_t *bytesp), (dbenv, gbytesp, bytesp));
1507 DBENV_METHOD(repmgr_set_incoming_queue_max,
1508     (u_int32_t gbytes, u_int32_t bytes), (dbenv, gbytes, bytes));
1509 
repmgr_set_socket(int (* approval_func)(DbEnv *,DB_REPMGR_SOCKET,int *,u_int32_t))1510 int DbEnv::repmgr_set_socket(int (*approval_func)(DbEnv *,
1511 	DB_REPMGR_SOCKET, int *, u_int32_t))
1512 {
1513 	DB_ENV *dbenv = unwrap(this);
1514 	int ret;
1515 
1516 	repmgr_set_socket_callback_ = approval_func;
1517 	if ((ret = dbenv->repmgr_set_socket(dbenv,
1518 	    approval_func == 0 ? 0 : _repmgr_set_socket_intercept_c)) != 0)
1519 		DB_ERROR(this, "DbEnv::repmgr_set_socket", ret, error_policy());
1520 
1521 	return (ret);
1522 }
1523 
1524 DBENV_METHOD(repmgr_set_ssl_config,
1525     (int which, char *value), (dbenv, which, value))
1526 
repmgr_channel(int eid,DbChannel ** dbchannel,u_int32_t flags)1527 int DbEnv::repmgr_channel(int eid, DbChannel **dbchannel, u_int32_t flags)
1528 {
1529 	DB_ENV *dbenv = unwrap(this);
1530 	DB_CHANNEL *channel;
1531 	int ret;
1532 
1533 	ret = dbenv->repmgr_channel(dbenv, eid, &channel, flags);
1534 	if (DB_RETOK_STD(ret)) {
1535 		*dbchannel = new DbChannel();
1536 		(*dbchannel)->imp_ = channel;
1537 		(*dbchannel)->dbenv_ = this;
1538 	} else
1539 		DB_ERROR(this, "DbEnv::repmgr_channel", ret, error_policy());
1540 
1541 	return (ret);
1542 }
1543 
repmgr_msg_dispatch(void (* arg)(DbEnv *,DbChannel *,Dbt *,u_int32_t,u_int32_t),u_int32_t flags)1544 int DbEnv::repmgr_msg_dispatch(
1545     void (*arg)(DbEnv *, DbChannel *, Dbt *, u_int32_t, u_int32_t),
1546     u_int32_t flags)
1547 {
1548 	DB_ENV *dbenv = unwrap(this);
1549 	int ret;
1550 
1551 	message_dispatch_callback_ = arg;
1552 	if ((ret = dbenv->repmgr_msg_dispatch(dbenv,
1553 	    arg == 0 ? 0 : _message_dispatch_intercept_c, flags)) != 0)
1554 		DB_ERROR(this, "DbEnv::repmgr_msg_dispatch", ret, error_policy());
1555 
1556 	return (ret);
1557 }
1558 
repmgr_local_site(DbSite ** dbsite)1559 int DbEnv::repmgr_local_site(DbSite **dbsite)
1560 {
1561 	DB_ENV *dbenv = unwrap(this);
1562 	DB_SITE *site;
1563 	int ret;
1564 
1565 	ret = dbenv->repmgr_local_site(dbenv, &site);
1566 	if (DB_RETOK_REPMGR_LOCALSITE(ret)) {
1567 		if (ret == 0) {
1568 			*dbsite = new DbSite();
1569 			(*dbsite)->imp_ = site;
1570 		}
1571 	} else
1572 		DB_ERROR(this, "DbEnv::repmgr_local_site", ret, error_policy());
1573 
1574 	return (ret);
1575 }
1576 
repmgr_site(const char * host,u_int port,DbSite ** dbsite,u_int32_t flags)1577 int DbEnv::repmgr_site(const char *host, u_int port, DbSite **dbsite,
1578     u_int32_t flags)
1579 {
1580 	DB_ENV *dbenv = unwrap(this);
1581 	DB_SITE *site;
1582 	int ret;
1583 
1584 	ret = dbenv->repmgr_site(dbenv, host, port, &site, flags);
1585 	if (DB_RETOK_STD(ret)) {
1586 		*dbsite = new DbSite();
1587 		(*dbsite)->imp_ = site;
1588 	} else
1589 		DB_ERROR(this, "DbEnv::repmgr_site", ret, error_policy());
1590 
1591 	return (ret);
1592 }
1593 
repmgr_site_by_eid(int eid,DbSite ** dbsite)1594 int DbEnv::repmgr_site_by_eid(int eid, DbSite **dbsite)
1595 {
1596 	DB_ENV *dbenv = unwrap(this);
1597 	DB_SITE *site;
1598 	int ret;
1599 
1600 	ret = dbenv->repmgr_site_by_eid(dbenv, eid, &site);
1601 	if (DB_RETOK_STD(ret)) {
1602 		*dbsite = new DbSite();
1603 		(*dbsite)->imp_ = site;
1604 	} else
1605 		DB_ERROR(this, "DbEnv::repmgr_site_by_eid", ret,
1606 		    error_policy());
1607 
1608 	return (ret);
1609 }
1610 
1611 DBENV_METHOD(repmgr_site_list, (u_int *countp, DB_REPMGR_SITE **listp),
1612     (dbenv, countp, listp))
1613 
repmgr_start(int nthreads,u_int32_t flags)1614 int DbEnv::repmgr_start(int nthreads, u_int32_t flags)
1615 {
1616 	DB_ENV *dbenv = unwrap(this);
1617 	int ret;
1618 
1619 	ret = dbenv->repmgr_start(dbenv, nthreads, flags);
1620 	if (!DB_RETOK_REPMGR_START(ret))
1621 		DB_ERROR(this, "DbEnv::repmgr_start", ret,
1622 		    error_policy());
1623 
1624 	return (ret);
1625 }
1626 
1627 DBENV_METHOD(repmgr_stat, (DB_REPMGR_STAT **statp, u_int32_t flags),
1628     (dbenv, statp, flags))
1629 DBENV_METHOD(repmgr_stat_print, (u_int32_t flags), (dbenv, flags))
1630 
1631 // End advanced replication API method implementations.
1632 
1633 DBENV_METHOD(get_timeout,
1634     (db_timeout_t *timeoutp, u_int32_t flags),
1635     (dbenv, timeoutp, flags))
1636 DBENV_METHOD(set_timeout,
1637     (db_timeout_t timeout, u_int32_t flags),
1638     (dbenv, timeout, flags))
1639 
1640 DBENV_METHOD(backup,
1641     (const char *target, u_int32_t flags), (dbenv, target, flags))
1642 DBENV_METHOD(dbbackup,
1643     (const char *dbfile, const char *target, u_int32_t flags),
1644     (dbenv, dbfile, target, flags))
1645 
1646 // static method
version(int * major,int * minor,int * patch)1647 char *DbEnv::version(int *major, int *minor, int *patch)
1648 {
1649 	return (db_version(major, minor, patch));
1650 }
1651 
1652 // static method
full_version(int * family,int * release,int * major,int * minor,int * patch)1653 char *DbEnv::full_version(int *family, int *release,
1654     int *major, int *minor, int *patch)
1655 {
1656 	return (db_full_version(family, release, major, minor, patch));
1657 }
1658 
1659 // static method
wrap_DB_ENV(DB_ENV * dbenv)1660 DbEnv *DbEnv::wrap_DB_ENV(DB_ENV *dbenv)
1661 {
1662 	DbEnv *wrapped_env = get_DbEnv(dbenv);
1663 	return (wrapped_env != NULL) ? wrapped_env : new DbEnv(dbenv, 0);
1664 }
1665 
1666 //static method used for testing
slices_enabled()1667 bool DbEnv::slices_enabled()
1668 {
1669 	DB_ENV *dbenv;
1670 	u_int32_t count;
1671 
1672 	if (db_env_create(&dbenv, 0) != 0)
1673 		return (false);
1674 	dbenv->set_errfile(dbenv, NULL);
1675 	dbenv->set_errcall(dbenv, NULL);
1676 
1677 	if (dbenv->get_slice_count(dbenv, &count) == DB_OPNOTSUP)
1678 		return (false);
1679 
1680 	(void)dbenv->close(dbenv, 0);
1681 
1682 	return (true);
1683 }
1684