📄 fs.c
字号:
static const struct
{
int bdb_major;
int bdb_minor;
const char *config_key;
const char *header;
const char *inactive;
const char *active;
} dbconfig_options[] = {
/* Controlled by "svnadmin create --bdb-txn-nosync" */
{ 4, 0, SVN_FS_CONFIG_BDB_TXN_NOSYNC,
/* header */
"#\n"
"# Disable fsync of log files on transaction commit. Read the\n"
"# documentation about DB_TXN_NOSYNC at:\n"
"#\n"
"# http://www.sleepycat.com/docs/api_c/env_set_flags.html\n"
"#\n"
"# [requires Berkeley DB 4.0]\n",
/* inactive */
"# set_flags DB_TXN_NOSYNC\n",
/* active */
"set_flags DB_TXN_NOSYNC\n" },
/* Controlled by "svnadmin create --bdb-log-keep" */
{ 4, 2, SVN_FS_CONFIG_BDB_LOG_AUTOREMOVE,
/* header */
"#\n"
"# Enable automatic removal of unused transaction log files.\n"
"# Read the documentation about DB_LOG_AUTOREMOVE at:\n"
"#\n"
"# http://www.sleepycat.com/docs/api_c/env_set_flags.html\n"
"#\n"
"# [requires Berkeley DB 4.2]\n",
/* inactive */
"# set_flags DB_LOG_AUTOREMOVE\n",
/* active */
"set_flags DB_LOG_AUTOREMOVE\n" },
};
static const int dbconfig_options_length =
sizeof (dbconfig_options)/sizeof (*dbconfig_options);
SVN_ERR (svn_io_file_open (&dbconfig_file, dbconfig_file_name,
APR_WRITE | APR_CREATE, APR_OS_DEFAULT,
fs->pool));
SVN_ERR (svn_io_file_write_full (dbconfig_file, dbconfig_contents,
sizeof (dbconfig_contents) - 1, NULL,
fs->pool));
/* Write the variable DB_CONFIG flags. */
for (i = 0; i < dbconfig_options_length; ++i)
{
void *value = NULL;
const char *choice;
if (fs->config)
{
value = apr_hash_get (fs->config,
dbconfig_options[i].config_key,
APR_HASH_KEY_STRING);
}
SVN_ERR(svn_io_file_write_full (dbconfig_file,
dbconfig_options[i].header,
strlen (dbconfig_options[i].header),
NULL, fs->pool));
if (((DB_VERSION_MAJOR == dbconfig_options[i].bdb_major
&& DB_VERSION_MINOR >= dbconfig_options[i].bdb_minor)
|| DB_VERSION_MAJOR > dbconfig_options[i].bdb_major)
&& value != NULL && strcmp (value, "0") != 0)
choice = dbconfig_options[i].active;
else
choice = dbconfig_options[i].inactive;
SVN_ERR (svn_io_file_write_full (dbconfig_file, choice, strlen (choice),
NULL, fs->pool));
}
SVN_ERR (svn_io_file_close (dbconfig_file, fs->pool));
return SVN_NO_ERROR;
}
/* Creating a new filesystem */
static fs_vtable_t fs_vtable = {
svn_fs_base__youngest_rev,
svn_fs_base__revision_prop,
svn_fs_base__revision_proplist,
svn_fs_base__change_rev_prop,
svn_fs_base__get_uuid,
svn_fs_base__set_uuid,
svn_fs_base__revision_root,
svn_fs_base__begin_txn,
svn_fs_base__open_txn,
svn_fs_base__purge_txn,
svn_fs_base__list_transactions,
svn_fs_base__deltify
};
static svn_error_t *
base_create (svn_fs_t *fs, const char *path, apr_pool_t *pool)
{
svn_error_t *svn_err;
const char *path_apr;
const char *path_native;
base_fs_data_t *bfd;
SVN_ERR (check_already_open (fs));
apr_pool_cleanup_register (fs->pool, fs, cleanup_fs_apr,
apr_pool_cleanup_null);
bfd = apr_pcalloc (fs->pool, sizeof (*bfd));
fs->vtable = &fs_vtable;
fs->fsap_data = bfd;
/* Initialize the fs's path. */
fs->path = apr_pstrdup (fs->pool, path);
SVN_ERR (svn_path_cstring_from_utf8 (&path_apr, fs->path, fs->pool));
SVN_ERR (bdb_write_config (fs));
svn_err = allocate_env (fs);
if (svn_err) goto error;
/* Create the Berkeley DB environment. */
SVN_ERR (svn_utf_cstring_from_utf8 (&path_native, fs->path, fs->pool));
svn_err = BDB_WRAP (fs, "creating environment",
bfd->env->open (bfd->env, path_native,
(DB_CREATE
| DB_INIT_LOCK
| DB_INIT_LOG
| DB_INIT_MPOOL
| DB_INIT_TXN),
0666));
if (svn_err) goto error;
/* Create the databases in the environment. */
svn_err = BDB_WRAP (fs, "creating 'nodes' table",
svn_fs_bdb__open_nodes_table (&bfd->nodes, bfd->env,
TRUE));
if (svn_err) goto error;
svn_err = BDB_WRAP (fs, "creating 'revisions' table",
svn_fs_bdb__open_revisions_table (&bfd->revisions,
bfd->env, TRUE));
if (svn_err) goto error;
svn_err = BDB_WRAP (fs, "creating 'transactions' table",
svn_fs_bdb__open_transactions_table (&bfd->transactions,
bfd->env, TRUE));
if (svn_err) goto error;
svn_err = BDB_WRAP (fs, "creating 'copies' table",
svn_fs_bdb__open_copies_table (&bfd->copies,
bfd->env, TRUE));
if (svn_err) goto error;
svn_err = BDB_WRAP (fs, "creating 'changes' table",
svn_fs_bdb__open_changes_table (&bfd->changes,
bfd->env, TRUE));
if (svn_err) goto error;
svn_err = BDB_WRAP (fs, "creating 'representations' table",
svn_fs_bdb__open_reps_table (&bfd->representations,
bfd->env, TRUE));
if (svn_err) goto error;
svn_err = BDB_WRAP (fs, "creating 'strings' table",
svn_fs_bdb__open_strings_table (&bfd->strings,
bfd->env, TRUE));
if (svn_err) goto error;
svn_err = BDB_WRAP (fs, "creating 'uuids' table",
svn_fs_bdb__open_uuids_table (&bfd->uuids,
bfd->env, TRUE));
if (svn_err) goto error;
/* Initialize the DAG subsystem. */
svn_err = svn_fs_base__dag_init_fs (fs);
if (svn_err) goto error;
return SVN_NO_ERROR;
error:
svn_error_clear (cleanup_fs (fs));
return svn_err;
}
/* Gaining access to an existing Berkeley DB-based filesystem. */
static svn_error_t *
base_open (svn_fs_t *fs, const char *path, apr_pool_t *pool)
{
svn_error_t *svn_err;
const char *path_native;
base_fs_data_t *bfd;
SVN_ERR (check_already_open (fs));
apr_pool_cleanup_register (fs->pool, fs, cleanup_fs_apr,
apr_pool_cleanup_null);
bfd = apr_pcalloc (fs->pool, sizeof (*bfd));
fs->vtable = &fs_vtable;
fs->fsap_data = bfd;
/* Initialize paths. */
fs->path = apr_pstrdup (fs->pool, path);
svn_err = allocate_env (fs);
if (svn_err) goto error;
/* Open the Berkeley DB environment. */
SVN_ERR (svn_utf_cstring_from_utf8 (&path_native, fs->path, fs->pool));
svn_err = BDB_WRAP (fs, "opening environment",
bfd->env->open (bfd->env, path_native,
(DB_CREATE
| DB_INIT_LOCK
| DB_INIT_LOG
| DB_INIT_MPOOL
| DB_INIT_TXN),
0666));
if (svn_err) goto error;
/* Open the various databases. */
svn_err = BDB_WRAP (fs, "opening 'nodes' table",
svn_fs_bdb__open_nodes_table (&bfd->nodes,
bfd->env, FALSE));
if (svn_err) goto error;
svn_err = BDB_WRAP (fs, "opening 'revisions' table",
svn_fs_bdb__open_revisions_table (&bfd->revisions,
bfd->env, FALSE));
if (svn_err) goto error;
svn_err = BDB_WRAP (fs, "opening 'transactions' table",
svn_fs_bdb__open_transactions_table (&bfd->transactions,
bfd->env, FALSE));
if (svn_err) goto error;
svn_err = BDB_WRAP (fs, "opening 'copies' table",
svn_fs_bdb__open_copies_table (&bfd->copies,
bfd->env, FALSE));
if (svn_err) goto error;
svn_err = BDB_WRAP (fs, "opening 'changes' table",
svn_fs_bdb__open_changes_table (&bfd->changes,
bfd->env, FALSE));
if (svn_err) goto error;
svn_err = BDB_WRAP (fs, "opening 'representations' table",
svn_fs_bdb__open_reps_table (&bfd->representations,
bfd->env, FALSE));
if (svn_err) goto error;
svn_err = BDB_WRAP (fs, "opening 'strings' table",
svn_fs_bdb__open_strings_table (&bfd->strings,
bfd->env, FALSE));
if (svn_err) goto error;
svn_err = BDB_WRAP (fs, "opening 'uuids' table",
svn_fs_bdb__open_uuids_table (&bfd->uuids,
bfd->env, FALSE));
if (svn_err) goto error;
return SVN_NO_ERROR;
error:
svn_error_clear (cleanup_fs (fs));
return svn_err;
}
/* Running recovery on a Berkeley DB-based filesystem. */
static svn_error_t *
base_bdb_recover (const char *path,
apr_pool_t *pool)
{
DB_ENV *env;
const char *path_native;
bdb_errcall_baton_t *ec_baton;
SVN_BDB_ERR (ec_baton, create_env (&env, &ec_baton, pool));
/* Here's the comment copied from db_recover.c:
Initialize the environment -- we don't actually do anything
else, that all that's needed to run recovery.
Note that we specify a private environment, as we're about to
create a region, and we don't want to leave it around. If we
leave the region around, the application that should create it
will simply join it instead, and will then be running with
incorrectly sized (and probably terribly small) caches. */
SVN_ERR (svn_utf_cstring_from_utf8 (&path_native, path, pool));
SVN_BDB_ERR (ec_baton, env->open (env, path_native,
(DB_RECOVER | DB_CREATE | DB_INIT_LOCK
| DB_INIT_LOG | DB_INIT_MPOOL
| DB_INIT_TXN | DB_PRIVATE),
0666));
SVN_BDB_ERR (ec_baton, env->close (env, 0));
return SVN_NO_ERROR;
}
/* This is the same as base_bdb_recover, but runs catastrophic
recovery instead of normal recovery. */
static svn_error_t *
bdb_catastrophic_recover (const char *path,
apr_pool_t *pool)
{
DB_ENV *env;
const char *path_native;
bdb_errcall_baton_t *ec_baton;
SVN_BDB_ERR (ec_baton, create_env (&env, &ec_baton, pool));
SVN_ERR (svn_utf_cstring_from_utf8 (&path_native, path, pool));
SVN_BDB_ERR (ec_baton, env->open (env, path_native,
(DB_RECOVER_FATAL | DB_CREATE
| DB_INIT_LOCK | DB_INIT_LOG
| DB_INIT_MPOOL | DB_INIT_TXN
| DB_PRIVATE),
0666));
SVN_BDB_ERR (ec_baton, env->close (env, 0));
return SVN_NO_ERROR;
}
/* Running the 'archive' command on a Berkeley DB-based filesystem. */
static svn_error_t *
base_bdb_logfiles (apr_array_header_t **logfiles,
const char *path,
svn_boolean_t only_unused,
apr_pool_t *pool)
{
DB_ENV *env;
const char *path_native;
char **filelist;
char **filename;
bdb_errcall_baton_t *ec_baton;
u_int32_t flags = only_unused ? 0 : DB_ARCH_LOG;
*logfiles = apr_array_make (pool, 4, sizeof (const char *));
SVN_BDB_ERR (ec_baton, create_env (&env, &ec_baton, pool));
SVN_ERR (svn_utf_cstring_from_utf8 (&path_native, path, pool));
SVN_BDB_ERR (ec_baton, env->open (env, path_native,
(DB_CREATE | DB_INIT_LOCK | DB_INIT_LOG
| DB_INIT_MPOOL | DB_INIT_TXN),
0666));
SVN_BDB_ERR (ec_baton, env->log_archive (env, &filelist, flags));
if (filelist == NULL)
{
SVN_BDB_ERR (ec_baton, env->close (env, 0));
return SVN_NO_ERROR;
}
for (filename = filelist; *filename != NULL; ++filename)
{
APR_ARRAY_PUSH (*logfiles, const char *) = apr_pstrdup (pool, *filename);
}
free (filelist);
SVN_BDB_ERR (ec_baton, env->close (env, 0));
return SVN_NO_ERROR;
}
/* Copying a live Berkeley DB-base filesystem. */
/**
* Delete all unused log files from DBD enviroment at @a live_path that exist
* in @a backup_path.
*/
static svn_error_t *
svn_fs_base__clean_logs(const char *live_path,
const char *backup_path,
apr_pool_t *pool)
{
apr_array_header_t *logfiles;
SVN_ERR (base_bdb_logfiles (&logfiles,
live_path,
TRUE, /* Only unused logs */
pool));
{ /* Process unused logs from live area */
int idx;
apr_pool_t *sub_pool = svn_pool_create (pool);
/* Process log files. */
for (idx = 0; idx < logfiles->nelts; idx++)
{
const char *log_file = APR_ARRAY_IDX (logfiles, idx, const char *);
const char *live_log_path;
const char *backup_log_path;
svn_pool_clear (sub_pool);
live_log_path = svn_path_join (live_path, log_file, sub_pool);
backup_log_path = svn_path_join (backup_path, log_file, sub_pool);
{ /* Compare files. No point in using MD5 and wasting CPU cycles as we
got full copies of both logs */
svn_boolean_t files_match = FALSE;
svn_node_kind_t kind;
/* Check to see if there is a corresponding log file in the backup
directory */
SVN_ERR (svn_io_check_path (backup_log_path, &kind, pool));
/* If the copy of the log exists, compare them */
if (kind == svn_node_file)
SVN_ERR (svn_io_files_contents_same_p (&files_match,
live_log_path,
backup_log_path,
sub_pool));
/* If log files do not match, go to the next log filr. */
if (files_match == FALSE)
continue;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -