Esempio n. 1
0
/* Get the format version from a wc-1 directory. If it is not a working copy
   directory, then it sets VERSION to zero and returns no error.  */
static svn_error_t *
get_old_version(int *version,
                const char *abspath,
                apr_pool_t *scratch_pool)
{
  svn_error_t *err;
  const char *format_file_path;
  svn_node_kind_t kind;

  /* Try reading the format number from the entries file.  */
  format_file_path = svn_wc__adm_child(abspath, SVN_WC__ADM_ENTRIES,
                                       scratch_pool);

  /* Since trying to open a non-existent file is quite expensive, try a
     quick stat call first. In wc-ng w/cs, this will be an early exit. */
  SVN_ERR(svn_io_check_path(format_file_path, &kind, scratch_pool));
  if (kind == svn_node_none)
    {
      *version = 0;
      return SVN_NO_ERROR;
    }

  err = svn_io_read_version_file(version, format_file_path, scratch_pool);
  if (err == NULL)
    return SVN_NO_ERROR;
  if (err->apr_err != SVN_ERR_BAD_VERSION_FILE_FORMAT
      && !APR_STATUS_IS_ENOENT(err->apr_err)
      && !APR_STATUS_IS_ENOTDIR(err->apr_err))
    return svn_error_createf(SVN_ERR_WC_MISSING, err, _("'%s' does not exist"),
                             svn_dirent_local_style(abspath, scratch_pool));
  svn_error_clear(err);

  /* This must be a really old working copy!  Fall back to reading the
     format file.

     Note that the format file might not exist in newer working copies
     (format 7 and higher), but in that case, the entries file should
     have contained the format number. */
  format_file_path = svn_wc__adm_child(abspath, SVN_WC__ADM_FORMAT,
                                       scratch_pool);
  err = svn_io_read_version_file(version, format_file_path, scratch_pool);
  if (err == NULL)
    return SVN_NO_ERROR;

  /* Whatever error may have occurred... we can just ignore. This is not
     a working copy directory. Signal the caller.  */
  svn_error_clear(err);

  *version = 0;
  return SVN_NO_ERROR;
}
Esempio n. 2
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);
}
Esempio n. 3
0
File: fs.c Progetto: Alkzndr/freebsd
static svn_error_t *
base_upgrade(svn_fs_t *fs, const char *path, apr_pool_t *pool,
             apr_pool_t *common_pool)
{
  const char *version_file_path;
  int old_format_number;
  svn_error_t *err;

  version_file_path = svn_dirent_join(path, FORMAT_FILE, pool);

  /* Read the old number so we've got it on hand later on. */
  err = svn_io_read_version_file(&old_format_number, version_file_path, pool);
  if (err && APR_STATUS_IS_ENOENT(err->apr_err))
    {
      /* Pre-1.2 filesystems do not have a 'format' file. */
      old_format_number = 0;
      svn_error_clear(err);
      err = SVN_NO_ERROR;
    }
  SVN_ERR(err);

  /* Bump the format file's stored version number. */
  SVN_ERR(svn_io_write_version_file(version_file_path,
                                    SVN_FS_BASE__FORMAT_NUMBER, pool));

  /* Check and see if we need to record the "bump" revision. */
  if (old_format_number < SVN_FS_BASE__MIN_FORWARD_DELTAS_FORMAT)
    {
      apr_pool_t *subpool = svn_pool_create(pool);
      svn_revnum_t youngest_rev;
      const char *value;

      /* Open the filesystem in a subpool (so we can control its
         closure) and do our fiddling.

         NOTE: By using base_open() here instead of open_databases(),
         we will end up re-reading the format file that we just wrote.
         But it's better to use the existing encapsulation of "opening
         the filesystem" rather than duplicating (or worse, partially
         duplicating) that logic here.  */
      SVN_ERR(base_open(fs, path, subpool, common_pool));

      /* Fetch the youngest rev, and record it */
      SVN_ERR(svn_fs_base__youngest_rev(&youngest_rev, fs, subpool));
      value = apr_psprintf(subpool, "%ld", youngest_rev);
      SVN_ERR(svn_fs_base__miscellaneous_set
              (fs, SVN_FS_BASE__MISC_FORWARD_DELTA_UPGRADE,
               value, subpool));
      svn_pool_destroy(subpool);
    }

  return SVN_NO_ERROR;
}
Esempio n. 4
0
File: fs.c Progetto: Alkzndr/freebsd
static svn_error_t *
base_open(svn_fs_t *fs, const char *path, apr_pool_t *pool,
          apr_pool_t *common_pool)
{
  int format;
  svn_error_t *svn_err;
  svn_boolean_t write_format_file = FALSE;

  /* Read the FS format number. */
  svn_err = svn_io_read_version_file(&format,
                                     svn_dirent_join(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.
         However, we stopped "upgrading on the fly" in 1.5, so older
         filesystems should only be bumped to 1.3, which is format "1". */
      svn_error_clear(svn_err);
      svn_err = SVN_NO_ERROR;
      format = 1;
      write_format_file = TRUE;
    }
  else if (svn_err)
    goto error;

  /* Create the environment and databases. */
  svn_err = open_databases(fs, FALSE, format, path, pool);
  if (svn_err) goto error;

  ((base_fs_data_t *) fs->fsap_data)->format = format;
  SVN_ERR(check_format(format));

  /* If we lack a format file, write one. */
  if (write_format_file)
    {
      svn_err = svn_io_write_version_file(svn_dirent_join(path, FORMAT_FILE,
                                                        pool),
                                          format, pool);
      if (svn_err) goto error;
    }

  SVN_ERR(populate_opened_fs(fs, pool));
  return SVN_NO_ERROR;

 error:
  svn_error_clear(cleanup_fs(fs));
  return svn_err;
}
Esempio n. 5
0
File: fs.c Progetto: Alkzndr/freebsd
static svn_error_t *
base_hotcopy(svn_fs_t *src_fs,
             svn_fs_t *dst_fs,
             const char *src_path,
             const char *dest_path,
             svn_boolean_t clean_logs,
             svn_boolean_t incremental,
             svn_cancel_func_t cancel_func,
             void *cancel_baton,
             apr_pool_t *pool)
{
  svn_error_t *err;
  u_int32_t pagesize;
  svn_boolean_t log_autoremove = FALSE;
  int format;

  if (incremental)
    return svn_error_createf(SVN_ERR_UNSUPPORTED_FEATURE, NULL,
                             _("BDB repositories do not support incremental "
                               "hotcopy"));

  /* Check the FS format number to be certain that we know how to
     hotcopy this FS.  Pre-1.2 filesystems did not have a format file (you
     could say they were format "0"), so we will error here.  This is not
     optimal, but since this has been the case since 1.2.0, and no one has
     complained, it apparently isn't much of a concern.  (We did not check
     the 'format' file in 1.2.x, but we did blindly try to copy 'locks',
     which would have errored just the same.)  */
  SVN_ERR(svn_io_read_version_file(
          &format, svn_dirent_join(src_path, FORMAT_FILE, pool), pool));
  SVN_ERR(check_format(format));

  /* If using Berkeley DB 4.2 or later, note whether the DB_LOG_AUTO_REMOVE
     feature is on.  If it is, we have a potential race condition:
     another process might delete a logfile while we're in the middle
     of copying all the logfiles.  (This is not a huge deal; at worst,
     the hotcopy fails with a file-not-found error.) */
#if SVN_BDB_VERSION_AT_LEAST(4, 2)
  err = check_env_flags(&log_autoremove,
#if SVN_BDB_VERSION_AT_LEAST(4, 7)
                          DB_LOG_AUTO_REMOVE,
 /* DB_LOG_AUTO_REMOVE was named DB_LOG_AUTOREMOVE before Berkeley DB 4.7. */
#else
                          DB_LOG_AUTOREMOVE,
#endif
                          src_path, pool);
#endif
  SVN_ERR(err);

  /* Copy the DB_CONFIG file. */
  SVN_ERR(svn_io_dir_file_copy(src_path, dest_path, "DB_CONFIG", pool));

  /* In order to copy the database files safely and atomically, we
     must copy them in chunks which are multiples of the page-size
     used by BDB.  See sleepycat docs for details, or svn issue #1818. */
#if SVN_BDB_VERSION_AT_LEAST(4, 2)
  SVN_ERR(get_db_pagesize(&pagesize, src_path, pool));
  if (pagesize < SVN__STREAM_CHUNK_SIZE)
    {
      /* use the largest multiple of BDB pagesize we can. */
      int multiple = SVN__STREAM_CHUNK_SIZE / pagesize;
      pagesize *= multiple;
    }
#else
  /* default to 128K chunks, which should be safe.
     BDB almost certainly uses a power-of-2 pagesize. */
  pagesize = (4096 * 32);
#endif

  /* Copy the databases.  */
  SVN_ERR(copy_db_file_safely(src_path, dest_path,
                              "nodes", pagesize, FALSE, pool));
  SVN_ERR(copy_db_file_safely(src_path, dest_path,
                              "transactions", pagesize, FALSE, pool));
  SVN_ERR(copy_db_file_safely(src_path, dest_path,
                              "revisions", pagesize, FALSE, pool));
  SVN_ERR(copy_db_file_safely(src_path, dest_path,
                              "copies", pagesize, FALSE, pool));
  SVN_ERR(copy_db_file_safely(src_path, dest_path,
                              "changes", pagesize, FALSE, pool));
  SVN_ERR(copy_db_file_safely(src_path, dest_path,
                              "representations", pagesize, FALSE, pool));
  SVN_ERR(copy_db_file_safely(src_path, dest_path,
                              "strings", pagesize, FALSE, pool));
  SVN_ERR(copy_db_file_safely(src_path, dest_path,
                              "uuids", pagesize, TRUE, pool));
  SVN_ERR(copy_db_file_safely(src_path, dest_path,
                              "locks", pagesize, TRUE, pool));
  SVN_ERR(copy_db_file_safely(src_path, dest_path,
                              "lock-tokens", pagesize, TRUE, pool));
  SVN_ERR(copy_db_file_safely(src_path, dest_path,
                              "node-origins", pagesize, TRUE, pool));
  SVN_ERR(copy_db_file_safely(src_path, dest_path,
                              "checksum-reps", pagesize, TRUE, pool));
  SVN_ERR(copy_db_file_safely(src_path, dest_path,
                              "miscellaneous", pagesize, TRUE, pool));

  {
    apr_array_header_t *logfiles;
    int idx;
    apr_pool_t *subpool;

    SVN_ERR(base_bdb_logfiles(&logfiles,
                              src_path,
                              FALSE,   /* All logs */
                              pool));

    /* Process log files. */
    subpool = svn_pool_create(pool);
    for (idx = 0; idx < logfiles->nelts; idx++)
      {
        svn_pool_clear(subpool);
        err = svn_io_dir_file_copy(src_path, dest_path,
                                   APR_ARRAY_IDX(logfiles, idx,
                                                 const char *),
                                   subpool);
        if (err)
          {
            if (log_autoremove)
              return
                svn_error_quick_wrap
                (err,
                 _("Error copying logfile;  the DB_LOG_AUTOREMOVE feature\n"
                   "may be interfering with the hotcopy algorithm.  If\n"
                   "the problem persists, try deactivating this feature\n"
                   "in DB_CONFIG"));
            else
              return svn_error_trace(err);
          }
      }
    svn_pool_destroy(subpool);
  }

  /* Since this is a copy we will have exclusive access to the repository. */
  err = bdb_recover(dest_path, TRUE, pool);
  if (err)
    {
      if (log_autoremove)
        return
          svn_error_quick_wrap
          (err,
           _("Error running catastrophic recovery on hotcopy;  the\n"
             "DB_LOG_AUTOREMOVE feature may be interfering with the\n"
             "hotcopy algorithm.  If the problem persists, try deactivating\n"
             "this feature in DB_CONFIG"));
      else
        return svn_error_trace(err);
    }

  /* Only now that the hotcopied filesystem is complete,
     stamp it with a format file. */
  SVN_ERR(svn_io_write_version_file(
             svn_dirent_join(dest_path, FORMAT_FILE, pool), format, pool));

  if (clean_logs)
    SVN_ERR(svn_fs_base__clean_logs(src_path, dest_path, pool));

  return SVN_NO_ERROR;
}