/* This implements the fs_library_vtable_t.hotcopy() API. Copy a possibly live Subversion filesystem SRC_FS from SRC_PATH to a DST_FS at DEST_PATH. If INCREMENTAL is TRUE, make an effort not to re-copy data which already exists in DST_FS. The CLEAN_LOGS argument is ignored and included for Subversion 1.0.x compatibility. Perform all temporary allocations in POOL. */ static svn_error_t * fs_hotcopy(svn_fs_t *src_fs, svn_fs_t *dst_fs, const char *src_path, const char *dst_path, svn_boolean_t clean_logs, svn_boolean_t incremental, svn_cancel_func_t cancel_func, void *cancel_baton, apr_pool_t *pool) { SVN_ERR(svn_fs__check_fs(src_fs, FALSE)); SVN_ERR(initialize_fs_struct(src_fs)); SVN_ERR(svn_fs_fs__open(src_fs, src_path, pool)); SVN_ERR(svn_fs_fs__initialize_caches(src_fs, pool)); SVN_ERR(fs_serialized_init(src_fs, pool, pool)); SVN_ERR(svn_fs__check_fs(dst_fs, FALSE)); SVN_ERR(initialize_fs_struct(dst_fs)); /* In INCREMENTAL mode, svn_fs_fs__hotcopy() will open DST_FS. Otherwise, it's not an FS yet --- possibly just an empty dir --- so can't be opened. */ return svn_fs_fs__hotcopy(src_fs, dst_fs, src_path, dst_path, incremental, cancel_func, cancel_baton, pool); }
svn_error_t * svn_fs_base__populate_uuid(svn_fs_t *fs, apr_pool_t *scratch_pool) { SVN_ERR(svn_fs__check_fs(fs, TRUE)); /* We hit the database. */ { const char *uuid; struct get_uuid_args args; args.idx = 1; args.uuid = &uuid; SVN_ERR(svn_fs_base__retry_txn(fs, txn_body_get_uuid, &args, FALSE, scratch_pool)); if (uuid) { /* Toss what we find into the cache. */ fs->uuid = apr_pstrdup(fs->pool, uuid); } } return SVN_NO_ERROR; }
/* This implements the fs_library_vtable_t.hotcopy() API. Copy a possibly live Subversion filesystem SRC_FS from SRC_PATH to a DST_FS at DEST_PATH. If INCREMENTAL is TRUE, make an effort not to re-copy data which already exists in DST_FS. The CLEAN_LOGS argument is ignored and included for Subversion 1.0.x compatibility. The NOTIFY_FUNC and NOTIFY_BATON arguments are also currently ignored. Perform all temporary allocations in SCRATCH_POOL. */ static svn_error_t * x_hotcopy(svn_fs_t *src_fs, svn_fs_t *dst_fs, const char *src_path, const char *dst_path, svn_boolean_t clean_logs, svn_boolean_t incremental, svn_fs_hotcopy_notify_t notify_func, void *notify_baton, svn_cancel_func_t cancel_func, void *cancel_baton, svn_mutex__t *common_pool_lock, apr_pool_t *scratch_pool, apr_pool_t *common_pool) { /* Open the source repo as usual. */ SVN_ERR(x_open(src_fs, src_path, common_pool_lock, scratch_pool, common_pool)); if (cancel_func) SVN_ERR(cancel_func(cancel_baton)); SVN_ERR(svn_fs__check_fs(dst_fs, FALSE)); SVN_ERR(initialize_fs_struct(dst_fs)); /* In INCREMENTAL mode, svn_fs_x__hotcopy() will open DST_FS. Otherwise, it's not an FS yet --- possibly just an empty dir --- so can't be opened. */ return svn_fs_x__hotcopy(src_fs, dst_fs, src_path, dst_path, incremental, notify_func, notify_baton, cancel_func, cancel_baton, common_pool_lock, scratch_pool, common_pool); }
svn_error_t * svn_fs_base__lock(svn_lock_t **lock, svn_fs_t *fs, const char *path, const char *token, const char *comment, svn_boolean_t is_dav_comment, apr_time_t expiration_date, svn_revnum_t current_rev, svn_boolean_t steal_lock, apr_pool_t *pool) { struct lock_args args; SVN_ERR(svn_fs__check_fs(fs, TRUE)); args.lock_p = lock; args.path = svn_fs__canonicalize_abspath(path, pool); args.token = token; args.comment = comment; args.is_dav_comment = is_dav_comment; args.steal_lock = steal_lock; args.expiration_date = expiration_date; args.current_rev = current_rev; return svn_fs_base__retry_txn(fs, txn_body_lock, &args, FALSE, pool); }
/* This implements the fs_library_vtable_t.uprade_fs() API. */ static svn_error_t * fs_upgrade(svn_fs_t *fs, const char *path, apr_pool_t *pool, apr_pool_t *common_pool) { SVN_ERR(svn_fs__check_fs(fs, FALSE)); initialize_fs_struct(fs); SVN_ERR(svn_fs_fs__open(fs, path, pool)); SVN_ERR(fs_serialized_init(fs, common_pool, pool)); return svn_fs_fs__upgrade(fs, pool); }
static svn_error_t * base_bdb_set_errcall(svn_fs_t *fs, void (*db_errcall_fcn)(const char *errpfx, char *msg)) { base_fs_data_t *bfd = fs->fsap_data; SVN_ERR(svn_fs__check_fs(fs, TRUE)); bfd->bdb->error_info->user_callback = db_errcall_fcn; return SVN_NO_ERROR; }
/* This implements the fs_library_vtable_t.create() API. Create a new fsfs-backed Subversion filesystem at path PATH and link it into *FS. Perform temporary allocations in POOL, and fs-global allocations in COMMON_POOL. */ static svn_error_t * fs_create(svn_fs_t *fs, const char *path, apr_pool_t *pool, apr_pool_t *common_pool) { SVN_ERR(svn_fs__check_fs(fs, FALSE)); SVN_ERR(initialize_fs_struct(fs)); SVN_ERR(svn_fs_fs__create(fs, path, pool)); SVN_ERR(svn_fs_fs__initialize_caches(fs, pool)); return fs_serialized_init(fs, common_pool, pool); }
svn_error_t * svn_fs_base__get_lock(svn_lock_t **lock, svn_fs_t *fs, const char *path, apr_pool_t *pool) { struct lock_token_get_args args; SVN_ERR(svn_fs__check_fs(fs, TRUE)); args.path = svn_fs__canonicalize_abspath(path, pool); args.lock_p = lock; return svn_fs_base__retry_txn(fs, txn_body_get_lock, &args, FALSE, pool); }
svn_error_t * svn_fs_base__get_locks(svn_fs_t *fs, const char *path, svn_fs_get_locks_callback_t get_locks_func, void *get_locks_baton, apr_pool_t *pool) { struct locks_get_args args; SVN_ERR(svn_fs__check_fs(fs, TRUE)); args.path = svn_fs__canonicalize_abspath(path, pool); args.get_locks_func = get_locks_func; args.get_locks_baton = get_locks_baton; return svn_fs_base__retry_txn(fs, txn_body_get_locks, &args, FALSE, pool); }
svn_error_t * svn_fs_base__unlock(svn_fs_t *fs, const char *path, const char *token, svn_boolean_t break_lock, apr_pool_t *pool) { struct unlock_args args; SVN_ERR(svn_fs__check_fs(fs, TRUE)); args.path = svn_fs__canonicalize_abspath(path, pool); args.token = token; args.break_lock = break_lock; return svn_fs_base__retry_txn(fs, txn_body_unlock, &args, TRUE, pool); }
static svn_error_t * fs_freeze(svn_fs_t *fs, svn_fs_freeze_func_t freeze_func, void *freeze_baton, apr_pool_t *pool) { struct fs_freeze_baton_t b; b.fs = fs; b.freeze_func = freeze_func; b.freeze_baton = freeze_baton; SVN_ERR(svn_fs__check_fs(fs, TRUE)); SVN_ERR(svn_fs_fs__with_write_lock(fs, fs_freeze_body, &b, pool)); return SVN_NO_ERROR; }
static svn_error_t * fs_pack(svn_fs_t *fs, const char *path, svn_fs_pack_notify_t notify_func, void *notify_baton, svn_cancel_func_t cancel_func, void *cancel_baton, apr_pool_t *pool) { SVN_ERR(svn_fs__check_fs(fs, FALSE)); SVN_ERR(initialize_fs_struct(fs)); SVN_ERR(svn_fs_fs__open(fs, path, pool)); SVN_ERR(svn_fs_fs__initialize_caches(fs, pool)); SVN_ERR(fs_serialized_init(fs, pool, pool)); return svn_fs_fs__pack(fs, notify_func, notify_baton, cancel_func, cancel_baton, pool); }
static svn_error_t * x_freeze(svn_fs_t *fs, svn_fs_freeze_func_t freeze_func, void *freeze_baton, apr_pool_t *scratch_pool) { x_freeze_baton_t b; b.fs = fs; b.freeze_func = freeze_func; b.freeze_baton = freeze_baton; SVN_ERR(svn_fs__check_fs(fs, TRUE)); SVN_ERR(svn_fs_x__with_pack_lock(fs, x_freeze_body2, &b, scratch_pool)); return SVN_NO_ERROR; }
static svn_error_t * fs_verify(svn_fs_t *fs, const char *path, svn_revnum_t start, svn_revnum_t end, svn_fs_progress_notify_func_t notify_func, void *notify_baton, svn_cancel_func_t cancel_func, void *cancel_baton, apr_pool_t *pool, apr_pool_t *common_pool) { SVN_ERR(svn_fs__check_fs(fs, FALSE)); SVN_ERR(initialize_fs_struct(fs)); SVN_ERR(svn_fs_fs__open(fs, path, pool)); SVN_ERR(svn_fs_fs__initialize_caches(fs, pool)); SVN_ERR(fs_serialized_init(fs, common_pool, pool)); return svn_fs_fs__verify(fs, start, end, notify_func, notify_baton, cancel_func, cancel_baton, pool); }
/* This implements the fs_library_vtable_t.create() API. Create a new fsfs-backed Subversion filesystem at path PATH and link it into *FS. Perform temporary allocations in POOL, and fs-global allocations in COMMON_POOL. The latter must be serialized using COMMON_POOL_LOCK. */ static svn_error_t * fs_create(svn_fs_t *fs, const char *path, svn_mutex__t *common_pool_lock, apr_pool_t *pool, apr_pool_t *common_pool) { SVN_ERR(svn_fs__check_fs(fs, FALSE)); SVN_ERR(initialize_fs_struct(fs)); SVN_ERR(svn_fs_fs__create(fs, path, pool)); SVN_ERR(svn_fs_fs__initialize_caches(fs, pool)); SVN_MUTEX__WITH_LOCK(common_pool_lock, fs_serialized_init(fs, common_pool, pool)); return SVN_NO_ERROR; }
static svn_error_t * fs_freeze(svn_fs_t *fs, svn_fs_freeze_func_t freeze_func, void *freeze_baton, apr_pool_t *pool) { fs_fs_data_t *ffd = fs->fsap_data; struct fs_freeze_baton_t b; b.fs = fs; b.freeze_func = freeze_func; b.freeze_baton = freeze_baton; SVN_ERR(svn_fs__check_fs(fs, TRUE)); if (ffd->format >= SVN_FS_FS__MIN_PACK_LOCK_FORMAT) SVN_ERR(svn_fs_fs__with_pack_lock(fs, fs_freeze_body2, &b, pool)); else SVN_ERR(fs_freeze_body2(&b, pool)); return SVN_NO_ERROR; }
svn_error_t * svn_fs_base__set_uuid(svn_fs_t *fs, const char *uuid, apr_pool_t *pool) { struct set_uuid_args args; SVN_ERR(svn_fs__check_fs(fs, TRUE)); if (! uuid) uuid = svn_uuid_generate(pool); args.idx = 1; args.uuid = uuid; SVN_ERR(svn_fs_base__retry_txn(fs, txn_body_set_uuid, &args, TRUE, pool)); /* Toss our value into the cache. */ if (uuid) fs->uuid = apr_pstrdup(fs->pool, uuid); return SVN_NO_ERROR; }
svn_error_t * svn_fs_base__get_uuid(svn_fs_t *fs, const char **uuid, apr_pool_t *pool) { base_fs_data_t *bfd = fs->fsap_data; SVN_ERR(svn_fs__check_fs(fs, TRUE)); /* Check for a cached UUID first. Failing that, we hit the database. */ if (bfd->uuid) { *uuid = apr_pstrdup(pool, bfd->uuid); } else { struct get_uuid_args args; apr_pool_t *scratch_pool = svn_pool_create(pool); args.idx = 1; args.uuid = uuid; SVN_ERR(svn_fs_base__retry_txn(fs, txn_body_get_uuid, &args, FALSE, scratch_pool)); if (*uuid) { *uuid = apr_pstrdup(pool, *uuid); /* Toss what we find into the cache. */ bfd->uuid = apr_pstrdup(fs->pool, *uuid); } svn_pool_destroy(scratch_pool); } return SVN_NO_ERROR; }
/* This implements the fs_library_vtable_t.open() API. Open an FSX Subversion filesystem located at PATH, set *FS to point to the correct vtable for the filesystem. Use SCRATCH_POOL for any temporary allocations, and COMMON_POOL for fs-global allocations. The latter must be serialized using COMMON_POOL_LOCK. */ static svn_error_t * x_open(svn_fs_t *fs, const char *path, svn_mutex__t *common_pool_lock, apr_pool_t *scratch_pool, apr_pool_t *common_pool) { apr_pool_t *subpool = svn_pool_create(scratch_pool); SVN_ERR(svn_fs__check_fs(fs, FALSE)); SVN_ERR(initialize_fs_struct(fs)); SVN_ERR(svn_fs_x__open(fs, path, subpool)); SVN_ERR(svn_fs_x__initialize_caches(fs, subpool)); SVN_MUTEX__WITH_LOCK(common_pool_lock, x_serialized_init(fs, common_pool, subpool)); svn_pool_destroy(subpool); return SVN_NO_ERROR; }
/* 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, int format, const char *path, apr_pool_t *pool) { base_fs_data_t *bfd; SVN_ERR(svn_fs__check_fs(fs, FALSE)); 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 ? N_("creating 'nodes' table") : N_("opening 'nodes' table")), svn_fs_bdb__open_nodes_table(&bfd->nodes, bfd->bdb->env, create))); SVN_ERR(BDB_WRAP(fs, (create ? N_("creating 'revisions' table") : N_("opening 'revisions' table")), svn_fs_bdb__open_revisions_table(&bfd->revisions, bfd->bdb->env, create))); SVN_ERR(BDB_WRAP(fs, (create ? N_("creating 'transactions' table") : N_("opening 'transactions' table")), svn_fs_bdb__open_transactions_table(&bfd->transactions, bfd->bdb->env, create))); SVN_ERR(BDB_WRAP(fs, (create ? N_("creating 'copies' table") : N_("opening 'copies' table")), svn_fs_bdb__open_copies_table(&bfd->copies, bfd->bdb->env, create))); SVN_ERR(BDB_WRAP(fs, (create ? N_("creating 'changes' table") : N_("opening 'changes' table")), svn_fs_bdb__open_changes_table(&bfd->changes, bfd->bdb->env, create))); SVN_ERR(BDB_WRAP(fs, (create ? N_("creating 'representations' table") : N_("opening 'representations' table")), svn_fs_bdb__open_reps_table(&bfd->representations, bfd->bdb->env, create))); SVN_ERR(BDB_WRAP(fs, (create ? N_("creating 'strings' table") : N_("opening 'strings' table")), svn_fs_bdb__open_strings_table(&bfd->strings, bfd->bdb->env, create))); SVN_ERR(BDB_WRAP(fs, (create ? N_("creating 'uuids' table") : N_("opening 'uuids' table")), svn_fs_bdb__open_uuids_table(&bfd->uuids, bfd->bdb->env, create))); SVN_ERR(BDB_WRAP(fs, (create ? N_("creating 'locks' table") : N_("opening 'locks' table")), svn_fs_bdb__open_locks_table(&bfd->locks, bfd->bdb->env, create))); SVN_ERR(BDB_WRAP(fs, (create ? N_("creating 'lock-tokens' table") : N_("opening 'lock-tokens' table")), svn_fs_bdb__open_lock_tokens_table(&bfd->lock_tokens, bfd->bdb->env, create))); if (format >= SVN_FS_BASE__MIN_NODE_ORIGINS_FORMAT) { SVN_ERR(BDB_WRAP(fs, (create ? N_("creating 'node-origins' table") : N_("opening 'node-origins' table")), svn_fs_bdb__open_node_origins_table(&bfd->node_origins, bfd->bdb->env, create))); } if (format >= SVN_FS_BASE__MIN_MISCELLANY_FORMAT) { SVN_ERR(BDB_WRAP(fs, (create ? N_("creating 'miscellaneous' table") : N_("opening 'miscellaneous' table")), svn_fs_bdb__open_miscellaneous_table(&bfd->miscellaneous, bfd->bdb->env, create))); } if (format >= SVN_FS_BASE__MIN_REP_SHARING_FORMAT) { SVN_ERR(BDB_WRAP(fs, (create ? N_("creating 'checksum-reps' table") : N_("opening 'checksum-reps' table")), svn_fs_bdb__open_checksum_reps_table(&bfd->checksum_reps, bfd->bdb->env, create))); } return SVN_NO_ERROR; }