⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 fs.c

📁 linux subdivision ying gai ke yi le ba
💻 C
📖 第 1 页 / 共 3 页
字号:
        }

        SVN_ERR (svn_io_remove_file (live_log_path, sub_pool));
      }

    svn_pool_destroy (sub_pool);
  }

  return SVN_NO_ERROR;
}


/* ### There -must- be a more elegant way to do a compile-time check
       for BDB 4.2 or later.  We're doing this because apparently
       env->get_flags() and DB->get_pagesize() don't exist in earlier
       versions of BDB.  */
#ifdef DB_LOG_AUTOREMOVE

/* Open the BDB environment at PATH and compare its configuration
   flags with FLAGS.  If every flag in FLAGS is set in the
   environment, then set *MATCH to true.  Else set *MATCH to false. */
static svn_error_t *
check_env_flags (svn_boolean_t *match,
                 u_int32_t flags,
                 const char *path,
                 apr_pool_t *pool)
{
  DB_ENV *env;
  u_int32_t envflags;
  const char *path_native;
  bdb_errcall_baton_t *ec_baton;

  SVN_BDB_ERR (ec_baton, create_env (&env, &ec_baton, pool));
  SVN_ERR (svn_utf_cstring_from_utf8 (&path_native, path, pool));

  SVN_BDB_ERR (ec_baton, env->open (env, path_native,
                                    (DB_CREATE | DB_INIT_LOCK | DB_INIT_LOG
                                     | DB_INIT_MPOOL | DB_INIT_TXN),
                          0666));

  SVN_BDB_ERR (ec_baton, env->get_flags (env, &envflags));
  SVN_BDB_ERR (ec_baton, env->close (env, 0));

  if (flags & envflags)
    *match = TRUE;
  else
    *match = FALSE;

  return SVN_NO_ERROR;
}


/* Set *PAGESIZE to the size of pages used to hold items in the
   database environment located at PATH.
*/
static svn_error_t *
get_db_pagesize (u_int32_t *pagesize,
                 const char *path,
                 apr_pool_t *pool)
{
  DB_ENV *env;
  DB *nodes_table;
  const char *path_native;
  bdb_errcall_baton_t *ec_baton;

  SVN_BDB_ERR (ec_baton, create_env (&env, &ec_baton, pool));
  SVN_ERR (svn_utf_cstring_from_utf8 (&path_native, path, pool));

  SVN_BDB_ERR (ec_baton, env->open (env, path_native,
                                    (DB_CREATE | DB_INIT_LOCK | DB_INIT_LOG
                                     | DB_INIT_MPOOL | DB_INIT_TXN),
                          0666));

  /* ### We're only asking for the pagesize on the 'nodes' table.
         Is this enough?  We never call DB->set_pagesize() on any of
         our tables, so presumably BDB is using the same default
         pagesize for all our databases, right? */
  SVN_BDB_ERR (ec_baton, svn_fs_bdb__open_nodes_table (&nodes_table, env,
                                                       FALSE));
  SVN_BDB_ERR (ec_baton, nodes_table->get_pagesize (nodes_table, pagesize));
  SVN_BDB_ERR (ec_baton, nodes_table->close (nodes_table, 0));
  SVN_BDB_ERR (ec_baton, env->close (env, 0));

  return SVN_NO_ERROR;
}
#endif /* DB_LOG_AUTOREMOVE */


/* Ensure compatibility with older APR 0.9.5 snapshots which don't
 * support the APR_LARGEFILE flag. */
#ifndef APR_LARGEFILE
#define APR_LARGEFILE (0)
#endif

/* Copy FILENAME from SRC_DIR to DST_DIR in byte increments of size
   CHUNKSIZE.  The read/write buffer of size CHUNKSIZE will be
   allocated in POOL. */
static svn_error_t *
copy_db_file_safely (const char *src_dir,
                     const char *dst_dir,
                     const char *filename,
                     u_int32_t chunksize,
                     apr_pool_t *pool)
{
  apr_file_t *s = NULL, *d = NULL;  /* init to null important for APR */
  const char *file_src_path = svn_path_join (src_dir, filename, pool);
  const char *file_dst_path = svn_path_join (dst_dir, filename, pool);  
  apr_status_t status;
  char *buf;

  /* Open source file. */
  status = apr_file_open (&s, file_src_path, (APR_READ | APR_LARGEFILE),
                          APR_OS_DEFAULT, pool);
  if (status)
    return svn_error_createf (status, NULL,
                              "Can't open file '%s' for reading.",
                              file_src_path);

  /* Open destination file. */
  status = apr_file_open (&d, file_dst_path, 
                          (APR_WRITE | APR_CREATE | APR_LARGEFILE),
                          APR_OS_DEFAULT, pool);
  if (status)
    return svn_error_createf (status, NULL,
                              "Can't open file '%s' for writing.",
                              file_dst_path);

  /* Allocate our read/write buffer. */
  buf = apr_palloc (pool, chunksize);

  /* Copy bytes till the cows come home. */
  while (1) 
    {
      apr_size_t bytes_this_time = chunksize;
      apr_status_t read_err;
      apr_status_t write_err;
      
      /* Read 'em. */
      read_err = apr_file_read(s, buf, &bytes_this_time);
      if (read_err && !APR_STATUS_IS_EOF(read_err))
        {
          apr_file_close(s);  /* toss any error */
          apr_file_close(d);  /* toss any error */
          return svn_error_createf (status, NULL,
                                    "Error reading file '%s'.",
                                    file_src_path);
        }
    
      /* Write 'em. */
      write_err = apr_file_write_full(d, buf, bytes_this_time, NULL);
      if (write_err)
        {
          apr_file_close(s);  /* toss any error */
          apr_file_close(d);  /* toss any error */
          return svn_error_createf (status, NULL,
                                    "Error writing file '%s'.",
                                    file_dst_path);
        }
    
      if (read_err && APR_STATUS_IS_EOF(read_err)) 
        {
          status = apr_file_close(s);
          if (status)
            return svn_error_createf (status, NULL, "Can't close file '%s'.",
                                      file_src_path);
          status = apr_file_close(d);
          if (status)
            return svn_error_createf (status, NULL, "Can't close file '%s'.",
                                      file_dst_path);

          break;  /* got EOF on read, all files closed, all done. */
        }
    }

  return SVN_NO_ERROR;
}




static svn_error_t *
base_hotcopy (const char *src_path,
              const char *dest_path,
              svn_boolean_t clean_logs,
              apr_pool_t *pool)
{
  svn_error_t *err;
  u_int32_t pagesize;
  svn_boolean_t log_autoremove = FALSE;

  /* If using DB 4.2 or later, note whether the DB_LOG_AUTOREMOVE
     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.) */
#ifdef DB_LOG_AUTOREMOVE
  SVN_ERR (check_env_flags (&log_autoremove, DB_LOG_AUTOREMOVE,
                            src_path, pool));
#endif

  /* 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. */
#ifdef DB_LOG_AUTOREMOVE
  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, pool));
  SVN_ERR (copy_db_file_safely (src_path, dest_path,
                                "transactions", pagesize, pool));
  SVN_ERR (copy_db_file_safely (src_path, dest_path,
                                "revisions", pagesize, pool));
  SVN_ERR (copy_db_file_safely (src_path, dest_path,
                                "copies", pagesize, pool));
  SVN_ERR (copy_db_file_safely (src_path, dest_path,
                                "changes", pagesize, pool));
  SVN_ERR (copy_db_file_safely (src_path, dest_path,
                                "representations", pagesize, pool));
  SVN_ERR (copy_db_file_safely (src_path, dest_path,
                                "strings", pagesize, pool));
  SVN_ERR (copy_db_file_safely (src_path, dest_path,
                                "uuids", pagesize, 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 err;
          }
      }
    svn_pool_destroy (subpool);
  }

  /* Since this is a copy we will have exclusive access to the repository. */
  err = bdb_catastrophic_recover (dest_path, 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 err;
    }

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

  return SVN_NO_ERROR;
}



/* Deleting a Berkeley DB-based filesystem.  */


static svn_error_t *
base_delete_fs (const char *path,
                apr_pool_t *pool)
{
  DB_ENV *env;
  const char *path_native;
  bdb_errcall_baton_t *ec_baton;

  /* First, use the Berkeley DB library function to remove any shared
     memory segments.  */
  SVN_BDB_ERR (ec_baton, create_env (&env, &ec_baton, pool));
  SVN_ERR (svn_utf_cstring_from_utf8 (&path_native, path, pool));
  SVN_BDB_ERR (ec_baton, env->remove (env, path_native, DB_FORCE));

  /* Remove the environment directory. */
  SVN_ERR (svn_io_remove_dir (path, pool));

  return SVN_NO_ERROR;
}



/* Miscellany */

const char *
svn_fs_base__canonicalize_abspath (const char *path, apr_pool_t *pool)
{
  char *newpath;
  int path_len;
  int path_i = 0, newpath_i = 0;
  svn_boolean_t eating_slashes = FALSE;

  /* No PATH?  No problem. */
  if (! path)
    return NULL;
  
  /* Empty PATH?  That's just "/". */
  if (! *path)
    return apr_pstrdup (pool, "/");

  /* Now, the fun begins.  Alloc enough room to hold PATH with an
     added leading '/'. */
  path_len = strlen (path);
  newpath = apr_pcalloc (pool, path_len + 2);

  /* No leading slash?  Fix that. */
  if (*path != '/')
    {
      newpath[newpath_i++] = '/';
    }
  
  for (path_i = 0; path_i < path_len; path_i++)
    {
      if (path[path_i] == '/')
        {
          /* The current character is a '/'.  If we are eating up
             extra '/' characters, skip this character.  Else, note
             that we are now eating slashes. */
          if (eating_slashes)
            continue;
          eating_slashes = TRUE;
        }
      else
        {
          /* The current character is NOT a '/'.  If we were eating
             slashes, we need not do that any more. */
          if (eating_slashes)
            eating_slashes = FALSE;
        }

      /* Copy the current character into our new buffer. */
      newpath[newpath_i++] = path[path_i];
    }
  
  /* Did we leave a '/' attached to the end of NEWPATH (other than in
     the root directory case)? */
  if ((newpath[newpath_i - 1] == '/') && (newpath_i > 1))
    newpath[newpath_i - 1] = '\0';

  return newpath;
}

static const svn_version_t *
base_version (void)
{
  SVN_VERSION_BODY;
}



/* Base FS library vtable, used by the FS loader library. */
static fs_library_vtable_t library_vtable = {
  base_version,
  base_create,
  base_open,
  base_delete_fs,
  base_hotcopy,
  base_bdb_set_errcall,
  base_bdb_recover,
  base_bdb_logfiles,
  svn_fs_base__id_parse
};

svn_error_t *
svn_fs_base__init (const svn_version_t *loader_version,
                   fs_library_vtable_t **vtable)
{
  static const svn_version_checklist_t checklist[] =
    {
      { "svn_subr",  svn_subr_version },
      { "svn_delta", svn_delta_version },
      { NULL, NULL }
    };

  /* Simplified version check to make sure we can safely use the
     VTABLE parameter. The FS loader does a more exhaustive check. */
  if (loader_version->major != SVN_VER_MAJOR)
    return svn_error_createf (SVN_ERR_VERSION_MISMATCH, NULL,
                              _("Unsupported FS loader version (%d) for bdb"),
                              loader_version->major);
  SVN_ERR (svn_ver_check_list (base_version(), checklist));
  SVN_ERR (check_bdb_version());

  *vtable = &library_vtable;
  return SVN_NO_ERROR;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -