1/*-
2 * See the file LICENSE for redistribution information.
3 *
4 * Copyright (c) 2001,2008 Oracle.  All rights reserved.
5 *
6 * $Id: db_server_cxxproc.cpp,v 12.22 2008/01/08 20:58:50 bostic Exp $
7 */
8
9#include "db_config.h"
10
11#include "db_int.h"
12#include "db_cxx.h"
13#include "db_server.h"
14
15extern "C" {
16#include "dbinc/db_server_int.h"
17#include "dbinc_auto/rpc_server_ext.h"
18}
19
20extern "C" void
21__env_get_cachesize_proc(
22	u_int dbenvcl_id,
23	__env_get_cachesize_reply *replyp)
24{
25	DbEnv *dbenv;
26	ct_entry *dbenv_ctp;
27
28	ACTIVATE_CTP(dbenv_ctp, dbenvcl_id, CT_ENV);
29	dbenv = (DbEnv *)dbenv_ctp->ct_anyp;
30
31	replyp->status = dbenv->get_cachesize(&replyp->gbytes,
32	    &replyp->bytes, (int *)&replyp->ncache);
33}
34
35extern "C" void
36__env_set_cachesize_proc(
37	u_int dbenvcl_id,
38	u_int32_t gbytes,
39	u_int32_t bytes,
40	u_int32_t ncache,
41	__env_set_cachesize_reply *replyp)
42{
43	DbEnv *dbenv;
44	ct_entry *dbenv_ctp;
45	int ret;
46
47	ACTIVATE_CTP(dbenv_ctp, dbenvcl_id, CT_ENV);
48	dbenv = (DbEnv *)dbenv_ctp->ct_anyp;
49
50	ret = dbenv->set_cachesize(gbytes, bytes, ncache);
51
52	replyp->status = ret;
53	return;
54}
55
56void
57__env_cdsgroup_begin_proc(u_int dbenvcl_id, __env_cdsgroup_begin_reply *replyp)
58{
59	DbEnv *dbenv;
60	DbTxn *txnp;
61	ct_entry *ctp, *dbenv_ctp;
62	int ret;
63
64	ACTIVATE_CTP(dbenv_ctp, dbenvcl_id, CT_ENV);
65	dbenv = (DbEnv *)dbenv_ctp->ct_anyp;
66
67	ctp = new_ct_ent(&replyp->status);
68	if (ctp == NULL)
69		return;
70
71	ret = dbenv->cdsgroup_begin(&txnp);
72	if (ret == 0) {
73		ctp->ct_txnp = txnp;
74		ctp->ct_type = CT_TXN;
75		ctp->ct_parent = NULL;
76		ctp->ct_envparent = dbenv_ctp;
77		replyp->txnidcl_id = ctp->ct_id;
78		__dbsrv_settimeout(ctp, dbenv_ctp->ct_timeout);
79		__dbsrv_active(ctp);
80	} else
81		__dbclear_ctp(ctp);
82
83	replyp->status = ret;
84	return;
85}
86
87extern "C" void
88__env_close_proc(
89	u_int dbenvcl_id,
90	u_int32_t flags,
91	__env_close_reply *replyp)
92{
93	ct_entry *dbenv_ctp;
94
95	ACTIVATE_CTP(dbenv_ctp, dbenvcl_id, CT_ENV);
96	replyp->status = __env_close_int(dbenvcl_id, flags, 0);
97	return;
98}
99
100extern "C" void
101__env_create_proc(
102	u_int32_t timeout,
103	__env_create_reply *replyp)
104{
105	DbEnv *dbenv;
106	ct_entry *ctp;
107
108	ctp = new_ct_ent(&replyp->status);
109	if (ctp == NULL)
110		return;
111
112	dbenv = new DbEnv(DB_CXX_NO_EXCEPTIONS);
113	ctp->ct_envp = dbenv;
114	ctp->ct_type = CT_ENV;
115	ctp->ct_parent = NULL;
116	ctp->ct_envparent = ctp;
117	__dbsrv_settimeout(ctp, timeout);
118	__dbsrv_active(ctp);
119	replyp->envcl_id = ctp->ct_id;
120
121	replyp->status = 0;
122	return;
123}
124
125extern "C" void
126__env_dbremove_proc(
127	u_int dbenvcl_id,
128	u_int txnpcl_id,
129	char *name,
130	char *subdb,
131	u_int32_t flags,
132	__env_dbremove_reply *replyp)
133{
134	int ret;
135	DbEnv *dbenv;
136	DbTxn *txnp;
137	ct_entry *dbenv_ctp, *txnp_ctp;
138
139	ACTIVATE_CTP(dbenv_ctp, dbenvcl_id, CT_ENV);
140	dbenv = (DbEnv *)dbenv_ctp->ct_anyp;
141
142	if (txnpcl_id != 0) {
143		ACTIVATE_CTP(txnp_ctp, txnpcl_id, CT_TXN);
144		txnp = (DbTxn *)txnp_ctp->ct_anyp;
145	} else
146		txnp = NULL;
147
148	ret = dbenv->dbremove(txnp, name, subdb, flags);
149
150	replyp->status = ret;
151	return;
152}
153
154void
155__env_dbrename_proc(
156	u_int dbenvcl_id,
157	u_int txnpcl_id,
158	char *name,
159	char *subdb,
160	char *newname,
161	u_int32_t flags,
162	__env_dbrename_reply *replyp)
163{
164	int ret;
165	DbEnv *dbenv;
166	DbTxn *txnp;
167	ct_entry *dbenv_ctp, *txnp_ctp;
168
169	ACTIVATE_CTP(dbenv_ctp, dbenvcl_id, CT_ENV);
170	dbenv = (DbEnv *)dbenv_ctp->ct_anyp;
171
172	if (txnpcl_id != 0) {
173		ACTIVATE_CTP(txnp_ctp, txnpcl_id, CT_TXN);
174		txnp = (DbTxn *)txnp_ctp->ct_anyp;
175	} else
176		txnp = NULL;
177
178	ret = dbenv->dbrename(txnp, name, subdb, newname, flags);
179
180	replyp->status = ret;
181	return;
182}
183
184extern "C" void
185__env_get_encrypt_flags_proc(
186	u_int dbenvcl_id,
187	__env_get_encrypt_flags_reply *replyp)
188{
189	DbEnv *dbenv;
190	ct_entry *dbenv_ctp;
191
192	ACTIVATE_CTP(dbenv_ctp, dbenvcl_id, CT_ENV);
193	dbenv = (DbEnv *)dbenv_ctp->ct_anyp;
194
195	replyp->status = dbenv->get_encrypt_flags(&replyp->flags);
196}
197
198extern "C" void
199__env_set_encrypt_proc(
200	u_int dbenvcl_id,
201	char *passwd,
202	u_int32_t flags,
203	__env_set_encrypt_reply *replyp)
204{
205	DbEnv *dbenv;
206	ct_entry *dbenv_ctp;
207	int ret;
208
209	ACTIVATE_CTP(dbenv_ctp, dbenvcl_id, CT_ENV);
210	dbenv = (DbEnv *)dbenv_ctp->ct_anyp;
211
212	ret = dbenv->set_encrypt(passwd, flags);
213
214	replyp->status = ret;
215	return;
216}
217
218extern "C" void
219__env_get_flags_proc(
220	u_int dbenvcl_id,
221	__env_get_flags_reply *replyp)
222{
223	DbEnv *dbenv;
224	ct_entry *dbenv_ctp;
225
226	ACTIVATE_CTP(dbenv_ctp, dbenvcl_id, CT_ENV);
227	dbenv = (DbEnv *)dbenv_ctp->ct_anyp;
228
229	replyp->status = dbenv->get_flags(&replyp->flags);
230}
231
232extern "C" void
233__env_set_flags_proc(
234	u_int dbenvcl_id,
235	u_int32_t flags,
236	u_int32_t onoff,
237	__env_set_flags_reply *replyp)
238{
239	DbEnv *dbenv;
240	ct_entry *dbenv_ctp;
241	int ret;
242
243	ACTIVATE_CTP(dbenv_ctp, dbenvcl_id, CT_ENV);
244	dbenv = (DbEnv *)dbenv_ctp->ct_anyp;
245
246	ret = dbenv->set_flags(flags, onoff);
247	if (onoff)
248		dbenv_ctp->ct_envdp.onflags = flags;
249	else
250		dbenv_ctp->ct_envdp.offflags = flags;
251
252	replyp->status = ret;
253	return;
254}
255
256extern "C" void
257__env_get_home_proc(
258	u_int dbenvcl_id,
259	__env_get_home_reply *replyp)
260{
261	DbEnv *dbenv;
262	ct_entry *dbenv_ctp;
263
264	ACTIVATE_CTP(dbenv_ctp, dbenvcl_id, CT_ENV);
265	dbenv = (DbEnv *)dbenv_ctp->ct_anyp;
266
267	replyp->status = dbenv->get_home((const char **)&replyp->home);
268}
269
270extern "C" void
271__env_get_open_flags_proc(
272	u_int dbenvcl_id,
273	__env_get_open_flags_reply *replyp)
274{
275	DbEnv *dbenv;
276	ct_entry *dbenv_ctp;
277
278	ACTIVATE_CTP(dbenv_ctp, dbenvcl_id, CT_ENV);
279	dbenv = (DbEnv *)dbenv_ctp->ct_anyp;
280
281	replyp->status = dbenv->get_open_flags(&replyp->flags);
282}
283
284extern "C" void
285__env_open_proc(
286	u_int dbenvcl_id,
287	char *home,
288	u_int32_t flags,
289	u_int32_t mode,
290	__env_open_reply *replyp)
291{
292	DbEnv *dbenv;
293	ct_entry *dbenv_ctp, *new_ctp;
294	u_int32_t newflags, shareflags;
295	int ret;
296	home_entry *fullhome;
297
298	ACTIVATE_CTP(dbenv_ctp, dbenvcl_id, CT_ENV);
299	dbenv = (DbEnv *)dbenv_ctp->ct_anyp;
300	fullhome = get_fullhome(home);
301	if (fullhome == NULL) {
302		ret = DB_NOSERVER_HOME;
303		goto out;
304	}
305
306	/*
307	 * If they are using locking do deadlock detection for them,
308	 * internally.
309	 */
310	if ((flags & DB_INIT_LOCK) &&
311	    (ret = dbenv->set_lk_detect(DB_LOCK_DEFAULT)) != 0)
312		goto out;
313
314	if (__dbsrv_verbose) {
315		dbenv->set_errfile(stderr);
316		dbenv->set_errpfx(fullhome->home);
317	} else
318		dbenv->set_errfile(NULL);
319
320	/*
321	 * Mask off flags we ignore
322	 */
323	newflags = (flags & ~DB_SERVER_FLAGMASK);
324	shareflags = (newflags & DB_SERVER_ENVFLAGS);
325	/*
326	 * Check now whether we can share a handle for this env.
327	 */
328	replyp->envcl_id = dbenvcl_id;
329	if ((new_ctp = __dbsrv_shareenv(dbenv_ctp, fullhome, shareflags))
330	    != NULL) {
331		/*
332		 * We can share, clean up old  ID, set new one.
333		 */
334		if (__dbsrv_verbose)
335			printf("Sharing env ID %ld\n", new_ctp->ct_id);
336		replyp->envcl_id = new_ctp->ct_id;
337		ret = __env_close_int(dbenvcl_id, 0, 0);
338	} else {
339		ret = dbenv->open(fullhome->home, newflags, mode);
340		dbenv_ctp->ct_envdp.home = fullhome;
341		dbenv_ctp->ct_envdp.envflags = shareflags;
342	}
343out:	replyp->status = ret;
344	return;
345}
346
347extern "C" void
348__env_remove_proc(
349	u_int dbenvcl_id,
350	char *home,
351	u_int32_t flags,
352	__env_remove_reply *replyp)
353{
354	DbEnv *dbenv;
355	ct_entry *dbenv_ctp;
356	int ret;
357	home_entry *fullhome;
358
359	ACTIVATE_CTP(dbenv_ctp, dbenvcl_id, CT_ENV);
360	dbenv = (DbEnv *)dbenv_ctp->ct_anyp;
361	fullhome = get_fullhome(home);
362	if (fullhome == NULL) {
363		replyp->status = DB_NOSERVER_HOME;
364		return;
365	}
366
367	ret = dbenv->remove(fullhome->home, flags);
368	__dbdel_ctp(dbenv_ctp);
369	replyp->status = ret;
370	return;
371}
372
373extern "C" void
374__txn_abort_proc(
375	u_int txnpcl_id,
376	__txn_abort_reply *replyp)
377{
378	DbTxn *txnp;
379	ct_entry *txnp_ctp;
380	int ret;
381
382	ACTIVATE_CTP(txnp_ctp, txnpcl_id, CT_TXN);
383	txnp = (DbTxn *)txnp_ctp->ct_anyp;
384
385	ret = txnp->abort();
386	__dbdel_ctp(txnp_ctp);
387	replyp->status = ret;
388	return;
389}
390
391extern "C" void
392__env_txn_begin_proc(
393	u_int dbenvcl_id,
394	u_int parentcl_id,
395	u_int32_t flags,
396	__env_txn_begin_reply *replyp)
397{
398	DbEnv *dbenv;
399	DbTxn *parent, *txnp;
400	ct_entry *ctp, *dbenv_ctp, *parent_ctp;
401	int ret;
402
403	ACTIVATE_CTP(dbenv_ctp, dbenvcl_id, CT_ENV);
404	dbenv = (DbEnv *)dbenv_ctp->ct_anyp;
405	parent_ctp = NULL;
406
407	ctp = new_ct_ent(&replyp->status);
408	if (ctp == NULL)
409		return;
410
411	if (parentcl_id != 0) {
412		ACTIVATE_CTP(parent_ctp, parentcl_id, CT_TXN);
413		parent = (DbTxn *)parent_ctp->ct_anyp;
414		ctp->ct_activep = parent_ctp->ct_activep;
415	} else
416		parent = NULL;
417
418	ret = dbenv->txn_begin(parent, &txnp, flags | DB_TXN_NOWAIT);
419	if (ret == 0) {
420		ctp->ct_txnp = txnp;
421		ctp->ct_type = CT_TXN;
422		ctp->ct_parent = parent_ctp;
423		ctp->ct_envparent = dbenv_ctp;
424		replyp->txnidcl_id = ctp->ct_id;
425		__dbsrv_settimeout(ctp, dbenv_ctp->ct_timeout);
426		__dbsrv_active(ctp);
427	} else
428		__dbclear_ctp(ctp);
429
430	replyp->status = ret;
431	return;
432}
433
434extern "C" void
435__txn_commit_proc(
436	u_int txnpcl_id,
437	u_int32_t flags,
438	__txn_commit_reply *replyp)
439{
440	DbTxn *txnp;
441	ct_entry *txnp_ctp;
442	int ret;
443
444	ACTIVATE_CTP(txnp_ctp, txnpcl_id, CT_TXN);
445	txnp = (DbTxn *)txnp_ctp->ct_anyp;
446
447	ret = txnp->commit(flags);
448	__dbdel_ctp(txnp_ctp);
449
450	replyp->status = ret;
451	return;
452}
453
454extern "C" void
455__txn_discard_proc(
456	u_int txnpcl_id,
457	u_int32_t flags,
458	__txn_discard_reply *replyp)
459{
460	DbTxn *txnp;
461	ct_entry *txnp_ctp;
462	int ret;
463
464	ACTIVATE_CTP(txnp_ctp, txnpcl_id, CT_TXN);
465	txnp = (DbTxn *)txnp_ctp->ct_anyp;
466
467	ret = txnp->discard(flags);
468	__dbdel_ctp(txnp_ctp);
469
470	replyp->status = ret;
471	return;
472}
473
474extern "C" void
475__txn_prepare_proc(
476	u_int txnpcl_id,
477	u_int8_t *gid,
478	__txn_prepare_reply *replyp)
479{
480	DbTxn *txnp;
481	ct_entry *txnp_ctp;
482	int ret;
483
484	ACTIVATE_CTP(txnp_ctp, txnpcl_id, CT_TXN);
485	txnp = (DbTxn *)txnp_ctp->ct_anyp;
486
487	ret = txnp->prepare(gid);
488	replyp->status = ret;
489	return;
490}
491
492extern "C" void
493__env_txn_recover_proc(
494	u_int dbenvcl_id,
495	u_int32_t count,
496	u_int32_t flags,
497	__env_txn_recover_reply *replyp,
498	int * freep)
499{
500	DbEnv *dbenv;
501	DbPreplist *dbprep, *p;
502	ct_entry *dbenv_ctp, *ctp;
503	long erri, i, retcount;
504	u_int32_t *txnidp;
505	int ret;
506	char *gid;
507
508	ACTIVATE_CTP(dbenv_ctp, dbenvcl_id, CT_ENV);
509	dbenv = (DbEnv *)dbenv_ctp->ct_anyp;
510	*freep = 0;
511
512	if ((ret = __os_malloc(dbenv->get_ENV(),
513	    count * sizeof(DbPreplist), &dbprep)) != 0)
514		goto out;
515	if ((ret = dbenv->txn_recover(dbprep, count, &retcount, flags)) != 0)
516		goto out;
517	/*
518	 * If there is nothing, success, but it's easy.
519	 */
520	replyp->retcount = retcount; // TODO: fix C++ txn_recover
521	if (retcount == 0) {
522		replyp->txn.txn_val = NULL;
523		replyp->txn.txn_len = 0;
524		replyp->gid.gid_val = NULL;
525		replyp->gid.gid_len = 0;
526	}
527
528	/*
529	 * We have our txn list.  Now we need to allocate the space for
530	 * the txn ID array and the GID array and set them up.
531	 */
532	if ((ret = __os_calloc(dbenv->get_ENV(), retcount, sizeof(u_int32_t),
533	    &replyp->txn.txn_val)) != 0)
534		goto out;
535	replyp->txn.txn_len = retcount * sizeof(u_int32_t);
536	if ((ret = __os_calloc(dbenv->get_ENV(), retcount, DB_XIDDATASIZE,
537	    &replyp->gid.gid_val)) != 0) {
538		__os_free(dbenv->get_ENV(), replyp->txn.txn_val);
539		goto out;
540	}
541	replyp->gid.gid_len = retcount * DB_XIDDATASIZE;
542
543	/*
544	 * Now walk through our results, creating parallel arrays
545	 * to send back.  For each entry we need to create a new
546	 * txn ctp and then fill in the array info.
547	 */
548	i = 0;
549	p = dbprep;
550	gid = replyp->gid.gid_val;
551	txnidp = replyp->txn.txn_val;
552	while (i++ < retcount) {
553		ctp = new_ct_ent(&ret);
554		if (ret != 0) {
555			i--;
556			goto out2;
557		}
558		ctp->ct_txnp = p->txn;
559		ctp->ct_type = CT_TXN;
560		ctp->ct_parent = NULL;
561		ctp->ct_envparent = dbenv_ctp;
562		__dbsrv_settimeout(ctp, dbenv_ctp->ct_timeout);
563		__dbsrv_active(ctp);
564
565		*txnidp = ctp->ct_id;
566		memcpy(gid, p->gid, DB_XIDDATASIZE);
567
568		p++;
569		txnidp++;
570		gid += DB_XIDDATASIZE;
571	}
572	/*
573	 * If we get here, we have success and we have to set freep
574	 * so it'll get properly freed next time.
575	 */
576	*freep = 1;
577out:
578	if (dbprep != NULL)
579		__os_free(dbenv->get_ENV(), dbprep);
580	replyp->status = ret;
581	return;
582out2:
583	/*
584	 * We had an error in the middle of creating our new txn
585	 * ct entries.  We have to unwind all that we have done.  Ugh.
586	 */
587	for (txnidp = replyp->txn.txn_val, erri = 0;
588	    erri < i; erri++, txnidp++) {
589		ctp = get_tableent(*txnidp);
590		__dbclear_ctp(ctp);
591	}
592	__os_free(dbenv->get_ENV(), replyp->txn.txn_val);
593	__os_free(dbenv->get_ENV(), replyp->gid.gid_val);
594	__os_free(dbenv->get_ENV(), dbprep);
595	replyp->status = ret;
596	return;
597}
598
599extern "C" void
600__db_associate_proc(
601	u_int dbpcl_id,
602	u_int txnpcl_id,
603	u_int sdbpcl_id,
604	u_int32_t flags,
605	__db_associate_reply *replyp)
606{
607	Db *dbp, *sdbp;
608	DbTxn *txnp;
609	ct_entry *dbp_ctp, *sdbp_ctp, *txnp_ctp;
610	int ret;
611
612	ACTIVATE_CTP(dbp_ctp, dbpcl_id, CT_DB);
613	dbp = (Db *)dbp_ctp->ct_anyp;
614	ACTIVATE_CTP(sdbp_ctp, sdbpcl_id, CT_DB);
615	sdbp = (Db *)sdbp_ctp->ct_anyp;
616	if (txnpcl_id != 0) {
617		ACTIVATE_CTP(txnp_ctp, txnpcl_id, CT_TXN);
618		txnp = (DbTxn *)txnp_ctp->ct_anyp;
619	} else
620		txnp = NULL;
621
622	/*
623	 * We do not support DB_CREATE for associate or the callbacks
624	 * implemented in the Java and JE RPC servers.   Users can only
625	 * access secondary indices on a read-only basis, so whatever they
626	 * are looking for needs to be there already.
627	 */
628	if (LF_ISSET(DB_RPC2ND_MASK | DB_CREATE))
629		ret = EINVAL;
630	else
631		ret = dbp->associate(txnp, sdbp, NULL, flags);
632
633	replyp->status = ret;
634	return;
635}
636
637extern "C" void
638__db_get_bt_minkey_proc(
639	u_int dbpcl_id,
640	__db_get_bt_minkey_reply *replyp)
641{
642	Db *dbp;
643	ct_entry *dbp_ctp;
644
645	ACTIVATE_CTP(dbp_ctp, dbpcl_id, CT_DB);
646	dbp = (Db *)dbp_ctp->ct_anyp;
647
648	replyp->status = dbp->get_bt_minkey(&replyp->minkey);
649}
650
651extern "C" void
652__db_set_bt_minkey_proc(
653	u_int dbpcl_id,
654	u_int32_t minkey,
655	__db_set_bt_minkey_reply *replyp)
656{
657	Db *dbp;
658	ct_entry *dbp_ctp;
659	int ret;
660
661	ACTIVATE_CTP(dbp_ctp, dbpcl_id, CT_DB);
662	dbp = (Db *)dbp_ctp->ct_anyp;
663
664	ret = dbp->set_bt_minkey(minkey);
665
666	replyp->status = ret;
667	return;
668}
669
670extern "C" void
671__db_close_proc(
672	u_int dbpcl_id,
673	u_int32_t flags,
674	__db_close_reply *replyp)
675{
676	ct_entry *dbp_ctp;
677
678	ACTIVATE_CTP(dbp_ctp, dbpcl_id, CT_DB);
679	replyp->status = __db_close_int(dbpcl_id, flags);
680	return;
681}
682
683extern "C" void
684__db_create_proc(
685	u_int dbenvcl_id,
686	u_int32_t flags,
687	__db_create_reply *replyp)
688{
689	Db *dbp;
690	DbEnv *dbenv;
691	ct_entry *dbenv_ctp, *dbp_ctp;
692
693	ACTIVATE_CTP(dbenv_ctp, dbenvcl_id, CT_ENV);
694	dbenv = (DbEnv *)dbenv_ctp->ct_anyp;
695
696	dbp_ctp = new_ct_ent(&replyp->status);
697	if (dbp_ctp == NULL)
698		return ;
699	/*
700	 * We actually require env's for databases.  The client should
701	 * have caught it, but just in case.
702	 */
703	DB_ASSERT(NULL, dbenv != NULL);
704	dbp = new Db(dbenv, flags);
705	dbp_ctp->ct_dbp = dbp;
706	dbp_ctp->ct_type = CT_DB;
707	dbp_ctp->ct_parent = dbenv_ctp;
708	dbp_ctp->ct_envparent = dbenv_ctp;
709	replyp->dbcl_id = dbp_ctp->ct_id;
710	replyp->status = 0;
711	return;
712}
713
714extern "C" void
715__db_del_proc(
716	u_int dbpcl_id,
717	u_int txnpcl_id,
718	u_int32_t keydlen,
719	u_int32_t keydoff,
720	u_int32_t keyulen,
721	u_int32_t keyflags,
722	void *keydata,
723	u_int32_t keysize,
724	u_int32_t flags,
725	__db_del_reply *replyp)
726{
727	Db *dbp;
728	DbTxn *txnp;
729	ct_entry *dbp_ctp, *txnp_ctp;
730	int ret;
731
732	ACTIVATE_CTP(dbp_ctp, dbpcl_id, CT_DB);
733	dbp = (Db *)dbp_ctp->ct_anyp;
734	if (txnpcl_id != 0) {
735		ACTIVATE_CTP(txnp_ctp, txnpcl_id, CT_TXN);
736		txnp = (DbTxn *)txnp_ctp->ct_anyp;
737	} else
738		txnp = NULL;
739
740	/* Set up key */
741	Dbt key(keydata, keysize);
742	key.set_dlen(keydlen);
743	key.set_ulen(keyulen);
744	key.set_doff(keydoff);
745	key.set_flags(keyflags);
746
747	ret = dbp->del(txnp, &key, flags);
748
749	replyp->status = ret;
750	return;
751}
752
753extern "C" void
754__db_get_encrypt_flags_proc(
755	u_int dbpcl_id,
756	__db_get_encrypt_flags_reply *replyp)
757{
758	Db *dbp;
759	ct_entry *dbp_ctp;
760
761	ACTIVATE_CTP(dbp_ctp, dbpcl_id, CT_DB);
762	dbp = (Db *)dbp_ctp->ct_anyp;
763
764	replyp->status = dbp->get_encrypt_flags(&replyp->flags);
765}
766
767extern "C" void
768__db_set_encrypt_proc(
769	u_int dbpcl_id,
770	char *passwd,
771	u_int32_t flags,
772	__db_set_encrypt_reply *replyp)
773{
774	Db *dbp;
775	ct_entry *dbp_ctp;
776	int ret;
777
778	ACTIVATE_CTP(dbp_ctp, dbpcl_id, CT_DB);
779	dbp = (Db *)dbp_ctp->ct_anyp;
780
781	ret = dbp->set_encrypt(passwd, flags);
782	replyp->status = ret;
783	return;
784}
785
786extern "C" void
787__db_get_q_extentsize_proc(
788	u_int dbpcl_id,
789	__db_get_q_extentsize_reply *replyp)
790{
791	Db *dbp;
792	ct_entry *dbp_ctp;
793
794	ACTIVATE_CTP(dbp_ctp, dbpcl_id, CT_DB);
795	dbp = (Db *)dbp_ctp->ct_anyp;
796
797	replyp->status = dbp->get_q_extentsize(&replyp->extentsize);
798}
799
800extern "C" void
801__db_set_q_extentsize_proc(
802	u_int dbpcl_id,
803	u_int32_t extentsize,
804	__db_set_q_extentsize_reply *replyp)
805{
806	Db *dbp;
807	ct_entry *dbp_ctp;
808	int ret;
809
810	ACTIVATE_CTP(dbp_ctp, dbpcl_id, CT_DB);
811	dbp = (Db *)dbp_ctp->ct_anyp;
812
813	ret = dbp->set_q_extentsize(extentsize);
814
815	replyp->status = ret;
816	return;
817}
818
819extern "C" void
820__db_get_flags_proc(
821	u_int dbpcl_id,
822	__db_get_flags_reply *replyp)
823{
824	Db *dbp;
825	ct_entry *dbp_ctp;
826
827	ACTIVATE_CTP(dbp_ctp, dbpcl_id, CT_DB);
828	dbp = (Db *)dbp_ctp->ct_anyp;
829
830	replyp->status = dbp->get_flags(&replyp->flags);
831}
832
833extern "C" void
834__db_set_flags_proc(
835	u_int dbpcl_id,
836	u_int32_t flags,
837	__db_set_flags_reply *replyp)
838{
839	Db *dbp;
840	ct_entry *dbp_ctp;
841	int ret;
842
843	ACTIVATE_CTP(dbp_ctp, dbpcl_id, CT_DB);
844	dbp = (Db *)dbp_ctp->ct_anyp;
845
846	ret = dbp->set_flags(flags);
847	dbp_ctp->ct_dbdp.setflags = flags;
848
849	replyp->status = ret;
850	return;
851}
852
853extern "C" void
854__db_get_proc(
855	u_int dbpcl_id,
856	u_int txnpcl_id,
857	u_int32_t keydlen,
858	u_int32_t keydoff,
859	u_int32_t keyulen,
860	u_int32_t keyflags,
861	void *keydata,
862	u_int32_t keysize,
863	u_int32_t datadlen,
864	u_int32_t datadoff,
865	u_int32_t dataulen,
866	u_int32_t dataflags,
867	void *datadata,
868	u_int32_t datasize,
869	u_int32_t flags,
870	__db_get_reply *replyp,
871	int * freep)
872{
873	Db *dbp;
874	DbTxn *txnp;
875	ct_entry *dbp_ctp, *txnp_ctp;
876	int ret;
877	void *tmpdata;
878
879	ACTIVATE_CTP(dbp_ctp, dbpcl_id, CT_DB);
880	dbp = (Db *)dbp_ctp->ct_anyp;
881	if (txnpcl_id != 0) {
882		ACTIVATE_CTP(txnp_ctp, txnpcl_id, CT_TXN);
883		txnp = (DbTxn *)txnp_ctp->ct_anyp;
884	} else
885		txnp = NULL;
886
887	replyp->keydata.keydata_val = NULL;
888	replyp->datadata.datadata_val = NULL;
889	*freep = 0;
890
891	/* Set up key and data */
892	Dbt key(keydata, keysize);
893	key.set_dlen(keydlen);
894	key.set_ulen(keyulen);
895	key.set_doff(keydoff);
896
897	Dbt data(datadata, datasize);
898	data.set_dlen(datadlen);
899	data.set_ulen(dataulen);
900	data.set_doff(datadoff);
901
902	/*
903	 * Ignore memory related flags on server.
904	 */
905	if (keyflags & DB_DBT_USERMEM) {
906		if ((ret = __os_umalloc(dbp->get_ENV(),
907		    keyulen, &tmpdata)) != 0)
908			goto err;
909		if (keydata)
910			memcpy(tmpdata, keydata, (keysize < keyulen) ?
911			    keysize : keyulen);
912		key.set_data(tmpdata);
913		key.set_flags(DB_DBT_USERMEM | (keyflags & DB_DBT_PARTIAL));
914	} else
915		key.set_flags(DB_DBT_MALLOC | (keyflags & DB_DBT_PARTIAL));
916
917	if (flags & (DB_MULTIPLE | DB_MULTIPLE_KEY) ||
918	    dataflags & DB_DBT_USERMEM) {
919		if ((ret = __os_umalloc(dbp->get_ENV(),
920		    dataulen, &tmpdata)) != 0)
921			goto err;
922		if (datadata)
923			memcpy(tmpdata, datadata,
924			    (datasize < dataulen) ?
925			    datasize : dataulen);
926		data.set_data(tmpdata);
927		data.set_flags(DB_DBT_USERMEM | (dataflags & DB_DBT_PARTIAL));
928	} else
929		data.set_flags(DB_DBT_MALLOC | (dataflags & DB_DBT_PARTIAL));
930
931	/* Got all our stuff, now do the get */
932	ret = dbp->get(txnp, &key, &data, flags);
933	/*
934	 * Otherwise just status.
935	 */
936	if (ret == 0) {
937		/*
938		 * XXX
939		 * We need to xdr_free whatever we are returning, next time.
940		 * However, DB does not allocate a new key if one was given
941		 * and we'd be free'ing up space allocated in the request.
942		 * So, allocate a new key/data pointer if it is the same one
943		 * as in the request.
944		 */
945		*freep = 1;
946		/*
947		 * Key
948		 */
949		if (key.get_data() == keydata) {
950			ret = __os_umalloc(dbp->get_ENV(),
951			    key.get_size(), &replyp->keydata.keydata_val);
952			if (ret != 0)
953				goto err;
954			memcpy(replyp->keydata.keydata_val,
955			    key.get_data(), key.get_size());
956		} else
957			replyp->keydata.keydata_val = (char *)key.get_data();
958
959		replyp->keydata.keydata_len = key.get_size();
960
961		/*
962		 * Data
963		 */
964		if (data.get_data() == datadata) {
965			ret = __os_umalloc(dbp->get_ENV(),
966			     data.get_size(), &replyp->datadata.datadata_val);
967			if (ret != 0)
968				goto err;
969			memcpy(replyp->datadata.datadata_val, data.get_data(),
970			    data.get_size());
971		} else
972			replyp->datadata.datadata_val = (char *)data.get_data();
973		replyp->datadata.datadata_len = data.get_size();
974	} else {
975err:		FREE_IF_CHANGED(dbp->get_ENV(), key.get_data(), keydata);
976		FREE_IF_CHANGED(dbp->get_ENV(), data.get_data(), datadata);
977		FREE_IF_CHANGED(dbp->get_ENV(),
978		    replyp->keydata.keydata_val, key.get_data());
979		replyp->keydata.keydata_val = NULL;
980		replyp->keydata.keydata_len = 0;
981		replyp->datadata.datadata_val = NULL;
982		replyp->datadata.datadata_len = 0;
983		*freep = 0;
984	}
985	replyp->status = ret;
986	return;
987}
988
989extern "C" void
990__db_get_h_ffactor_proc(
991	u_int dbpcl_id,
992	__db_get_h_ffactor_reply *replyp)
993{
994	Db *dbp;
995	ct_entry *dbp_ctp;
996
997	ACTIVATE_CTP(dbp_ctp, dbpcl_id, CT_DB);
998	dbp = (Db *)dbp_ctp->ct_anyp;
999
1000	replyp->status = dbp->get_h_ffactor(&replyp->ffactor);
1001}
1002
1003extern "C" void
1004__db_set_h_ffactor_proc(
1005	u_int dbpcl_id,
1006	u_int32_t ffactor,
1007	__db_set_h_ffactor_reply *replyp)
1008{
1009	Db *dbp;
1010	ct_entry *dbp_ctp;
1011	int ret;
1012
1013	ACTIVATE_CTP(dbp_ctp, dbpcl_id, CT_DB);
1014	dbp = (Db *)dbp_ctp->ct_anyp;
1015
1016	ret = dbp->set_h_ffactor(ffactor);
1017
1018	replyp->status = ret;
1019	return;
1020}
1021
1022extern "C" void
1023__db_get_h_nelem_proc(
1024	u_int dbpcl_id,
1025	__db_get_h_nelem_reply *replyp)
1026{
1027	Db *dbp;
1028	ct_entry *dbp_ctp;
1029
1030	ACTIVATE_CTP(dbp_ctp, dbpcl_id, CT_DB);
1031	dbp = (Db *)dbp_ctp->ct_anyp;
1032
1033	replyp->status = dbp->get_h_nelem(&replyp->nelem);
1034}
1035
1036extern "C" void
1037__db_set_h_nelem_proc(
1038	u_int dbpcl_id,
1039	u_int32_t nelem,
1040	__db_set_h_nelem_reply *replyp)
1041{
1042	Db *dbp;
1043	ct_entry *dbp_ctp;
1044	int ret;
1045
1046	ACTIVATE_CTP(dbp_ctp, dbpcl_id, CT_DB);
1047	dbp = (Db *)dbp_ctp->ct_anyp;
1048
1049	ret = dbp->set_h_nelem(nelem);
1050
1051	replyp->status = ret;
1052	return;
1053}
1054
1055extern "C" void
1056__db_key_range_proc(
1057	u_int dbpcl_id,
1058	u_int txnpcl_id,
1059	u_int32_t keydlen,
1060	u_int32_t keydoff,
1061	u_int32_t keyulen,
1062	u_int32_t keyflags,
1063	void *keydata,
1064	u_int32_t keysize,
1065	u_int32_t flags,
1066	__db_key_range_reply *replyp)
1067{
1068	Db *dbp;
1069	DB_KEY_RANGE range;
1070	DbTxn *txnp;
1071	ct_entry *dbp_ctp, *txnp_ctp;
1072	int ret;
1073
1074	ACTIVATE_CTP(dbp_ctp, dbpcl_id, CT_DB);
1075	dbp = (Db *)dbp_ctp->ct_anyp;
1076	if (txnpcl_id != 0) {
1077		ACTIVATE_CTP(txnp_ctp, txnpcl_id, CT_TXN);
1078		txnp = (DbTxn *)txnp_ctp->ct_anyp;
1079	} else
1080		txnp = NULL;
1081
1082	/* Set up key */
1083	Dbt key(keydata, keysize);
1084	key.set_dlen(keydlen);
1085	key.set_ulen(keyulen);
1086	key.set_doff(keydoff);
1087	key.set_flags(keyflags);
1088
1089	ret = dbp->key_range(txnp, &key, &range, flags);
1090
1091	replyp->status = ret;
1092	replyp->less = range.less;
1093	replyp->equal = range.equal;
1094	replyp->greater = range.greater;
1095	return;
1096}
1097
1098extern "C" void
1099__db_get_lorder_proc(
1100	u_int dbpcl_id,
1101	__db_get_lorder_reply *replyp)
1102{
1103	Db *dbp;
1104	ct_entry *dbp_ctp;
1105
1106	ACTIVATE_CTP(dbp_ctp, dbpcl_id, CT_DB);
1107	dbp = (Db *)dbp_ctp->ct_anyp;
1108
1109	replyp->status = dbp->get_lorder((int *)&replyp->lorder);
1110}
1111
1112extern "C" void
1113__db_set_lorder_proc(
1114	u_int dbpcl_id,
1115	u_int32_t lorder,
1116	__db_set_lorder_reply *replyp)
1117{
1118	Db *dbp;
1119	ct_entry *dbp_ctp;
1120	int ret;
1121
1122	ACTIVATE_CTP(dbp_ctp, dbpcl_id, CT_DB);
1123	dbp = (Db *)dbp_ctp->ct_anyp;
1124
1125	ret = dbp->set_lorder(lorder);
1126
1127	replyp->status = ret;
1128	return;
1129}
1130
1131extern "C" void
1132__db_get_dbname_proc(
1133	u_int dbpcl_id,
1134	__db_get_dbname_reply *replyp)
1135{
1136	Db *dbp;
1137	ct_entry *dbp_ctp;
1138
1139	ACTIVATE_CTP(dbp_ctp, dbpcl_id, CT_DB);
1140	dbp = (Db *)dbp_ctp->ct_anyp;
1141
1142	replyp->status = dbp->get_dbname(
1143	    (const char **)&replyp->filename, (const char **)&replyp->dbname);
1144}
1145
1146extern "C" void
1147__db_get_open_flags_proc(
1148	u_int dbpcl_id,
1149	__db_get_open_flags_reply *replyp)
1150{
1151	Db *dbp;
1152	ct_entry *dbp_ctp;
1153
1154	ACTIVATE_CTP(dbp_ctp, dbpcl_id, CT_DB);
1155	dbp = (Db *)dbp_ctp->ct_anyp;
1156
1157	replyp->status = dbp->get_open_flags(&replyp->flags);
1158}
1159
1160extern "C" void
1161__db_open_proc(
1162	u_int dbpcl_id,
1163	u_int txnpcl_id,
1164	char *name,
1165	char *subdb,
1166	u_int32_t type,
1167	u_int32_t flags,
1168	u_int32_t mode,
1169	__db_open_reply *replyp)
1170{
1171	Db *dbp;
1172	DbTxn *txnp;
1173	DBTYPE dbtype;
1174	ct_entry *dbp_ctp, *new_ctp, *txnp_ctp;
1175	int isswapped, ret;
1176
1177	ACTIVATE_CTP(dbp_ctp, dbpcl_id, CT_DB);
1178	dbp = (Db *)dbp_ctp->ct_anyp;
1179	if (txnpcl_id != 0) {
1180		ACTIVATE_CTP(txnp_ctp, txnpcl_id, CT_TXN);
1181		txnp = (DbTxn *)txnp_ctp->ct_anyp;
1182	} else
1183		txnp = NULL;
1184
1185	replyp->dbcl_id = dbpcl_id;
1186	if ((new_ctp = __dbsrv_sharedb(
1187	    dbp_ctp, name, subdb, (DBTYPE)type, flags)) != NULL) {
1188		/*
1189		 * We can share, clean up old ID, set new one.
1190		 */
1191		if (__dbsrv_verbose)
1192			printf("Sharing db ID %ld\n", new_ctp->ct_id);
1193		replyp->dbcl_id = new_ctp->ct_id;
1194		ret = __db_close_int(dbpcl_id, 0);
1195		goto out;
1196	}
1197	ret = dbp->open(txnp, name, subdb, (DBTYPE)type, flags, mode);
1198	if (ret == 0) {
1199		(void)dbp->get_type(&dbtype);
1200		replyp->type = dbtype;
1201		/*
1202		 * We need to determine the byte order of the database
1203		 * and send it back to the client.  Determine it by
1204		 * the server's native order and the swapped value of
1205		 * the DB itself.
1206		 */
1207		(void)dbp->get_byteswapped(&isswapped);
1208		if (__db_isbigendian() == 0) {
1209			if (isswapped == 0)
1210				replyp->lorder = 4321;
1211			else
1212				replyp->lorder = 1234;
1213		} else {
1214			if (isswapped == 0)
1215				replyp->lorder = 1234;
1216			else
1217				replyp->lorder = 4321;
1218		}
1219		dbp_ctp->ct_dbdp.type = dbtype;
1220		dbp_ctp->ct_dbdp.dbflags = LF_ISSET(DB_SERVER_DBFLAGS);
1221		if (name == NULL)
1222			dbp_ctp->ct_dbdp.db = NULL;
1223		else if ((ret = __os_strdup(dbp->get_ENV(), name,
1224		    &dbp_ctp->ct_dbdp.db)) != 0)
1225			goto out;
1226		if (subdb == NULL)
1227			dbp_ctp->ct_dbdp.subdb = NULL;
1228		else if ((ret = __os_strdup(dbp->get_ENV(), subdb,
1229		    &dbp_ctp->ct_dbdp.subdb)) != 0)
1230			goto out;
1231	}
1232out:
1233	replyp->status = ret;
1234	return;
1235}
1236
1237extern "C" void
1238__db_get_pagesize_proc(
1239	u_int dbpcl_id,
1240	__db_get_pagesize_reply *replyp)
1241{
1242	Db *dbp;
1243	ct_entry *dbp_ctp;
1244
1245	ACTIVATE_CTP(dbp_ctp, dbpcl_id, CT_DB);
1246	dbp = (Db *)dbp_ctp->ct_anyp;
1247
1248	replyp->status = dbp->get_pagesize(&replyp->pagesize);
1249}
1250
1251extern "C" void
1252__db_set_pagesize_proc(
1253	u_int dbpcl_id,
1254	u_int32_t pagesize,
1255	__db_set_pagesize_reply *replyp)
1256{
1257	Db *dbp;
1258	ct_entry *dbp_ctp;
1259	int ret;
1260
1261	ACTIVATE_CTP(dbp_ctp, dbpcl_id, CT_DB);
1262	dbp = (Db *)dbp_ctp->ct_anyp;
1263
1264	ret = dbp->set_pagesize(pagesize);
1265
1266	replyp->status = ret;
1267	return;
1268}
1269
1270extern "C" void
1271__db_get_priority_proc(
1272	u_int dbpcl_id,
1273	__db_get_priority_reply *replyp)
1274{
1275	Db *dbp;
1276	ct_entry *dbp_ctp;
1277
1278	ACTIVATE_CTP(dbp_ctp, dbpcl_id, CT_DB);
1279	dbp = (Db *)dbp_ctp->ct_anyp;
1280
1281	replyp->status =
1282	    dbp->get_priority((DB_CACHE_PRIORITY *)&replyp->priority);
1283}
1284
1285extern "C" void
1286__db_set_priority_proc(
1287	u_int dbpcl_id,
1288	u_int32_t priority,
1289	__db_set_priority_reply *replyp)
1290{
1291	Db *dbp;
1292	ct_entry *dbp_ctp;
1293	int ret;
1294
1295	ACTIVATE_CTP(dbp_ctp, dbpcl_id, CT_DB);
1296	dbp = (Db *)dbp_ctp->ct_anyp;
1297
1298	ret = dbp->set_priority((DB_CACHE_PRIORITY)priority);
1299
1300	replyp->status = ret;
1301	return;
1302}
1303
1304extern "C" void
1305__db_pget_proc(
1306	u_int dbpcl_id,
1307	u_int txnpcl_id,
1308	u_int32_t skeydlen,
1309	u_int32_t skeydoff,
1310	u_int32_t skeyulen,
1311	u_int32_t skeyflags,
1312	void *skeydata,
1313	u_int32_t skeysize,
1314	u_int32_t pkeydlen,
1315	u_int32_t pkeydoff,
1316	u_int32_t pkeyulen,
1317	u_int32_t pkeyflags,
1318	void *pkeydata,
1319	u_int32_t pkeysize,
1320	u_int32_t datadlen,
1321	u_int32_t datadoff,
1322	u_int32_t dataulen,
1323	u_int32_t dataflags,
1324	void *datadata,
1325	u_int32_t datasize,
1326	u_int32_t flags,
1327	__db_pget_reply *replyp,
1328	int * freep)
1329{
1330	Db *dbp;
1331	DbTxn *txnp;
1332	ct_entry *dbp_ctp, *txnp_ctp;
1333	void *tmpdata;
1334	int ret;
1335
1336	ACTIVATE_CTP(dbp_ctp, dbpcl_id, CT_DB);
1337	dbp = (Db *)dbp_ctp->ct_anyp;
1338	if (txnpcl_id != 0) {
1339		ACTIVATE_CTP(txnp_ctp, txnpcl_id, CT_TXN);
1340		txnp = (DbTxn *)txnp_ctp->ct_anyp;
1341	} else
1342		txnp = NULL;
1343
1344	replyp->skeydata.skeydata_val = NULL;
1345	replyp->pkeydata.pkeydata_val = NULL;
1346	replyp->datadata.datadata_val = NULL;
1347	*freep = 0;
1348
1349	/* Set up skey, pkey and data */
1350	Dbt skey(skeydata, skeysize);
1351	skey.set_dlen(skeydlen);
1352	skey.set_ulen(skeyulen);
1353	skey.set_doff(skeydoff);
1354
1355	Dbt pkey(pkeydata, pkeysize);
1356	pkey.set_dlen(pkeydlen);
1357	pkey.set_ulen(pkeyulen);
1358	pkey.set_doff(pkeydoff);
1359
1360	Dbt data(datadata, datasize);
1361	data.set_dlen(datadlen);
1362	data.set_ulen(dataulen);
1363	data.set_doff(datadoff);
1364
1365	/*
1366	 * Ignore memory related flags on server.
1367	 */
1368	if (skeyflags & DB_DBT_USERMEM) {
1369		if ((ret = __os_umalloc(dbp->get_ENV(),
1370		    skeyulen, &tmpdata)) != 0)
1371			goto err;
1372		if (skeydata)
1373			memcpy(tmpdata, skeydata, (skeysize < skeyulen) ?
1374			    skeysize : skeyulen);
1375		skey.set_data(tmpdata);
1376		skey.set_flags(DB_DBT_USERMEM | (skeyflags & DB_DBT_PARTIAL));
1377	} else
1378		skey.set_flags(DB_DBT_MALLOC | (skeyflags & DB_DBT_PARTIAL));
1379
1380	if (pkeyflags & DB_DBT_USERMEM) {
1381		if ((ret = __os_umalloc(dbp->get_ENV(),
1382		    pkeyulen, &tmpdata)) != 0)
1383			goto err;
1384		if (pkeydata)
1385			memcpy(tmpdata, pkeydata, (pkeysize < pkeyulen) ?
1386			    pkeysize : pkeyulen);
1387		pkey.set_data(tmpdata);
1388		pkey.set_flags(DB_DBT_USERMEM | (pkeyflags & DB_DBT_PARTIAL));
1389	} else
1390		pkey.set_flags(DB_DBT_MALLOC | (pkeyflags & DB_DBT_PARTIAL));
1391
1392	if (flags & (DB_MULTIPLE | DB_MULTIPLE_KEY) ||
1393	    dataflags & DB_DBT_USERMEM) {
1394		if ((ret = __os_umalloc(dbp->get_ENV(),
1395		    dataulen, &tmpdata)) != 0)
1396			goto err;
1397		if (datadata)
1398			memcpy(tmpdata, datadata,
1399			    (datasize < dataulen) ?
1400			    datasize : dataulen);
1401		data.set_data(tmpdata);
1402		data.set_flags(DB_DBT_USERMEM | (dataflags & DB_DBT_PARTIAL));
1403	} else
1404		data.set_flags(DB_DBT_MALLOC | (dataflags & DB_DBT_PARTIAL));
1405
1406	/* Got all our stuff, now do the get */
1407	ret = dbp->pget(txnp, &skey, &pkey, &data, flags);
1408	/*
1409	 * Otherwise just status.
1410	 */
1411	if (ret == 0) {
1412		/*
1413		 * XXX
1414		 * We need to xdr_free whatever we are returning, next time.
1415		 * However, DB does not allocate a new key if one was given
1416		 * and we'd be free'ing up space allocated in the request.
1417		 * So, allocate a new key/data pointer if it is the same one
1418		 * as in the request.
1419		 */
1420		*freep = 1;
1421		/*
1422		 * Key
1423		 */
1424		if (skey.get_data() == skeydata) {
1425			ret = __os_umalloc(dbp->get_ENV(),
1426			    skey.get_size(), &replyp->skeydata.skeydata_val);
1427			if (ret != 0)
1428				goto err;
1429			memcpy(replyp->skeydata.skeydata_val, skey.get_data(),
1430			    skey.get_size());
1431		} else
1432			replyp->skeydata.skeydata_val = (char *)skey.get_data();
1433
1434		replyp->skeydata.skeydata_len = skey.get_size();
1435
1436		/*
1437		 * Primary key
1438		 */
1439		if (pkey.get_data() == pkeydata) {
1440			ret = __os_umalloc(dbp->get_ENV(),
1441			     pkey.get_size(), &replyp->pkeydata.pkeydata_val);
1442			if (ret != 0)
1443				goto err;
1444			memcpy(replyp->pkeydata.pkeydata_val, pkey.get_data(),
1445			    pkey.get_size());
1446		} else
1447			replyp->pkeydata.pkeydata_val = (char *)pkey.get_data();
1448		replyp->pkeydata.pkeydata_len = pkey.get_size();
1449
1450		/*
1451		 * Data
1452		 */
1453		if (data.get_data() == datadata) {
1454			ret = __os_umalloc(dbp->get_ENV(),
1455			     data.get_size(), &replyp->datadata.datadata_val);
1456			if (ret != 0)
1457				goto err;
1458			memcpy(replyp->datadata.datadata_val, data.get_data(),
1459			    data.get_size());
1460		} else
1461			replyp->datadata.datadata_val = (char *)data.get_data();
1462		replyp->datadata.datadata_len = data.get_size();
1463	} else {
1464err:		FREE_IF_CHANGED(dbp->get_ENV(), skey.get_data(), skeydata);
1465		FREE_IF_CHANGED(dbp->get_ENV(), pkey.get_data(), pkeydata);
1466		FREE_IF_CHANGED(dbp->get_ENV(), data.get_data(), datadata);
1467		FREE_IF_CHANGED(dbp->get_ENV(),
1468		    replyp->skeydata.skeydata_val, skey.get_data());
1469		FREE_IF_CHANGED(dbp->get_ENV(),
1470		    replyp->pkeydata.pkeydata_val, pkey.get_data());
1471		FREE_IF_CHANGED(dbp->get_ENV(),
1472		    replyp->datadata.datadata_val, data.get_data());
1473		replyp->skeydata.skeydata_val = NULL;
1474		replyp->skeydata.skeydata_len = 0;
1475		replyp->pkeydata.pkeydata_val = NULL;
1476		replyp->pkeydata.pkeydata_len = 0;
1477		replyp->datadata.datadata_val = NULL;
1478		replyp->datadata.datadata_len = 0;
1479		*freep = 0;
1480	}
1481	replyp->status = ret;
1482	return;
1483}
1484
1485extern "C" void
1486__db_put_proc(
1487	u_int dbpcl_id,
1488	u_int txnpcl_id,
1489	u_int32_t keydlen,
1490	u_int32_t keydoff,
1491	u_int32_t keyulen,
1492	u_int32_t keyflags,
1493	void *keydata,
1494	u_int32_t keysize,
1495	u_int32_t datadlen,
1496	u_int32_t datadoff,
1497	u_int32_t dataulen,
1498	u_int32_t dataflags,
1499	void *datadata,
1500	u_int32_t datasize,
1501	u_int32_t flags,
1502	__db_put_reply *replyp,
1503	int * freep)
1504{
1505	Db *dbp;
1506	DbTxn *txnp;
1507	ct_entry *dbp_ctp, *txnp_ctp;
1508	int ret;
1509
1510	ACTIVATE_CTP(dbp_ctp, dbpcl_id, CT_DB);
1511	dbp = (Db *)dbp_ctp->ct_anyp;
1512	if (txnpcl_id != 0) {
1513		ACTIVATE_CTP(txnp_ctp, txnpcl_id, CT_TXN);
1514		txnp = (DbTxn *)txnp_ctp->ct_anyp;
1515	} else
1516		txnp = NULL;
1517
1518	replyp->keydata.keydata_val = NULL;
1519	*freep = 0;
1520
1521	/* Set up key and data */
1522	Dbt key(keydata, keysize);
1523	key.set_dlen(keydlen);
1524	key.set_ulen(keyulen);
1525	key.set_doff(keydoff);
1526	key.set_flags(DB_DBT_MALLOC | (keyflags & DB_DBT_PARTIAL));
1527
1528	Dbt data(datadata, datasize);
1529	data.set_dlen(datadlen);
1530	data.set_ulen(dataulen);
1531	data.set_doff(datadoff);
1532	data.set_flags(dataflags);
1533
1534	/* Got all our stuff, now do the put */
1535	ret = dbp->put(txnp, &key, &data, flags);
1536	/*
1537	 * If the client did a DB_APPEND, set up key in reply.
1538	 * Otherwise just status.
1539	 */
1540	if (ret == 0 && (flags == DB_APPEND)) {
1541		/*
1542		 * XXX
1543		 * We need to xdr_free whatever we are returning, next time.
1544		 * However, DB does not allocate a new key if one was given
1545		 * and we'd be free'ing up space allocated in the request.
1546		 * So, allocate a new key/data pointer if it is the same one
1547		 * as in the request.
1548		 */
1549		*freep = 1;
1550		/*
1551		 * Key
1552		 */
1553		if (key.get_data() == keydata) {
1554			ret = __os_umalloc(dbp->get_ENV(),
1555			    key.get_size(), &replyp->keydata.keydata_val);
1556			if (ret != 0)
1557				goto err;
1558			memcpy(replyp->keydata.keydata_val,
1559			    key.get_data(), key.get_size());
1560		} else
1561			replyp->keydata.keydata_val = (char *)key.get_data();
1562
1563		replyp->keydata.keydata_len = key.get_size();
1564	} else {
1565err:		FREE_IF_CHANGED(dbp->get_ENV(), key.get_data(), keydata);
1566		FREE_IF_CHANGED(dbp->get_ENV(),
1567		    replyp->keydata.keydata_val, key.get_data());
1568		replyp->keydata.keydata_val = NULL;
1569		replyp->keydata.keydata_len = 0;
1570		*freep = 0;
1571	}
1572	replyp->status = ret;
1573	return;
1574}
1575
1576extern "C" void
1577__db_get_re_delim_proc(
1578	u_int dbpcl_id,
1579	__db_get_re_delim_reply *replyp)
1580{
1581	Db *dbp;
1582	ct_entry *dbp_ctp;
1583
1584	ACTIVATE_CTP(dbp_ctp, dbpcl_id, CT_DB);
1585	dbp = (Db *)dbp_ctp->ct_anyp;
1586
1587	replyp->status = dbp->get_re_delim((int *)&replyp->delim);
1588}
1589
1590extern "C" void
1591__db_set_re_delim_proc(
1592	u_int dbpcl_id,
1593	u_int32_t delim,
1594	__db_set_re_delim_reply *replyp)
1595{
1596	Db *dbp;
1597	ct_entry *dbp_ctp;
1598	int ret;
1599
1600	ACTIVATE_CTP(dbp_ctp, dbpcl_id, CT_DB);
1601	dbp = (Db *)dbp_ctp->ct_anyp;
1602
1603	ret = dbp->set_re_delim(delim);
1604
1605	replyp->status = ret;
1606	return;
1607}
1608
1609extern "C" void
1610__db_get_re_len_proc(
1611	u_int dbpcl_id,
1612	__db_get_re_len_reply *replyp)
1613{
1614	Db *dbp;
1615	ct_entry *dbp_ctp;
1616
1617	ACTIVATE_CTP(dbp_ctp, dbpcl_id, CT_DB);
1618	dbp = (Db *)dbp_ctp->ct_anyp;
1619
1620	replyp->status = dbp->get_re_len(&replyp->len);
1621}
1622
1623extern "C" void
1624__db_set_re_len_proc(
1625	u_int dbpcl_id,
1626	u_int32_t len,
1627	__db_set_re_len_reply *replyp)
1628{
1629	Db *dbp;
1630	ct_entry *dbp_ctp;
1631	int ret;
1632
1633	ACTIVATE_CTP(dbp_ctp, dbpcl_id, CT_DB);
1634	dbp = (Db *)dbp_ctp->ct_anyp;
1635
1636	ret = dbp->set_re_len(len);
1637
1638	replyp->status = ret;
1639	return;
1640}
1641
1642void
1643__db_get_re_pad_proc(
1644	u_int dbpcl_id,
1645	__db_get_re_pad_reply *replyp)
1646{
1647	Db *dbp;
1648	ct_entry *dbp_ctp;
1649
1650	ACTIVATE_CTP(dbp_ctp, dbpcl_id, CT_DB);
1651	dbp = (Db *)dbp_ctp->ct_anyp;
1652
1653	replyp->status = dbp->get_re_pad((int *)&replyp->pad);
1654}
1655
1656extern "C" void
1657__db_set_re_pad_proc(
1658	u_int dbpcl_id,
1659	u_int32_t pad,
1660	__db_set_re_pad_reply *replyp)
1661{
1662	Db *dbp;
1663	ct_entry *dbp_ctp;
1664	int ret;
1665
1666	ACTIVATE_CTP(dbp_ctp, dbpcl_id, CT_DB);
1667	dbp = (Db *)dbp_ctp->ct_anyp;
1668
1669	ret = dbp->set_re_pad(pad);
1670
1671	replyp->status = ret;
1672	return;
1673}
1674
1675extern "C" void
1676__db_remove_proc(
1677	u_int dbpcl_id,
1678	char *name,
1679	char *subdb,
1680	u_int32_t flags,
1681	__db_remove_reply *replyp)
1682{
1683	Db *dbp;
1684	ct_entry *dbp_ctp;
1685	int ret;
1686
1687	ACTIVATE_CTP(dbp_ctp, dbpcl_id, CT_DB);
1688	dbp = (Db *)dbp_ctp->ct_anyp;
1689
1690	ret = dbp->remove(name, subdb, flags);
1691	__dbdel_ctp(dbp_ctp);
1692
1693	replyp->status = ret;
1694	return;
1695}
1696
1697extern "C" void
1698__db_rename_proc(
1699	u_int dbpcl_id,
1700	char *name,
1701	char *subdb,
1702	char *newname,
1703	u_int32_t flags,
1704	__db_rename_reply *replyp)
1705{
1706	Db *dbp;
1707	ct_entry *dbp_ctp;
1708	int ret;
1709
1710	ACTIVATE_CTP(dbp_ctp, dbpcl_id, CT_DB);
1711	dbp = (Db *)dbp_ctp->ct_anyp;
1712
1713	ret = dbp->rename(name, subdb, newname, flags);
1714	__dbdel_ctp(dbp_ctp);
1715
1716	replyp->status = ret;
1717	return;
1718}
1719
1720extern "C" void
1721__db_stat_proc(
1722	u_int dbpcl_id,
1723	u_int txnpcl_id,
1724	u_int32_t flags,
1725	__db_stat_reply *replyp,
1726	int * freep)
1727{
1728	Db *dbp;
1729	DbTxn *txnp;
1730	DBTYPE type;
1731	ct_entry *dbp_ctp, *txnp_ctp;
1732	u_int32_t *q, *p, *retsp;
1733	int i, len, ret;
1734	void *sp;
1735
1736	ACTIVATE_CTP(dbp_ctp, dbpcl_id, CT_DB);
1737	dbp = (Db *)dbp_ctp->ct_anyp;
1738	if (txnpcl_id != 0) {
1739		ACTIVATE_CTP(txnp_ctp, txnpcl_id, CT_TXN);
1740		txnp = (DbTxn *)txnp_ctp->ct_anyp;
1741	} else
1742		txnp = NULL;
1743
1744	ret = dbp->stat(txnp, &sp, flags);
1745	replyp->status = ret;
1746	if (ret != 0)
1747		return;
1748	/*
1749	 * We get here, we have success.  Allocate an array so that
1750	 * we can use the list generator.  Generate the reply, free
1751	 * up the space.
1752	 */
1753	/*
1754	 * XXX This assumes that all elements of all stat structures
1755	 * are u_int32_t fields.  They are, currently.
1756	 */
1757	(void)dbp->get_type(&type);
1758	if (type == DB_HASH)
1759		len = sizeof(DB_HASH_STAT);
1760	else if (type == DB_QUEUE)
1761		len = sizeof(DB_QUEUE_STAT);
1762	else            /* BTREE or RECNO are same stats */
1763		len = sizeof(DB_BTREE_STAT);
1764	replyp->stats.stats_len = len / sizeof(u_int32_t);
1765
1766	if ((ret = __os_umalloc(dbp->get_ENV(),
1767	    len * replyp->stats.stats_len, &retsp)) != 0)
1768		goto out;
1769	for (i = 0, q = retsp, p = (u_int32_t *)sp; i < len;
1770	    i++, q++, p++)
1771		*q = *p;
1772	replyp->stats.stats_val = retsp;
1773	__os_ufree(dbp->get_ENV(), sp);
1774	if (ret == 0)
1775		*freep = 1;
1776out:
1777	replyp->status = ret;
1778	return;
1779}
1780
1781extern "C" void
1782__db_sync_proc(
1783	u_int dbpcl_id,
1784	u_int32_t flags,
1785	__db_sync_reply *replyp)
1786{
1787	Db *dbp;
1788	ct_entry *dbp_ctp;
1789	int ret;
1790
1791	ACTIVATE_CTP(dbp_ctp, dbpcl_id, CT_DB);
1792	dbp = (Db *)dbp_ctp->ct_anyp;
1793
1794	ret = dbp->sync(flags);
1795
1796	replyp->status = ret;
1797	return;
1798}
1799
1800extern "C" void
1801__db_truncate_proc(
1802	u_int dbpcl_id,
1803	u_int txnpcl_id,
1804	u_int32_t flags,
1805	__db_truncate_reply *replyp)
1806{
1807	Db *dbp;
1808	DbTxn *txnp;
1809	ct_entry *dbp_ctp, *txnp_ctp;
1810	u_int32_t count;
1811	int ret;
1812
1813	ACTIVATE_CTP(dbp_ctp, dbpcl_id, CT_DB);
1814	dbp = (Db *)dbp_ctp->ct_anyp;
1815	if (txnpcl_id != 0) {
1816		ACTIVATE_CTP(txnp_ctp, txnpcl_id, CT_TXN);
1817		txnp = (DbTxn *)txnp_ctp->ct_anyp;
1818	} else
1819		txnp = NULL;
1820
1821	ret = dbp->truncate(txnp, &count, flags);
1822	replyp->status = ret;
1823	if (ret == 0)
1824		replyp->count = count;
1825	return;
1826}
1827
1828extern "C" void
1829__db_cursor_proc(
1830	u_int dbpcl_id,
1831	u_int txnpcl_id,
1832	u_int32_t flags,
1833	__db_cursor_reply *replyp)
1834{
1835	Db *dbp;
1836	Dbc *dbc;
1837	DbTxn *txnp;
1838	ct_entry *dbc_ctp, *env_ctp, *dbp_ctp, *txnp_ctp;
1839	int ret;
1840
1841	ACTIVATE_CTP(dbp_ctp, dbpcl_id, CT_DB);
1842	dbp = (Db *)dbp_ctp->ct_anyp;
1843	dbc_ctp = new_ct_ent(&replyp->status);
1844	if (dbc_ctp == NULL)
1845		return;
1846
1847	if (txnpcl_id != 0) {
1848		ACTIVATE_CTP(txnp_ctp, txnpcl_id, CT_TXN);
1849		txnp = (DbTxn *)txnp_ctp->ct_anyp;
1850		dbc_ctp->ct_activep = txnp_ctp->ct_activep;
1851	} else
1852		txnp = NULL;
1853
1854	if ((ret = dbp->cursor(txnp, &dbc, flags)) == 0) {
1855		dbc_ctp->ct_dbc = dbc;
1856		dbc_ctp->ct_type = CT_CURSOR;
1857		dbc_ctp->ct_parent = dbp_ctp;
1858		env_ctp = dbp_ctp->ct_envparent;
1859		dbc_ctp->ct_envparent = env_ctp;
1860		__dbsrv_settimeout(dbc_ctp, env_ctp->ct_timeout);
1861		__dbsrv_active(dbc_ctp);
1862		replyp->dbcidcl_id = dbc_ctp->ct_id;
1863	} else
1864		__dbclear_ctp(dbc_ctp);
1865
1866	replyp->status = ret;
1867	return;
1868}
1869
1870extern "C" void
1871__db_join_proc(
1872	u_int dbpcl_id,
1873	u_int32_t *curs,
1874	u_int32_t curslen,
1875	u_int32_t flags,
1876	__db_join_reply *replyp)
1877{
1878	Db *dbp;
1879	Dbc **jcurs, **c;
1880	Dbc *dbc;
1881	ct_entry *dbc_ctp, *ctp, *dbp_ctp;
1882	size_t size;
1883	u_int32_t *cl, i;
1884	int ret;
1885
1886	ACTIVATE_CTP(dbp_ctp, dbpcl_id, CT_DB);
1887	dbp = (Db *)dbp_ctp->ct_anyp;
1888
1889	dbc_ctp = new_ct_ent(&replyp->status);
1890	if (dbc_ctp == NULL)
1891		return;
1892
1893	size = (curslen + 1) * sizeof(Dbc *);
1894	if ((ret = __os_calloc(dbp->get_ENV(),
1895	    curslen + 1, sizeof(Dbc *), &jcurs)) != 0) {
1896		replyp->status = ret;
1897		__dbclear_ctp(dbc_ctp);
1898		return;
1899	}
1900	/*
1901	 * If our curslist has a parent txn, we need to use it too
1902	 * for the activity timeout.  All cursors must be part of
1903	 * the same transaction, so just check the first.
1904	 */
1905	ctp = get_tableent(*curs);
1906	DB_ASSERT(dbp->get_ENV(), ctp->ct_type == CT_CURSOR);
1907	/*
1908	 * If we are using a transaction, set the join activity timer
1909	 * to point to the parent transaction.
1910	 */
1911	if (ctp->ct_activep != &ctp->ct_active)
1912		dbc_ctp->ct_activep = ctp->ct_activep;
1913	for (i = 0, cl = curs, c = jcurs; i < curslen; i++, cl++, c++) {
1914		ctp = get_tableent(*cl);
1915		if (ctp == NULL) {
1916			replyp->status = DB_NOSERVER_ID;
1917			goto out;
1918		}
1919		/*
1920		 * If we are using a txn, the join cursor points to the
1921		 * transaction timeout.  If we are not using a transaction,
1922		 * then all the curslist cursors must point to the join
1923		 * cursor's timeout so that we do not timeout any of the
1924		 * curlist cursors while the join cursor is active.
1925		 * Change the type of the curslist ctps to CT_JOIN so that
1926		 * we know they are part of a join list and we can distinguish
1927		 * them and later restore them when the join cursor is closed.
1928		 */
1929		DB_ASSERT(dbp->get_ENV(), ctp->ct_type == CT_CURSOR);
1930		ctp->ct_type |= CT_JOIN;
1931		ctp->ct_origp = ctp->ct_activep;
1932		/*
1933		 * Setting this to the ct_active field of the dbc_ctp is
1934		 * really just a way to distinguish which join dbc this
1935		 * cursor is part of.  The ct_activep of this cursor is
1936		 * not used at all during its lifetime as part of a join
1937		 * cursor.
1938		 */
1939		ctp->ct_activep = &dbc_ctp->ct_active;
1940		*c = ctp->ct_dbc;
1941	}
1942	*c = NULL;
1943	if ((ret = dbp->join(jcurs, &dbc, flags)) == 0) {
1944		dbc_ctp->ct_dbc = dbc;
1945		dbc_ctp->ct_type = (CT_JOINCUR | CT_CURSOR);
1946		dbc_ctp->ct_parent = dbp_ctp;
1947		dbc_ctp->ct_envparent = dbp_ctp->ct_envparent;
1948		__dbsrv_settimeout(dbc_ctp, dbp_ctp->ct_envparent->ct_timeout);
1949		__dbsrv_active(dbc_ctp);
1950		replyp->dbcidcl_id = dbc_ctp->ct_id;
1951	} else {
1952		__dbclear_ctp(dbc_ctp);
1953		/*
1954		 * If we get an error, undo what we did above to any cursors.
1955		 */
1956		for (cl = curs; *cl != 0; cl++) {
1957			ctp = get_tableent(*cl);
1958			ctp->ct_type = CT_CURSOR;
1959			ctp->ct_activep = ctp->ct_origp;
1960		}
1961	}
1962
1963	replyp->status = ret;
1964out:
1965	__os_free(dbp->get_ENV(), jcurs);
1966	return;
1967}
1968
1969extern "C" void
1970__dbc_close_proc(
1971	u_int dbccl_id,
1972	__dbc_close_reply *replyp)
1973{
1974	ct_entry *dbc_ctp;
1975
1976	ACTIVATE_CTP(dbc_ctp, dbccl_id, CT_CURSOR);
1977	replyp->status = __dbc_close_int(dbc_ctp);
1978	return;
1979}
1980
1981extern "C" void
1982__dbc_count_proc(
1983	u_int dbccl_id,
1984	u_int32_t flags,
1985	__dbc_count_reply *replyp)
1986{
1987	Dbc *dbc;
1988	ct_entry *dbc_ctp;
1989	db_recno_t num;
1990	int ret;
1991
1992	ACTIVATE_CTP(dbc_ctp, dbccl_id, CT_CURSOR);
1993	dbc = (Dbc *)dbc_ctp->ct_anyp;
1994
1995	ret = dbc->count(&num, flags);
1996	replyp->status = ret;
1997	if (ret == 0)
1998		replyp->dupcount = num;
1999	return;
2000}
2001
2002extern "C" void
2003__dbc_del_proc(
2004	u_int dbccl_id,
2005	u_int32_t flags,
2006	__dbc_del_reply *replyp)
2007{
2008	Dbc *dbc;
2009	ct_entry *dbc_ctp;
2010	int ret;
2011
2012	ACTIVATE_CTP(dbc_ctp, dbccl_id, CT_CURSOR);
2013	dbc = (Dbc *)dbc_ctp->ct_anyp;
2014
2015	ret = dbc->del(flags);
2016
2017	replyp->status = ret;
2018	return;
2019}
2020
2021extern "C" void
2022__dbc_dup_proc(
2023	u_int dbccl_id,
2024	u_int32_t flags,
2025	__dbc_dup_reply *replyp)
2026{
2027	Dbc *dbc, *newdbc;
2028	ct_entry *dbc_ctp, *new_ctp;
2029	int ret;
2030
2031	ACTIVATE_CTP(dbc_ctp, dbccl_id, CT_CURSOR);
2032	dbc = (Dbc *)dbc_ctp->ct_anyp;
2033
2034	new_ctp = new_ct_ent(&replyp->status);
2035	if (new_ctp == NULL)
2036		return;
2037
2038	if ((ret = dbc->dup(&newdbc, flags)) == 0) {
2039		new_ctp->ct_dbc = newdbc;
2040		new_ctp->ct_type = CT_CURSOR;
2041		new_ctp->ct_parent = dbc_ctp->ct_parent;
2042		new_ctp->ct_envparent = dbc_ctp->ct_envparent;
2043		/*
2044		 * If our cursor has a parent txn, we need to use it too.
2045		 */
2046		if (dbc_ctp->ct_activep != &dbc_ctp->ct_active)
2047			new_ctp->ct_activep = dbc_ctp->ct_activep;
2048		__dbsrv_settimeout(new_ctp, dbc_ctp->ct_timeout);
2049		__dbsrv_active(new_ctp);
2050		replyp->dbcidcl_id = new_ctp->ct_id;
2051	} else
2052		__dbclear_ctp(new_ctp);
2053
2054	replyp->status = ret;
2055	return;
2056}
2057
2058extern "C" void
2059__dbc_get_proc(
2060	u_int dbccl_id,
2061	u_int32_t keydlen,
2062	u_int32_t keydoff,
2063	u_int32_t keyulen,
2064	u_int32_t keyflags,
2065	void *keydata,
2066	u_int32_t keysize,
2067	u_int32_t datadlen,
2068	u_int32_t datadoff,
2069	u_int32_t dataulen,
2070	u_int32_t dataflags,
2071	void *datadata,
2072	u_int32_t datasize,
2073	u_int32_t flags,
2074	__dbc_get_reply *replyp,
2075	int * freep)
2076{
2077	Dbc *dbc;
2078	DbEnv *dbenv;
2079	ct_entry *dbc_ctp;
2080	int ret;
2081	void *tmpdata;
2082
2083	ACTIVATE_CTP(dbc_ctp, dbccl_id, CT_CURSOR);
2084	dbc = (Dbc *)dbc_ctp->ct_anyp;
2085	dbenv = DbEnv::get_DbEnv(((DBC *)dbc)->dbp->dbenv);
2086
2087	replyp->keydata.keydata_val = NULL;
2088	replyp->datadata.datadata_val = NULL;
2089	*freep = 0;
2090
2091	/* Set up key and data */
2092	Dbt key(keydata, keysize);
2093	key.set_dlen(keydlen);
2094	key.set_ulen(keyulen);
2095	key.set_doff(keydoff);
2096
2097	Dbt data(datadata, datasize);
2098	data.set_dlen(datadlen);
2099	data.set_ulen(dataulen);
2100	data.set_doff(datadoff);
2101
2102	/*
2103	 * Ignore memory related flags on server.
2104	 */
2105	if (keyflags & DB_DBT_USERMEM) {
2106		if ((ret = __os_umalloc(
2107		    dbenv->get_ENV(), keyulen, &tmpdata)) != 0)
2108			goto err;
2109		if (keydata)
2110			memcpy(tmpdata, keydata, (keysize < keyulen) ?
2111			    keysize : keyulen);
2112		key.set_data(tmpdata);
2113		key.set_flags(DB_DBT_USERMEM | (keyflags & DB_DBT_PARTIAL));
2114	} else
2115		key.set_flags(DB_DBT_MALLOC | (keyflags & DB_DBT_PARTIAL));
2116
2117	if (flags & (DB_MULTIPLE | DB_MULTIPLE_KEY) ||
2118	    dataflags & DB_DBT_USERMEM) {
2119		if ((ret = __os_umalloc(dbenv->get_ENV(),
2120		    dataulen, &tmpdata)) != 0)
2121			goto err;
2122		if (datadata)
2123			memcpy(tmpdata, datadata,
2124			    (datasize < dataulen) ?
2125			    datasize : dataulen);
2126		data.set_data(tmpdata);
2127		data.set_flags(DB_DBT_USERMEM | (dataflags & DB_DBT_PARTIAL));
2128	} else
2129		data.set_flags(DB_DBT_MALLOC | (dataflags & DB_DBT_PARTIAL));
2130
2131	/* Got all our stuff, now do the get */
2132	ret = dbc->get(&key, &data, flags);
2133
2134	/*
2135	 * Otherwise just status.
2136	 */
2137	if (ret == 0) {
2138		/*
2139		 * XXX
2140		 * We need to xdr_free whatever we are returning, next time.
2141		 * However, DB does not allocate a new key if one was given
2142		 * and we'd be free'ing up space allocated in the request.
2143		 * So, allocate a new key/data pointer if it is the same one
2144		 * as in the request.
2145		 */
2146		*freep = 1;
2147		/*
2148		 * Key
2149		 */
2150		if (key.get_data() == keydata) {
2151			ret = __os_umalloc(dbenv->get_ENV(), key.get_size(),
2152			    &replyp->keydata.keydata_val);
2153			if (ret != 0)
2154				goto err;
2155			memcpy(replyp->keydata.keydata_val,
2156			    key.get_data(), key.get_size());
2157		} else
2158			replyp->keydata.keydata_val = (char *)key.get_data();
2159
2160		replyp->keydata.keydata_len = key.get_size();
2161
2162		/*
2163		 * Data
2164		 */
2165		if (data.get_data() == datadata) {
2166			ret = __os_umalloc(dbenv->get_ENV(), data.get_size(),
2167			    &replyp->datadata.datadata_val);
2168			if (ret != 0)
2169				goto err;
2170			memcpy(replyp->datadata.datadata_val, data.get_data(),
2171			    data.get_size());
2172		} else
2173			replyp->datadata.datadata_val = (char *)data.get_data();
2174		replyp->datadata.datadata_len = data.get_size();
2175	} else {
2176err:		FREE_IF_CHANGED(dbenv->get_ENV(),
2177		    key.get_data(), keydata);
2178		FREE_IF_CHANGED(dbenv->get_ENV(),
2179		    data.get_data(), datadata);
2180		FREE_IF_CHANGED(dbenv->get_ENV(),
2181		    replyp->keydata.keydata_val, key.get_data());
2182		FREE_IF_CHANGED(dbenv->get_ENV(),
2183		    replyp->datadata.datadata_val, data.get_data());
2184		replyp->keydata.keydata_val = NULL;
2185		replyp->keydata.keydata_len = 0;
2186		replyp->datadata.datadata_val = NULL;
2187		replyp->datadata.datadata_len = 0;
2188		*freep = 0;
2189	}
2190	replyp->status = ret;
2191	return;
2192}
2193
2194extern "C" void
2195__dbc_pget_proc(
2196	u_int dbccl_id,
2197	u_int32_t skeydlen,
2198	u_int32_t skeydoff,
2199	u_int32_t skeyulen,
2200	u_int32_t skeyflags,
2201	void *skeydata,
2202	u_int32_t skeysize,
2203	u_int32_t pkeydlen,
2204	u_int32_t pkeydoff,
2205	u_int32_t pkeyulen,
2206	u_int32_t pkeyflags,
2207	void *pkeydata,
2208	u_int32_t pkeysize,
2209	u_int32_t datadlen,
2210	u_int32_t datadoff,
2211	u_int32_t dataulen,
2212	u_int32_t dataflags,
2213	void *datadata,
2214	u_int32_t datasize,
2215	u_int32_t flags,
2216	__dbc_pget_reply *replyp,
2217	int * freep)
2218{
2219	Dbc *dbc;
2220	DbEnv *dbenv;
2221	ct_entry *dbc_ctp;
2222	int ret;
2223
2224	ACTIVATE_CTP(dbc_ctp, dbccl_id, CT_CURSOR);
2225	dbc = (Dbc *)dbc_ctp->ct_anyp;
2226	dbenv = DbEnv::get_DbEnv(((DBC *)dbc)->dbp->dbenv);
2227
2228	replyp->skeydata.skeydata_val = NULL;
2229	replyp->pkeydata.pkeydata_val = NULL;
2230	replyp->datadata.datadata_val = NULL;
2231	*freep = 0;
2232
2233	/*
2234	 * Ignore memory related flags on server.
2235	 */
2236	/* Set up key and data */
2237	Dbt skey(skeydata, skeysize);
2238	skey.set_dlen(skeydlen);
2239	skey.set_ulen(skeyulen);
2240	skey.set_doff(skeydoff);
2241	skey.set_flags(DB_DBT_MALLOC | (skeyflags & DB_DBT_PARTIAL));
2242
2243	Dbt pkey(pkeydata, pkeysize);
2244	pkey.set_dlen(pkeydlen);
2245	pkey.set_ulen(pkeyulen);
2246	pkey.set_doff(pkeydoff);
2247	pkey.set_flags(DB_DBT_MALLOC | (pkeyflags & DB_DBT_PARTIAL));
2248
2249	Dbt data(datadata, datasize);
2250	data.set_dlen(datadlen);
2251	data.set_ulen(dataulen);
2252	data.set_doff(datadoff);
2253	data.set_flags(DB_DBT_MALLOC | (dataflags & DB_DBT_PARTIAL));
2254
2255	/* Got all our stuff, now do the get */
2256	ret = dbc->pget(&skey, &pkey, &data, flags);
2257	/*
2258	 * Otherwise just status.
2259	 */
2260	if (ret == 0) {
2261		/*
2262		 * XXX
2263		 * We need to xdr_free whatever we are returning, next time.
2264		 * However, DB does not allocate a new key if one was given
2265		 * and we'd be free'ing up space allocated in the request.
2266		 * So, allocate a new key/data pointer if it is the same one
2267		 * as in the request.
2268		 */
2269		*freep = 1;
2270		/*
2271		 * Key
2272		 */
2273		if (skey.get_data() == skeydata) {
2274			ret = __os_umalloc(dbenv->get_ENV(),
2275			    skey.get_size(), &replyp->skeydata.skeydata_val);
2276			if (ret != 0)
2277				goto err;
2278			memcpy(replyp->skeydata.skeydata_val, skey.get_data(),
2279			    skey.get_size());
2280		} else
2281			replyp->skeydata.skeydata_val = (char *)skey.get_data();
2282		replyp->skeydata.skeydata_len = skey.get_size();
2283
2284		/*
2285		 * Primary key
2286		 */
2287		if (pkey.get_data() == pkeydata) {
2288			ret = __os_umalloc(dbenv->get_ENV(),
2289			     pkey.get_size(), &replyp->pkeydata.pkeydata_val);
2290			if (ret != 0)
2291				goto err;
2292			memcpy(replyp->pkeydata.pkeydata_val, pkey.get_data(),
2293			    pkey.get_size());
2294		} else
2295			replyp->pkeydata.pkeydata_val = (char *)pkey.get_data();
2296		replyp->pkeydata.pkeydata_len = pkey.get_size();
2297
2298		/*
2299		 * Data
2300		 */
2301		if (data.get_data() == datadata) {
2302			ret = __os_umalloc(dbenv->get_ENV(),
2303			     data.get_size(), &replyp->datadata.datadata_val);
2304			if (ret != 0)
2305				goto err;
2306			memcpy(replyp->datadata.datadata_val, data.get_data(),
2307			    data.get_size());
2308		} else
2309			replyp->datadata.datadata_val = (char *)data.get_data();
2310		replyp->datadata.datadata_len = data.get_size();
2311	} else {
2312err:		FREE_IF_CHANGED(dbenv->get_ENV(),
2313		    skey.get_data(), skeydata);
2314		FREE_IF_CHANGED(dbenv->get_ENV(),
2315		    pkey.get_data(), pkeydata);
2316		FREE_IF_CHANGED(dbenv->get_ENV(),
2317		    data.get_data(), datadata);
2318		FREE_IF_CHANGED(dbenv->get_ENV(),
2319		    replyp->skeydata.skeydata_val, skey.get_data());
2320		FREE_IF_CHANGED(dbenv->get_ENV(),
2321		    replyp->pkeydata.pkeydata_val, pkey.get_data());
2322		FREE_IF_CHANGED(dbenv->get_ENV(),
2323		    replyp->datadata.datadata_val, data.get_data());
2324		replyp->skeydata.skeydata_val = NULL;
2325		replyp->skeydata.skeydata_len = 0;
2326		replyp->pkeydata.pkeydata_val = NULL;
2327		replyp->pkeydata.pkeydata_len = 0;
2328		replyp->datadata.datadata_val = NULL;
2329		replyp->datadata.datadata_len = 0;
2330		*freep = 0;
2331	}
2332	replyp->status = ret;
2333	return;
2334}
2335
2336extern "C" void
2337__dbc_put_proc(
2338	u_int dbccl_id,
2339	u_int32_t keydlen,
2340	u_int32_t keydoff,
2341	u_int32_t keyulen,
2342	u_int32_t keyflags,
2343	void *keydata,
2344	u_int32_t keysize,
2345	u_int32_t datadlen,
2346	u_int32_t datadoff,
2347	u_int32_t dataulen,
2348	u_int32_t dataflags,
2349	void *datadata,
2350	u_int32_t datasize,
2351	u_int32_t flags,
2352	__dbc_put_reply *replyp,
2353	int * freep)
2354{
2355	Db *dbp;
2356	Dbc *dbc;
2357	ct_entry *dbc_ctp;
2358	int ret;
2359	DBTYPE dbtype;
2360
2361	ACTIVATE_CTP(dbc_ctp, dbccl_id, CT_CURSOR);
2362	dbc = (Dbc *)dbc_ctp->ct_anyp;
2363	dbp = (Db *)dbc_ctp->ct_parent->ct_anyp;
2364
2365	/* Set up key and data */
2366	Dbt key(keydata, keysize);
2367	key.set_dlen(keydlen);
2368	key.set_ulen(keyulen);
2369	key.set_doff(keydoff);
2370	/*
2371	 * Ignore memory related flags on server.
2372	 */
2373	key.set_flags(DB_DBT_MALLOC | (keyflags & DB_DBT_PARTIAL));
2374
2375	Dbt data(datadata, datasize);
2376	data.set_dlen(datadlen);
2377	data.set_ulen(dataulen);
2378	data.set_doff(datadoff);
2379	data.set_flags(dataflags);
2380
2381	/* Got all our stuff, now do the put */
2382	ret = dbc->put(&key, &data, flags);
2383
2384	*freep = 0;
2385	replyp->keydata.keydata_val = NULL;
2386	replyp->keydata.keydata_len = 0;
2387	if (ret == 0 && (flags == DB_AFTER || flags == DB_BEFORE)) {
2388		ret = dbp->get_type(&dbtype);
2389		if (ret == 0 && dbtype == DB_RECNO) {
2390			/*
2391			 * We need to xdr_free whatever we are returning, next
2392			 * time.
2393			 */
2394			replyp->keydata.keydata_val = (char *)key.get_data();
2395			replyp->keydata.keydata_len = key.get_size();
2396		}
2397	}
2398	replyp->status = ret;
2399	return;
2400}
2401
2402extern "C" void
2403__dbc_get_priority_proc(
2404	u_int dbccl_id,
2405	__dbc_get_priority_reply *replyp)
2406{
2407	Dbc *dbc;
2408	ct_entry *dbc_ctp;
2409
2410	ACTIVATE_CTP(dbc_ctp, dbccl_id, CT_CURSOR);
2411	dbc = (Dbc *)dbc_ctp->ct_anyp;
2412
2413	replyp->status =
2414	    dbc->get_priority((DB_CACHE_PRIORITY *)&replyp->priority);
2415}
2416
2417extern "C" void
2418__dbc_set_priority_proc(
2419	u_int dbccl_id,
2420	u_int32_t priority,
2421	__dbc_set_priority_reply *replyp)
2422{
2423	Dbc *dbc;
2424	ct_entry *dbc_ctp;
2425	int ret;
2426
2427	ACTIVATE_CTP(dbc_ctp, dbccl_id, CT_CURSOR);
2428	dbc = (Dbc *)dbc_ctp->ct_anyp;
2429
2430	ret = dbc->set_priority((DB_CACHE_PRIORITY)priority);
2431
2432	replyp->status = ret;
2433	return;
2434}
2435