📄 fs.c
字号:
}; 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;}static svn_error_t *base_serialized_init(svn_fs_t *fs, apr_pool_t *common_pool, apr_pool_t *pool){ /* Nothing to do here. */ return SVN_NO_ERROR;}/* Creating a new filesystem */static fs_vtable_t fs_vtable = { base_serialized_init, 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, svn_fs_base__lock, svn_fs_base__generate_lock_token, svn_fs_base__unlock, svn_fs_base__get_lock, svn_fs_base__get_locks, base_bdb_set_errcall,};/* Where the format number is stored. */#define FORMAT_FILE "format"/* Depending on CREATE, create or open the environment and databases for filesystem FS in PATH. Use POOL for temporary allocations. */static svn_error_t *open_databases(svn_fs_t *fs, svn_boolean_t create, const char *path, apr_pool_t *pool){ base_fs_data_t *bfd; SVN_ERR(check_already_open(fs)); 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); if (create) SVN_ERR(bdb_write_config(fs)); /* Create the Berkeley DB environment. */ { svn_error_t *err = svn_fs_bdb__open(&(bfd->bdb), path, SVN_BDB_STANDARD_ENV_FLAGS, 0666, fs->pool); if (err) { if (create) return svn_error_createf (err->apr_err, err, _("Berkeley DB error for filesystem '%s'" " while creating environment:\n"), fs->path); else return svn_error_createf (err->apr_err, err, _("Berkeley DB error for filesystem '%s'" " while opening environment:\n"), fs->path); } } /* We must register the FS cleanup function *after* opening the environment, so that it's run before the environment baton cleanup. */ apr_pool_cleanup_register(fs->pool, fs, cleanup_fs_apr, apr_pool_cleanup_null); /* Create the databases in the environment. */ SVN_ERR(BDB_WRAP(fs, (create ? "creating 'nodes' table" : "opening 'nodes' table"), svn_fs_bdb__open_nodes_table(&bfd->nodes, bfd->bdb->env, create))); SVN_ERR(BDB_WRAP(fs, (create ? "creating 'revisions' table" : "opening 'revisions' table"), svn_fs_bdb__open_revisions_table(&bfd->revisions, bfd->bdb->env, create))); SVN_ERR(BDB_WRAP(fs, (create ? "creating 'transactions' table" : "opening 'transactions' table"), svn_fs_bdb__open_transactions_table(&bfd->transactions, bfd->bdb->env, create))); SVN_ERR(BDB_WRAP(fs, (create ? "creating 'copies' table" : "opening 'copies' table"), svn_fs_bdb__open_copies_table(&bfd->copies, bfd->bdb->env, create))); SVN_ERR(BDB_WRAP(fs, (create ? "creating 'changes' table" : "opening 'changes' table"), svn_fs_bdb__open_changes_table(&bfd->changes, bfd->bdb->env, create))); SVN_ERR(BDB_WRAP(fs, (create ? "creating 'representations' table" : "opening 'representations' table"), svn_fs_bdb__open_reps_table(&bfd->representations, bfd->bdb->env, create))); SVN_ERR(BDB_WRAP(fs, (create ? "creating 'strings' table" : "opening 'strings' table"), svn_fs_bdb__open_strings_table(&bfd->strings, bfd->bdb->env, create))); SVN_ERR(BDB_WRAP(fs, (create ? "creating 'uuids' table" : "opening 'uuids' table"), svn_fs_bdb__open_uuids_table(&bfd->uuids, bfd->bdb->env, create))); SVN_ERR(BDB_WRAP(fs, (create ? "creating 'locks' table" : "opening 'locks' table"), svn_fs_bdb__open_locks_table(&bfd->locks, bfd->bdb->env, create))); SVN_ERR(BDB_WRAP(fs, (create ? "creating 'lock-nodes' table" : "opening 'lock-nodes' table"), svn_fs_bdb__open_lock_tokens_table(&bfd->lock_tokens, bfd->bdb->env, create))); return SVN_NO_ERROR;}static svn_error_t *base_create(svn_fs_t *fs, const char *path, apr_pool_t *pool){ int format = SVN_FS_BASE__FORMAT_NUMBER; /* Create the environment and databases. */ svn_error_t *svn_err = open_databases(fs, TRUE, path, pool); if (svn_err) goto error; /* Initialize the DAG subsystem. */ svn_err = svn_fs_base__dag_init_fs(fs); if (svn_err) goto error; /* See if we had an explicitly specified pre 1.4 compatible. */ if (fs->config && apr_hash_get(fs->config, SVN_FS_CONFIG_PRE_1_4_COMPATIBLE, APR_HASH_KEY_STRING)) format = 1; /* This filesystem is ready. Stamp it with a format number. */ svn_err = svn_io_write_version_file (svn_path_join(fs->path, FORMAT_FILE, pool), format, pool); 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. *//* Return the error SVN_ERR_FS_UNSUPPORTED_FORMAT if FS's format number is not the same as the format number supported by this Subversion. */static svn_error_t *check_format(int format){ /* We support format 1 and 2 simultaneously. */ if (format == 1 && SVN_FS_BASE__FORMAT_NUMBER == 2) return SVN_NO_ERROR; if (format != SVN_FS_BASE__FORMAT_NUMBER) { return svn_error_createf (SVN_ERR_FS_UNSUPPORTED_FORMAT, NULL, _("Expected FS format '%d'; found format '%d'"), SVN_FS_BASE__FORMAT_NUMBER, format); } return SVN_NO_ERROR;}static svn_error_t *base_open(svn_fs_t *fs, const char *path, apr_pool_t *pool){ int format; /* Create the environment and databases. */ svn_error_t *svn_err = open_databases(fs, FALSE, path, pool); if (svn_err) goto error; /* Read the FS format number. */ svn_err = svn_io_read_version_file (&format, svn_path_join(fs->path, FORMAT_FILE, pool), pool); if (svn_err && APR_STATUS_IS_ENOENT(svn_err->apr_err)) { /* Pre-1.2 filesystems did not have a format file (you could say they were format "0"), so they get upgraded on the fly. */ svn_error_clear(svn_err); format = SVN_FS_BASE__FORMAT_NUMBER; svn_err = svn_io_write_version_file (svn_path_join(fs->path, FORMAT_FILE, pool), format, pool); if (svn_err) goto error; } else if (svn_err) goto error; /* Now we've got a format number no matter what. */ ((base_fs_data_t *) fs->fsap_data)->format = format; SVN_ERR(check_format(format)); return SVN_NO_ERROR; error: svn_error_clear(cleanup_fs(fs)); return svn_err;}/* Running recovery on a Berkeley DB-based filesystem. *//* Recover a database at PATH. Perform catastrophic recovery if FATAL is TRUE. Use POOL for temporary allocation. */static svn_error_t *bdb_recover(const char *path, svn_boolean_t fatal, apr_pool_t *pool){ bdb_env_baton_t *bdb; /* 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. */ /* Note that since we're using a private environment, we shoudl /not/ initialize locking. We want the environment files to go away. */ SVN_ERR(svn_fs_bdb__open(&bdb, path, ((fatal ? DB_RECOVER_FATAL : DB_RECOVER) | SVN_BDB_PRIVATE_ENV_FLAGS), 0666, pool)); SVN_ERR(svn_fs_bdb__close(bdb)); return SVN_NO_ERROR;}static svn_error_t *base_bdb_recover(const char *path, apr_pool_t *pool){ return bdb_recover(path, FALSE, pool);}/* 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){ bdb_env_baton_t *bdb; char **filelist; char **filename; u_int32_t flags = only_unused ? 0 : DB_ARCH_LOG; *logfiles = apr_array_make(pool, 4, sizeof(const char *)); SVN_ERR(svn_fs_bdb__open(&bdb, path, SVN_BDB_STANDARD_ENV_FLAGS, 0666, pool)); SVN_BDB_ERR(bdb, bdb->env->log_archive(bdb->env, &filelist, flags)); if (filelist == NULL) return svn_fs_bdb__close(bdb); for (filename = filelist; *filename != NULL; ++filename) { APR_ARRAY_PUSH(*logfiles, const char *) = apr_pstrdup(pool, *filename); } free(filelist); return svn_fs_bdb__close(bdb);}/* 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));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -