Import BSDDB 4.7.25 (as of svn r89086)

This commit is contained in:
Zachary Ware
2017-09-04 13:40:25 -05:00
parent 4b29e0458f
commit 8f590873d0
4781 changed files with 2241032 additions and 6 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,825 @@
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 2000,2008 Oracle. All rights reserved.
*
* $Id: db_server_util.c 63573 2008-05-23 21:43:21Z trent.nelson $
*/
#include "db_config.h"
#include "db_int.h"
#ifdef HAVE_SYSTEM_INCLUDE_FILES
#include <rpc/rpc.h>
#endif
#include "db_server.h"
#include "dbinc_auto/clib_ext.h"
#include "dbinc/db_server_int.h"
#include "dbinc_auto/common_ext.h"
#include "dbinc_auto/rpc_server_ext.h"
static int add_home __P((char *));
static int add_passwd __P((char *));
static int env_recover __P((char *));
static void __dbclear_child __P((ct_entry *));
static LIST_HEAD(cthead, ct_entry) __dbsrv_head;
static LIST_HEAD(homehead, home_entry) __dbsrv_home;
static long __dbsrv_defto = DB_SERVER_TIMEOUT;
static long __dbsrv_maxto = DB_SERVER_MAXTIMEOUT;
static long __dbsrv_idleto = DB_SERVER_IDLETIMEOUT;
static char *logfile = NULL;
static char *prog;
static void usage __P((void));
static void version_check __P((void));
int __dbsrv_verbose = 0;
int
main(argc, argv)
int argc;
char **argv;
{
extern int __dbsrv_main();
extern char *optarg;
CLIENT *cl;
int ch, ret;
char *passwd;
prog = argv[0];
version_check();
ret = 0;
/*
* Check whether another server is running or not. There
* is a race condition where two servers could be racing to
* register with the portmapper. The goal of this check is to
* forbid running additional servers (like those started from
* the test suite) if the user is already running one.
*
* XXX
* This does not solve nor prevent two servers from being
* started at the same time and running recovery at the same
* time on the same environments.
*/
if ((cl = clnt_create("localhost",
DB_RPC_SERVERPROG, DB_RPC_SERVERVERS, "tcp")) != NULL) {
fprintf(stderr,
"%s: Berkeley DB RPC server already running.\n", prog);
clnt_destroy(cl);
return (EXIT_FAILURE);
}
LIST_INIT(&__dbsrv_home);
while ((ch = getopt(argc, argv, "h:I:L:P:t:T:Vv")) != EOF)
switch (ch) {
case 'h':
(void)add_home(optarg);
break;
case 'I':
if (__db_getlong(NULL, prog,
optarg, 1, LONG_MAX, &__dbsrv_idleto))
return (EXIT_FAILURE);
break;
case 'L':
logfile = optarg;
break;
case 'P':
passwd = strdup(optarg);
memset(optarg, 0, strlen(optarg));
if (passwd == NULL) {
fprintf(stderr, "%s: strdup: %s\n",
prog, strerror(errno));
return (EXIT_FAILURE);
}
if ((ret = add_passwd(passwd)) != 0) {
fprintf(stderr, "%s: strdup: %s\n",
prog, strerror(ret));
return (EXIT_FAILURE);
}
break;
case 't':
if (__db_getlong(NULL, prog,
optarg, 1, LONG_MAX, &__dbsrv_defto))
return (EXIT_FAILURE);
break;
case 'T':
if (__db_getlong(NULL, prog,
optarg, 1, LONG_MAX, &__dbsrv_maxto))
return (EXIT_FAILURE);
break;
case 'V':
printf("%s\n", db_version(NULL, NULL, NULL));
return (EXIT_SUCCESS);
case 'v':
__dbsrv_verbose = 1;
break;
default:
usage();
}
/*
* Check default timeout against maximum timeout
*/
if (__dbsrv_defto > __dbsrv_maxto)
__dbsrv_defto = __dbsrv_maxto;
/*
* Check default timeout against idle timeout
* It would be bad to timeout environments sooner than txns.
*/
if (__dbsrv_defto > __dbsrv_idleto)
fprintf(stderr,
"%s: WARNING: Idle timeout %ld is less than resource timeout %ld\n",
prog, __dbsrv_idleto, __dbsrv_defto);
LIST_INIT(&__dbsrv_head);
/*
* If a client crashes during an RPC, our reply to it
* generates a SIGPIPE. Ignore SIGPIPE so we don't exit unnecessarily.
*/
#ifdef SIGPIPE
signal(SIGPIPE, SIG_IGN);
#endif
if (logfile != NULL && __db_util_logset("berkeley_db_svc", logfile))
return (EXIT_FAILURE);
/*
* Now that we are ready to start, run recovery on all the
* environments specified.
*/
if (env_recover(prog) != 0)
return (EXIT_FAILURE);
/*
* We've done our setup, now call the generated server loop
*/
if (__dbsrv_verbose)
printf("%s: Ready to receive requests\n", prog);
__dbsrv_main();
abort();
/* NOTREACHED */
return (0);
}
static void
usage()
{
fprintf(stderr, "usage: %s %s\n\t%s\n", prog,
"[-Vv] [-h home] [-P passwd]",
"[-I idletimeout] [-L logfile] [-t def_timeout] [-T maxtimeout]");
exit(EXIT_FAILURE);
}
static void
version_check()
{
int v_major, v_minor, v_patch;
/* Make sure we're loaded with the right version of the DB library. */
(void)db_version(&v_major, &v_minor, &v_patch);
if (v_major != DB_VERSION_MAJOR ||
v_minor != DB_VERSION_MINOR || v_patch != DB_VERSION_PATCH) {
fprintf(stderr,
"%s: version %d.%d.%d doesn't match library version %d.%d.%d\n",
prog, DB_VERSION_MAJOR, DB_VERSION_MINOR,
DB_VERSION_PATCH, v_major, v_minor, v_patch);
exit(EXIT_FAILURE);
}
}
/*
* PUBLIC: void __dbsrv_settimeout __P((ct_entry *, u_int32_t));
*/
void
__dbsrv_settimeout(ctp, to)
ct_entry *ctp;
u_int32_t to;
{
if (to > (u_int32_t)__dbsrv_maxto)
ctp->ct_timeout = __dbsrv_maxto;
else if (to <= 0)
ctp->ct_timeout = __dbsrv_defto;
else
ctp->ct_timeout = to;
}
/*
* PUBLIC: void __dbsrv_timeout __P((int));
*/
void
__dbsrv_timeout(force)
int force;
{
static long to_hint = -1;
time_t t;
long to;
ct_entry *ctp, *nextctp;
if ((t = time(NULL)) == -1)
return;
/*
* Check hint. If hint is further in the future
* than now, no work to do.
*/
if (!force && to_hint > 0 && t < to_hint)
return;
to_hint = -1;
/*
* Timeout transactions or cursors holding DB resources.
* Do this before timing out envs to properly release resources.
*
* !!!
* We can just loop through this list looking for cursors and txns.
* We do not need to verify txn and cursor relationships at this
* point because we maintain the list in LIFO order *and* we
* maintain activity in the ultimate txn parent of any cursor
* so either everything in a txn is timing out, or nothing.
* So, since we are LIFO, we will correctly close/abort all the
* appropriate handles, in the correct order.
*/
for (ctp = LIST_FIRST(&__dbsrv_head); ctp != NULL; ctp = nextctp) {
nextctp = LIST_NEXT(ctp, entries);
switch (ctp->ct_type) {
case CT_TXN:
to = *(ctp->ct_activep) + ctp->ct_timeout;
/* TIMEOUT */
if (to < t) {
if (__dbsrv_verbose)
printf("Timing out txn id %ld\n",
ctp->ct_id);
(void)((DB_TXN *)ctp->ct_anyp)->
abort((DB_TXN *)ctp->ct_anyp);
__dbdel_ctp(ctp);
/*
* If we timed out an txn, we may have closed
* all sorts of ctp's.
* So start over with a guaranteed good ctp.
*/
nextctp = LIST_FIRST(&__dbsrv_head);
} else if ((to_hint > 0 && to_hint > to) ||
to_hint == -1)
to_hint = to;
break;
case CT_CURSOR:
case (CT_JOINCUR | CT_CURSOR):
to = *(ctp->ct_activep) + ctp->ct_timeout;
/* TIMEOUT */
if (to < t) {
if (__dbsrv_verbose)
printf("Timing out cursor %ld\n",
ctp->ct_id);
(void)__dbc_close_int(ctp);
/*
* Start over with a guaranteed good ctp.
*/
nextctp = LIST_FIRST(&__dbsrv_head);
} else if ((to_hint > 0 && to_hint > to) ||
to_hint == -1)
to_hint = to;
break;
default:
break;
}
}
/*
* Timeout idle handles.
* If we are forcing a timeout, we'll close all env handles.
*/
for (ctp = LIST_FIRST(&__dbsrv_head); ctp != NULL; ctp = nextctp) {
nextctp = LIST_NEXT(ctp, entries);
if (ctp->ct_type != CT_ENV)
continue;
to = *(ctp->ct_activep) + ctp->ct_idle;
/* TIMEOUT */
if (to < t || force) {
if (__dbsrv_verbose)
printf("Timing out env id %ld\n", ctp->ct_id);
(void)__env_close_int(ctp->ct_id, 0, 1);
/*
* If we timed out an env, we may have closed
* all sorts of ctp's (maybe even all of them.
* So start over with a guaranteed good ctp.
*/
nextctp = LIST_FIRST(&__dbsrv_head);
}
}
}
/*
* RECURSIVE FUNCTION. We need to clear/free any number of levels of nested
* layers.
*/
static void
__dbclear_child(parent)
ct_entry *parent;
{
ct_entry *ctp, *nextctp;
for (ctp = LIST_FIRST(&__dbsrv_head); ctp != NULL;
ctp = nextctp) {
nextctp = LIST_NEXT(ctp, entries);
if (ctp->ct_type == 0)
continue;
if (ctp->ct_parent == parent) {
__dbclear_child(ctp);
/*
* Need to do this here because le_next may
* have changed with the recursive call and we
* don't want to point to a removed entry.
*/
nextctp = LIST_NEXT(ctp, entries);
__dbclear_ctp(ctp);
}
}
}
/*
* PUBLIC: void __dbclear_ctp __P((ct_entry *));
*/
void
__dbclear_ctp(ctp)
ct_entry *ctp;
{
LIST_REMOVE(ctp, entries);
__os_free(NULL, ctp);
}
/*
* PUBLIC: void __dbdel_ctp __P((ct_entry *));
*/
void
__dbdel_ctp(parent)
ct_entry *parent;
{
__dbclear_child(parent);
__dbclear_ctp(parent);
}
/*
* PUBLIC: ct_entry *new_ct_ent __P((int *));
*/
ct_entry *
new_ct_ent(errp)
int *errp;
{
time_t t;
ct_entry *ctp, *octp;
int ret;
if ((ret = __os_malloc(NULL, sizeof(ct_entry), &ctp)) != 0) {
*errp = ret;
return (NULL);
}
memset(ctp, 0, sizeof(ct_entry));
/*
* Get the time as ID. We may service more than one request per
* second however. If we are, then increment id value until we
* find an unused one. We insert entries in LRU fashion at the
* head of the list. So, if the first entry doesn't match, then
* we know for certain that we can use our entry.
*/
if ((t = time(NULL)) == -1) {
*errp = __os_get_errno();
__os_free(NULL, ctp);
return (NULL);
}
octp = LIST_FIRST(&__dbsrv_head);
if (octp != NULL && octp->ct_id >= t)
t = octp->ct_id + 1;
ctp->ct_id = (long)t;
ctp->ct_idle = __dbsrv_idleto;
ctp->ct_activep = &ctp->ct_active;
ctp->ct_origp = NULL;
ctp->ct_refcount = 1;
LIST_INSERT_HEAD(&__dbsrv_head, ctp, entries);
return (ctp);
}
/*
* PUBLIC: ct_entry *get_tableent __P((long));
*/
ct_entry *
get_tableent(id)
long id;
{
ct_entry *ctp;
for (ctp = LIST_FIRST(&__dbsrv_head); ctp != NULL;
ctp = LIST_NEXT(ctp, entries))
if (ctp->ct_id == id)
return (ctp);
return (NULL);
}
/*
* PUBLIC: ct_entry *__dbsrv_sharedb __P((ct_entry *, const char *,
* PUBLIC: const char *, DBTYPE, u_int32_t));
*/
ct_entry *
__dbsrv_sharedb(db_ctp, name, subdb, type, flags)
ct_entry *db_ctp;
const char *name, *subdb;
DBTYPE type;
u_int32_t flags;
{
ct_entry *ctp;
/*
* Check if we can share a db handle. Criteria for sharing are:
* If any of the non-sharable flags are set, we cannot share.
* Must be a db ctp, obviously.
* Must share the same env parent.
* Must be the same type, or current one DB_UNKNOWN.
* Must be same byteorder, or current one must not care.
* All flags must match.
* Must be same name, but don't share in-memory databases.
* Must be same subdb name.
*/
if (flags & DB_SERVER_DBNOSHARE)
return (NULL);
for (ctp = LIST_FIRST(&__dbsrv_head); ctp != NULL;
ctp = LIST_NEXT(ctp, entries)) {
/*
* Skip ourselves.
*/
if (ctp == db_ctp)
continue;
if (ctp->ct_type != CT_DB)
continue;
if (ctp->ct_envparent != db_ctp->ct_envparent)
continue;
if (type != DB_UNKNOWN && ctp->ct_dbdp.type != type)
continue;
if (ctp->ct_dbdp.dbflags != LF_ISSET(DB_SERVER_DBFLAGS))
continue;
if (db_ctp->ct_dbdp.setflags != 0 &&
ctp->ct_dbdp.setflags != db_ctp->ct_dbdp.setflags)
continue;
if (name == NULL || ctp->ct_dbdp.db == NULL ||
strcmp(name, ctp->ct_dbdp.db) != 0)
continue;
if (subdb != ctp->ct_dbdp.subdb &&
(subdb == NULL || ctp->ct_dbdp.subdb == NULL ||
strcmp(subdb, ctp->ct_dbdp.subdb) != 0))
continue;
/*
* If we get here, then we match.
*/
ctp->ct_refcount++;
return (ctp);
}
return (NULL);
}
/*
* PUBLIC: ct_entry *__dbsrv_shareenv
* PUBLIC: __P((ct_entry *, home_entry *, u_int32_t));
*/
ct_entry *
__dbsrv_shareenv(env_ctp, home, flags)
ct_entry *env_ctp;
home_entry *home;
u_int32_t flags;
{
ct_entry *ctp;
/*
* Check if we can share an env. Criteria for sharing are:
* Must be an env ctp, obviously.
* Must share the same home env.
* All flags must match.
*/
for (ctp = LIST_FIRST(&__dbsrv_head); ctp != NULL;
ctp = LIST_NEXT(ctp, entries)) {
/*
* Skip ourselves.
*/
if (ctp == env_ctp)
continue;
if (ctp->ct_type != CT_ENV)
continue;
if (ctp->ct_envdp.home != home)
continue;
if (ctp->ct_envdp.envflags != flags)
continue;
if (ctp->ct_envdp.onflags != env_ctp->ct_envdp.onflags)
continue;
if (ctp->ct_envdp.offflags != env_ctp->ct_envdp.offflags)
continue;
/*
* If we get here, then we match. The only thing left to
* check is the timeout. Since the server timeout set by
* the client is a hint, for sharing we'll give them the
* benefit of the doubt and grant them the longer timeout.
*/
if (ctp->ct_timeout < env_ctp->ct_timeout)
ctp->ct_timeout = env_ctp->ct_timeout;
ctp->ct_refcount++;
return (ctp);
}
return (NULL);
}
/*
* PUBLIC: void __dbsrv_active __P((ct_entry *));
*/
void
__dbsrv_active(ctp)
ct_entry *ctp;
{
time_t t;
ct_entry *envctp;
if (ctp == NULL)
return;
if ((t = time(NULL)) == -1)
return;
*(ctp->ct_activep) = t;
if ((envctp = ctp->ct_envparent) == NULL)
return;
*(envctp->ct_activep) = t;
return;
}
/*
* PUBLIC: int __db_close_int __P((long, u_int32_t));
*/
int
__db_close_int(id, flags)
long id;
u_int32_t flags;
{
DB *dbp;
int ret;
ct_entry *ctp;
ctp = get_tableent(id);
if (ctp == NULL)
return (DB_NOSERVER_ID);
if (__dbsrv_verbose && ctp->ct_refcount != 1)
printf("Deref'ing dbp id %ld, refcount %d\n",
id, ctp->ct_refcount);
if (--ctp->ct_refcount != 0)
return (0);
if (__dbsrv_verbose)
printf("Closing dbp id %ld\n", id);
dbp = ctp->ct_dbp;
ret = dbp->close(dbp, flags);
if (ctp->ct_dbdp.db != NULL)
__os_free(NULL, ctp->ct_dbdp.db);
if (ctp->ct_dbdp.subdb != NULL)
__os_free(NULL, ctp->ct_dbdp.subdb);
__dbdel_ctp(ctp);
return (ret);
}
/*
* PUBLIC: int __dbc_close_int __P((ct_entry *));
*/
int
__dbc_close_int(dbc_ctp)
ct_entry *dbc_ctp;
{
DBC *dbc;
int ret;
ct_entry *ctp;
dbc = (DBC *)dbc_ctp->ct_anyp;
ret = dbc->close(dbc);
/*
* If this cursor is a join cursor then we need to fix up the
* cursors that it was joined from so that they are independent again.
*/
if (dbc_ctp->ct_type & CT_JOINCUR)
for (ctp = LIST_FIRST(&__dbsrv_head); ctp != NULL;
ctp = LIST_NEXT(ctp, entries)) {
/*
* Test if it is a join cursor, and if it is part
* of this one.
*/
if ((ctp->ct_type & CT_JOIN) &&
ctp->ct_activep == &dbc_ctp->ct_active) {
ctp->ct_type &= ~CT_JOIN;
ctp->ct_activep = ctp->ct_origp;
__dbsrv_active(ctp);
}
}
__dbclear_ctp(dbc_ctp);
return (ret);
}
/*
* PUBLIC: int __env_close_int __P((long, u_int32_t, int));
*/
int
__env_close_int(id, flags, force)
long id;
u_int32_t flags;
int force;
{
DB_ENV *dbenv;
int ret;
ct_entry *ctp, *dbctp, *nextctp;
ctp = get_tableent(id);
if (ctp == NULL)
return (DB_NOSERVER_ID);
if (__dbsrv_verbose && ctp->ct_refcount != 1)
printf("Deref'ing env id %ld, refcount %d\n",
id, ctp->ct_refcount);
/*
* If we are timing out, we need to force the close, no matter
* what the refcount.
*/
if (--ctp->ct_refcount != 0 && !force)
return (0);
dbenv = ctp->ct_envp;
if (__dbsrv_verbose)
printf("Closing env id %ld\n", id);
/*
* If we're timing out an env, we want to close all of its
* database handles as well. All of the txns and cursors
* must have been timed out prior to timing out the env.
*/
if (force)
for (dbctp = LIST_FIRST(&__dbsrv_head);
dbctp != NULL; dbctp = nextctp) {
nextctp = LIST_NEXT(dbctp, entries);
if (dbctp->ct_type != CT_DB)
continue;
if (dbctp->ct_envparent != ctp)
continue;
/*
* We found a DB handle that is part of this
* environment. Close it.
*/
__db_close_int(dbctp->ct_id, 0);
/*
* If we timed out a dbp, we may have removed
* multiple ctp entries. Start over with a
* guaranteed good ctp.
*/
nextctp = LIST_FIRST(&__dbsrv_head);
}
ret = dbenv->close(dbenv, flags);
__dbdel_ctp(ctp);
return (ret);
}
static int
add_home(home)
char *home;
{
home_entry *hp, *homep;
int ret;
if ((ret = __os_malloc(NULL, sizeof(home_entry), &hp)) != 0)
return (ret);
if ((ret = __os_malloc(NULL, strlen(home)+1, &hp->home)) != 0)
return (ret);
memcpy(hp->home, home, strlen(home)+1);
hp->dir = home;
hp->passwd = NULL;
/*
* This loop is to remove any trailing path separators,
* to assure hp->name points to the last component.
*/
hp->name = __db_rpath(home);
if (hp->name != NULL) {
*(hp->name) = '\0';
hp->name++;
} else
hp->name = home;
while (*(hp->name) == '\0') {
hp->name = __db_rpath(home);
*(hp->name) = '\0';
hp->name++;
}
/*
* Now we have successfully added it. Make sure there are no
* identical names.
*/
for (homep = LIST_FIRST(&__dbsrv_home); homep != NULL;
homep = LIST_NEXT(homep, entries))
if (strcmp(homep->name, hp->name) == 0) {
printf("Already added home name %s, at directory %s\n",
hp->name, homep->dir);
__os_free(NULL, hp->home);
__os_free(NULL, hp);
return (-1);
}
LIST_INSERT_HEAD(&__dbsrv_home, hp, entries);
if (__dbsrv_verbose)
printf("Added home %s in dir %s\n", hp->name, hp->dir);
return (0);
}
static int
add_passwd(passwd)
char *passwd;
{
home_entry *hp;
/*
* We add the passwd to the last given home dir. If there
* isn't a home dir, or the most recent one already has a
* passwd, then there is a user error.
*/
hp = LIST_FIRST(&__dbsrv_home);
if (hp == NULL || hp->passwd != NULL)
return (EINVAL);
/*
* We've already strdup'ed the passwd above, so we don't need
* to malloc new space, just point to it.
*/
hp->passwd = passwd;
return (0);
}
/*
* PUBLIC: home_entry *get_fullhome __P((char *));
*/
home_entry *
get_fullhome(name)
char *name;
{
home_entry *hp;
if (name == NULL)
return (NULL);
for (hp = LIST_FIRST(&__dbsrv_home); hp != NULL;
hp = LIST_NEXT(hp, entries))
if (strcmp(name, hp->name) == 0)
return (hp);
return (NULL);
}
static int
env_recover(progname)
char *progname;
{
DB_ENV *dbenv;
home_entry *hp;
u_int32_t flags;
int exitval, ret;
for (hp = LIST_FIRST(&__dbsrv_home); hp != NULL;
hp = LIST_NEXT(hp, entries)) {
exitval = 0;
if ((ret = db_env_create(&dbenv, 0)) != 0) {
fprintf(stderr, "%s: db_env_create: %s\n",
progname, db_strerror(ret));
exit(EXIT_FAILURE);
}
if (__dbsrv_verbose == 1)
(void)dbenv->set_verbose(dbenv, DB_VERB_RECOVERY, 1);
dbenv->set_errfile(dbenv, stderr);
dbenv->set_errpfx(dbenv, progname);
if (hp->passwd != NULL)
(void)dbenv->set_encrypt(dbenv, hp->passwd,
DB_ENCRYPT_AES);
/*
* Initialize the env with DB_RECOVER. That is all we
* have to do to run recovery.
*/
if (__dbsrv_verbose)
printf("Running recovery on %s\n", hp->home);
flags = DB_CREATE | DB_INIT_LOCK | DB_INIT_LOG | DB_INIT_MPOOL |
DB_INIT_TXN | DB_USE_ENVIRON | DB_RECOVER;
if ((ret = dbenv->open(dbenv, hp->home, flags, 0)) != 0) {
dbenv->err(dbenv, ret, "DB_ENV->open");
goto error;
}
if (0) {
error: exitval = 1;
}
if ((ret = dbenv->close(dbenv, 0)) != 0) {
exitval = 1;
fprintf(stderr, "%s: dbenv->close: %s\n",
progname, db_strerror(ret));
}
if (exitval)
return (exitval);
}
return (0);
}

1273
rpc_server/c/gen_db_server.c Normal file

File diff suppressed because it is too large Load Diff

452
rpc_server/clsrv.html Normal file
View File

@@ -0,0 +1,452 @@
<!doctype html public "-//w3c//dtd html 4.0 transitional//en">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<meta name="GENERATOR" content="Mozilla/4.76 [en] (X11; U; FreeBSD 4.3-RELEASE i386) [Netscape]">
</head>
<body>
<center>
<h1>
&nbsp;Client/Server Interface for Berkeley DB</h1></center>
<center><i>Susan LoVerso</i>
<br><i>Rev 1.3</i>
<br><i>1999 Nov 29</i></center>
<p>We provide an interface allowing client/server access to Berkeley DB.&nbsp;&nbsp;
Our goal is to provide a client and server library to allow users to separate
the functionality of their applications yet still have access to the full
benefits of Berkeley DB.&nbsp; The goal is to provide a totally seamless
interface with minimal modification to existing applications as well.
<p>The client/server interface for Berkeley DB can be broken up into several
layers.&nbsp; At the lowest level there is the transport mechanism to send
out the messages over the network.&nbsp; Above that layer is the messaging
layer to interpret what comes over the wire, and bundle/unbundle message
contents.&nbsp; The next layer is Berkeley DB itself.
<p>The transport layer uses ONC RPC (RFC 1831) and XDR (RFC 1832).&nbsp;
We declare our message types and operations supported by our program and
the RPC library and utilities pretty much take care of the rest.&nbsp;
The
<i>rpcgen</i> program generates all of the low level code needed.&nbsp;
We need to define both sides of the RPC.
<br>&nbsp;
<h2>
<a NAME="DB Modifications"></a>DB Modifications</h2>
To achieve the goal of a seamless interface, it is necessary to impose
a constraint on the application. That constraint is simply that all database
access must be done through an open environment.&nbsp; I.e. this model
does not support standalone databases.&nbsp; The reason for this constraint
is so that we have an environment structure internally to store our connection
to the server.&nbsp; Imposing this constraint means that we can provide
the seamless interface just by adding a single environment method: <a href="../docs/api_c/env_set_rpc_server.html">DBENV->set_rpc_server()</a>.
<p>The planned interface for this method is:
<pre>DBENV->set_rpc_server(dbenv,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* DB_ENV structure */
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; hostname&nbsp;&nbsp;&nbsp; /* Host of server */
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cl_timeout, /* Client timeout (sec) */
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; srv_timeout,/* Server timeout (sec) */
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; flags);&nbsp;&nbsp;&nbsp;&nbsp; /* Flags: unused */</pre>
This new method takes the hostname of the server, establishes our connection
and an environment on the server.&nbsp; If a server timeout is specified,
then we send that to the server as well (and the server may or may not
choose to use that value).&nbsp; This timeout is how long the server will
allow the environment to remain idle before declaring it dead and releasing
resources on the server.&nbsp; The pointer to the connection is stored
on the client in the DBENV structure and is used by all other methods to
figure out with whom to communicate.&nbsp; If a client timeout is specified,
it indicates how long the client is willing to wait for a reply from the
server.&nbsp; If the values are 0, then defaults are used.&nbsp; Flags
is currently unused, but exists because we always need to have a placeholder
for flags and it would be used for specifying authentication desired (were
we to provide an authentication scheme at some point) or other uses not
thought of yet!
<p>This client code is part of the monolithic DB library.&nbsp; The user
accesses the client functions via a new flag to <a href="../docs/api_c/db_env_create.html">db_env_create()</a>.&nbsp;
That flag is DB_CLIENT.&nbsp; By using this flag the user indicates they
want to have the client methods rather than the standard methods for the
environment.&nbsp; Also by issuing this flag, the user needs to connect
to the server via the <a href="../docs/api_c/env_set_rpc_server.html">DBENV->set_rpc_server()</a>
method.
<p>We need two new fields in the <i>DB_ENV </i>structure.&nbsp; One is
the socket descriptor to communicate to the server, the other field is
the client identifier the server gives to us.&nbsp; The <i>DB, </i>and<i>
DBC </i>only need one additional field, the client identifier.&nbsp; The
<i>DB_TXN</i>
structure does not need modification, we are overloading the <i>txn_id
</i>field.
<h2>
Issues</h2>
We need to figure out what to do in case of client and server crashes.&nbsp;
Both the client library and the server program are stateful.&nbsp; They
both consume local resources during the lifetime of the connection.&nbsp;
Should one end drop that connection, the other side needs to release those
resources.
<p>If the server crashes, then the client will get an error back.&nbsp;
I have chosen to implement time-outs on the client side, using a default
or allowing the application to specify one through the <a href="../docs/api_c/env_set_rpc_server.html">DBENV->set_rpc_server()</a>
method.&nbsp; Either the current operation will time-out waiting for the
reply or the next operation called will time out (or get back some other
kind of error regarding the server's non-existence).&nbsp; In any case,
if the client application gets back such an error, it should abort any
open transactions locally, close any databases, and close its environment.&nbsp;
It may then decide to retry to connect to the server periodically or whenever
it comes back.&nbsp; If the last operation a client did was a transaction
commit that did not return or timed out from the server, the client cannot
determine if the transaction was committed or not but must release the
local transaction resources. Once the server is back up, recovery must
be run on the server.&nbsp;&nbsp; If the transaction commit completed on
the server before the crash, then the operation is redone, if the transaction
commit did not get to the server, the pieces of the transaction are undone
on recover.&nbsp; The client can then re-establish its connection and begin
again.&nbsp; This is effectively like beginning over.&nbsp; The client
cannot use ID's from its previous connection to the server.&nbsp; However,
if recovery is run, then consistency is assured.
<p>If the client crashes, the server needs to somehow figure this out.&nbsp;
The server is just sitting there waiting for a request to come in.&nbsp;
A server must be able to time-out a client.&nbsp; Similar to ftpd, if a
connection is idle for N seconds, then the server decides the client is
dead and releases that client's resources, aborting any open transactions,
closing any open databases and environments.&nbsp;&nbsp; The server timing
out a client is not a trivial issue however.&nbsp; The generated function
for the server just calls <i>svc_run()</i>.&nbsp; The server code I write
contains procedures to do specific things.&nbsp; We do not have access
to the code calling <i>select()</i>.&nbsp; Timing out the select is not
good enough even if we could do so.&nbsp; We want to time-out idle environments,
not simply cause a time-out if the server is idle a while.&nbsp; See the
discussion of the <a href="#The Server Program">server program</a> for
a description of how we accomplish this.
<p>Since rpcgen generates the main() function of the server, I do not yet
know how we are going to have the server multi-threaded or multi-process
without changing the generated code.&nbsp; The RPC book indicates that
the only way to accomplish this is through modifying the generated code
in the server.&nbsp; <b>For the moment we will ignore this issue while
we get the core server working, as it is only a performance issue.</b>
<p>We do not do any security or authentication.&nbsp; Someone could get
the code and modify it to spoof messages, trick the server, etc.&nbsp;
RPC has some amount of authentication built into it.&nbsp; I haven't yet
looked into it much to know if we want to use it or just point a user at
it.&nbsp; The changes to the client code are fairly minor, the changes
to our server procs are fairly minor.&nbsp; We would have to add code to
a <i>sed</i> script or <i>awk</i> script to change the generated server
code (yet again) in the dispatch routine to perform authentication.
<p>We will need to get an official program number from Sun.&nbsp; We can
get this by sending mail to <i>rpc@sun.com</i> and presumably at some point
they will send us back a program number that we will encode into our XDR
description file.&nbsp; Until we release this we can use a program number
in the "user defined" number space.
<br>&nbsp;
<h2>
<a NAME="The Server Program"></a>The Server Program</h2>
The server is a standalone program that the user builds and runs, probably
as a daemon like process.&nbsp; This program is linked against the Berkeley
DB library and the RPC library (which is part of the C library on my FreeBSD
machine, others may have/need <i>-lrpclib</i>).&nbsp; The server basically
is a slave to the client process.&nbsp; All messages from the client are
synchronous and two-way.&nbsp; The server handles messages one at a time,
and sends a reply back before getting another message.&nbsp; There are
no asynchronous messages generated by the server to the client.
<p>We have made a choice to modify the generated code for the server.&nbsp;
The changes will be minimal, generally calling functions we write, that
are in other source files.&nbsp; The first change is adding a call to our
time-out function as described below.&nbsp; The second change is changing
the name of the generated <i>main()</i> function to <i>__dbsrv_main()</i>,
and adding our own <i>main()</i> function so that we can parse options,
and set up other initialization we require.&nbsp; I have a <i>sed</i> script
that is run from the distribution scripts that massages the generated code
to make these minor changes.
<p>Primarily the code needed for the server is the collection of the specified
RPC functions.&nbsp; Each function receives the structure indicated, and
our code takes out what it needs and passes the information into DB itself.&nbsp;
The server needs to maintain a translation table for identifiers that we
pass back to the client for the environment, transaction and database handles.
<p>The table that the server maintains, assuming one client per server
process/thread, should contain the handle to the environment, database
or transaction, a link to maintain parent/child relationships between transactions,
or databases and cursors, this handle's identifier, a type so that we can
error if the client passes us a bad id for this call, and a link to this
handle's environment entry (for time out/activity purposes).&nbsp; The
table contains, in entries used by environments, a time-out value and an
activity time stamp.&nbsp; Its use is described below for timing out idle
clients.
<p>Here is how we time out clients in the server.&nbsp; We have to modify
the generated server code, but only to add one line during the dispatch
function to run the time-out function.&nbsp; The call is made right before
the return of the dispatch function, after the reply is sent to the client,
so that client's aren't kept waiting for server bookkeeping activities.&nbsp;
This time-out function then runs every time the server processes a request.&nbsp;
In the time-out function we maintain a time-out hint that is the youngest
environment to time-out.&nbsp; If the current time is less than the hint
we know we do not need to run through the list of open handles.&nbsp; If
the hint is expired, then we go through the list of open environment handles,
and if they are past their expiration, then we close them and clean up.&nbsp;
If they are not, we set up the hint for the next time.
<p>Each entry in the open handle table has a pointer back to its environment's
entry.&nbsp; Every operation within this environment can then update the
single environment activity record.&nbsp; Every environment can have a
different time-out.&nbsp; The <a href="../docs/api_c/env_set_rpc_server.html">DBENV->set_rpc_server
</a>call
takes a server time-out value.&nbsp; If this value is 0 then a default
(currently 5 minutes) is used.&nbsp; This time-out value is only a hint
to the server.&nbsp; It may choose to disregard this value or set the time-out
based on its own implementation.
<p>For completeness, the flaws of this time-out implementation should be
pointed out.&nbsp; First, it is possible that a client could crash with
open handles, and no other requests come in to the server.&nbsp; Therefore
the time-out function never gets run and those resources are not released
(until a request does come in).&nbsp; Similarly, this time-out is not exact.&nbsp;
The time-out function uses its hint and if it computes a hint on one run,
an earlier time-out might be created before that time-out expires.&nbsp;
This issue simply yields a handle that doesn't get released until that
original hint expires.&nbsp; To illustrate, consider that at the time that
the time-out function is run, the youngest time-out is 5 minutes in the
future.&nbsp; Soon after, a new environment is opened that has a time-out
of 1 minute.&nbsp; If this environment becomes idle (and other operations
are going on), the time-out function will not release that environment
until the original 5 minute hint expires.&nbsp; This is not a problem since
the resources will eventually be released.
<p>On a similar note, if a client crashes during an RPC, our reply generates
a SIGPIPE, and our server crashes unless we catch it.&nbsp; Using <i>signal(SIGPIPE,
SIG_IGN) </i>we can ignore it, and the server will go on.&nbsp; This is
a call&nbsp; in our <i>main()</i> function that we write.&nbsp; Eventually
this client's handles would be timed out as described above.&nbsp; We need
this only for the unfortunate window of a client crashing during the RPC.
<p>The options below are primarily for control of the program itself,.&nbsp;
Details relating to databases and environments should be passed from the
client to the server, since the server can serve many clients, many environments
and many databases.&nbsp; Therefore it makes more sense for the client
to set the cache size of its own environment, rather than setting a default
cachesize on the server that applies as a blanket to any environment it
may be called upon to open.&nbsp; Options are:
<ul>
<li>
<b>-t&nbsp;</b> to set the default time-out given to an environment.</li>
<li>
<b>-T</b> to set the maximum time-out allowed for the server.</li>
<li>
<b>-L</b> to log the execution of the server process to a specified file.</li>
<li>
<b>-v</b> to run in verbose mode.</li>
<li>
<b>-M</b>&nbsp; to specify the maximum number of outstanding child server
processes/threads we can have at any given time.&nbsp; The default is 10.
<b>[We
are not yet doing multiple threads/processes.]</b></li>
</ul>
<h2>
The Client Code</h2>
The client code contains all of the supported functions and methods used
in this model.&nbsp; There are several methods in the <i>__db_env
</i>and
<i>__db</i>
structures that currently do not apply, such as the callbacks.&nbsp; Those
fields that are not applicable to the client model point to NULL to notify
the user of their error.&nbsp; Some method functions remain unchanged,
as well such as the error calls.
<p>The client code contains each method function that goes along with the
<a href="#Remote Procedure Calls">RPC
calls</a> described elsewhere.&nbsp; The client library also contains its
own version of <a href="../docs/api_c/env_create.html">db_env_create()</a>,
which does not result in any messages going over to the server (since we
do not yet know what server we are talking to).&nbsp; This function sets
up the pointers to the correct client functions.
<p>All of the method functions that handle the messaging have a basic flow
similar to this:
<ul>
<li>
Local arg parsing that may be needed</li>
<li>
Marshalling the message header and the arguments we need to send to the
server</li>
<li>
Sending the message</li>
<li>
Receiving a reply</li>
<li>
Unmarshalling the reply</li>
<li>
Local results processing that may be needed</li>
</ul>
<h2>
Generated Code</h2>
Almost all of the code is generated from a source file describing the interface
and an <i>awk</i> script.&nbsp;&nbsp; This awk script generates six (6)
files for us.&nbsp; It also modifies one.&nbsp; The files are:
<ol>
<li>
Client file - The C source file created containing the client code.</li>
<li>
Client template file - The C template source file created containing interfaces
for handling client-local issues such as resource allocation, but with
a consistent interface with the client code generated.</li>
<li>
Server file - The C source file created containing the server code.</li>
<li>
Server template file - The C template source file created containing interfaces
for handling server-local issues such as resource allocation, calling into
the DB library but with a consistent interface with the server code generated.</li>
<li>
XDR file - The XDR message description file created.</li>
<li>
Server sed file - A sed script that contains commands to apply to the server
procedure file (i.e. the real source file that the server template file
becomes) so that minor interface changes can be consistently and easily
applied to the real code.</li>
<li>
Server procedure file - This is the file that is modified by the sed script
generated.&nbsp; It originated from the server template file.</li>
</ol>
The awk script reads a source file, <i>db_server/rpc.src </i>that describes
each operation and what sorts of arguments it takes and what it returns
from the server.&nbsp; The syntax of the source file describes the interface
to that operation.&nbsp; There are four (4) parts to the syntax:
<ol>
<li>
<b>BEGIN</b> <b><i>function version# codetype</i></b> - begins a new functional
interface for the given <b><i>function</i></b>.&nbsp; Each function has
a <b><i>version number</i></b>, currently all of them are at version number
one (1).&nbsp; The <b><i>code type</i></b> indicates to the awk script
what kind of code to generate.&nbsp; The choices are:</li>
<ul>
<li>
<b>CODE </b>- Generate all code, and return a status value.&nbsp; If specified,
the client code will simply return the status to the user upon completion
of the RPC call.</li>
<li>
<b>RETCODE </b>- Generate all code and call a return function in the client
template file to deal with client issues or with other returned items.&nbsp;
If specified, the client code generated will call a function of the form
<i>__dbcl_&lt;name>_ret()
</i>where
&lt;name> is replaced with the function name given here.&nbsp; This function
is placed in the template file because this indicates that something special
must occur on return.&nbsp; The arguments to this function are the same
as those for the client function, with the addition of the reply message
structure.</li>
<li>
<b>NOCLNTCODE - </b>Generate XDR and server code, but no corresponding
client code. (This is used for functions that are not named the same thing
on both sides.&nbsp; The only use of this at the moment is db_env_create
and db_create.&nbsp; The environment create call to the server is actually
called from the <a href="../docs/api_c/env_set_rpc_server.html">DBENV->set_rpc_server()</a>
method.&nbsp; The db_create code exists elsewhere in the library and we
modify that code for the client call.)</li>
</ul>
<li>
<b>ARG <i>RPC-type C-type varname [list-type]</i></b>- each line of this
describes an argument to the function.&nbsp; The argument is called <b><i>varname</i></b>.&nbsp;
The <b><i>C-type</i></b> given is what it should look like in the C code
generated, such as <b>DB *, u_int32_t, const char *</b>.&nbsp; The
<b><i>RPC-type</i></b>
is an indication about how the RPC request message should be constructed.&nbsp;
The RPC-types allowed are described below.</li>
<li>
<b>RET <i>RPC-type C-type varname [list-type]</i></b>- each line of this
describes what the server should return from this procedure call (in addition
to a status, which is always returned and should not be specified).&nbsp;
The argument is called <b><i>varname</i></b>.&nbsp; The <b><i>C-type</i></b>
given is what it should look like in the C code generated, such as <b>DB
*, u_int32_t, const char *</b>.&nbsp; The <b><i>RPC-type</i></b> is an
indication about how the RPC reply message should be constructed.&nbsp;
The RPC-types are described below.</li>
<li>
<b>END </b>- End the description of this function.&nbsp; The result is
that when the awk script encounters the <b>END</b> tag, it now has all
the information it needs to construct the generated code for this function.</li>
</ol>
The <b><i>RPC-type</i></b> must be one of the following:
<ul>
<li>
<b>IGNORE </b>- This argument is not passed to the server and should be
ignored when constructing the XDR code.&nbsp; <b>Only allowed for an ARG
specfication.</b></li>
<li>
<b>STRING</b> - This argument is a string.</li>
<li>
<b>INT </b>- This argument is an integer of some sort.</li>
<li>
<b>DBT </b>- This argument is a DBT, resulting in its decomposition into
the request message.</li>
<li>
<b>LIST</b> - This argument is an opaque list passed to the server (NULL-terminated).&nbsp;
If an argument of this type is given, it must have a <b><i>list-type</i></b>
specified that is one of:</li>
<ul>
<li>
<b>STRING</b></li>
<li>
<b>INT</b></li>
<li>
<b>ID</b>.</li>
</ul>
<li>
<b>ID</b> - This argument is an identifier.</li>
</ul>
So, for example, the source for the DB->join RPC call looks like:
<pre>BEGIN&nbsp;&nbsp; dbjoin&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; RETCODE
ARG&nbsp;&nbsp;&nbsp;&nbsp; ID&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; DB *&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; dbp&nbsp;
ARG&nbsp;&nbsp;&nbsp;&nbsp; LIST&nbsp;&nbsp;&nbsp; DBC **&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; curs&nbsp;&nbsp;&nbsp; ID
ARG&nbsp;&nbsp;&nbsp;&nbsp; IGNORE&nbsp; DBC **&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; dbcpp&nbsp;
ARG&nbsp;&nbsp;&nbsp;&nbsp; INT&nbsp;&nbsp;&nbsp;&nbsp; u_int32_t&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; flags
RET&nbsp;&nbsp;&nbsp;&nbsp; ID&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; long&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; dbcid
END</pre>
Our first line tells us we are writing the dbjoin function.&nbsp; It requires
special code on the client so we indicate that with the RETCODE.&nbsp;
This method takes four arguments.&nbsp; For the RPC request we need the
database ID from the dbp, we construct a NULL-terminated list of IDs for
the cursor list, we ignore the argument to return the cursor handle to
the user, and we pass along the flags.&nbsp; On the return, the reply contains
a status, by default, and additionally, it contains the ID of the newly
created cursor.
<h2>
Building and Installing</h2>
I need to verify with Don Anderson, but I believe we should just build
the server program, just like we do for db_stat, db_checkpoint, etc.&nbsp;
Basically it can be treated as a utility program from the building and
installation perspective.
<p>As mentioned early on, in the section on <a href="#DB Modifications">DB
Modifications</a>, we have a single library, but allowing the user to access
the client portion by sending a flag to <a href="../docs/api_c/env_create.html">db_env_create()</a>.&nbsp;
The Makefile is modified to include the new files.
<p>Testing is performed in two ways.&nbsp; First I have a new example program,
that should become part of the example directory.&nbsp; It is basically
a merging of ex_access.c and ex_env.c.&nbsp; This example is adequate to
test basic functionality, as it does just does database put/get calls and
appropriate open and close calls.&nbsp; However, in order to test the full
set of functions a more generalized scheme is required.&nbsp; For the moment,
I am going to modify the Tcl interface to accept the server information.&nbsp;
Nothing else should need to change in Tcl.&nbsp; Then we can either write
our own test modules or use a subset of the existing ones to test functionality
on a regular basis.
</body>
</html>

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,750 @@
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 2000,2008 Oracle. All rights reserved.
*
* $Id: db_server_cxxutil.cpp 63573 2008-05-23 21:43:21Z trent.nelson $
*/
#include "db_config.h"
#include "db_int.h"
#include "db_cxx.h"
#include "db_server.h"
#include "dbinc_auto/clib_ext.h"
extern "C" {
#include "dbinc/db_server_int.h"
#include "dbinc_auto/rpc_server_ext.h"
#include "dbinc_auto/common_ext.h"
extern int __dbsrv_main __P((void));
}
static int add_home __P((char *));
static int add_passwd __P((char *));
static int env_recover __P((char *));
static void __dbclear_child __P((ct_entry *));
static LIST_HEAD(cthead, ct_entry) __dbsrv_head;
static LIST_HEAD(homehead, home_entry) __dbsrv_home;
static long __dbsrv_defto = DB_SERVER_TIMEOUT;
static long __dbsrv_maxto = DB_SERVER_MAXTIMEOUT;
static long __dbsrv_idleto = DB_SERVER_IDLETIMEOUT;
static char *logfile = NULL;
static char *prog;
static void usage __P((char *));
static void version_check __P((void));
int __dbsrv_verbose = 0;
int
main(
int argc,
char **argv)
{
extern char *optarg;
CLIENT *cl;
int ch, ret;
char *passwd;
prog = argv[0];
version_check();
/*
* Check whether another server is running or not. There
* is a race condition where two servers could be racing to
* register with the portmapper. The goal of this check is to
* forbid running additional servers (like those started from
* the test suite) if the user is already running one.
*
* XXX
* This does not solve nor prevent two servers from being
* started at the same time and running recovery at the same
* time on the same environments.
*/
if ((cl = clnt_create("localhost",
DB_RPC_SERVERPROG, DB_RPC_SERVERVERS, "tcp")) != NULL) {
fprintf(stderr,
"%s: Berkeley DB RPC server already running.\n", prog);
clnt_destroy(cl);
return (EXIT_FAILURE);
}
LIST_INIT(&__dbsrv_home);
while ((ch = getopt(argc, argv, "h:I:L:P:t:T:Vv")) != EOF)
switch (ch) {
case 'h':
(void)add_home(optarg);
break;
case 'I':
if (__db_getlong(NULL, prog,
optarg, 1, LONG_MAX, &__dbsrv_idleto))
return (EXIT_FAILURE);
break;
case 'L':
logfile = optarg;
break;
case 'P':
passwd = strdup(optarg);
memset(optarg, 0, strlen(optarg));
if (passwd == NULL) {
fprintf(stderr, "%s: strdup: %s\n",
prog, strerror(errno));
return (EXIT_FAILURE);
}
if ((ret = add_passwd(passwd)) != 0) {
fprintf(stderr, "%s: strdup: %s\n",
prog, strerror(ret));
return (EXIT_FAILURE);
}
break;
case 't':
if (__db_getlong(NULL, prog,
optarg, 1, LONG_MAX, &__dbsrv_defto))
return (EXIT_FAILURE);
break;
case 'T':
if (__db_getlong(NULL, prog,
optarg, 1, LONG_MAX, &__dbsrv_maxto))
return (EXIT_FAILURE);
break;
case 'V':
printf("%s\n", db_version(NULL, NULL, NULL));
return (EXIT_SUCCESS);
case 'v':
__dbsrv_verbose = 1;
break;
default:
usage(prog);
}
/*
* Check default timeout against maximum timeout
*/
if (__dbsrv_defto > __dbsrv_maxto)
__dbsrv_defto = __dbsrv_maxto;
/*
* Check default timeout against idle timeout
* It would be bad to timeout environments sooner than txns.
*/
if (__dbsrv_defto > __dbsrv_idleto)
fprintf(stderr,
"%s: WARNING: Idle timeout %ld is less than resource timeout %ld\n",
prog, __dbsrv_idleto, __dbsrv_defto);
LIST_INIT(&__dbsrv_head);
/*
* If a client crashes during an RPC, our reply to it
* generates a SIGPIPE. Ignore SIGPIPE so we don't exit unnecessarily.
*/
#ifdef SIGPIPE
signal(SIGPIPE, SIG_IGN);
#endif
if (logfile != NULL && __db_util_logset("berkeley_db_svc", logfile))
return (EXIT_FAILURE);
/*
* Now that we are ready to start, run recovery on all the
* environments specified.
*/
if (env_recover(prog) != 0)
return (EXIT_FAILURE);
/*
* We've done our setup, now call the generated server loop
*/
if (__dbsrv_verbose)
printf("%s: Ready to receive requests\n", prog);
__dbsrv_main();
/* NOTREACHED */
abort();
}
static void
usage(char *prog)
{
fprintf(stderr, "usage: %s %s\n\t%s\n", prog,
"[-Vv] [-h home] [-P passwd]",
"[-I idletimeout] [-L logfile] [-t def_timeout] [-T maxtimeout]");
exit(EXIT_FAILURE);
}
static void
version_check()
{
int v_major, v_minor, v_patch;
/* Make sure we're loaded with the right version of the DB library. */
(void)db_version(&v_major, &v_minor, &v_patch);
if (v_major != DB_VERSION_MAJOR ||
v_minor != DB_VERSION_MINOR || v_patch != DB_VERSION_PATCH) {
fprintf(stderr,
"%s: version %d.%d.%d doesn't match library version %d.%d.%d\n",
prog, DB_VERSION_MAJOR, DB_VERSION_MINOR,
DB_VERSION_PATCH, v_major, v_minor, v_patch);
exit(EXIT_FAILURE);
}
}
extern "C" void
__dbsrv_settimeout(
ct_entry *ctp,
u_int32_t to)
{
if (to > (u_int32_t)__dbsrv_maxto)
ctp->ct_timeout = __dbsrv_maxto;
else if (to <= 0)
ctp->ct_timeout = __dbsrv_defto;
else
ctp->ct_timeout = to;
}
extern "C" void
__dbsrv_timeout(int force)
{
static long to_hint = -1;
time_t t;
long to;
ct_entry *ctp, *nextctp;
if ((t = time(NULL)) == -1)
return;
/*
* Check hint. If hint is further in the future
* than now, no work to do.
*/
if (!force && to_hint > 0 && t < to_hint)
return;
to_hint = -1;
/*
* Timeout transactions or cursors holding DB resources.
* Do this before timing out envs to properly release resources.
*
* !!!
* We can just loop through this list looking for cursors and txns.
* We do not need to verify txn and cursor relationships at this
* point because we maintain the list in LIFO order *and* we
* maintain activity in the ultimate txn parent of any cursor
* so either everything in a txn is timing out, or nothing.
* So, since we are LIFO, we will correctly close/abort all the
* appropriate handles, in the correct order.
*/
for (ctp = LIST_FIRST(&__dbsrv_head); ctp != NULL; ctp = nextctp) {
nextctp = LIST_NEXT(ctp, entries);
switch (ctp->ct_type) {
case CT_TXN:
to = *(ctp->ct_activep) + ctp->ct_timeout;
/* TIMEOUT */
if (to < t) {
if (__dbsrv_verbose)
printf("Timing out txn id %ld\n",
ctp->ct_id);
(void)((DbTxn *)ctp->ct_anyp)->abort();
__dbdel_ctp(ctp);
/*
* If we timed out an txn, we may have closed
* all sorts of ctp's.
* So start over with a guaranteed good ctp.
*/
nextctp = LIST_FIRST(&__dbsrv_head);
} else if ((to_hint > 0 && to_hint > to) ||
to_hint == -1)
to_hint = to;
break;
case CT_CURSOR:
case (CT_JOINCUR | CT_CURSOR):
to = *(ctp->ct_activep) + ctp->ct_timeout;
/* TIMEOUT */
if (to < t) {
if (__dbsrv_verbose)
printf("Timing out cursor %ld\n",
ctp->ct_id);
(void)__dbc_close_int(ctp);
/*
* Start over with a guaranteed good ctp.
*/
nextctp = LIST_FIRST(&__dbsrv_head);
} else if ((to_hint > 0 && to_hint > to) ||
to_hint == -1)
to_hint = to;
break;
default:
break;
}
}
/*
* Timeout idle handles.
* If we are forcing a timeout, we'll close all env handles.
*/
for (ctp = LIST_FIRST(&__dbsrv_head); ctp != NULL; ctp = nextctp) {
nextctp = LIST_NEXT(ctp, entries);
if (ctp->ct_type != CT_ENV)
continue;
to = *(ctp->ct_activep) + ctp->ct_idle;
/* TIMEOUT */
if (to < t || force) {
if (__dbsrv_verbose)
printf("Timing out env id %ld\n", ctp->ct_id);
(void)__env_close_int(ctp->ct_id, 0, 1);
/*
* If we timed out an env, we may have closed
* all sorts of ctp's (maybe even all of them.
* So start over with a guaranteed good ctp.
*/
nextctp = LIST_FIRST(&__dbsrv_head);
}
}
}
/*
* RECURSIVE FUNCTION. We need to clear/free any number of levels of nested
* layers.
*/
static void
__dbclear_child(ct_entry *parent)
{
ct_entry *ctp, *nextctp;
for (ctp = LIST_FIRST(&__dbsrv_head); ctp != NULL;
ctp = nextctp) {
nextctp = LIST_NEXT(ctp, entries);
if (ctp->ct_type == 0)
continue;
if (ctp->ct_parent == parent) {
__dbclear_child(ctp);
/*
* Need to do this here because le_next may
* have changed with the recursive call and we
* don't want to point to a removed entry.
*/
nextctp = LIST_NEXT(ctp, entries);
__dbclear_ctp(ctp);
}
}
}
extern "C" void
__dbclear_ctp(ct_entry *ctp)
{
LIST_REMOVE(ctp, entries);
__os_free(NULL, ctp);
}
extern "C" void
__dbdel_ctp(ct_entry *parent)
{
__dbclear_child(parent);
__dbclear_ctp(parent);
}
extern "C" ct_entry *
new_ct_ent(int *errp)
{
time_t t;
ct_entry *ctp, *octp;
int ret;
if ((ret = __os_malloc(NULL, sizeof(ct_entry), &ctp)) != 0) {
*errp = ret;
return (NULL);
}
memset(ctp, 0, sizeof(ct_entry));
/*
* Get the time as ID. We may service more than one request per
* second however. If we are, then increment id value until we
* find an unused one. We insert entries in LRU fashion at the
* head of the list. So, if the first entry doesn't match, then
* we know for certain that we can use our entry.
*/
if ((t = time(NULL)) == -1) {
*errp = __os_get_errno();
__os_free(NULL, ctp);
return (NULL);
}
octp = LIST_FIRST(&__dbsrv_head);
if (octp != NULL && octp->ct_id >= t)
t = octp->ct_id + 1;
ctp->ct_id = t;
ctp->ct_idle = __dbsrv_idleto;
ctp->ct_activep = &ctp->ct_active;
ctp->ct_origp = NULL;
ctp->ct_refcount = 1;
LIST_INSERT_HEAD(&__dbsrv_head, ctp, entries);
return (ctp);
}
extern "C" ct_entry *
get_tableent(long id)
{
ct_entry *ctp;
for (ctp = LIST_FIRST(&__dbsrv_head); ctp != NULL;
ctp = LIST_NEXT(ctp, entries))
if (ctp->ct_id == id)
return (ctp);
return (NULL);
}
extern "C" ct_entry *
__dbsrv_sharedb(ct_entry *db_ctp,
const char *name, const char *subdb, DBTYPE type, u_int32_t flags)
{
ct_entry *ctp;
/*
* Check if we can share a db handle. Criteria for sharing are:
* If any of the non-sharable flags are set, we cannot share.
* Must be a db ctp, obviously.
* Must share the same env parent.
* Must be the same type, or current one DB_UNKNOWN.
* Must be same byteorder, or current one must not care.
* All flags must match.
* Must be same name, but don't share in-memory databases.
* Must be same subdb name.
*/
if (flags & DB_SERVER_DBNOSHARE)
return (NULL);
for (ctp = LIST_FIRST(&__dbsrv_head); ctp != NULL;
ctp = LIST_NEXT(ctp, entries)) {
/*
* Skip ourselves.
*/
if (ctp == db_ctp)
continue;
if (ctp->ct_type != CT_DB)
continue;
if (ctp->ct_envparent != db_ctp->ct_envparent)
continue;
if (type != DB_UNKNOWN && ctp->ct_dbdp.type != type)
continue;
if (ctp->ct_dbdp.dbflags != LF_ISSET(DB_SERVER_DBFLAGS))
continue;
if (db_ctp->ct_dbdp.setflags != 0 &&
ctp->ct_dbdp.setflags != db_ctp->ct_dbdp.setflags)
continue;
if (name == NULL || ctp->ct_dbdp.db == NULL ||
strcmp(name, ctp->ct_dbdp.db) != 0)
continue;
if (subdb != ctp->ct_dbdp.subdb &&
(subdb == NULL || ctp->ct_dbdp.subdb == NULL ||
strcmp(subdb, ctp->ct_dbdp.subdb) != 0))
continue;
/*
* If we get here, then we match.
*/
ctp->ct_refcount++;
return (ctp);
}
return (NULL);
}
extern "C" ct_entry *
__dbsrv_shareenv(ct_entry *env_ctp, home_entry *home, u_int32_t flags)
{
ct_entry *ctp;
/*
* Check if we can share an env. Criteria for sharing are:
* Must be an env ctp, obviously.
* Must share the same home env.
* All flags must match.
*/
for (ctp = LIST_FIRST(&__dbsrv_head); ctp != NULL;
ctp = LIST_NEXT(ctp, entries)) {
/*
* Skip ourselves.
*/
if (ctp == env_ctp)
continue;
if (ctp->ct_type != CT_ENV)
continue;
if (ctp->ct_envdp.home != home)
continue;
if (ctp->ct_envdp.envflags != flags)
continue;
if (ctp->ct_envdp.onflags != env_ctp->ct_envdp.onflags)
continue;
if (ctp->ct_envdp.offflags != env_ctp->ct_envdp.offflags)
continue;
/*
* If we get here, then we match. The only thing left to
* check is the timeout. Since the server timeout set by
* the client is a hint, for sharing we'll give them the
* benefit of the doubt and grant them the longer timeout.
*/
if (ctp->ct_timeout < env_ctp->ct_timeout)
ctp->ct_timeout = env_ctp->ct_timeout;
ctp->ct_refcount++;
return (ctp);
}
return (NULL);
}
extern "C" void
__dbsrv_active(ct_entry *ctp)
{
time_t t;
ct_entry *envctp;
if (ctp == NULL)
return;
if ((t = time(NULL)) == -1)
return;
*(ctp->ct_activep) = t;
if ((envctp = ctp->ct_envparent) == NULL)
return;
*(envctp->ct_activep) = t;
return;
}
extern "C" int
__db_close_int(long id, u_int32_t flags)
{
Db *dbp;
int ret;
ct_entry *ctp;
ret = 0;
ctp = get_tableent(id);
if (ctp == NULL)
return (DB_NOSERVER_ID);
DB_ASSERT(NULL, ctp->ct_type == CT_DB);
if (__dbsrv_verbose && ctp->ct_refcount != 1)
printf("Deref'ing dbp id %ld, refcount %d\n",
id, ctp->ct_refcount);
if (--ctp->ct_refcount != 0)
return (ret);
dbp = ctp->ct_dbp;
if (__dbsrv_verbose)
printf("Closing dbp id %ld\n", id);
ret = dbp->close(flags);
__dbdel_ctp(ctp);
return (ret);
}
extern "C" int
__dbc_close_int(ct_entry *dbc_ctp)
{
Dbc *dbc;
int ret;
ct_entry *ctp;
dbc = (Dbc *)dbc_ctp->ct_anyp;
ret = dbc->close();
/*
* If this cursor is a join cursor then we need to fix up the
* cursors that it was joined from so that they are independent again.
*/
if (dbc_ctp->ct_type & CT_JOINCUR)
for (ctp = LIST_FIRST(&__dbsrv_head); ctp != NULL;
ctp = LIST_NEXT(ctp, entries)) {
/*
* Test if it is a join cursor, and if it is part
* of this one.
*/
if ((ctp->ct_type & CT_JOIN) &&
ctp->ct_activep == &dbc_ctp->ct_active) {
ctp->ct_type &= ~CT_JOIN;
ctp->ct_activep = ctp->ct_origp;
__dbsrv_active(ctp);
}
}
__dbclear_ctp(dbc_ctp);
return (ret);
}
extern "C" int
__env_close_int(long id, u_int32_t flags, int force)
{
DbEnv *dbenv;
int ret;
ct_entry *ctp, *dbctp, *nextctp;
ret = 0;
ctp = get_tableent(id);
if (ctp == NULL)
return (DB_NOSERVER_ID);
DB_ASSERT(NULL, ctp->ct_type == CT_ENV);
if (__dbsrv_verbose && ctp->ct_refcount != 1)
printf("Deref'ing env id %ld, refcount %d\n",
id, ctp->ct_refcount);
/*
* If we are timing out, we need to force the close, no matter
* what the refcount.
*/
if (--ctp->ct_refcount != 0 && !force)
return (ret);
dbenv = ctp->ct_envp;
if (__dbsrv_verbose)
printf("Closing env id %ld\n", id);
/*
* If we're timing out an env, we want to close all of its
* database handles as well. All of the txns and cursors
* must have been timed out prior to timing out the env.
*/
if (force)
for (dbctp = LIST_FIRST(&__dbsrv_head);
dbctp != NULL; dbctp = nextctp) {
nextctp = LIST_NEXT(dbctp, entries);
if (dbctp->ct_type != CT_DB)
continue;
if (dbctp->ct_envparent != ctp)
continue;
/*
* We found a DB handle that is part of this
* environment. Close it.
*/
__db_close_int(dbctp->ct_id, 0);
/*
* If we timed out a dbp, we may have removed
* multiple ctp entries. Start over with a
* guaranteed good ctp.
*/
nextctp = LIST_FIRST(&__dbsrv_head);
}
ret = dbenv->close(flags);
__dbdel_ctp(ctp);
return (ret);
}
static int
add_home(char *home)
{
home_entry *hp, *homep;
int ret;
if ((ret = __os_malloc(NULL, sizeof(home_entry), &hp)) != 0)
return (ret);
if ((ret = __os_malloc(NULL, strlen(home)+1, &hp->home)) != 0)
return (ret);
memcpy(hp->home, home, strlen(home)+1);
hp->dir = home;
hp->passwd = NULL;
/*
* This loop is to remove any trailing path separators,
* to assure hp->name points to the last component.
*/
hp->name = __db_rpath(home);
if (hp->name != NULL) {
*(hp->name) = '\0';
hp->name++;
} else
hp->name = home;
while (*(hp->name) == '\0') {
hp->name = __db_rpath(home);
*(hp->name) = '\0';
hp->name++;
}
/*
* Now we have successfully added it. Make sure there are no
* identical names.
*/
for (homep = LIST_FIRST(&__dbsrv_home); homep != NULL;
homep = LIST_NEXT(homep, entries))
if (strcmp(homep->name, hp->name) == 0) {
printf("Already added home name %s, at directory %s\n",
hp->name, homep->dir);
return (-1);
}
LIST_INSERT_HEAD(&__dbsrv_home, hp, entries);
if (__dbsrv_verbose)
printf("Added home %s in dir %s\n", hp->name, hp->dir);
return (0);
}
static int
add_passwd(char *passwd)
{
home_entry *hp;
/*
* We add the passwd to the last given home dir. If there
* isn't a home dir, or the most recent one already has a
* passwd, then there is a user error.
*/
hp = LIST_FIRST(&__dbsrv_home);
if (hp == NULL || hp->passwd != NULL)
return (EINVAL);
/*
* We've already strdup'ed the passwd above, so we don't need
* to malloc new space, just point to it.
*/
hp->passwd = passwd;
return (0);
}
extern "C" home_entry *
get_fullhome(char *name)
{
home_entry *hp;
if (name == NULL)
return (NULL);
for (hp = LIST_FIRST(&__dbsrv_home); hp != NULL;
hp = LIST_NEXT(hp, entries))
if (strcmp(name, hp->name) == 0)
return (hp);
return (NULL);
}
static int
env_recover(char *progname)
{
DbEnv *dbenv;
home_entry *hp;
u_int32_t flags;
int exitval, ret;
for (hp = LIST_FIRST(&__dbsrv_home); hp != NULL;
hp = LIST_NEXT(hp, entries)) {
exitval = 0;
dbenv = new DbEnv(DB_CXX_NO_EXCEPTIONS);
if (__dbsrv_verbose == 1)
(void)dbenv->set_verbose(DB_VERB_RECOVERY, 1);
dbenv->set_errfile(stderr);
dbenv->set_errpfx(progname);
if (hp->passwd != NULL)
(void)dbenv->set_encrypt(hp->passwd, DB_ENCRYPT_AES);
/*
* Initialize the env with DB_RECOVER. That is all we
* have to do to run recovery.
*/
if (__dbsrv_verbose)
printf("Running recovery on %s\n", hp->home);
flags = DB_CREATE | DB_INIT_LOCK | DB_INIT_LOG | DB_INIT_MPOOL |
DB_INIT_TXN | DB_USE_ENVIRON | DB_RECOVER;
if ((ret = dbenv->open(hp->home, flags, 0)) != 0) {
dbenv->err(ret, "DbEnv->open");
goto error;
}
if (0) {
error: exitval = 1;
}
if ((ret = dbenv->close(0)) != 0) {
exitval = 1;
fprintf(stderr, "%s: dbenv->close: %s\n",
progname, db_strerror(ret));
}
if (exitval)
return (exitval);
}
return (0);
}

946
rpc_server/db_server.x Normal file
View File

@@ -0,0 +1,946 @@
/* Do not edit: automatically built by gen_rpc.awk. */
struct __env_create_msg {
unsigned int timeout;
};
struct __env_create_reply {
/* num return vars: 1 */
int status;
unsigned int envcl_id;
};
struct __env_cdsgroup_begin_msg {
unsigned int dbenvcl_id;
};
struct __env_cdsgroup_begin_reply {
/* num return vars: 1 */
int status;
unsigned int txnidcl_id;
};
struct __env_close_msg {
unsigned int dbenvcl_id;
unsigned int flags;
};
struct __env_close_reply {
/* num return vars: 0 */
int status;
};
struct __env_dbremove_msg {
unsigned int dbenvcl_id;
unsigned int txnpcl_id;
string name<>;
string subdb<>;
unsigned int flags;
};
struct __env_dbremove_reply {
/* num return vars: 0 */
int status;
};
struct __env_dbrename_msg {
unsigned int dbenvcl_id;
unsigned int txnpcl_id;
string name<>;
string subdb<>;
string newname<>;
unsigned int flags;
};
struct __env_dbrename_reply {
/* num return vars: 0 */
int status;
};
struct __env_get_cachesize_msg {
unsigned int dbenvcl_id;
};
struct __env_get_cachesize_reply {
/* num return vars: 3 */
int status;
unsigned int gbytes;
unsigned int bytes;
unsigned int ncache;
};
struct __env_get_encrypt_flags_msg {
unsigned int dbenvcl_id;
};
struct __env_get_encrypt_flags_reply {
/* num return vars: 1 */
int status;
unsigned int flags;
};
struct __env_get_flags_msg {
unsigned int dbenvcl_id;
};
struct __env_get_flags_reply {
/* num return vars: 1 */
int status;
unsigned int flags;
};
struct __env_get_home_msg {
unsigned int dbenvcl_id;
};
struct __env_get_home_reply {
/* num return vars: 1 */
int status;
string home<>;
};
struct __env_get_open_flags_msg {
unsigned int dbenvcl_id;
};
struct __env_get_open_flags_reply {
/* num return vars: 1 */
int status;
unsigned int flags;
};
struct __env_open_msg {
unsigned int dbenvcl_id;
string home<>;
unsigned int flags;
unsigned int mode;
};
struct __env_open_reply {
/* num return vars: 1 */
int status;
unsigned int envcl_id;
};
struct __env_remove_msg {
unsigned int dbenvcl_id;
string home<>;
unsigned int flags;
};
struct __env_remove_reply {
/* num return vars: 0 */
int status;
};
struct __env_set_cachesize_msg {
unsigned int dbenvcl_id;
unsigned int gbytes;
unsigned int bytes;
unsigned int ncache;
};
struct __env_set_cachesize_reply {
/* num return vars: 0 */
int status;
};
struct __env_set_encrypt_msg {
unsigned int dbenvcl_id;
string passwd<>;
unsigned int flags;
};
struct __env_set_encrypt_reply {
/* num return vars: 0 */
int status;
};
struct __env_set_flags_msg {
unsigned int dbenvcl_id;
unsigned int flags;
unsigned int onoff;
};
struct __env_set_flags_reply {
/* num return vars: 0 */
int status;
};
struct __env_txn_begin_msg {
unsigned int dbenvcl_id;
unsigned int parentcl_id;
unsigned int flags;
};
struct __env_txn_begin_reply {
/* num return vars: 1 */
int status;
unsigned int txnidcl_id;
};
struct __env_txn_recover_msg {
unsigned int dbenvcl_id;
unsigned int count;
unsigned int flags;
};
struct __env_txn_recover_reply {
/* num return vars: 3 */
int status;
unsigned int txn<>;
opaque gid<>;
unsigned int retcount;
};
struct __db_create_msg {
unsigned int dbenvcl_id;
unsigned int flags;
};
struct __db_create_reply {
/* num return vars: 1 */
int status;
unsigned int dbcl_id;
};
struct __db_associate_msg {
unsigned int dbpcl_id;
unsigned int txnpcl_id;
unsigned int sdbpcl_id;
unsigned int flags;
};
struct __db_associate_reply {
/* num return vars: 0 */
int status;
};
struct __db_close_msg {
unsigned int dbpcl_id;
unsigned int flags;
};
struct __db_close_reply {
/* num return vars: 0 */
int status;
};
struct __db_cursor_msg {
unsigned int dbpcl_id;
unsigned int txnpcl_id;
unsigned int flags;
};
struct __db_cursor_reply {
/* num return vars: 1 */
int status;
unsigned int dbcidcl_id;
};
struct __db_del_msg {
unsigned int dbpcl_id;
unsigned int txnpcl_id;
unsigned int keydlen;
unsigned int keydoff;
unsigned int keyulen;
unsigned int keyflags;
opaque keydata<>;
unsigned int flags;
};
struct __db_del_reply {
/* num return vars: 0 */
int status;
};
struct __db_get_msg {
unsigned int dbpcl_id;
unsigned int txnpcl_id;
unsigned int keydlen;
unsigned int keydoff;
unsigned int keyulen;
unsigned int keyflags;
opaque keydata<>;
unsigned int datadlen;
unsigned int datadoff;
unsigned int dataulen;
unsigned int dataflags;
opaque datadata<>;
unsigned int flags;
};
struct __db_get_reply {
/* num return vars: 2 */
int status;
opaque keydata<>;
opaque datadata<>;
};
struct __db_get_bt_minkey_msg {
unsigned int dbpcl_id;
};
struct __db_get_bt_minkey_reply {
/* num return vars: 1 */
int status;
unsigned int minkey;
};
struct __db_get_dbname_msg {
unsigned int dbpcl_id;
};
struct __db_get_dbname_reply {
/* num return vars: 2 */
int status;
string filename<>;
string dbname<>;
};
struct __db_get_encrypt_flags_msg {
unsigned int dbpcl_id;
};
struct __db_get_encrypt_flags_reply {
/* num return vars: 1 */
int status;
unsigned int flags;
};
struct __db_get_flags_msg {
unsigned int dbpcl_id;
};
struct __db_get_flags_reply {
/* num return vars: 1 */
int status;
unsigned int flags;
};
struct __db_get_h_ffactor_msg {
unsigned int dbpcl_id;
};
struct __db_get_h_ffactor_reply {
/* num return vars: 1 */
int status;
unsigned int ffactor;
};
struct __db_get_h_nelem_msg {
unsigned int dbpcl_id;
};
struct __db_get_h_nelem_reply {
/* num return vars: 1 */
int status;
unsigned int nelem;
};
struct __db_get_lorder_msg {
unsigned int dbpcl_id;
};
struct __db_get_lorder_reply {
/* num return vars: 1 */
int status;
unsigned int lorder;
};
struct __db_get_open_flags_msg {
unsigned int dbpcl_id;
};
struct __db_get_open_flags_reply {
/* num return vars: 1 */
int status;
unsigned int flags;
};
struct __db_get_pagesize_msg {
unsigned int dbpcl_id;
};
struct __db_get_pagesize_reply {
/* num return vars: 1 */
int status;
unsigned int pagesize;
};
struct __db_get_priority_msg {
unsigned int dbpcl_id;
};
struct __db_get_priority_reply {
/* num return vars: 1 */
int status;
unsigned int priority;
};
struct __db_get_q_extentsize_msg {
unsigned int dbpcl_id;
};
struct __db_get_q_extentsize_reply {
/* num return vars: 1 */
int status;
unsigned int extentsize;
};
struct __db_get_re_delim_msg {
unsigned int dbpcl_id;
};
struct __db_get_re_delim_reply {
/* num return vars: 1 */
int status;
unsigned int delim;
};
struct __db_get_re_len_msg {
unsigned int dbpcl_id;
};
struct __db_get_re_len_reply {
/* num return vars: 1 */
int status;
unsigned int len;
};
struct __db_get_re_pad_msg {
unsigned int dbpcl_id;
};
struct __db_get_re_pad_reply {
/* num return vars: 1 */
int status;
unsigned int pad;
};
struct __db_join_msg {
unsigned int dbpcl_id;
unsigned int curs<>;
unsigned int flags;
};
struct __db_join_reply {
/* num return vars: 1 */
int status;
unsigned int dbcidcl_id;
};
struct __db_key_range_msg {
unsigned int dbpcl_id;
unsigned int txnpcl_id;
unsigned int keydlen;
unsigned int keydoff;
unsigned int keyulen;
unsigned int keyflags;
opaque keydata<>;
unsigned int flags;
};
struct __db_key_range_reply {
/* num return vars: 3 */
int status;
double less;
double equal;
double greater;
};
struct __db_open_msg {
unsigned int dbpcl_id;
unsigned int txnpcl_id;
string name<>;
string subdb<>;
unsigned int type;
unsigned int flags;
unsigned int mode;
};
struct __db_open_reply {
/* num return vars: 3 */
int status;
unsigned int dbcl_id;
unsigned int type;
unsigned int lorder;
};
struct __db_pget_msg {
unsigned int dbpcl_id;
unsigned int txnpcl_id;
unsigned int skeydlen;
unsigned int skeydoff;
unsigned int skeyulen;
unsigned int skeyflags;
opaque skeydata<>;
unsigned int pkeydlen;
unsigned int pkeydoff;
unsigned int pkeyulen;
unsigned int pkeyflags;
opaque pkeydata<>;
unsigned int datadlen;
unsigned int datadoff;
unsigned int dataulen;
unsigned int dataflags;
opaque datadata<>;
unsigned int flags;
};
struct __db_pget_reply {
/* num return vars: 3 */
int status;
opaque skeydata<>;
opaque pkeydata<>;
opaque datadata<>;
};
struct __db_put_msg {
unsigned int dbpcl_id;
unsigned int txnpcl_id;
unsigned int keydlen;
unsigned int keydoff;
unsigned int keyulen;
unsigned int keyflags;
opaque keydata<>;
unsigned int datadlen;
unsigned int datadoff;
unsigned int dataulen;
unsigned int dataflags;
opaque datadata<>;
unsigned int flags;
};
struct __db_put_reply {
/* num return vars: 1 */
int status;
opaque keydata<>;
};
struct __db_remove_msg {
unsigned int dbpcl_id;
string name<>;
string subdb<>;
unsigned int flags;
};
struct __db_remove_reply {
/* num return vars: 0 */
int status;
};
struct __db_rename_msg {
unsigned int dbpcl_id;
string name<>;
string subdb<>;
string newname<>;
unsigned int flags;
};
struct __db_rename_reply {
/* num return vars: 0 */
int status;
};
struct __db_set_bt_minkey_msg {
unsigned int dbpcl_id;
unsigned int minkey;
};
struct __db_set_bt_minkey_reply {
/* num return vars: 0 */
int status;
};
struct __db_set_encrypt_msg {
unsigned int dbpcl_id;
string passwd<>;
unsigned int flags;
};
struct __db_set_encrypt_reply {
/* num return vars: 0 */
int status;
};
struct __db_set_flags_msg {
unsigned int dbpcl_id;
unsigned int flags;
};
struct __db_set_flags_reply {
/* num return vars: 0 */
int status;
};
struct __db_set_h_ffactor_msg {
unsigned int dbpcl_id;
unsigned int ffactor;
};
struct __db_set_h_ffactor_reply {
/* num return vars: 0 */
int status;
};
struct __db_set_h_nelem_msg {
unsigned int dbpcl_id;
unsigned int nelem;
};
struct __db_set_h_nelem_reply {
/* num return vars: 0 */
int status;
};
struct __db_set_lorder_msg {
unsigned int dbpcl_id;
unsigned int lorder;
};
struct __db_set_lorder_reply {
/* num return vars: 0 */
int status;
};
struct __db_set_pagesize_msg {
unsigned int dbpcl_id;
unsigned int pagesize;
};
struct __db_set_pagesize_reply {
/* num return vars: 0 */
int status;
};
struct __db_set_priority_msg {
unsigned int dbpcl_id;
unsigned int priority;
};
struct __db_set_priority_reply {
/* num return vars: 0 */
int status;
};
struct __db_set_q_extentsize_msg {
unsigned int dbpcl_id;
unsigned int extentsize;
};
struct __db_set_q_extentsize_reply {
/* num return vars: 0 */
int status;
};
struct __db_set_re_delim_msg {
unsigned int dbpcl_id;
unsigned int delim;
};
struct __db_set_re_delim_reply {
/* num return vars: 0 */
int status;
};
struct __db_set_re_len_msg {
unsigned int dbpcl_id;
unsigned int len;
};
struct __db_set_re_len_reply {
/* num return vars: 0 */
int status;
};
struct __db_set_re_pad_msg {
unsigned int dbpcl_id;
unsigned int pad;
};
struct __db_set_re_pad_reply {
/* num return vars: 0 */
int status;
};
struct __db_stat_msg {
unsigned int dbpcl_id;
unsigned int txnpcl_id;
unsigned int flags;
};
struct __db_stat_reply {
/* num return vars: 1 */
int status;
unsigned int stats<>;
};
struct __db_sync_msg {
unsigned int dbpcl_id;
unsigned int flags;
};
struct __db_sync_reply {
/* num return vars: 0 */
int status;
};
struct __db_truncate_msg {
unsigned int dbpcl_id;
unsigned int txnpcl_id;
unsigned int flags;
};
struct __db_truncate_reply {
/* num return vars: 1 */
int status;
unsigned int count;
};
struct __dbc_close_msg {
unsigned int dbccl_id;
};
struct __dbc_close_reply {
/* num return vars: 0 */
int status;
};
struct __dbc_count_msg {
unsigned int dbccl_id;
unsigned int flags;
};
struct __dbc_count_reply {
/* num return vars: 1 */
int status;
unsigned int dupcount;
};
struct __dbc_del_msg {
unsigned int dbccl_id;
unsigned int flags;
};
struct __dbc_del_reply {
/* num return vars: 0 */
int status;
};
struct __dbc_dup_msg {
unsigned int dbccl_id;
unsigned int flags;
};
struct __dbc_dup_reply {
/* num return vars: 1 */
int status;
unsigned int dbcidcl_id;
};
struct __dbc_get_msg {
unsigned int dbccl_id;
unsigned int keydlen;
unsigned int keydoff;
unsigned int keyulen;
unsigned int keyflags;
opaque keydata<>;
unsigned int datadlen;
unsigned int datadoff;
unsigned int dataulen;
unsigned int dataflags;
opaque datadata<>;
unsigned int flags;
};
struct __dbc_get_reply {
/* num return vars: 2 */
int status;
opaque keydata<>;
opaque datadata<>;
};
struct __dbc_get_priority_msg {
unsigned int dbccl_id;
};
struct __dbc_get_priority_reply {
/* num return vars: 1 */
int status;
unsigned int priority;
};
struct __dbc_pget_msg {
unsigned int dbccl_id;
unsigned int skeydlen;
unsigned int skeydoff;
unsigned int skeyulen;
unsigned int skeyflags;
opaque skeydata<>;
unsigned int pkeydlen;
unsigned int pkeydoff;
unsigned int pkeyulen;
unsigned int pkeyflags;
opaque pkeydata<>;
unsigned int datadlen;
unsigned int datadoff;
unsigned int dataulen;
unsigned int dataflags;
opaque datadata<>;
unsigned int flags;
};
struct __dbc_pget_reply {
/* num return vars: 3 */
int status;
opaque skeydata<>;
opaque pkeydata<>;
opaque datadata<>;
};
struct __dbc_put_msg {
unsigned int dbccl_id;
unsigned int keydlen;
unsigned int keydoff;
unsigned int keyulen;
unsigned int keyflags;
opaque keydata<>;
unsigned int datadlen;
unsigned int datadoff;
unsigned int dataulen;
unsigned int dataflags;
opaque datadata<>;
unsigned int flags;
};
struct __dbc_put_reply {
/* num return vars: 1 */
int status;
opaque keydata<>;
};
struct __dbc_set_priority_msg {
unsigned int dbccl_id;
unsigned int priority;
};
struct __dbc_set_priority_reply {
/* num return vars: 0 */
int status;
};
struct __txn_abort_msg {
unsigned int txnpcl_id;
};
struct __txn_abort_reply {
/* num return vars: 0 */
int status;
};
struct __txn_commit_msg {
unsigned int txnpcl_id;
unsigned int flags;
};
struct __txn_commit_reply {
/* num return vars: 0 */
int status;
};
struct __txn_discard_msg {
unsigned int txnpcl_id;
unsigned int flags;
};
struct __txn_discard_reply {
/* num return vars: 0 */
int status;
};
struct __txn_prepare_msg {
unsigned int txnpcl_id;
opaque gid[128];
};
struct __txn_prepare_reply {
/* num return vars: 0 */
int status;
};
program DB_RPC_SERVERPROG {
version DB_RPC_SERVERVERS {
__env_create_reply __DB_env_create(__env_create_msg) = 1;
__env_cdsgroup_begin_reply __DB_env_cdsgroup_begin(__env_cdsgroup_begin_msg) = 2;
__env_close_reply __DB_env_close(__env_close_msg) = 3;
__env_dbremove_reply __DB_env_dbremove(__env_dbremove_msg) = 4;
__env_dbrename_reply __DB_env_dbrename(__env_dbrename_msg) = 5;
__env_get_cachesize_reply __DB_env_get_cachesize(__env_get_cachesize_msg) = 6;
__env_get_encrypt_flags_reply __DB_env_get_encrypt_flags(__env_get_encrypt_flags_msg) = 7;
__env_get_flags_reply __DB_env_get_flags(__env_get_flags_msg) = 8;
__env_get_home_reply __DB_env_get_home(__env_get_home_msg) = 9;
__env_get_open_flags_reply __DB_env_get_open_flags(__env_get_open_flags_msg) = 10;
__env_open_reply __DB_env_open(__env_open_msg) = 11;
__env_remove_reply __DB_env_remove(__env_remove_msg) = 12;
__env_set_cachesize_reply __DB_env_set_cachesize(__env_set_cachesize_msg) = 13;
__env_set_encrypt_reply __DB_env_set_encrypt(__env_set_encrypt_msg) = 14;
__env_set_flags_reply __DB_env_set_flags(__env_set_flags_msg) = 15;
__env_txn_begin_reply __DB_env_txn_begin(__env_txn_begin_msg) = 16;
__env_txn_recover_reply __DB_env_txn_recover(__env_txn_recover_msg) = 17;
__db_create_reply __DB_db_create(__db_create_msg) = 18;
__db_associate_reply __DB_db_associate(__db_associate_msg) = 19;
__db_close_reply __DB_db_close(__db_close_msg) = 20;
__db_cursor_reply __DB_db_cursor(__db_cursor_msg) = 21;
__db_del_reply __DB_db_del(__db_del_msg) = 22;
__db_get_reply __DB_db_get(__db_get_msg) = 23;
__db_get_bt_minkey_reply __DB_db_get_bt_minkey(__db_get_bt_minkey_msg) = 24;
__db_get_dbname_reply __DB_db_get_dbname(__db_get_dbname_msg) = 25;
__db_get_encrypt_flags_reply __DB_db_get_encrypt_flags(__db_get_encrypt_flags_msg) = 26;
__db_get_flags_reply __DB_db_get_flags(__db_get_flags_msg) = 27;
__db_get_h_ffactor_reply __DB_db_get_h_ffactor(__db_get_h_ffactor_msg) = 28;
__db_get_h_nelem_reply __DB_db_get_h_nelem(__db_get_h_nelem_msg) = 29;
__db_get_lorder_reply __DB_db_get_lorder(__db_get_lorder_msg) = 30;
__db_get_open_flags_reply __DB_db_get_open_flags(__db_get_open_flags_msg) = 31;
__db_get_pagesize_reply __DB_db_get_pagesize(__db_get_pagesize_msg) = 32;
__db_get_priority_reply __DB_db_get_priority(__db_get_priority_msg) = 33;
__db_get_q_extentsize_reply __DB_db_get_q_extentsize(__db_get_q_extentsize_msg) = 34;
__db_get_re_delim_reply __DB_db_get_re_delim(__db_get_re_delim_msg) = 35;
__db_get_re_len_reply __DB_db_get_re_len(__db_get_re_len_msg) = 36;
__db_get_re_pad_reply __DB_db_get_re_pad(__db_get_re_pad_msg) = 37;
__db_join_reply __DB_db_join(__db_join_msg) = 38;
__db_key_range_reply __DB_db_key_range(__db_key_range_msg) = 39;
__db_open_reply __DB_db_open(__db_open_msg) = 40;
__db_pget_reply __DB_db_pget(__db_pget_msg) = 41;
__db_put_reply __DB_db_put(__db_put_msg) = 42;
__db_remove_reply __DB_db_remove(__db_remove_msg) = 43;
__db_rename_reply __DB_db_rename(__db_rename_msg) = 44;
__db_set_bt_minkey_reply __DB_db_set_bt_minkey(__db_set_bt_minkey_msg) = 45;
__db_set_encrypt_reply __DB_db_set_encrypt(__db_set_encrypt_msg) = 46;
__db_set_flags_reply __DB_db_set_flags(__db_set_flags_msg) = 47;
__db_set_h_ffactor_reply __DB_db_set_h_ffactor(__db_set_h_ffactor_msg) = 48;
__db_set_h_nelem_reply __DB_db_set_h_nelem(__db_set_h_nelem_msg) = 49;
__db_set_lorder_reply __DB_db_set_lorder(__db_set_lorder_msg) = 50;
__db_set_pagesize_reply __DB_db_set_pagesize(__db_set_pagesize_msg) = 51;
__db_set_priority_reply __DB_db_set_priority(__db_set_priority_msg) = 52;
__db_set_q_extentsize_reply __DB_db_set_q_extentsize(__db_set_q_extentsize_msg) = 53;
__db_set_re_delim_reply __DB_db_set_re_delim(__db_set_re_delim_msg) = 54;
__db_set_re_len_reply __DB_db_set_re_len(__db_set_re_len_msg) = 55;
__db_set_re_pad_reply __DB_db_set_re_pad(__db_set_re_pad_msg) = 56;
__db_stat_reply __DB_db_stat(__db_stat_msg) = 57;
__db_sync_reply __DB_db_sync(__db_sync_msg) = 58;
__db_truncate_reply __DB_db_truncate(__db_truncate_msg) = 59;
__dbc_close_reply __DB_dbc_close(__dbc_close_msg) = 60;
__dbc_count_reply __DB_dbc_count(__dbc_count_msg) = 61;
__dbc_del_reply __DB_dbc_del(__dbc_del_msg) = 62;
__dbc_dup_reply __DB_dbc_dup(__dbc_dup_msg) = 63;
__dbc_get_reply __DB_dbc_get(__dbc_get_msg) = 64;
__dbc_get_priority_reply __DB_dbc_get_priority(__dbc_get_priority_msg) = 65;
__dbc_pget_reply __DB_dbc_pget(__dbc_pget_msg) = 66;
__dbc_put_reply __DB_dbc_put(__dbc_put_msg) = 67;
__dbc_set_priority_reply __DB_dbc_set_priority(__dbc_set_priority_msg) = 68;
__txn_abort_reply __DB_txn_abort(__txn_abort_msg) = 69;
__txn_commit_reply __DB_txn_commit(__txn_commit_msg) = 70;
__txn_discard_reply __DB_txn_discard(__txn_discard_msg) = 71;
__txn_prepare_reply __DB_txn_prepare(__txn_prepare_msg) = 72;
} = 4007;
} = 351457;

648
rpc_server/rpc.src Normal file
View File

@@ -0,0 +1,648 @@
# See the file LICENSE for redistribution information.
#
# Copyright (c) 1999,2008 Oracle. All rights reserved.
#
# $Id: rpc.src,v 12.38 2008/05/09 17:06:02 bschmeck Exp $
#
# Syntax:
# BEGIN function_name {CODE | LINKONLY | RETCODE}
# CODE: generate XDR and client code, return status
# Used for functions that just return a status and nothing else.
# RETCODE:generate XDR and client code, call return function
# (generate template return function)
# Used for functions that returns data.
# LINKONLY:
# No code needs to be generated, the function is hand-coded.
#
# ARG {IGNORE | STRING | INT | DBT | LIST | ID | CONST} C-type varname
# IGNORE: not passed to server
# STRING: string passed to server
# DBT: DBT arg passed to server
# LIST: list passed to server (NULL-terminated list of something)
# INT: integer passed to server
# ID: cl_id from arg passed to server
# GID: global id passed to server
# CONST: do not generate COMPQUIET (for NOFUNC only)
# FUNCPROT prototype
# FUNCARG functiontype
# These two *MUST* go together and FUNCPROT *MUST* be first. These
# are for the tricky user-supplied functions to some methods. They
# are not supported in RPC, so will be ignored, but the complicated
# syntax of their argument requires we have a special flag for them
# that contains the verbatim text to use in the prototype and the
# c-type, respectively. The FUNCARG must include the function, and
# must call it 'funcN', where N is the count of functions. Almost
# always it must be func0. A *very* few methods have more than one
# user-supplied functions, in those cases, it must be func0, func1, etc.
#
# All messages automatically return "status" and return that from
# the call to the function. RET's are additional things the server
# may return. RET is like ARG but does not need the IGNORE option.
# ARETs are RETs which are returned in arguments by the client.
# {RET | ARET} {STRING | INT | DBT | LIST | ID} varname [GID | INT | ID]
# STRING: string from server
# DBT: DBT arg from server
# LIST: list from server (NULL-terminated list)
# Must have list type of GID, ID or INT specified
# INT: integer from server
# ID: id from server stored in cl_id
# END function end.
#
# NOFUNC function_name prototype
# Connect the method to an "unsupported function" error message.
######################################################
# DB_ENV handle create.
######################################################
BEGIN env_create RETCODE
ARG IGNORE DB_ENV * dbenv
ARG INT long timeout
RET ID long env
END
######################################################
# DB_ENV handle methods.
######################################################
BEGIN env_cdsgroup_begin RETCODE
ARG ID DB_ENV * dbenv
ARG IGNORE DB_TXN ** txnpp
RET ID long txnid
END
BEGIN env_close CODE
ARG ID DB_ENV * dbenv
ARG INT u_int32_t flags
END
BEGIN env_dbremove CODE
ARG ID DB_ENV * dbenv
ARG ID DB_TXN * txnp
ARG STRING const char * name
ARG STRING const char * subdb
ARG INT u_int32_t flags
END
BEGIN env_dbrename CODE
ARG ID DB_ENV * dbenv
ARG ID DB_TXN * txnp
ARG STRING const char * name
ARG STRING const char * subdb
ARG STRING const char * newname
ARG INT u_int32_t flags
END
LOCAL env_err
LOCAL env_errx
NOFUNC env_failchk DB_ENV *, u_int32_t
NOFUNC env_fileid_reset DB_ENV *, const char *, u_int32_t
NOFUNC env_get_cache_max DB_ENV *, u_int32_t *, u_int32_t *
BEGIN env_get_cachesize CODE
ARG ID DB_ENV * dbenv
ARET INT u_int32_t gbytes
ARET INT u_int32_t bytes
ARET INT int ncache
END
NOFUNC env_get_data_dirs DB_ENV *, const char ***
BEGIN env_get_encrypt_flags CODE
ARG ID DB_ENV * dbenv
ARET INT u_int32_t flags
END
LOCAL env_get_errcall
LOCAL env_get_errfile
LOCAL env_get_errpfx
BEGIN env_get_flags CODE
ARG ID DB_ENV * dbenv
ARET INT u_int32_t flags
END
BEGIN env_get_home CODE
ARG ID DB_ENV * dbenv
ARET STRING const char * home
END
NOFUNC env_get_intermediate_dir_mode DB_ENV *, const char **
NOFUNC env_get_lg_bsize DB_ENV *, u_int32_t *
NOFUNC env_get_lg_dir DB_ENV *, const char **
NOFUNC env_get_lg_filemode DB_ENV *, int *
NOFUNC env_get_lg_max DB_ENV *, u_int32_t *
NOFUNC env_get_lg_regionmax DB_ENV *, u_int32_t *
NOFUNC env_get_lk_conflicts DB_ENV *, const u_int8_t **, int *
NOFUNC env_get_lk_detect DB_ENV *, u_int32_t *
NOFUNC env_get_lk_max_lockers DB_ENV *, u_int32_t *
NOFUNC env_get_lk_max_locks DB_ENV *, u_int32_t *
NOFUNC env_get_lk_max_objects DB_ENV *, u_int32_t *
NOFUNC env_get_lk_partitions DB_ENV *, u_int32_t *
NOFUNC env_get_mp_max_openfd DB_ENV *, int *
NOFUNC env_get_mp_max_write DB_ENV *, int *, db_timeout_t *
NOFUNC env_get_mp_mmapsize DB_ENV *, size_t *
LOCAL env_get_msgfile
BEGIN env_get_open_flags CODE
ARG ID DB_ENV * dbenv
ARET INT u_int32_t flags
END
NOFUNC env_get_shm_key DB_ENV *, long *
NOFUNC env_get_thread_count DB_ENV *, u_int32_t *
NOFUNC env_get_timeout DB_ENV *, db_timeout_t *, u_int32_t
NOFUNC env_get_tmp_dir DB_ENV *, const char **
NOFUNC env_get_tx_max DB_ENV *, u_int32_t *
NOFUNC env_get_tx_timestamp DB_ENV *, time_t *
NOFUNC env_get_verbose DB_ENV *, u_int32_t, int *
LOCAL env_is_bigendian
NOFUNC env_lock_detect DB_ENV *, u_int32_t, u_int32_t, int *
NOFUNC env_lock_get DB_ENV *, u_int32_t, u_int32_t, const DBT *, db_lockmode_t, DB_LOCK *
NOFUNC env_lock_id DB_ENV *, u_int32_t *
NOFUNC env_lock_id_free DB_ENV *, u_int32_t
NOFUNC env_lock_put DB_ENV *, DB_LOCK *
NOFUNC env_lock_stat DB_ENV *, DB_LOCK_STAT **, u_int32_t
NOFUNC env_lock_stat_print DB_ENV *, u_int32_t
NOFUNC env_lock_vec DB_ENV *, u_int32_t, u_int32_t, DB_LOCKREQ *, int, DB_LOCKREQ **
NOFUNC env_log_archive DB_ENV *, char ***, u_int32_t
NOFUNC env_log_cursor DB_ENV *, DB_LOGC **, u_int32_t
NOFUNC env_log_file DB_ENV *, const DB_LSN *, char *, size_t
NOFUNC env_log_flush DB_ENV *, const DB_LSN *
NOFUNC env_log_get_config DB_ENV *, u_int32_t, int *
NOFUNC env_log_printf DB_ENV *, DB_TXN *, const char *, ...
NOFUNC env_log_put DB_ENV *, DB_LSN *, const DBT *, u_int32_t
NOFUNC env_log_set_config DB_ENV *, u_int32_t, int
NOFUNC env_log_stat DB_ENV *, DB_LOG_STAT **, u_int32_t
NOFUNC env_log_stat_print DB_ENV *, u_int32_t
NOFUNC env_lsn_reset DB_ENV *, const char *, u_int32_t
NOFUNC env_memp_fcreate DB_ENV *, DB_MPOOLFILE **, u_int32_t
NOFUNC env_memp_register DB_ENV *, int, int (*)(DB_ENV *, db_pgno_t, void *, DBT *), int (*)(DB_ENV *, db_pgno_t, void *, DBT *)
NOFUNC env_memp_stat DB_ENV *, DB_MPOOL_STAT **, DB_MPOOL_FSTAT ***, u_int32_t
NOFUNC env_memp_stat_print DB_ENV *, u_int32_t
NOFUNC env_memp_sync DB_ENV *, DB_LSN *
NOFUNC env_memp_trickle DB_ENV *, int, int *
NOFUNC env_mutex_alloc DB_ENV *, u_int32_t, u_int32_t *
NOFUNC env_mutex_free DB_ENV *, u_int32_t
NOFUNC env_mutex_get_align DB_ENV *, u_int32_t *
NOFUNC env_mutex_get_increment DB_ENV *, u_int32_t *
NOFUNC env_mutex_get_max DB_ENV *, u_int32_t *
NOFUNC env_mutex_get_tas_spins DB_ENV *, u_int32_t *
NOFUNC env_mutex_lock DB_ENV *, u_int32_t
NOFUNC env_mutex_set_align DB_ENV *, u_int32_t
NOFUNC env_mutex_set_increment DB_ENV *, u_int32_t
NOFUNC env_mutex_set_max DB_ENV *, u_int32_t
NOFUNC env_mutex_set_tas_spins DB_ENV *, u_int32_t
NOFUNC env_mutex_stat DB_ENV *, DB_MUTEX_STAT **, u_int32_t
NOFUNC env_mutex_stat_print DB_ENV *, u_int32_t
NOFUNC env_mutex_unlock DB_ENV *, u_int32_t
BEGIN env_open RETCODE
ARG ID DB_ENV * dbenv
ARG STRING const char * home
ARG INT u_int32_t flags
ARG INT int mode
RET ID long env
END
BEGIN env_remove RETCODE
ARG ID DB_ENV * dbenv
ARG STRING const char * home
ARG INT u_int32_t flags
END
NOFUNC env_rep_elect DB_ENV *, u_int32_t, u_int32_t, u_int32_t
NOFUNC env_rep_flush DB_ENV *
NOFUNC env_rep_get_clockskew DB_ENV *, u_int32_t *, u_int32_t *
NOFUNC env_rep_get_config DB_ENV *, u_int32_t, int *
NOFUNC env_rep_get_limit DB_ENV *, u_int32_t *, u_int32_t *
NOFUNC env_rep_get_nsites DB_ENV *, u_int32_t *
NOFUNC env_rep_get_priority DB_ENV *, u_int32_t *
NOFUNC env_rep_get_request DB_ENV *, u_int32_t *, u_int32_t *
NOFUNC env_rep_get_timeout DB_ENV *, int, db_timeout_t *
NOFUNC env_rep_process_message DB_ENV *, DBT *, DBT *, int, DB_LSN *
NOFUNC env_rep_set_clockskew DB_ENV *, u_int32_t, u_int32_t
NOFUNC env_rep_set_config DB_ENV *, u_int32_t, int
NOFUNC env_rep_set_limit DB_ENV *, u_int32_t, u_int32_t
NOFUNC env_rep_set_nsites DB_ENV *, u_int32_t
NOFUNC env_rep_set_priority DB_ENV *, u_int32_t
NOFUNC env_rep_set_request DB_ENV *, u_int32_t, u_int32_t
NOFUNC env_rep_set_timeout DB_ENV *, int, db_timeout_t
NOFUNC env_rep_set_transport DB_ENV *, int, int (*)(DB_ENV *, const DBT *, const DBT *, const DB_LSN *, int, u_int32_t)
NOFUNC env_rep_start DB_ENV *, DBT *, u_int32_t
NOFUNC env_rep_stat DB_ENV *, DB_REP_STAT **, u_int32_t
NOFUNC env_rep_stat_print DB_ENV *, u_int32_t
NOFUNC env_rep_sync DB_ENV *, u_int32_t
NOFUNC env_repmgr_add_remote_site DB_ENV *, const char *, u_int, int *, u_int32_t
NOFUNC env_repmgr_get_ack_policy DB_ENV *, int *
NOFUNC env_repmgr_set_ack_policy DB_ENV *, int
NOFUNC env_repmgr_set_local_site DB_ENV *, const char *, u_int, u_int32_t
NOFUNC env_repmgr_site_list DB_ENV *, u_int *, DB_REPMGR_SITE **
NOFUNC env_repmgr_start DB_ENV *, int, u_int32_t
NOFUNC env_repmgr_stat DB_ENV *, DB_REPMGR_STAT **, u_int32_t
NOFUNC env_repmgr_stat_print DB_ENV *, u_int32_t
NOFUNC env_set_alloc DB_ENV *, void *(*)(size_t), void *(*)(void *, size_t), void (*)(void *)
NOFUNC env_set_app_dispatch DB_ENV *, int (*)(DB_ENV *, DBT *, DB_LSN *, db_recops)
NOFUNC env_set_cache_max DB_ENV *, u_int32_t, u_int32_t
BEGIN env_set_cachesize CODE
ARG ID DB_ENV * dbenv
ARG INT u_int32_t gbytes
ARG INT u_int32_t bytes
ARG INT int ncache
END
NOFUNC env_set_data_dir DB_ENV *, const char *
BEGIN env_set_encrypt CODE
ARG ID DB_ENV * dbenv
ARG STRING const char * passwd
ARG INT u_int32_t flags
END
LOCAL env_set_errcall
LOCAL env_set_errfile
LOCAL env_set_errpfx
NOFUNC env_set_event_notify DB_ENV *, void (*)(DB_ENV *, u_int32_t, void *)
NOFUNC env_set_feedback DB_ENV *, void (*)(DB_ENV *, int, int)
BEGIN env_set_flags CODE
ARG ID DB_ENV * dbenv
ARG INT u_int32_t flags
ARG INT int onoff
END
NOFUNC env_set_intermediate_dir_mode DB_ENV *, const char *
NOFUNC env_set_isalive DB_ENV *, int (*)(DB_ENV *, pid_t, db_threadid_t, u_int32_t)
NOFUNC env_set_lg_bsize DB_ENV *, u_int32_t
NOFUNC env_set_lg_dir DB_ENV *, const char *
NOFUNC env_set_lg_filemode DB_ENV *, int
NOFUNC env_set_lg_max DB_ENV *, u_int32_t
NOFUNC env_set_lg_regionmax DB_ENV *, u_int32_t
NOFUNC env_set_lk_conflicts DB_ENV *, u_int8_t *, int
NOFUNC env_set_lk_detect DB_ENV *, u_int32_t
NOFUNC env_set_lk_max_lockers DB_ENV *, u_int32_t
NOFUNC env_set_lk_max_locks DB_ENV *, u_int32_t
NOFUNC env_set_lk_max_objects DB_ENV *, u_int32_t
NOFUNC env_set_lk_partitions DB_ENV *, u_int32_t
NOFUNC env_set_mp_max_openfd DB_ENV *, int
NOFUNC env_set_mp_max_write DB_ENV *, int, db_timeout_t
NOFUNC env_set_mp_mmapsize DB_ENV *, size_t
LOCAL env_set_msgcall
LOCAL env_set_msgfile
NOFUNC env_set_paniccall DB_ENV *, void (*)(DB_ENV *, int)
BEGIN env_set_rpc_server LINKONLY
ARG ID DB_ENV * dbenv
END
NOFUNC env_set_shm_key DB_ENV *, long
NOFUNC env_set_thread_count DB_ENV *, u_int32_t
NOFUNC env_set_thread_id DB_ENV *, void (*)(DB_ENV *, pid_t *, db_threadid_t*)
NOFUNC env_set_thread_id_string DB_ENV *, char *(*)(DB_ENV *, pid_t, db_threadid_t, char *)
NOFUNC env_set_timeout DB_ENV *, u_int32_t, u_int32_t
NOFUNC env_set_tmp_dir DB_ENV *, const char *
NOFUNC env_set_tx_max DB_ENV *, u_int32_t
NOFUNC env_set_tx_timestamp DB_ENV *, time_t *
NOFUNC env_set_verbose DB_ENV *, u_int32_t, int
NOFUNC env_stat_print DB_ENV *, u_int32_t
BEGIN env_txn_begin RETCODE
ARG ID DB_ENV * dbenv
ARG ID DB_TXN * parent
ARG IGNORE DB_TXN ** txnpp
ARG INT u_int32_t flags
RET ID long txnid
END
NOFUNC env_txn_checkpoint DB_ENV *, u_int32_t, u_int32_t, u_int32_t
BEGIN env_txn_recover RETCODE
ARG ID DB_ENV * dbenv
ARG IGNORE DB_PREPLIST * preplist
ARG INT long count
ARG IGNORE long * retp
ARG INT u_int32_t flags
RET LIST DB_TXN * txn ID
RET LIST u_int8_t * gid GID
RET INT long retcount
END
NOFUNC env_txn_stat DB_ENV *, DB_TXN_STAT **, u_int32_t
NOFUNC env_txn_stat_print DB_ENV *, u_int32_t
######################################################
# DB handle create.
######################################################
BEGIN db_create RETCODE
ARG IGNORE DB * dbp
ARG ID DB_ENV * dbenv
ARG INT u_int32_t flags
RET ID long db
END
######################################################
# DB handle methods.
######################################################
BEGIN db_associate CODE
ARG ID DB * dbp
ARG ID DB_TXN * txnp
ARG ID DB * sdbp
FUNCPROT int (*)(DB *, const DBT *, const DBT *, DBT *)
FUNCARG int (*func0) __P((DB *, const DBT *, const DBT *, DBT *))
ARG INT u_int32_t flags
END
BEGIN db_close RETCODE
ARG ID DB * dbp
ARG INT u_int32_t flags
END
NOFUNC db_compact DB *, DB_TXN *, DBT *, DBT *, DB_COMPACT *, u_int32_t, DBT *
BEGIN db_cursor RETCODE
ARG ID DB * dbp
ARG ID DB_TXN * txnp
ARG IGNORE DBC ** dbcpp
ARG INT u_int32_t flags
RET ID long dbcid
END
BEGIN db_del CODE
ARG ID DB * dbp
ARG ID DB_TXN * txnp
ARG DBT DBT * key
ARG INT u_int32_t flags
END
LOCAL db_err
LOCAL db_errx
LOCAL db_exists
NOFUNC db_fd DB *, int *
BEGIN db_get RETCODE
ARG ID DB * dbp
ARG ID DB_TXN * txnp
ARG DBT DBT * key
ARG DBT DBT * data
ARG INT u_int32_t flags
RET DBT DBT * key
RET DBT DBT * data
END
BEGIN db_get_bt_minkey CODE
ARG ID DB * dbp
ARET INT u_int32_t minkey
END
LOCAL db_get_byteswapped
NOFUNC db_get_cachesize DB *, u_int32_t *, u_int32_t *, int *
BEGIN db_get_dbname CODE
ARG ID DB * dbp
ARET STRING const char * filename
ARET STRING const char * dbname
END
BEGIN db_get_encrypt_flags CODE
ARG ID DB * dbp
ARET INT u_int32_t flags
END
LOCAL db_get_env
LOCAL db_get_errcall
LOCAL db_get_errfile
LOCAL db_get_errpfx
BEGIN db_get_flags CODE
ARG ID DB * dbp
ARET INT u_int32_t flags
END
BEGIN db_get_h_ffactor CODE
ARG ID DB * dbp
ARET INT u_int32_t ffactor
END
BEGIN db_get_h_nelem CODE
ARG ID DB * dbp
ARET INT u_int32_t nelem
END
BEGIN db_get_lorder CODE
ARG ID DB * dbp
ARET INT int lorder
END
NOFUNC db_get_mpf DB *
LOCAL db_get_msgfile
LOCAL db_get_multiple
BEGIN db_get_open_flags CODE
ARG ID DB * dbp
ARET INT u_int32_t flags
END
BEGIN db_get_pagesize CODE
ARG ID DB * dbp
ARET INT u_int32_t pagesize
END
BEGIN db_get_priority CODE
ARG ID DB * dbp
ARET INT DB_CACHE_PRIORITY priority
END
BEGIN db_get_q_extentsize CODE
ARG ID DB * dbp
ARET INT u_int32_t extentsize
END
BEGIN db_get_re_delim CODE
ARG ID DB * dbp
ARET INT int delim
END
BEGIN db_get_re_len CODE
ARG ID DB * dbp
ARET INT u_int32_t len
END
BEGIN db_get_re_pad CODE
ARG ID DB * dbp
ARET INT int pad
END
NOFUNC db_get_re_source DB *, const char **
LOCAL db_get_transactional
LOCAL db_get_type
BEGIN db_join RETCODE
ARG ID DB * dbp
ARG LIST DBC ** curs ID
ARG IGNORE DBC ** dbcp
ARG INT u_int32_t flags
RET ID long dbcid
END
BEGIN db_key_range RETCODE
ARG ID DB * dbp
ARG ID DB_TXN * txnp
ARG DBT DBT * key
ARG IGNORE DB_KEY_RANGE * range
ARG INT u_int32_t flags
RET DBL double less
RET DBL double equal
RET DBL double greater
END
BEGIN db_open RETCODE
ARG ID DB * dbp
ARG ID DB_TXN * txnp
ARG STRING const char * name
ARG STRING const char * subdb
ARG INT DBTYPE type
ARG INT u_int32_t flags
ARG INT int mode
RET ID long db
RET INT DBTYPE type
RET INT int lorder
END
BEGIN db_pget RETCODE
ARG ID DB * dbp
ARG ID DB_TXN * txnp
ARG DBT DBT * skey
ARG DBT DBT * pkey
ARG DBT DBT * data
ARG INT u_int32_t flags
RET DBT DBT * skey
RET DBT DBT * pkey
RET DBT DBT * data
END
BEGIN db_put RETCODE
ARG ID DB * dbp
ARG ID DB_TXN * txnp
ARG DBT DBT * key
ARG DBT DBT * data
ARG INT u_int32_t flags
RET DBT DBT * key
END
BEGIN db_remove RETCODE
ARG ID DB * dbp
ARG STRING const char * name
ARG STRING const char * subdb
ARG INT u_int32_t flags
END
BEGIN db_rename RETCODE
ARG ID DB * dbp
ARG STRING const char * name
ARG STRING const char * subdb
ARG STRING const char * newname
ARG INT u_int32_t flags
END
NOFUNC db_set_alloc DB *, void *(*)(size_t), void *(*)(void *, size_t), void (*)(void *)
NOFUNC db_set_append_recno DB *, int (*)(DB *, DBT *, db_recno_t)
NOFUNC db_set_bt_compare DB *, int (*)(DB *, const DBT *, const DBT *)
BEGIN db_set_bt_minkey CODE
ARG ID DB * dbp
ARG INT u_int32_t minkey
END
NOFUNC db_set_bt_prefix DB *, size_t(*)(DB *, const DBT *, const DBT *)
NOFUNC db_set_cachesize DB *, u_int32_t, u_int32_t, int
NOFUNC db_set_dup_compare DB *, int (*)(DB *, const DBT *, const DBT *)
BEGIN db_set_encrypt CODE
ARG ID DB * dbp
ARG STRING const char * passwd
ARG INT u_int32_t flags
END
LOCAL db_set_errcall
LOCAL db_set_errfile
LOCAL db_set_errpfx
NOFUNC db_set_feedback DB *, void (*)(DB *, int, int)
BEGIN db_set_flags CODE
ARG ID DB * dbp
ARG INT u_int32_t flags
END
NOFUNC db_set_h_compare DB *, int (*)(DB *, const DBT *, const DBT *)
BEGIN db_set_h_ffactor CODE
ARG ID DB * dbp
ARG INT u_int32_t ffactor
END
NOFUNC db_set_h_hash DB *, u_int32_t(*)(DB *, const void *, u_int32_t)
BEGIN db_set_h_nelem CODE
ARG ID DB * dbp
ARG INT u_int32_t nelem
END
BEGIN db_set_lorder CODE
ARG ID DB * dbp
ARG INT int lorder
END
LOCAL db_set_msgcall
LOCAL db_set_msgfile
BEGIN db_set_pagesize CODE
ARG ID DB * dbp
ARG INT u_int32_t pagesize
END
NOFUNC db_set_paniccall DB *, void (*)(DB_ENV *, int)
BEGIN db_set_priority CODE
ARG ID DB * dbp
ARG INT DB_CACHE_PRIORITY priority
END
BEGIN db_set_q_extentsize CODE
ARG ID DB * dbp
ARG INT u_int32_t extentsize
END
BEGIN db_set_re_delim CODE
ARG ID DB * dbp
ARG INT int delim
END
BEGIN db_set_re_len CODE
ARG ID DB * dbp
ARG INT u_int32_t len
END
BEGIN db_set_re_pad CODE
ARG ID DB * dbp
ARG INT int pad
END
NOFUNC db_set_re_source DB *, const char *
BEGIN db_stat RETCODE
ARG ID DB * dbp
ARG ID DB_TXN * txnp
ARG IGNORE void * sp
ARG INT u_int32_t flags
RET LIST u_int32_t * stats INT
END
NOFUNC db_stat_print DB *, u_int32_t
BEGIN db_sync CODE
ARG ID DB * dbp
ARG INT u_int32_t flags
END
BEGIN db_truncate RETCODE
ARG ID DB * dbp
ARG ID DB_TXN * txnp
ARG IGNORE u_int32_t * countp
ARG INT u_int32_t flags
RET INT u_int32_t count
END
NOFUNC db_upgrade DB *, const char *, u_int32_t
NOFUNC db_verify DB *, const char *, const char *, FILE *, u_int32_t
######################################################
# DBC handle methods.
######################################################
BEGIN dbc_close RETCODE
ARG ID DBC * dbc
END
BEGIN dbc_count RETCODE
ARG ID DBC * dbc
ARG IGNORE db_recno_t * countp
ARG INT u_int32_t flags
RET INT db_recno_t dupcount
END
BEGIN dbc_del CODE
ARG ID DBC * dbc
ARG INT u_int32_t flags
END
BEGIN dbc_dup RETCODE
ARG ID DBC * dbc
ARG IGNORE DBC ** dbcp
ARG INT u_int32_t flags
RET ID long dbcid
END
BEGIN dbc_get RETCODE
ARG ID DBC * dbc
ARG DBT DBT * key
ARG DBT DBT * data
ARG INT u_int32_t flags
RET DBT DBT * key
RET DBT DBT * data
END
BEGIN dbc_get_priority CODE
ARG ID DBC * dbc
ARET INT DB_CACHE_PRIORITY priority
END
BEGIN dbc_pget RETCODE
ARG ID DBC * dbc
ARG DBT DBT * skey
ARG DBT DBT * pkey
ARG DBT DBT * data
ARG INT u_int32_t flags
RET DBT DBT * skey
RET DBT DBT * pkey
RET DBT DBT * data
END
BEGIN dbc_put RETCODE
ARG ID DBC * dbc
ARG DBT DBT * key
ARG DBT DBT * data
ARG INT u_int32_t flags
RET DBT DBT * key
END
BEGIN dbc_set_priority CODE
ARG ID DBC * dbc
ARG INT DB_CACHE_PRIORITY priority
END
######################################################
# DB_TXN handle methods.
######################################################
BEGIN txn_abort RETCODE
ARG ID DB_TXN * txnp
END
BEGIN txn_commit RETCODE
ARG ID DB_TXN * txnp
ARG INT u_int32_t flags
END
BEGIN txn_discard RETCODE
ARG ID DB_TXN * txnp
ARG INT u_int32_t flags
END
NOFUNC txn_get_name DB_TXN *, const char **
LOCAL txn_id
BEGIN txn_prepare CODE
ARG ID DB_TXN * txnp
ARG GID u_int8_t * gid
END
NOFUNC txn_set_name DB_TXN *, const char *
NOFUNC txn_set_timeout DB_TXN *, u_int32_t, u_int32_t