FreeBSD/contrib/subversion/subversion/libsvn_fs_x/hotcopy.c
/* Copy the revision and revprop files (possibly sharded / packed) from
 * SRC_FS to DST_FS.  Do not re-copy data which already exists in DST_FS.
 * When copying packed or unpacked shards, checkpoint the result in DST_FS
 * for every shard by updating the 'current' file if necessary.  Assume
 * the >= SVN_FS_FS__MIN_NO_GLOBAL_IDS_FORMAT filesystem format without
 * global next-ID counters.  Indicate progress via the optional NOTIFY_FUNC
 * callback using NOTIFY_BATON.  Use SCRATCH_POOL for temporary allocations.
 */
Copy the revision and revprop files (possibly sharded / packed) from
SRC_FS to DST_FS.  Do not re-copy data which already exists in DST_FS.
When copying packed or unpacked shards, checkpoint the result in DST_FS
for every shard by updating the 'current' file if necessary.  Assume
the >= SVN_FS_FS__MIN_NO_GLOBAL_IDS_FORMAT filesystem format without
global next-ID counters.  Indicate progress via the optional NOTIFY_FUNC
callback using NOTIFY_BATON.  Use SCRATCH_POOL for temporary allocations.
Copy the revision and revprop files ( possibly sharded / packed ) from SRC_FS to DST_FS . Do not re - copy data which already exists in DST_FS . When copying packed or unpacked shards checkpoint the result in DST_FS for every shard by updating the ' current ' file if necessary . Assume the > = SVN_FS_FS__MIN_NO_GLOBAL_IDS_FORMAT filesystem format without global next - ID counters . Indicate progress via the optional NOTIFY_FUNC callback using NOTIFY_BATON . Use SCRATCH_POOL for temporary allocations .
static svn_error_t *
hotcopy_revisions(svn_fs_t *src_fs,
                  svn_fs_t *dst_fs,
                  svn_revnum_t src_youngest,
                  svn_revnum_t dst_youngest,
                  svn_boolean_t incremental,
                  const char *src_revs_dir,
                  const char *dst_revs_dir,
                  const char *src_revprops_dir,
                  const char *dst_revprops_dir,
                  svn_fs_hotcopy_notify_t notify_func,
                  void* notify_baton,
                  svn_cancel_func_t cancel_func,
                  void* cancel_baton,
                  apr_pool_t *scratch_pool)
{
  svn_fs_x__data_t *src_ffd = src_fs->fsap_data;
  int max_files_per_dir = src_ffd->max_files_per_dir;
  svn_revnum_t src_min_unpacked_rev;
  svn_revnum_t dst_min_unpacked_rev;
  svn_revnum_t rev;
  apr_pool_t *iterpool;
  SVN_ERR(svn_fs_x__read_min_unpacked_rev(&src_min_unpacked_rev, src_fs,
                                          scratch_pool));
  SVN_ERR(svn_fs_x__read_min_unpacked_rev(&dst_min_unpacked_rev, dst_fs,
                                          scratch_pool));
  if (src_min_unpacked_rev < dst_min_unpacked_rev)
    return svn_error_createf(SVN_ERR_UNSUPPORTED_FEATURE, NULL,
                             _("The hotcopy destination already contains "
                               "more packed revisions (%lu) than the "
                               "hotcopy source contains (%lu)"),
                             dst_min_unpacked_rev - 1,
                             src_min_unpacked_rev - 1);
  SVN_ERR(svn_io_dir_file_copy(src_fs->path, dst_fs->path,
                               PATH_MIN_UNPACKED_REV, scratch_pool));
  if (cancel_func)
    SVN_ERR(cancel_func(cancel_baton));
  iterpool = svn_pool_create(scratch_pool);
  for (rev = 0; rev < src_min_unpacked_rev; rev += max_files_per_dir)
    {
      svn_boolean_t skipped = TRUE;
      svn_revnum_t pack_end_rev;
      svn_pool_clear(iterpool);
      if (cancel_func)
        SVN_ERR(cancel_func(cancel_baton));
      SVN_ERR(hotcopy_copy_packed_shard(&skipped, &dst_min_unpacked_rev,
                                        src_fs, dst_fs,
                                        rev, max_files_per_dir,
                                        iterpool));
      pack_end_rev = rev + max_files_per_dir - 1;
      if (pack_end_rev > dst_youngest)
        {
          SVN_ERR(svn_fs_x__write_current(dst_fs, pack_end_rev, iterpool));
        }
      if (notify_func && !skipped)
        notify_func(notify_baton, rev, pack_end_rev, iterpool);
      if (incremental)
        {
          SVN_ERR(hotcopy_remove_rev_files(dst_fs, rev,
                                           rev + max_files_per_dir,
                                           max_files_per_dir, iterpool));
          SVN_ERR(hotcopy_remove_revprop_files(dst_fs, rev,
                                               rev + max_files_per_dir,
                                               max_files_per_dir,
                                               iterpool));
        }
      SVN_ERR(remove_folder(svn_fs_x__path_rev_shard(dst_fs, rev, iterpool),
                            cancel_func, cancel_baton, iterpool));
      if (rev > 0)
        SVN_ERR(remove_folder(svn_fs_x__path_revprops_shard(dst_fs, rev,
                                                            iterpool),
                              cancel_func, cancel_baton, iterpool));
    }
  if (cancel_func)
    SVN_ERR(cancel_func(cancel_baton));
  SVN_ERR_ASSERT(rev == src_min_unpacked_rev);
  SVN_ERR_ASSERT(src_min_unpacked_rev == dst_min_unpacked_rev);
  for (; rev <= src_youngest; rev++)
    {
      svn_boolean_t skipped = TRUE;
      svn_pool_clear(iterpool);
      if (cancel_func)
        SVN_ERR(cancel_func(cancel_baton));
      SVN_ERR(hotcopy_copy_shard_file(&skipped, src_revs_dir, dst_revs_dir,
                                      rev, max_files_per_dir,
                                      iterpool));
      SVN_ERR(hotcopy_copy_shard_file(&skipped, src_revprops_dir,
                                      dst_revprops_dir,
                                      rev, max_files_per_dir,
                                      iterpool));
      if (rev > dst_youngest)
        {
          if (max_files_per_dir && (rev % max_files_per_dir == 0))
            {
              SVN_ERR(svn_fs_x__write_current(dst_fs, rev, iterpool));
            }
        }
      if (notify_func && !skipped)
        notify_func(notify_baton, rev, rev, iterpool);
    }
  svn_pool_destroy(iterpool);
  SVN_ERR_ASSERT(rev == src_youngest + 1);
  return SVN_NO_ERROR;
}
static svn_error_t * hotcopy_revisions ( svn_fs_t * src_fs , svn_fs_t * dst_fs , svn_revnum_t src_youngest , svn_revnum_t dst_youngest , svn_boolean_t incremental , const char * src_revs_dir , const char * dst_revs_dir , const char * src_revprops_dir , const char * dst_revprops_dir , svn_fs_hotcopy_notify_t notify_func , void * notify_baton , svn_cancel_func_t cancel_func , void * cancel_baton , apr_pool_t * scratch_pool ) { svn_fs_x__data_t * src_ffd = src_fs -> fsap_data ; int max_files_per_dir = src_ffd -> max_files_per_dir ; svn_revnum_t src_min_unpacked_rev ; svn_revnum_t dst_min_unpacked_rev ; svn_revnum_t rev ; apr_pool_t * iterpool ; SVN_ERR ( svn_fs_x__read_min_unpacked_rev ( & src_min_unpacked_rev , src_fs , scratch_pool ) ) ; SVN_ERR ( svn_fs_x__read_min_unpacked_rev ( & dst_min_unpacked_rev , dst_fs , scratch_pool ) ) ; if ( src_min_unpacked_rev < dst_min_unpacked_rev ) return svn_error_createf ( SVN_ERR_UNSUPPORTED_FEATURE , NULL , _ ( " " " " " " ) , dst_min_unpacked_rev - 1 , src_min_unpacked_rev - 1 ) ; SVN_ERR ( svn_io_dir_file_copy ( src_fs -> path , dst_fs -> path , PATH_MIN_UNPACKED_REV , scratch_pool ) ) ; if ( cancel_func ) SVN_ERR ( cancel_func ( cancel_baton ) ) ; iterpool = svn_pool_create ( scratch_pool ) ; for ( rev = 0 ; rev < src_min_unpacked_rev ; rev += max_files_per_dir ) { svn_boolean_t skipped = TRUE ; svn_revnum_t pack_end_rev ; svn_pool_clear ( iterpool ) ; if ( cancel_func ) SVN_ERR ( cancel_func ( cancel_baton ) ) ; SVN_ERR ( hotcopy_copy_packed_shard ( & skipped , & dst_min_unpacked_rev , src_fs , dst_fs , rev , max_files_per_dir , iterpool ) ) ; pack_end_rev = rev + max_files_per_dir - 1 ; if ( pack_end_rev > dst_youngest ) { SVN_ERR ( svn_fs_x__write_current ( dst_fs , pack_end_rev , iterpool ) ) ; } if ( notify_func && ! skipped ) notify_func ( notify_baton , rev , pack_end_rev , iterpool ) ; if ( incremental ) { SVN_ERR ( hotcopy_remove_rev_files ( dst_fs , rev , rev + max_files_per_dir , max_files_per_dir , iterpool ) ) ; SVN_ERR ( hotcopy_remove_revprop_files ( dst_fs , rev , rev + max_files_per_dir , max_files_per_dir , iterpool ) ) ; } SVN_ERR ( remove_folder ( svn_fs_x__path_rev_shard ( dst_fs , rev , iterpool ) , cancel_func , cancel_baton , iterpool ) ) ; if ( rev > 0 ) SVN_ERR ( remove_folder ( svn_fs_x__path_revprops_shard ( dst_fs , rev , iterpool ) , cancel_func , cancel_baton , iterpool ) ) ; } if ( cancel_func ) SVN_ERR ( cancel_func ( cancel_baton ) ) ; SVN_ERR_ASSERT ( rev == src_min_unpacked_rev ) ; SVN_ERR_ASSERT ( src_min_unpacked_rev == dst_min_unpacked_rev ) ; for ( ; rev <= src_youngest ; rev ++ ) { svn_boolean_t skipped = TRUE ; svn_pool_clear ( iterpool ) ; if ( cancel_func ) SVN_ERR ( cancel_func ( cancel_baton ) ) ; SVN_ERR ( hotcopy_copy_shard_file ( & skipped , src_revs_dir , dst_revs_dir , rev , max_files_per_dir , iterpool ) ) ; SVN_ERR ( hotcopy_copy_shard_file ( & skipped , src_revprops_dir , dst_revprops_dir , rev , max_files_per_dir , iterpool ) ) ; if ( rev > dst_youngest ) { if ( max_files_per_dir && ( rev % max_files_per_dir == 0 ) ) { SVN_ERR ( svn_fs_x__write_current ( dst_fs , rev , iterpool ) ) ; } } if ( notify_func && ! skipped ) notify_func ( notify_baton , rev , rev , iterpool ) ; } svn_pool_destroy ( iterpool ) ; SVN_ERR_ASSERT ( rev == src_youngest + 1 ) ; return SVN_NO_ERROR ; }
Copy the revision and revprop files (possibly sharded / packed) from
 SRC_FS to DST_FS.
Copy the revision and revprop files ( possibly sharded / packed ) from SRC_FS to DST_FS .
/* Copy the min unpacked rev, and read its value. */ /* We only support packs coming from the hotcopy source.
    * The destination should not be packed independently from
    * the source. This also catches the case where users accidentally
    * swap the source and destination arguments. */ /*
   * Copy the necessary rev files.
   */ /* First, copy packed shards. */ /* Copy the packed shard. */ /* Whenever this pack did not previously exist in the destination,
       * update 'current' to the most recent packed rev (so readers can see
       * new revisions which arrived in this pack). */ /* When notifying about packed shards, make things simpler by either
       * reporting a full revision range, i.e [pack start, pack end] or
       * reporting nothing. There is one case when this approach might not
       * be exact (incremental hotcopy with a pack replacing last unpacked
       * revisions), but generally this is good enough. */ /* Remove revision files which are now packed. */ /* Now that all revisions have moved into the pack, the original
       * rev dir can be removed. */ /* Now, copy pairs of non-packed revisions and revprop files.
   * If necessary, update 'current' after copying all files from a shard. */ /* Copying non-packed revisions is racy in case the source repository is
       * being packed concurrently with this hotcopy operation.  With the pack
       * lock, however, the race is impossible, because hotcopy and pack
       * operations block each other.
       *
       * We assume that all revisions coming after 'min-unpacked-rev' really
       * are unpacked and that's not necessarily true with concurrent packing.
       * Don't try to be smart in this edge case, because handling it properly
       * might require copying *everything* from the start. Just abort the
       * hotcopy with an ENOENT (revision file moved to a pack, so it is no
       * longer where we expect it to be). */ /* Copy the rev file. */ /* Copy the revprop file. */ /* Whenever this revision did not previously exist in the destination,
       * checkpoint the progress via 'current' (do that once per full shard
       * in order not to slow things down). */ /* We assume that all revisions were copied now, i.e. we didn't exit the
   * above loop early. 'rev' was last incremented during exit of the loop. */