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

📄 fs_fs.c

📁 subversion-1.4.3-1.tar.gz 配置svn的源码
💻 C
📖 第 1 页 / 共 5 页
字号:
/* Same as unlock_proto_rev(), but requires that the transaction list   lock is already held. */static svn_error_t *unlock_proto_rev_list_locked(svn_fs_t *fs, const char *txn_id,                             void *lockcookie,                             apr_pool_t *pool){  struct unlock_proto_rev_baton b;  b.txn_id = txn_id;  b.lockcookie = lockcookie;  return unlock_proto_rev_body(fs, &b, pool);}/* A structure used by get_writable_proto_rev() and   get_writable_proto_rev_body(), which see. */struct get_writable_proto_rev_baton{  apr_file_t **file;  void **lockcookie;  const char *txn_id;};/* Callback used in the implementation of get_writable_proto_rev(). */static svn_error_t *get_writable_proto_rev_body(svn_fs_t *fs, void *baton, apr_pool_t *pool){  struct get_writable_proto_rev_baton *b = baton;  apr_file_t **file = b->file;  void **lockcookie = b->lockcookie;  const char *txn_id = b->txn_id;  svn_error_t *err;  fs_fs_shared_txn_data_t *txn = get_shared_txn(fs, txn_id, TRUE);  /* First, ensure that no thread in this process (including this one)     is currently writing to this transaction's proto-rev file. */  if (txn->being_written)    return svn_error_createf(SVN_ERR_FS_TRANSACTION_NOT_MUTABLE, NULL,                             _("Cannot write to the prototype revision file "                               "of transaction '%s' because a previous "                               "representation is currently being written by "                               "this process"),                             txn_id);  /* We know that no thread in this process is writing to the proto-rev     file, and by extension, that no thread in this process is holding a     lock on the prototype revision lock file.  It is therefore safe     for us to attempt to lock this file, to see if any other process     is holding a lock. */  {    apr_file_t *lockfile;    apr_status_t apr_err;    const char *lockfile_path = path_txn_proto_rev_lock(fs, txn_id, pool);    /* Open the proto-rev lockfile, creating it if necessary, as it may       not exist if the transaction dates from before the lockfiles were       introduced.       ### We'd also like to use something like svn_io_file_lock2(), but           that forces us to create a subpool just to be able to unlock           the file, which seems a waste. */    SVN_ERR(svn_io_file_open(&lockfile, lockfile_path,                             APR_WRITE | APR_CREATE, APR_OS_DEFAULT, pool));    apr_err = apr_file_lock(lockfile,                            APR_FLOCK_EXCLUSIVE | APR_FLOCK_NONBLOCK);    if (apr_err)      {        svn_error_clear(svn_io_file_close(lockfile, pool));        if (APR_STATUS_IS_EAGAIN(apr_err))          return svn_error_createf(SVN_ERR_FS_TRANSACTION_NOT_MUTABLE, NULL,                                   _("Cannot write to the prototype revision "                                     "file of transaction '%s' because a "                                     "previous representation is currently "                                     "being written by another process"),                                   txn_id);        return svn_error_wrap_apr(apr_err,                                  _("Can't get exclusive lock on file '%s'"),                                  svn_path_local_style(lockfile_path, pool));      }    *lockcookie = lockfile;  }  /* We've successfully locked the transaction; mark it as such. */  txn->being_written = TRUE;  /* Now open the prototype revision file and seek to the end. */  err = svn_io_file_open(file, path_txn_proto_rev(fs, txn_id, pool),                         APR_WRITE | APR_BUFFERED, APR_OS_DEFAULT, pool);  /* You might expect that we could dispense with the following seek     and achieve the same thing by opening the file using APR_APPEND.     Unfortunately, APR's buffered file implementation unconditionally     places its initial file pointer at the start of the file (even for     files opened with APR_APPEND), so we need this seek to reconcile     the APR file pointer to the OS file pointer (since we need to be     able to read the current file position later). */  if (!err)    {      apr_off_t offset = 0;      err = svn_io_file_seek(*file, APR_END, &offset, 0);    }  if (err)    {      svn_error_clear(unlock_proto_rev_list_locked(fs, txn_id, *lockcookie,                                                   pool));      *lockcookie = NULL;    }  return err;}/* Get a handle to the prototype revision file for transaction TXN_ID in   filesystem FS, and lock it for writing.  Return FILE, a file handle   positioned at the end of the file, and LOCKCOOKIE, a cookie that   should be passed to unlock_proto_rev() to unlock the file once FILE   has been closed.   If the prototype revision file is already locked, return error   SVN_ERR_FS_TRANSACTION_NOT_MUTABLE.   Perform all allocations in POOL. */static svn_error_t *get_writable_proto_rev(apr_file_t **file,                       void **lockcookie,                       svn_fs_t *fs, const char *txn_id,                       apr_pool_t *pool){  struct get_writable_proto_rev_baton b;  b.file = file;  b.lockcookie = lockcookie;  b.txn_id = txn_id;  return with_txnlist_lock(fs, get_writable_proto_rev_body, &b, pool);}/* Callback used in the implementation of purge_shared_txn(). */static svn_error_t *purge_shared_txn_body(svn_fs_t *fs, void *baton, apr_pool_t *pool){  const char *txn_id = *(const char **)baton;  free_shared_txn(fs, txn_id);  return SVN_NO_ERROR;}/* Purge the shared data for transaction TXN_ID in filesystem FS.   Perform all allocations in POOL. */static svn_error_t *purge_shared_txn(svn_fs_t *fs, const char *txn_id, apr_pool_t *pool){  return with_txnlist_lock(fs, purge_shared_txn_body, &txn_id, pool);}/* Fetch the current offset of FILE into *OFFSET_P. */static svn_error_t *get_file_offset(apr_off_t *offset_p, apr_file_t *file, apr_pool_t *pool){  apr_off_t offset;  /* Note that, for buffered files, one (possibly surprising) side-effect     of this call is to flush any unwritten data to disk. */  offset = 0;  SVN_ERR(svn_io_file_seek(file, APR_CUR, &offset, pool));  *offset_p = offset;  return SVN_NO_ERROR;}/* Read the format version from FILE and return it in *PFORMAT.   Use POOL for temporary allocation. */static svn_error_t *read_format(int *pformat, const char *file, apr_pool_t *pool){  svn_error_t *err = svn_io_read_version_file(pformat, file, pool);  if (err && APR_STATUS_IS_ENOENT(err->apr_err))    {      /* Treat an absent format file as format 1.  Do not try to         create the format file on the fly, because the repository         might be read-only for us, or this might be a read-only         operation, and the spirit of FSFS is to make no changes         whatseover in read-only operations.  See thread starting at         http://subversion.tigris.org/servlets/ReadMsg?list=dev&msgNo=97600         for more. */      svn_error_clear(err);      err = SVN_NO_ERROR;      *pformat = 1;    }  return err;}/* Return the error SVN_ERR_FS_UNSUPPORTED_FORMAT if FS's format   number is not the same as the format number supported by this   Subversion. */static svn_error_t *check_format(int format){  /* We support format 1 and 2 simultaneously */  if (format == 1 && SVN_FS_FS__FORMAT_NUMBER == 2)    return SVN_NO_ERROR;  if (format != SVN_FS_FS__FORMAT_NUMBER)    {      return svn_error_createf         (SVN_ERR_FS_UNSUPPORTED_FORMAT, NULL,         _("Expected FS format '%d'; found format '%d'"),          SVN_FS_FS__FORMAT_NUMBER, format);    }  return SVN_NO_ERROR;}svn_error_t *svn_fs_fs__open(svn_fs_t *fs, const char *path, apr_pool_t *pool){  fs_fs_data_t *ffd = fs->fsap_data;  apr_file_t *current_file, *uuid_file;  int format;  char buf[APR_UUID_FORMATTED_LENGTH + 2];  apr_size_t limit;  fs->path = apr_pstrdup(fs->pool, path);  /* Attempt to open the 'current' file of this repository.  There     isn't much need for specific state associated with an open fs_fs     repository. */  SVN_ERR(svn_io_file_open(&current_file, path_current(fs, pool),                           APR_READ, APR_OS_DEFAULT, pool));  SVN_ERR(svn_io_file_close(current_file, pool));  /* Read the FS format number. */  SVN_ERR(read_format(&format, path_format(fs, pool), pool));  /* Now we've got a format number no matter what. */  ffd->format = format;  SVN_ERR(check_format(format));  /* Read in and cache the repository uuid. */  SVN_ERR(svn_io_file_open(&uuid_file, path_uuid(fs, pool),                           APR_READ | APR_BUFFERED, APR_OS_DEFAULT, pool));  limit = sizeof(buf);  SVN_ERR(svn_io_read_length_line(uuid_file, buf, &limit, pool));  ffd->uuid = apr_pstrdup(fs->pool, buf);    SVN_ERR(svn_io_file_close(uuid_file, pool));  return SVN_NO_ERROR;}/* Find the youngest revision in a repository at path FS_PATH and   return it in *YOUNGEST_P.  Perform temporary allocations in   POOL. */static svn_error_t *get_youngest(svn_revnum_t *youngest_p,             const char *fs_path,             apr_pool_t *pool){  apr_file_t *current_file;  char buf[81];  apr_size_t len;  SVN_ERR(svn_io_file_open(&current_file,                           svn_path_join(fs_path, PATH_CURRENT, pool),                           APR_READ, APR_OS_DEFAULT, pool));  len = sizeof(buf) - 1;  SVN_ERR(svn_io_file_read(current_file, buf, &len, pool));  buf[len] = '\0';    *youngest_p = SVN_STR_TO_REV(buf);    SVN_ERR(svn_io_file_close(current_file, pool));    return SVN_NO_ERROR;}svn_error_t *svn_fs_fs__hotcopy(const char *src_path,                   const char *dst_path,                   apr_pool_t *pool){  const char *src_subdir, *dst_subdir;  svn_revnum_t youngest, rev;  apr_pool_t *iterpool;  svn_node_kind_t kind;  int format;  /* Check format to be sure we know how to hotcopy this FS. */  SVN_ERR(read_format(&format,                      svn_path_join(src_path, PATH_FORMAT, pool),                      pool));  SVN_ERR(check_format(format));  /* Copy the current file. */  SVN_ERR(svn_io_dir_file_copy(src_path, dst_path, PATH_CURRENT, pool));  /* Copy the uuid. */  SVN_ERR(svn_io_dir_file_copy(src_path, dst_path, PATH_UUID, pool));  /* Find the youngest revision from this current file. */  SVN_ERR(get_youngest(&youngest, dst_path, pool));  /* Copy the necessary rev files. */  src_subdir = svn_path_join(src_path, PATH_REVS_DIR, pool);  dst_subdir = svn_path_join(dst_path, PATH_REVS_DIR, pool);  SVN_ERR(svn_io_make_dir_recursively(dst_subdir, pool));  iterpool = svn_pool_create(pool);  for (rev = 0; rev <= youngest; rev++)    {      SVN_ERR(svn_io_dir_file_copy(src_subdir, dst_subdir,                                   apr_psprintf(iterpool, "%ld", rev),                                   iterpool));      svn_pool_clear(iterpool);    }  /* Copy the necessary revprop files. */  src_subdir = svn_path_join(src_path, PATH_REVPROPS_DIR, pool);  dst_subdir = svn_path_join(dst_path, PATH_REVPROPS_DIR, pool);  SVN_ERR(svn_io_make_dir_recursively(dst_subdir, pool));  for (rev = 0; rev <= youngest; rev++)    {      svn_pool_clear(iterpool);      SVN_ERR(svn_io_dir_file_copy(src_subdir, dst_subdir,                                   apr_psprintf(iterpool, "%ld", rev),                                   iterpool));    }  svn_pool_destroy(iterpool);  /* Make an empty transactions directory for now.  Eventually some     method of copying in progress transactions will need to be     developed.*/  dst_subdir = svn_path_join(dst_path, PATH_TXNS_DIR, pool);  SVN_ERR(svn_io_make_dir_recursively(dst_subdir, pool));  /* Now copy the locks tree. */  src_subdir = svn_path_join(src_path, PATH_LOCKS_DIR, pool);  SVN_ERR(svn_io_check_path(src_subdir, &kind, pool));  if (kind == svn_node_dir)    SVN_ERR(svn_io_copy_dir_recursively(src_subdir, dst_path,                                        PATH_LOCKS_DIR, TRUE, NULL,                                        NULL, pool));  /* Hotcopied FS is complete. Stamp it with a format file. */  SVN_ERR(svn_io_write_version_file           (svn_path_join(dst_path, PATH_FORMAT, pool), format, pool));  return SVN_NO_ERROR;}svn_error_t *svn_fs_fs__youngest_rev(svn_revnum_t *youngest_p,                        svn_fs_t *fs,                        apr_pool_t *pool){  SVN_ERR(get_youngest(youngest_p, fs->path, pool));    return SVN_NO_ERROR;}/* Given a revision file FILE that has been pre-positioned at the   beginning of a Node-Rev header block, read in that header block and   store it in the apr_hash_t HEADERS.  All allocations will be from   POOL. */static svn_error_t * read_header_block(apr_hash_t **headers,                                       apr_file_t *file,                                       apr_pool_t *pool){  *headers = apr_hash_make(pool);    while (1)    {      char header_str[1024];      const char *name, *value;      apr_size_t i = 0, header_len;      apr_size_t limit;      char *local_name, *local_value;      limit = sizeof(header_str);      SVN_ERR(svn_io_read_length_line(file, header_str, &limit, pool));      if (strlen(header_str) == 0)        break; /* end of header block */            header_len = strlen(header_str);      while (header_str[i] != ':')        {          if (header_str[i] == '\0')            return svn_error_create(SVN_ERR_FS_CORRUPT, NULL,                                    _("Found malformed header in "

⌨️ 快捷键说明

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