Exemplo n.º 1
0
/* Create a packed filesystem in DIR.  Set the shard size to
   SHARD_SIZE and create NUM_REVS number of revisions (in addition to
   r0).  Use POOL for allocations.  After this function successfully
   completes, the filesystem's youngest revision number will be the
   same as NUM_REVS.  */
static svn_error_t *
create_packed_filesystem(const char *dir,
                         const svn_test_opts_t *opts,
                         int num_revs,
                         int shard_size,
                         apr_pool_t *pool)
{
  svn_fs_t *fs;
  svn_fs_txn_t *txn;
  svn_fs_root_t *txn_root;
  const char *conflict;
  svn_revnum_t after_rev;
  apr_pool_t *subpool = svn_pool_create(pool);
  apr_pool_t *iterpool;
  int version;

  /* Create a filesystem, then close it */
  SVN_ERR(svn_test__create_fs(&fs, dir, opts, subpool));
  svn_pool_destroy(subpool);

  subpool = svn_pool_create(pool);

  /* Rewrite the format file */
  SVN_ERR(svn_io_read_version_file(&version,
                                   svn_dirent_join(dir, "format", subpool),
                                   subpool));
  SVN_ERR(write_format(dir, version, shard_size, subpool));

  /* Reopen the filesystem */
  SVN_ERR(svn_fs_open(&fs, dir, NULL, subpool));

  /* Revision 1: the Greek tree */
  SVN_ERR(svn_fs_begin_txn(&txn, fs, 0, subpool));
  SVN_ERR(svn_fs_txn_root(&txn_root, txn, subpool));
  SVN_ERR(svn_test__create_greek_tree(txn_root, subpool));
  SVN_ERR(svn_fs_commit_txn(&conflict, &after_rev, txn, subpool));
  SVN_TEST_ASSERT(SVN_IS_VALID_REVNUM(after_rev));

  /* Revisions 2 thru NUM_REVS-1: content tweaks to "iota". */
  iterpool = svn_pool_create(subpool);
  while (after_rev < num_revs)
    {
      svn_pool_clear(iterpool);
      SVN_ERR(svn_fs_begin_txn(&txn, fs, after_rev, iterpool));
      SVN_ERR(svn_fs_txn_root(&txn_root, txn, iterpool));
      SVN_ERR(svn_test__set_file_contents(txn_root, "iota",
                                          get_rev_contents(after_rev + 1,
                                                           iterpool),
                                          iterpool));
      SVN_ERR(svn_fs_commit_txn(&conflict, &after_rev, txn, iterpool));
      SVN_TEST_ASSERT(SVN_IS_VALID_REVNUM(after_rev));
    }
  svn_pool_destroy(iterpool);
  svn_pool_destroy(subpool);

  /* Now pack the FS */
  return svn_fs_pack(dir, NULL, NULL, NULL, NULL, pool);
}
Exemplo n.º 2
0
/* Create a packed filesystem in DIR.  Set the shard size to SHARD_SIZE
   and create MAX_REV number of revisions.  Use POOL for allocations. */
static svn_error_t *
create_packed_filesystem(const char *dir,
                         svn_test_opts_t *opts,
                         int max_rev,
                         int shard_size,
                         apr_pool_t *pool)
{
  svn_fs_t *fs;
  svn_fs_txn_t *txn;
  svn_fs_root_t *txn_root;
  const char *conflict;
  svn_revnum_t after_rev;
  apr_pool_t *subpool = svn_pool_create(pool);
  apr_pool_t *iterpool;

  /* Create a filesystem, then close it */
  SVN_ERR(svn_test__create_fs(&fs, dir, opts, subpool));
  svn_pool_destroy(subpool);

  subpool = svn_pool_create(pool);

  /* Rewrite the format file */
  SVN_ERR(write_format(dir, SVN_FS_FS__MIN_PACKED_FORMAT,
                       shard_size, subpool));

  /* Reopen the filesystem */
  SVN_ERR(svn_fs_open(&fs, dir, NULL, subpool));

  /* Revision 1: the Greek tree */
  SVN_ERR(svn_fs_begin_txn(&txn, fs, 0, subpool));
  SVN_ERR(svn_fs_txn_root(&txn_root, txn, subpool));
  SVN_ERR(svn_test__create_greek_tree(txn_root, subpool));
  SVN_ERR(svn_fs_commit_txn(&conflict, &after_rev, txn, subpool));

  /* Revisions 2-11: A bunch of random changes. */
  iterpool = svn_pool_create(subpool);
  while (after_rev < max_rev + 1)
    {
      svn_pool_clear(iterpool);
      SVN_ERR(svn_fs_begin_txn(&txn, fs, after_rev, iterpool));
      SVN_ERR(svn_fs_txn_root(&txn_root, txn, iterpool));
      SVN_ERR(svn_test__set_file_contents(txn_root, "iota",
                                          get_rev_contents(after_rev + 1,
                                                           iterpool),
                                          iterpool));
      SVN_ERR(svn_fs_commit_txn(&conflict, &after_rev, txn, iterpool));
    }
  svn_pool_destroy(iterpool);
  svn_pool_destroy(subpool);

  /* Now pack the FS */
  return svn_fs_pack(dir, NULL, NULL, NULL, NULL, pool);
}
Exemplo n.º 3
0
static svn_error_t *
commit_packed_fs(const svn_test_opts_t *opts,
                 apr_pool_t *pool)
{
  svn_fs_t *fs;
  svn_fs_txn_t *txn;
  svn_fs_root_t *txn_root;
  const char *conflict;
  svn_revnum_t after_rev;

  /* Bail (with success) on known-untestable scenarios */
  if ((strcmp(opts->fs_type, "fsfs") != 0)
      || (opts->server_minor_version && (opts->server_minor_version < 6)))
    return SVN_NO_ERROR;

  /* Create the packed FS and open it. */
  SVN_ERR(create_packed_filesystem(REPO_NAME, opts, MAX_REV, 5, pool));
  SVN_ERR(svn_fs_open(&fs, REPO_NAME, NULL, pool));

  /* Now do a commit. */
  SVN_ERR(svn_fs_begin_txn(&txn, fs, MAX_REV, pool));
  SVN_ERR(svn_fs_txn_root(&txn_root, txn, pool));
  SVN_ERR(svn_test__set_file_contents(txn_root, "iota",
          "How much better is it to get wisdom than gold! and to get "
          "understanding rather to be chosen than silver!", pool));
  SVN_ERR(svn_fs_commit_txn(&conflict, &after_rev, txn, pool));
  SVN_TEST_ASSERT(SVN_IS_VALID_REVNUM(after_rev));

  return SVN_NO_ERROR;
}
Exemplo n.º 4
0
static svn_error_t *
recover_fully_packed(const svn_test_opts_t *opts,
                     apr_pool_t *pool)
{
  apr_pool_t *subpool;
  svn_fs_t *fs;
  svn_fs_txn_t *txn;
  svn_fs_root_t *txn_root;
  const char *conflict;
  svn_revnum_t after_rev;
  svn_error_t *err;

  /* Bail (with success) on known-untestable scenarios */
  if ((strcmp(opts->fs_type, "fsfs") != 0)
      || (opts->server_minor_version && (opts->server_minor_version < 7)))
    return SVN_NO_ERROR;

  /* Create a packed FS for which every revision will live in a pack
     digest file, and then recover it. */
  SVN_ERR(create_packed_filesystem(REPO_NAME, opts, MAX_REV, SHARD_SIZE, pool));
  SVN_ERR(svn_fs_recover(REPO_NAME, NULL, NULL, pool));

  /* Add another revision, re-pack, re-recover. */
  subpool = svn_pool_create(pool);
  SVN_ERR(svn_fs_open(&fs, REPO_NAME, NULL, subpool));
  SVN_ERR(svn_fs_begin_txn(&txn, fs, MAX_REV, subpool));
  SVN_ERR(svn_fs_txn_root(&txn_root, txn, subpool));
  SVN_ERR(svn_test__set_file_contents(txn_root, "A/mu", "new-mu", subpool));
  SVN_ERR(svn_fs_commit_txn(&conflict, &after_rev, txn, subpool));
  SVN_TEST_ASSERT(SVN_IS_VALID_REVNUM(after_rev));
  svn_pool_destroy(subpool);
  SVN_ERR(svn_fs_pack(REPO_NAME, NULL, NULL, NULL, NULL, pool));
  SVN_ERR(svn_fs_recover(REPO_NAME, NULL, NULL, pool));

  /* Now, delete the youngest revprop file, and recover again.  This
     time we want to see an error! */
  SVN_ERR(svn_io_remove_file2(
              svn_dirent_join_many(pool, REPO_NAME, PATH_REVPROPS_DIR,
                                   apr_psprintf(pool, "%ld/%ld",
                                                after_rev / SHARD_SIZE,
                                                after_rev),
                                   NULL),
              FALSE, pool));
  err = svn_fs_recover(REPO_NAME, NULL, NULL, pool);
  if (! err)
    return svn_error_create(SVN_ERR_TEST_FAILED, NULL,
                            "Expected SVN_ERR_FS_CORRUPT error; got none");
  if (err->apr_err != SVN_ERR_FS_CORRUPT)
    return svn_error_create(SVN_ERR_TEST_FAILED, err,
                            "Expected SVN_ERR_FS_CORRUPT error; got:");
  svn_error_clear(err);
  return SVN_NO_ERROR;
}
Exemplo n.º 5
0
static svn_error_t *
get_set_revprop_packed_fs(const svn_test_opts_t *opts,
                          apr_pool_t *pool)
{
  svn_fs_t *fs;
  svn_fs_txn_t *txn;
  svn_fs_root_t *txn_root;
  const char *conflict;
  svn_revnum_t after_rev;
  svn_string_t *prop_value;
  apr_pool_t *subpool;

  /* Bail (with success) on known-untestable scenarios */
  if ((strcmp(opts->fs_type, "fsfs") != 0)
      || (opts->server_minor_version && (opts->server_minor_version < 7)))
    return SVN_NO_ERROR;

  /* Create the packed FS and open it. */
  SVN_ERR(create_packed_filesystem(REPO_NAME, opts, MAX_REV, SHARD_SIZE, pool));
  SVN_ERR(svn_fs_open(&fs, REPO_NAME, NULL, pool));

  subpool = svn_pool_create(pool);
  /* Do a commit to trigger packing. */
  SVN_ERR(svn_fs_begin_txn(&txn, fs, MAX_REV, subpool));
  SVN_ERR(svn_fs_txn_root(&txn_root, txn, subpool));
  SVN_ERR(svn_test__set_file_contents(txn_root, "iota", "new-iota",  subpool));
  SVN_ERR(svn_fs_commit_txn(&conflict, &after_rev, txn, subpool));
  SVN_TEST_ASSERT(SVN_IS_VALID_REVNUM(after_rev));
  svn_pool_clear(subpool);

  /* Pack the repository. */
  SVN_ERR(svn_fs_pack(REPO_NAME, NULL, NULL, NULL, NULL, pool));

  /* Try to get revprop for revision 0. */
  SVN_ERR(svn_fs_revision_prop(&prop_value, fs, 0, SVN_PROP_REVISION_AUTHOR,
                               pool));

  /* Try to change revprop for revision 0. */
  SVN_ERR(svn_fs_change_rev_prop(fs, 0, SVN_PROP_REVISION_AUTHOR,
                                 svn_string_create("tweaked-author", pool),
                                 pool));

  return SVN_NO_ERROR;
}
Exemplo n.º 6
0
static svn_error_t *
changes_fetch_ordering(const char **msg,
                       svn_boolean_t msg_only,
                       svn_test_opts_t *opts,
                       apr_pool_t *pool)
{
  svn_fs_t *fs;
  svn_revnum_t youngest_rev = 0;
  const char *txn_name;
  svn_fs_txn_t *txn;
  svn_fs_root_t *txn_root, *rev_root;
  struct changes_args args;
  apr_pool_t *subpool = svn_pool_create(pool);
  apr_hash_index_t *hi;

  *msg = "verify ordered-ness of fetched compressed changes";

  if (msg_only)
    return SVN_NO_ERROR;

  /* Create a new fs and repos */
  SVN_ERR(svn_test__create_fs
          (&fs, "test-repo-changes-fetch-ordering",
           "bdb", pool));

  /*** REVISION 1: Make some files and dirs. ***/
  SVN_ERR(svn_fs_begin_txn(&txn, fs, youngest_rev, subpool));
  SVN_ERR(svn_fs_txn_root(&txn_root, txn, subpool));
  {
    static svn_test__txn_script_command_t script_entries[] = {
      { 'a', "dir1",        0 },
      { 'a', "file1",       "This is the file 'file1'.\n" },
      { 'a', "dir1/file2",  "This is the file 'file2'.\n" },
      { 'a', "dir1/file3",  "This is the file 'file3'.\n" },
      { 'a', "dir1/file4",  "This is the file 'file4'.\n" },
    };
    SVN_ERR(svn_test__txn_script_exec(txn_root, script_entries, 5, subpool));
  }
  SVN_ERR(svn_fs_commit_txn(NULL, &youngest_rev, txn, subpool));
  svn_pool_clear(subpool);

  /*** REVISION 2: Delete and add some stuff, non-depth-first. ***/
  SVN_ERR(svn_fs_begin_txn(&txn, fs, youngest_rev, subpool));
  /* Don't use subpool, txn_name is used after subpool is cleared */
  SVN_ERR(svn_fs_txn_name(&txn_name, txn, pool));
  SVN_ERR(svn_fs_txn_root(&txn_root, txn, subpool));
  {
    static svn_test__txn_script_command_t script_entries[] = {
      { 'd', "file1",       "This is the file 'file1'.\n" },
      { 'd', "dir1/file2",  "This is the file 'file2'.\n" },
      { 'd', "dir1/file3",  "This is the file 'file3'.\n" },
      { 'a', "dir1/file5",  "This is the file 'file4'.\n" },
      { 'a', "dir1/dir2",   0 },
      { 'd', "dir1",        0 },
      { 'a', "dir3",        0 },
    };
    SVN_ERR(svn_test__txn_script_exec(txn_root, script_entries, 7, subpool));
  }
  SVN_ERR(svn_fs_commit_txn(NULL, &youngest_rev, txn, subpool));
  svn_pool_clear(subpool);

  /*** TEST:  We should have only three changes, the deletion of 'file1'
       the deletion of 'dir1', and the addition of 'dir3'. ***/
  args.fs = fs;
  args.key = txn_name;
  SVN_ERR(svn_fs_base__retry_txn(fs, txn_body_changes_fetch, &args,
                                 subpool));
  if ((! args.changes) || (apr_hash_count(args.changes) != 3))
    return svn_error_create(SVN_ERR_TEST_FAILED, NULL,
                            "expected changes");
  for (hi = apr_hash_first(subpool, args.changes);
       hi; hi = apr_hash_next(hi))
    {
      const void *key;
      void *val;
      svn_fs_path_change_t *change;

      /* KEY will be the path, VAL the change. */
      apr_hash_this(hi, &key, NULL, &val);
      change = val;

      if ((change->change_kind == svn_fs_path_change_add)
          && (strcmp(key, "/dir3") == 0))
        ;
      else if ((change->change_kind == svn_fs_path_change_delete)
               && ((strcmp(key, "/dir1") == 0)
                   || (strcmp(key, "/file1") == 0)))
        ;
      else
        return svn_error_create(SVN_ERR_TEST_FAILED, NULL,
                                "got wrong changes");
    }

  /*** REVISION 3: Do the same stuff as in revision 1. ***/
  SVN_ERR(svn_fs_begin_txn(&txn, fs, youngest_rev, subpool));
  SVN_ERR(svn_fs_txn_root(&txn_root, txn, subpool));
  {
    static svn_test__txn_script_command_t script_entries[] = {
      { 'a', "dir1",        0 },
      { 'a', "file1",       "This is the file 'file1'.\n" },
      { 'a', "dir1/file2",  "This is the file 'file2'.\n" },
      { 'a', "dir1/file3",  "This is the file 'file3'.\n" },
      { 'a', "dir1/file4",  "This is the file 'file4'.\n" },
    };
    SVN_ERR(svn_test__txn_script_exec(txn_root, script_entries, 5, subpool));
  }
  SVN_ERR(svn_fs_commit_txn(NULL, &youngest_rev, txn, subpool));
  svn_pool_clear(subpool);

  /*** REVISION 4: Do the same stuff as in revision 2, but use a copy
       overwrite of the top directory (instead of a delete) to test
       that the 'replace' change type works, too.  (And add 'dir4'
       instead of 'dir3', since 'dir3' still exists).  ***/
  SVN_ERR(svn_fs_begin_txn(&txn, fs, youngest_rev, subpool));
  /* Don't use subpool, txn_name is used after subpool is cleared */
  SVN_ERR(svn_fs_txn_name(&txn_name, txn, pool));
  SVN_ERR(svn_fs_txn_root(&txn_root, txn, subpool));
  SVN_ERR(svn_fs_revision_root(&rev_root, fs, 1, subpool));
  {
    static svn_test__txn_script_command_t script_entries[] = {
      { 'd', "file1",       "This is the file 'file1'.\n" },
      { 'd', "dir1/file2",  "This is the file 'file2'.\n" },
      { 'd', "dir1/file3",  "This is the file 'file3'.\n" },
      { 'a', "dir1/file5",  "This is the file 'file4'.\n" },
      { 'a', "dir1/dir2",   0 },
    };
    SVN_ERR(svn_test__txn_script_exec(txn_root, script_entries, 5, subpool));
    SVN_ERR(svn_fs_copy(rev_root, "dir1", txn_root, "dir1", subpool));
    SVN_ERR(svn_fs_make_dir(txn_root, "dir4", subpool));
  }
  SVN_ERR(svn_fs_commit_txn(NULL, &youngest_rev, txn, subpool));
  svn_pool_clear(subpool);

  /*** TEST:  We should have only three changes, the deletion of 'file1'
       the replacement of 'dir1', and the addition of 'dir4'. ***/
  args.fs = fs;
  args.key = txn_name;
  SVN_ERR(svn_fs_base__retry_txn(fs, txn_body_changes_fetch, &args,
                                 subpool));
  if ((! args.changes) || (apr_hash_count(args.changes) != 3))
    return svn_error_create(SVN_ERR_TEST_FAILED, NULL,
                            "expected changes");
  for (hi = apr_hash_first(subpool, args.changes);
       hi; hi = apr_hash_next(hi))
    {
      const void *key;
      void *val;
      svn_fs_path_change_t *change;

      /* KEY will be the path, VAL the change. */
      apr_hash_this(hi, &key, NULL, &val);
      change = val;

      if ((change->change_kind == svn_fs_path_change_add)
          && (strcmp(key, "/dir4") == 0))
        ;
      else if ((change->change_kind == svn_fs_path_change_replace)
               && (strcmp(key, "/dir1") == 0))
        ;
      else if ((change->change_kind == svn_fs_path_change_delete)
               && (strcmp(key, "/file1") == 0))
        ;
      else
        return svn_error_create(SVN_ERR_TEST_FAILED, NULL,
                                "got wrong changes");
    }

  return SVN_NO_ERROR;
}