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

📄 lock.c

📁 subversion-1.4.3-1.tar.gz 配置svn的源码
💻 C
📖 第 1 页 / 共 4 页
字号:
/* * lock.c:  routines for locking working copy subdirectories. * * ==================================================================== * Copyright (c) 2000-2006 CollabNet.  All rights reserved. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution.  The terms * are also available at http://subversion.tigris.org/license-1.html. * If newer versions of this license are posted there, you may use a * newer version instead, at your option. * * This software consists of voluntary contributions made by many * individuals.  For exact contribution history, see the revision * history and logs, available at http://subversion.tigris.org/. * ==================================================================== */#include <assert.h>#include <apr_pools.h>#include <apr_time.h>#include "svn_pools.h"#include "svn_path.h"#include "svn_sorts.h"#include "wc.h"#include "adm_files.h"#include "lock.h"#include "questions.h"#include "props.h"#include "log.h"#include "entries.h"#include "svn_private_config.h"struct svn_wc_adm_access_t{  /* PATH to directory which contains the administrative area */  const char *path;  enum svn_wc__adm_access_type {    /* SVN_WC__ADM_ACCESS_UNLOCKED indicates no lock is held allowing       read-only access */    svn_wc__adm_access_unlocked,    /* SVN_WC__ADM_ACCESS_WRITE_LOCK indicates that a write lock is held       allowing read-write access */    svn_wc__adm_access_write_lock,    /* SVN_WC__ADM_ACCESS_CLOSED indicates that the baton has been       closed. */    svn_wc__adm_access_closed  } type;  /* LOCK_EXISTS is set TRUE when the write lock exists */  svn_boolean_t lock_exists;  /* SET_OWNER is TRUE if SET is allocated from this access baton */  svn_boolean_t set_owner;  /* The working copy format version number for the directory */  int wc_format;  /* SET is a hash of svn_wc_adm_access_t* keyed on char* representing the     path to directories that are open. */  apr_hash_t *set;  /* ENTRIES is the cached entries for PATH, without those in state     deleted. ENTRIES_HIDDEN is the cached entries including those in     state deleted or state absent. Either may be NULL. */  apr_hash_t *entries;  apr_hash_t *entries_hidden;  /* A hash mapping const char * entry names to hashes of wcprops.     These hashes map const char * names to svn_string_t * values.     NULL of the wcprops hasn't been read into memory.     ### Since there are typically just one or two wcprops per entry,     ### we could use a more compact way of storing them. */  apr_hash_t *wcprops;  /* POOL is used to allocate cached items, they need to persist for the     lifetime of this access baton */  apr_pool_t *pool;};/* This is a placeholder used in the set hash to represent missing   directories.  Only its address is important, it contains no useful   data. */static svn_wc_adm_access_t missing;static svn_error_t *do_close(svn_wc_adm_access_t *adm_access, svn_boolean_t preserve_lock,         svn_boolean_t recurse);/* Defining this conditional will result in a client that will refuse to   upgrade working copies.  This can be useful if you want to avoid   problems caused by accidentally running a development version of SVN   on a working copy that you typically use with an older version. */#ifndef SVN_DISABLE_WC_UPGRADE/* Write, to LOG_ACCUM, log entries to convert an old WC that did not have   propcaching into a WC that uses propcaching.  Do this conversion for   the directory of ADM_ACCESS and its file children.  Use POOL for    temporary allocations.  */static svn_error_t *introduce_propcaching(svn_stringbuf_t *log_accum,                      svn_wc_adm_access_t *adm_access,                      apr_pool_t *pool){  apr_hash_t *entries;  apr_hash_index_t *hi;  apr_pool_t *subpool = svn_pool_create(pool);    SVN_ERR(svn_wc_entries_read(&entries, adm_access, FALSE, pool));  /* Reinstall the properties for each file and this dir; subdirs are handled     when they're opened. */  for (hi = apr_hash_first(pool, entries); hi; hi = apr_hash_next(hi))    {      void *val;      const svn_wc_entry_t *entry;      svn_wc_entry_t tmpentry;      apr_hash_t *base_props, *props;      apr_hash_this(hi, NULL, NULL, &val);      entry = val;      if (entry->kind != svn_node_file          && strcmp(entry->name, SVN_WC_ENTRY_THIS_DIR) != 0)        continue;      svn_pool_clear(subpool);            SVN_ERR(svn_wc__load_props(&base_props, &props, adm_access,                                 entry->name, subpool));      SVN_ERR(svn_wc__install_props(&log_accum, adm_access, entry->name,                                    base_props, props, TRUE, subpool));      /* Make sure we get rid of that prop-time field.         It only wastes space in new WCs. */      tmpentry.prop_time = 0;      SVN_ERR(svn_wc__loggy_entry_modify(&log_accum, adm_access,                                         entry->name, &tmpentry,                                         SVN_WC__ENTRY_MODIFY_PROP_TIME,                                         pool));    }  return SVN_NO_ERROR;}/* Write, to LOG_ACCUM, commands to convert a WC that has wcprops in individual   files to use one wcprops file per directory.   Do this for ADM_ACCESS and its file children, using POOL for temporary   allocations. */static svn_error_t *convert_wcprops(svn_stringbuf_t *log_accum,                svn_wc_adm_access_t *adm_access,                apr_pool_t *pool){  apr_hash_t *entries;  apr_hash_index_t *hi;  apr_pool_t *subpool = svn_pool_create(pool);    SVN_ERR(svn_wc_entries_read(&entries, adm_access, FALSE, pool));  /* Walk over the entries, adding a modify-wcprop command for each wcprop.     Note that the modifications happen in memory and are just written once     at the end of the log execution, so this isn't as inefficient as it     might sound. */  for (hi = apr_hash_first(pool, entries); hi; hi = apr_hash_next(hi))    {      void *val;      const svn_wc_entry_t *entry;      apr_hash_t *wcprops;      apr_hash_index_t *hj;      apr_hash_this(hi, NULL, NULL, &val);      entry = val;      if (entry->kind != svn_node_file          && strcmp(entry->name, SVN_WC_ENTRY_THIS_DIR) != 0)        continue;      svn_pool_clear(subpool);            SVN_ERR(svn_wc__wcprop_list(&wcprops, entry->name, adm_access, subpool));      /* Create a subsubpool for the inner loop...         No, just kidding.  There are typically just one or two wcprops         per entry... */      for (hj = apr_hash_first(subpool, wcprops); hj; hj = apr_hash_next(hj))        {          const void *key2;          void *val2;          const char *propname;          svn_string_t *propval;          apr_hash_this(hj, &key2, NULL, &val2);          propname = key2;          propval = val2;          SVN_ERR(svn_wc__loggy_modify_wcprop(&log_accum, adm_access,                                              entry->name, propname,                                              propval->data,                                              subpool));        }    }  return SVN_NO_ERROR;}/* Maybe upgrade the working copy directory represented by ADM_ACCESS   to the latest 'SVN_WC__VERSION'.  ADM_ACCESS must contain a write   lock.  Use POOL for all temporary allocation.   Not all upgrade paths are necessarily supported.  For example,   upgrading a version 1 working copy results in an error.   Sometimes the format file can contain "0" while the administrative   directory is being constructed; calling this on a format 0 working   copy has no effect and returns no error. */static svn_error_t *maybe_upgrade_format(svn_wc_adm_access_t *adm_access, apr_pool_t *pool){  SVN_ERR(svn_wc__check_format(adm_access->wc_format,                               adm_access->path,                               pool));  /* We can upgrade all formats that are accepted by     svn_wc__check_format. */  if (adm_access->wc_format != SVN_WC__VERSION)    {      svn_boolean_t cleanup_required;      svn_stringbuf_t *log_accum = svn_stringbuf_create("", pool);      /* Don't try to mess with the WC if there are old log files left. */      SVN_ERR(svn_wc__adm_is_cleanup_required(&cleanup_required,                                              adm_access, pool));      if (cleanup_required)        return SVN_NO_ERROR;      /* First, loggily upgrade the format file. */      SVN_ERR(svn_wc__loggy_upgrade_format(&log_accum, adm_access,                                           SVN_WC__VERSION, pool));      /* Possibly convert an old WC that doesn't use propcaching. */      if (adm_access->wc_format <= SVN_WC__NO_PROPCACHING_VERSION)        SVN_ERR(introduce_propcaching(log_accum, adm_access, pool));      /* If the WC uses one file per entry for wcprops, give back some inodes         to the poor user. */      if (adm_access->wc_format <= SVN_WC__WCPROPS_MANY_FILES_VERSION)        SVN_ERR(convert_wcprops(log_accum, adm_access, pool));      SVN_ERR(svn_wc__write_log(adm_access, 0, log_accum, pool));      if (adm_access->wc_format <= SVN_WC__WCPROPS_MANY_FILES_VERSION)        {          const char *access_path = svn_wc_adm_access_path(adm_access);          /* Remove wcprops directory, dir-props, README.txt and empty-file             files.             We just silently ignore errors, because keeping these files is             not catastrophic. */          svn_error_clear(svn_io_remove_dir            (svn_wc__adm_path(access_path, FALSE, pool, SVN_WC__ADM_WCPROPS,                              NULL), pool));          svn_error_clear(svn_io_remove_file            (svn_wc__adm_path(access_path, FALSE, pool,                              SVN_WC__ADM_DIR_WCPROPS, NULL), pool));          svn_error_clear(svn_io_remove_file            (svn_wc__adm_path(access_path, FALSE, pool,                              SVN_WC__ADM_EMPTY_FILE, NULL), pool));          svn_error_clear(svn_io_remove_file            (svn_wc__adm_path(access_path, FALSE, pool,                              SVN_WC__ADM_README, NULL), pool));        }      SVN_ERR(svn_wc__run_log(adm_access, NULL, pool));    }  return SVN_NO_ERROR;}#else/* Alternate version of the above for use when working copy upgrades   are disabled.  Return an error if the working copy described by   ADM_ACCESS is not at the latest 'SVN_WC__VERSION'.  Use POOL for all   temporary allocation.  */static svn_error_t *maybe_upgrade_format(svn_wc_adm_access_t *adm_access, apr_pool_t *pool){  SVN_ERR(svn_wc__check_format(adm_access->wc_format,                               adm_access->path,                               pool));  if (adm_access->wc_format != SVN_WC__VERSION)    {      return svn_error_createf(SVN_ERR_WC_UNSUPPORTED_FORMAT, NULL,                               "Would upgrade working copy '%s' from old "                               "format (%d) to current format (%d), "                               "but automatic upgrade has been disabled",                               svn_path_local_style(adm_access->path, pool),                               adm_access->wc_format, SVN_WC__VERSION);    }  return SVN_NO_ERROR;}#endif/* Create a physical lock file in the admin directory for ADM_ACCESS. Wait   up to WAIT_FOR seconds if the lock already exists retrying every   second.    Note: most callers of this function determine the wc_format for the   lock soon afterwards.  We recommend calling maybe_upgrade_format()   as soon as you have the wc_format for a lock, since that's a good   opportunity to drag old working directories into the modern era. */static svn_error_t *create_lock(svn_wc_adm_access_t *adm_access, int wait_for, apr_pool_t *pool){  svn_error_t *err;  for (;;)    {      err = svn_wc__make_adm_thing(adm_access, SVN_WC__ADM_LOCK,                                   svn_node_file, APR_OS_DEFAULT, 0, pool);      if (err)        {          if (APR_STATUS_IS_EEXIST(err->apr_err))            {              svn_error_clear(err);              if (wait_for <= 0)                break;              wait_for--;              apr_sleep(apr_time_from_sec(1));  /* micro-seconds */            }          else            return err;        }      else        return SVN_NO_ERROR;    }  return svn_error_createf(SVN_ERR_WC_LOCKED, NULL,                           _("Working copy '%s' locked"),                           svn_path_local_style(adm_access->path, pool));}/* Remove the physical lock in the admin directory for PATH. It is   acceptable for the administrative area to have disappeared, such as when   the directory is removed from the working copy.  It is an error for the   lock to have disappeared if the administrative area still exists. */static svn_error_t *remove_lock(const char *path, apr_pool_t *pool){  svn_error_t *err = svn_wc__remove_adm_file(path, pool, SVN_WC__ADM_LOCK,                                             NULL);  if (err)    {      if (svn_wc__adm_path_exists(path, FALSE, pool, NULL))        return err;      svn_error_clear(err);    }  return SVN_NO_ERROR;}/* An APR pool cleanup handler.  This handles access batons that have not   been closed when their pool gets destroyed.  The physical locks   associated with such batons remain in the working copy if they are   protecting a log file. */static apr_status_tpool_cleanup(void *p){  svn_wc_adm_access_t *lock = p;  svn_boolean_t cleanup;  svn_error_t *err;  if (lock->type == svn_wc__adm_access_closed)    return SVN_NO_ERROR;  err = svn_wc__adm_is_cleanup_required(&cleanup, lock, lock->pool);  if (!err)

⌨️ 快捷键说明

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