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