⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 db_load.c

📁 linux 下的源代码分析阅读器 red hat公司新版
💻 C
📖 第 1 页 / 共 2 页
字号:
/*- * See the file LICENSE for redistribution information. * * Copyright (c) 1996,2007 Oracle.  All rights reserved. * * $Id: db_load.c,v 12.23 2007/05/17 17:17:42 bostic Exp $ */#include "db_config.h"#include "db_int.h"#include "dbinc/db_page.h"#include "dbinc/db_am.h"#ifndef lintstatic const char copyright[] =    "Copyright (c) 1996,2007 Oracle.  All rights reserved.\n";#endiftypedef struct {			/* XXX: Globals. */	const char *progname;		/* Program name. */	char	*hdrbuf;		/* Input file header. */	u_long	lineno;			/* Input file line number. */	u_long	origline;		/* Original file line number. */	int	endodata;		/* Reached the end of a database. */	int	endofile;		/* Reached the end of the input. */	int	version;		/* Input version. */	char	*home;			/* Env home. */	char	*passwd;		/* Env passwd. */	int	private;		/* Private env. */	u_int32_t cache;		/* Env cache size. */} LDG;int	db_load_badend __P((DB_ENV *));void	db_load_badnum __P((DB_ENV *));int	db_load_configure __P((DB_ENV *, DB *, char **, char **, int *));int	db_load_convprintable __P((DB_ENV *, char *, char **));int	db_load_db_init __P((DB_ENV *, char *, u_int32_t, int *));int	db_load_dbt_rdump __P((DB_ENV *, DBT *));int	db_load_dbt_rprint __P((DB_ENV *, DBT *));int	db_load_dbt_rrecno __P((DB_ENV *, DBT *, int));int	db_load_dbt_to_recno __P((DB_ENV *, DBT *, db_recno_t *));int	db_load_env_create __P((DB_ENV **, LDG *));int	db_load_load __P((DB_ENV *, char *, DBTYPE, char **, u_int, LDG *, int *));int	db_load_main __P((int, char *[]));int	db_load_rheader __P((DB_ENV *, DB *, DBTYPE *, char **, int *, int *));int	db_load_usage __P((void));int	db_load_version_check __P((void));const char *progname;#define	G(f)	((LDG *)dbenv->app_private)->f					/* Flags to the load function. */#define	LDF_NOHEADER	0x01		/* No dump header. */#define	LDF_NOOVERWRITE	0x02		/* Don't overwrite existing rows. */#define	LDF_PASSWORD	0x04		/* Encrypt created databases. */intdb_load(args)	char *args;{	int argc;	char **argv;	__db_util_arg("db_load", args, &argc, &argv);	return (db_load_main(argc, argv) ? EXIT_FAILURE : EXIT_SUCCESS);}#include <stdio.h>#define	ERROR_RETURN	ERRORintdb_load_main(argc, argv)	int argc;	char *argv[];{	enum { NOTSET, FILEID_RESET, LSN_RESET, STANDARD_LOAD } mode;	extern char *optarg;	extern int optind, __db_getopt_reset;	DBTYPE dbtype;	DB_ENV	*dbenv;	LDG ldg;	u_int ldf;	int ch, existed, exitval, ret;	char **clist, **clp;	if ((progname = __db_rpath(argv[0])) == NULL)		progname = argv[0];	else		++progname;	if ((ret = db_load_version_check()) != 0)		return (ret);	ldg.progname = progname;	ldg.lineno = 0;	ldg.endodata = ldg.endofile = 0;	ldg.version = 1;	ldg.cache = MEGABYTE;	ldg.hdrbuf = NULL;	ldg.home = NULL;	ldg.passwd = NULL;	mode = NOTSET;	ldf = 0;	exitval = existed = 0;	dbtype = DB_UNKNOWN;	/* Allocate enough room for configuration arguments. */	if ((clp = clist =	    (char **)calloc((size_t)argc + 1, sizeof(char *))) == NULL) {		fprintf(stderr, "%s: %s\n", ldg.progname, strerror(ENOMEM));		return (EXIT_FAILURE);	}	/*	 * There are two modes for db_load: -r and everything else.  The -r	 * option zeroes out the database LSN's or resets the file ID, it	 * doesn't really "load" a new database.  The functionality is in	 * db_load because we don't have a better place to put it, and we	 * don't want to create a new utility for just that functionality.	 */	__db_getopt_reset = 1;	while ((ch = getopt(argc, argv, "c:f:h:nP:r:Tt:V")) != EOF)		switch (ch) {		case 'c':			if (mode != NOTSET && mode != STANDARD_LOAD)				return (db_load_usage());			mode = STANDARD_LOAD;			*clp++ = optarg;			break;		case 'f':			if (mode != NOTSET && mode != STANDARD_LOAD)				return (db_load_usage());			mode = STANDARD_LOAD;			if (freopen(optarg, "r", stdin) == NULL) {				fprintf(stderr, "%s: %s: reopen: %s\n",				    ldg.progname, optarg, strerror(errno));				return (EXIT_FAILURE);			}			break;		case 'h':			ldg.home = optarg;			break;		case 'n':			if (mode != NOTSET && mode != STANDARD_LOAD)				return (db_load_usage());			mode = STANDARD_LOAD;			ldf |= LDF_NOOVERWRITE;			break;		case 'P':			ldg.passwd = strdup(optarg);			memset(optarg, 0, strlen(optarg));			if (ldg.passwd == NULL) {				fprintf(stderr, "%s: strdup: %s\n",				    ldg.progname, strerror(errno));				return (EXIT_FAILURE);			}			ldf |= LDF_PASSWORD;			break;		case 'r':			if (mode == STANDARD_LOAD)				return (db_load_usage());			if (strcmp(optarg, "lsn") == 0)				mode = LSN_RESET;			else if (strcmp(optarg, "fileid") == 0)				mode = FILEID_RESET;			else				return (db_load_usage());			break;		case 'T':			if (mode != NOTSET && mode != STANDARD_LOAD)				return (db_load_usage());			mode = STANDARD_LOAD;			ldf |= LDF_NOHEADER;			break;		case 't':			if (mode != NOTSET && mode != STANDARD_LOAD)				return (db_load_usage());			mode = STANDARD_LOAD;			if (strcmp(optarg, "btree") == 0) {				dbtype = DB_BTREE;				break;			}			if (strcmp(optarg, "hash") == 0) {				dbtype = DB_HASH;				break;			}			if (strcmp(optarg, "recno") == 0) {				dbtype = DB_RECNO;				break;			}			if (strcmp(optarg, "queue") == 0) {				dbtype = DB_QUEUE;				break;			}			return (db_load_usage());		case 'V':			printf("%s\n", db_version(NULL, NULL, NULL));			return (EXIT_SUCCESS);		case '?':		default:			return (db_load_usage());		}	argc -= optind;	argv += optind;	if (argc != 1)		return (db_load_usage());	/* Handle possible interruptions. */	__db_util_siginit();	/*	 * Create an environment object initialized for error reporting, and	 * then open it.	 */	if (db_load_env_create(&dbenv, &ldg) != 0)		goto shutdown;	/* If we're resetting the LSNs, that's an entirely separate path. */	switch (mode) {	case FILEID_RESET:		exitval = dbenv->fileid_reset(		    dbenv, argv[0], ldf & LDF_PASSWORD ? DB_ENCRYPT : 0);		break;	case LSN_RESET:		exitval = dbenv->lsn_reset(		    dbenv, argv[0], ldf & LDF_PASSWORD ? DB_ENCRYPT : 0);		break;	case NOTSET:	case STANDARD_LOAD:		while (!ldg.endofile)			if (db_load_load(dbenv, argv[0], dbtype, clist, ldf,			    &ldg, &existed) != 0)				goto shutdown;		break;	}	if (0) {shutdown:	exitval = 1;	}	if ((ret = dbenv->close(dbenv, 0)) != 0) {		exitval = 1;		fprintf(stderr,		    "%s: dbenv->close: %s\n", ldg.progname, db_strerror(ret));	}	/* Resend any caught signal. */	__db_util_sigresend();	free(clist);	if (ldg.passwd != NULL)		free(ldg.passwd);	/*	 * Return 0 on success, 1 if keys existed already, and 2 on failure.	 *	 * Technically, this is wrong, because exit of anything other than	 * 0 is implementation-defined by the ANSI C standard.  I don't see	 * any good solutions that don't involve API changes.	 */	return (exitval == 0 ? (existed == 0 ? 0 : 1) : 2);}/* * load -- *	Load a database. */intdb_load_load(dbenv, name, argtype, clist, flags, ldg, existedp)	DB_ENV *dbenv;	char *name, **clist;	DBTYPE argtype;	u_int flags;	LDG *ldg;	int *existedp;{	DB *dbp;	DBT key, rkey, data, *readp, *writep;	DBTYPE dbtype;	DB_TXN *ctxn, *txn;	db_recno_t recno, datarecno;	u_int32_t put_flags;	int ascii_recno, checkprint, hexkeys, keyflag, keys, resize, ret, rval;	char *subdb;	put_flags = LF_ISSET(LDF_NOOVERWRITE) ? DB_NOOVERWRITE : 0;	G(endodata) = 0;	subdb = NULL;	ctxn = txn = NULL;	memset(&key, 0, sizeof(DBT));	memset(&data, 0, sizeof(DBT));	memset(&rkey, 0, sizeof(DBT));retry_db:	dbtype = DB_UNKNOWN;	keys = -1;	hexkeys = -1;	keyflag = -1;	/* Create the DB object. */	if ((ret = db_create(&dbp, dbenv, 0)) != 0) {		dbenv->err(dbenv, ret, "db_create");		goto err;	}	/* Read the header -- if there's no header, we expect flat text. */	if (LF_ISSET(LDF_NOHEADER)) {		checkprint = 1;		dbtype = argtype;	} else {		if (db_load_rheader(dbenv,		    dbp, &dbtype, &subdb, &checkprint, &keys) != 0)			goto err;		if (G(endofile))			goto done;	}	/*	 * Apply command-line configuration changes.  (We apply command-line	 * configuration changes to all databases that are loaded, e.g., all	 * subdatabases.)	 */	if (db_load_configure(dbenv, dbp, clist, &subdb, &keyflag))		goto err;	if (keys != 1) {		if (keyflag == 1) {			dbp->err(dbp, EINVAL, "No keys specified in file");			goto err;		}	}	else if (keyflag == 0) {		dbp->err(dbp, EINVAL, "Keys specified in file");		goto err;	}	else		keyflag = 1;	if (dbtype == DB_BTREE || dbtype == DB_HASH) {		if (keyflag == 0)			dbp->err(dbp,			    EINVAL, "Btree and Hash must specify keys");		else			keyflag = 1;	}	if (argtype != DB_UNKNOWN) {		if (dbtype == DB_RECNO || dbtype == DB_QUEUE)			if (keyflag != 1 && argtype != DB_RECNO &&			    argtype != DB_QUEUE) {				dbenv->errx(dbenv,			   "improper database type conversion specified");				goto err;			}		dbtype = argtype;	}	if (dbtype == DB_UNKNOWN) {		dbenv->errx(dbenv, "no database type specified");		goto err;	}	if (keyflag == -1)		keyflag = 0;	/*	 * Recno keys have only been printed in hexadecimal starting	 * with db_dump format version 3 (DB 3.2).	 *	 * !!!	 * Note that version is set in db_load_rheader(), which must be called before	 * this assignment.	 */	hexkeys = (G(version) >= 3 && keyflag == 1 && checkprint == 0);	if (keyflag == 1 && (dbtype == DB_RECNO || dbtype == DB_QUEUE))		ascii_recno = 1;	else		ascii_recno = 0;	/* If configured with a password, encrypt databases we create. */	if (LF_ISSET(LDF_PASSWORD) &&	    (ret = dbp->set_flags(dbp, DB_ENCRYPT)) != 0) {		dbp->err(dbp, ret, "DB->set_flags: DB_ENCRYPT");		goto err;	}#if 0	Set application-specific btree comparison or hash functions here.	For example:	if ((ret = dbp->set_bt_compare(dbp, local_comparison_func)) != 0) {		dbp->err(dbp, ret, "DB->set_bt_compare");		goto err;	}	if ((ret = dbp->set_h_hash(dbp, local_hash_func)) != 0) {		dbp->err(dbp, ret, "DB->set_h_hash");		goto err;	}#endif	/* Open the DB file. */	if ((ret = dbp->open(dbp, NULL, name, subdb, dbtype,	    DB_CREATE | (TXN_ON(dbenv) ? DB_AUTO_COMMIT : 0),	    __db_omode("rw-rw-rw-"))) != 0) {		dbp->err(dbp, ret, "DB->open: %s", name);		goto err;	}	if (ldg->private != 0) {		if ((ret = __db_util_cache(dbp, &ldg->cache, &resize)) != 0)			goto err;		if (resize) {			if ((ret = dbp->close(dbp, 0)) != 0)				goto err;			dbp = NULL;			if ((ret = dbenv->close(dbenv, 0)) != 0)				goto err;			if ((ret = db_load_env_create(&dbenv, ldg)) != 0)				goto err;			goto retry_db;		}	}	/* Initialize the key/data pair. */	readp = writep = &key;	if (dbtype == DB_RECNO || dbtype == DB_QUEUE) {		key.size = sizeof(recno);		if (keyflag) {			key.data = &datarecno;			if (checkprint) {				readp = &rkey;				goto key_data;			}		} else			key.data = &recno;	} elsekey_data:	if ((readp->data = malloc(readp->ulen = 1024)) == NULL) {			dbenv->err(dbenv, ENOMEM, NULL);			goto err;		}	if ((data.data = malloc(data.ulen = 1024)) == NULL) {		dbenv->err(dbenv, ENOMEM, NULL);		goto err;	}	if (TXN_ON(dbenv) &&	    (ret = dbenv->txn_begin(dbenv, NULL, &txn, 0)) != 0)		goto err;	/* Get each key/data pair and add them to the database. */	for (recno = 1; !__db_util_interrupted(); ++recno) {		if (!keyflag) {			if (checkprint) {				if (db_load_dbt_rprint(dbenv, &data))					goto err;			} else {				if (db_load_dbt_rdump(dbenv, &data))					goto err;			}		} else {			if (checkprint) {				if (db_load_dbt_rprint(dbenv, readp))					goto err;				if (ascii_recno &&				    db_load_dbt_to_recno(dbenv, readp, &datarecno) != 0)					goto err;				if (!G(endodata) && db_load_dbt_rprint(dbenv, &data))					goto odd_count;			} else {				if (ascii_recno) {					if (db_load_dbt_rrecno(dbenv, readp, hexkeys))						goto err;				} else					if (db_load_dbt_rdump(dbenv, readp))						goto err;				if (!G(endodata) && db_load_dbt_rdump(dbenv, &data)) {odd_count:				dbenv->errx(dbenv,					    "odd number of key/data pairs");					goto err;				}			}		}		if (G(endodata))			break;retry:		if (txn != NULL)			if ((ret = dbenv->txn_begin(dbenv, txn, &ctxn, 0)) != 0)				goto err;		switch (ret = dbp->put(dbp, ctxn, writep, &data, put_flags)) {		case 0:			if (ctxn != NULL) {				if ((ret =				    ctxn->commit(ctxn, DB_TXN_NOSYNC)) != 0)					goto err;				ctxn = NULL;			}			break;		case DB_KEYEXIST:			*existedp = 1;			dbenv->errx(dbenv,			    "%s: line %d: key already exists, not loaded:",			    name,			    !keyflag ? recno : recno * 2 - 1);			(void)dbenv->prdbt(&key,			    checkprint, 0, stderr, __db_pr_callback, 0);			break;		case DB_LOCK_DEADLOCK:			/* If we have a child txn, retry--else it's fatal. */			if (ctxn != NULL) {				if ((ret = ctxn->abort(ctxn)) != 0)					goto err;				ctxn = NULL;				goto retry;			}			/* FALLTHROUGH */		default:			dbenv->err(dbenv, ret, NULL);			if (ctxn != NULL) {				(void)ctxn->abort(ctxn);				ctxn = NULL;			}			goto err;		}		if (ctxn != NULL) {			if ((ret = ctxn->abort(ctxn)) != 0)				goto err;			ctxn = NULL;		}	}done:	rval = 0;	DB_ASSERT(dbenv, ctxn == NULL);	if (txn != NULL && (ret = txn->commit(txn, 0)) != 0) {		txn = NULL;		goto err;	}	if (0) {err:		rval = 1;		DB_ASSERT(dbenv, ctxn == NULL);		if (txn != NULL)			(void)txn->abort(txn);	}	/* Close the database. */	if (dbp != NULL && (ret = dbp->close(dbp, 0)) != 0) {		dbenv->err(dbenv, ret, "DB->close");		rval = 1;	}	if (G(hdrbuf) != NULL)		free(G(hdrbuf));	G(hdrbuf) = NULL;	/* Free allocated memory. */	if (subdb != NULL)		free(subdb);	if (dbtype != DB_RECNO && dbtype != DB_QUEUE && key.data != NULL)		free(key.data);	if (rkey.data != NULL)		free(rkey.data);	free(data.data);	return (rval);}/* * env_create -- *	Create the environment and initialize it for error reporting. */intdb_load_env_create(dbenvp, ldg)	DB_ENV **dbenvp;	LDG *ldg;{	DB_ENV *dbenv;	int ret;	if ((ret = db_env_create(dbenvp, 0)) != 0) {		fprintf(stderr,		    "%s: db_env_create: %s\n", ldg->progname, db_strerror(ret));		return (ret);	}	dbenv = *dbenvp;	dbenv->set_errfile(dbenv, stderr);	dbenv->set_errpfx(dbenv, ldg->progname);	if (ldg->passwd != NULL && (ret = dbenv->set_encrypt(dbenv,	    ldg->passwd, DB_ENCRYPT_AES)) != 0) {		dbenv->err(dbenv, ret, "set_passwd");		return (ret);	}	if ((ret = db_load_db_init(dbenv, ldg->home, ldg->cache, &ldg->private)) != 0)		return (ret);	dbenv->app_private = ldg;	return (0);}/* * db_init -- *	Initialize the environment. */intdb_load_db_init(dbenv, home, cache, is_private)	DB_ENV *dbenv;	char *home;	u_int32_t cache;	int *is_private;{	u_int32_t flags;	int ret;	*is_private = 0;	/* We may be loading into a live environment.  Try and join. */	flags = DB_USE_ENVIRON |	    DB_INIT_LOCK | DB_INIT_LOG | DB_INIT_MPOOL | DB_INIT_TXN;	if ((ret = dbenv->open(dbenv, home, flags, 0)) == 0)		return (0);	if (ret == DB_VERSION_MISMATCH)		goto err;	/*	 * We're trying to load a database.	 *	 * An environment is required because we may be trying to look at	 * databases in directories other than the current one.  We could	 * avoid using an environment iff the -h option wasn't specified,	 * but that seems like more work than it's worth.	 *	 * No environment exists (or, at least no environment that includes	 * an mpool region exists).  Create one, but make it private so that	 * no files are actually created.	 */	LF_CLR(DB_INIT_LOCK | DB_INIT_LOG | DB_INIT_TXN);	LF_SET(DB_CREATE | DB_PRIVATE);	*is_private = 1;	if ((ret = dbenv->set_cachesize(dbenv, 0, cache, 1)) != 0) {		dbenv->err(dbenv, ret, "set_cachesize");		return (1);	}	if ((ret = dbenv->open(dbenv, home, flags, 0)) == 0)		return (0);	/* An environment is required. */err:	dbenv->err(dbenv, ret, "DB_ENV->open");	return (1);}#define	FLAG(name, value, keyword, flag)				\	if (strcmp(name, keyword) == 0) {				\		switch (*value) {					\

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -