📄 db_server_cxxutil.cpp
字号:
/*- * See the file LICENSE for redistribution information. * * Copyright (c) 2000-2002 * Sleepycat Software. All rights reserved. */#include "db_config.h"#ifndef lintstatic const char revid[] = "$Id: db_server_cxxutil.cpp,v 1.8 2002/05/23 07:49:34 mjc Exp $";#endif /* not lint */#ifndef NO_SYSTEM_INCLUDES#include <sys/types.h>#if TIME_WITH_SYS_TIME#include <sys/time.h>#include <time.h>#else#if HAVE_SYS_TIME_H#include <sys/time.h>#else#include <time.h>#endif#endif#include <rpc/rpc.h>#include <limits.h>#include <signal.h>#include <stdio.h>#include <stdlib.h>#include <string.h>#include <unistd.h>#endif#include "dbinc_auto/db_server.h"#include "db_int.h"#include "db_cxx.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;intmain( 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 voidusage(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 voidversion_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)__dbenv_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 *
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -