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

📄 fs_fs.c

📁 subversion-1.4.3-1.tar.gz 配置svn的源码
💻 C
📖 第 1 页 / 共 5 页
字号:
/* fs_fs.c --- filesystem operations specific to fs_fs * * ==================================================================== * 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 <stdlib.h>#include <stdio.h>#include <string.h>#include <ctype.h>#include <assert.h>#include <apr_general.h>#include <apr_pools.h>#include <apr_file_io.h>#include <apr_uuid.h>#include <apr_md5.h>#include <apr_thread_mutex.h>#include "svn_pools.h"#include "svn_fs.h"#include "svn_path.h"#include "svn_hash.h"#include "svn_md5.h"#include "svn_sorts.h"#include "svn_time.h"#include "fs.h"#include "err.h"#include "tree.h"#include "lock.h"#include "revs-txns.h"#include "key-gen.h"#include "fs_fs.h"#include "id.h"#include "../libsvn_fs/fs-loader.h"#include "svn_private_config.h"/* Following are defines that specify the textual elements of the   native filesystem directories and revision files. *//* Names of special files in the fs_fs filesystem. */#define PATH_FORMAT        "format"        /* Contains format number */#define PATH_UUID          "uuid"          /* Contains UUID */#define PATH_CURRENT       "current"       /* Youngest revision */#define PATH_LOCK_FILE     "write-lock"    /* Revision lock file */#define PATH_REVS_DIR      "revs"          /* Directory of revisions */#define PATH_REVPROPS_DIR  "revprops"      /* Directory of revprops */#define PATH_TXNS_DIR      "transactions"  /* Directory of transactions */#define PATH_LOCKS_DIR     "locks"         /* Directory of locks *//* Names of special files and file extensions for transactions */#define PATH_CHANGES       "changes"       /* Records changes made so far */#define PATH_TXN_PROPS     "props"         /* Transaction properties */#define PATH_NEXT_IDS      "next-ids"      /* Next temporary ID assignments */#define PATH_REV           "rev"           /* Proto rev file */#define PATH_REV_LOCK      "rev-lock"      /* Proto rev (write) lock file */#define PATH_PREFIX_NODE   "node."         /* Prefix for node filename */#define PATH_EXT_TXN       ".txn"          /* Extension of txn dir */#define PATH_EXT_CHILDREN  ".children"     /* Extension for dir contents */#define PATH_EXT_PROPS     ".props"        /* Extension for node props *//* Headers used to describe node-revision in the revision file. */#define HEADER_ID          "id"#define HEADER_TYPE        "type"#define HEADER_COUNT       "count"#define HEADER_PROPS       "props"#define HEADER_TEXT        "text"#define HEADER_CPATH       "cpath"#define HEADER_PRED        "pred"#define HEADER_COPYFROM    "copyfrom"#define HEADER_COPYROOT    "copyroot"/* Kinds that a change can be. */#define ACTION_MODIFY      "modify"#define ACTION_ADD         "add"#define ACTION_DELETE      "delete"#define ACTION_REPLACE     "replace"#define ACTION_RESET       "reset"/* True and False flags. */#define FLAG_TRUE          "true"#define FLAG_FALSE         "false"/* Kinds that a node-rev can be. */#define KIND_FILE          "file"#define KIND_DIR           "dir"/* Kinds of representation. */#define REP_PLAIN          "PLAIN"#define REP_DELTA          "DELTA"/* Notes:To avoid opening and closing the rev-files all the time, it wouldprobably be advantageous to keep each rev-file open for thelifetime of the transaction object.  I'll leave that as a lateroptimization for now.I didn't keep track of pool lifetimes at all in this code.  Thereare likely some errors because of that.   *//* The vtable associated with an open transaction object. */static txn_vtable_t txn_vtable = {  svn_fs_fs__commit_txn,  svn_fs_fs__abort_txn,  svn_fs_fs__txn_prop,  svn_fs_fs__txn_proplist,  svn_fs_fs__change_txn_prop,  svn_fs_fs__txn_root};/* Pathname helper functions */static const char *path_format(svn_fs_t *fs, apr_pool_t *pool){  return svn_path_join(fs->path, PATH_FORMAT, pool);}static const char *path_uuid(svn_fs_t *fs, apr_pool_t *pool){  return svn_path_join(fs->path, PATH_UUID, pool);}static const char *path_current(svn_fs_t *fs, apr_pool_t *pool){  return svn_path_join(fs->path, PATH_CURRENT, pool);}static const char *path_lock(svn_fs_t *fs, apr_pool_t *pool){  return svn_path_join(fs->path, PATH_LOCK_FILE, pool);}const char *svn_fs_fs__path_rev(svn_fs_t *fs, svn_revnum_t rev, apr_pool_t *pool){  return svn_path_join_many(pool, fs->path, PATH_REVS_DIR,                            apr_psprintf(pool, "%ld", rev), NULL);}static const char *path_revprops(svn_fs_t *fs, svn_revnum_t rev, apr_pool_t *pool){  return svn_path_join_many(pool, fs->path, PATH_REVPROPS_DIR,                            apr_psprintf(pool, "%ld", rev), NULL);}static const char *path_txn_dir(svn_fs_t *fs, const char *txn_id, apr_pool_t *pool){  return svn_path_join_many(pool, fs->path, PATH_TXNS_DIR,                            apr_pstrcat(pool, txn_id, PATH_EXT_TXN, NULL),                            NULL);}static const char *path_txn_changes(svn_fs_t *fs, const char *txn_id, apr_pool_t *pool){  return svn_path_join(path_txn_dir(fs, txn_id, pool), PATH_CHANGES, pool);}static const char *path_txn_props(svn_fs_t *fs, const char *txn_id, apr_pool_t *pool){  return svn_path_join(path_txn_dir(fs, txn_id, pool), PATH_TXN_PROPS, pool);}static const char *path_txn_next_ids(svn_fs_t *fs, const char *txn_id, apr_pool_t *pool){  return svn_path_join(path_txn_dir(fs, txn_id, pool), PATH_NEXT_IDS, pool);}static const char *path_txn_proto_rev(svn_fs_t *fs, const char *txn_id, apr_pool_t *pool){  return svn_path_join(path_txn_dir(fs, txn_id, pool), PATH_REV, pool);}static const char *path_txn_proto_rev_lock(svn_fs_t *fs, const char *txn_id, apr_pool_t *pool){  return svn_path_join(path_txn_dir(fs, txn_id, pool), PATH_REV_LOCK, pool);}static const char *path_txn_node_rev(svn_fs_t *fs, const svn_fs_id_t *id, apr_pool_t *pool){  const char *txn_id = svn_fs_fs__id_txn_id(id);  const char *node_id = svn_fs_fs__id_node_id(id);  const char *copy_id = svn_fs_fs__id_copy_id(id);  const char *name = apr_psprintf(pool, PATH_PREFIX_NODE "%s.%s",                                  node_id, copy_id);  return svn_path_join(path_txn_dir(fs, txn_id, pool), name, pool);}static const char *path_txn_node_props(svn_fs_t *fs, const svn_fs_id_t *id, apr_pool_t *pool){  return apr_pstrcat(pool, path_txn_node_rev(fs, id, pool), PATH_EXT_PROPS,                     NULL);}static const char *path_txn_node_children(svn_fs_t *fs, const svn_fs_id_t *id, apr_pool_t *pool){  return apr_pstrcat(pool, path_txn_node_rev(fs, id, pool),                     PATH_EXT_CHILDREN, NULL);}/* Functions for working with shared transaction data. *//* Return the transaction object for transaction TXN_ID from the   transaction list of filesystem FS (which must already be locked via the   txn_list_lock mutex).  If the transaction does not exist in the list,   then create a new transaction object and return it (if CREATE_NEW is   true) or return NULL (otherwise). */static fs_fs_shared_txn_data_t *get_shared_txn(svn_fs_t *fs, const char *txn_id, svn_boolean_t create_new){  fs_fs_data_t *ffd = fs->fsap_data;  fs_fs_shared_data_t *ffsd = ffd->shared;  fs_fs_shared_txn_data_t *txn;  for (txn = ffsd->txns; txn; txn = txn->next)    if (strcmp(txn->txn_id, txn_id) == 0)      break;  if (txn || !create_new)    return txn;  /* Use the transaction object from the (single-object) freelist,     if one is available, or otherwise create a new object. */  if (ffsd->free_txn)    {      txn = ffsd->free_txn;      ffsd->free_txn = NULL;    }  else    {      apr_pool_t *subpool = svn_pool_create(ffsd->common_pool);      txn = apr_palloc(subpool, sizeof(*txn));      txn->pool = subpool;    }  assert(strlen(txn_id) < sizeof(txn->txn_id));  strcpy(txn->txn_id, txn_id);  txn->being_written = FALSE;  /* Link this transaction into the head of the list.  We will typically     be dealing with only one active transaction at a time, so it makes     sense for searches through the transaction list to look at the     newest transactions first.  */  txn->next = ffsd->txns;  ffsd->txns = txn;  return txn;}/* Free the transaction object for transaction TXN_ID, and remove it   from the transaction list of filesystem FS (which must already be   locked via the txn_list_lock mutex).  Do nothing if the transaction   does not exist. */static voidfree_shared_txn(svn_fs_t *fs, const char *txn_id){  fs_fs_data_t *ffd = fs->fsap_data;  fs_fs_shared_data_t *ffsd = ffd->shared;  fs_fs_shared_txn_data_t *txn, *prev = NULL;  for (txn = ffsd->txns; txn; prev = txn, txn = txn->next)    if (strcmp(txn->txn_id, txn_id) == 0)      break;  if (!txn)    return;  if (prev)    prev->next = txn->next;  else    ffsd->txns = txn->next;  /* As we typically will be dealing with one transaction after another,     we will maintain a single-object free list so that we can hopefully     keep reusing the same transaction object. */  if (!ffsd->free_txn)    ffsd->free_txn = txn;  else    svn_pool_destroy(txn->pool);}/* Obtain a lock on the transaction list of filesystem FS, call BODY   with FS, BATON, and POOL, and then unlock the transaction list.   Return what BODY returned. */static svn_error_t *with_txnlist_lock(svn_fs_t *fs,                  svn_error_t *(*body)(svn_fs_t *fs,                                       void *baton,                                       apr_pool_t *pool),                  void *baton,                  apr_pool_t *pool){  svn_error_t *err;#if APR_HAS_THREADS  fs_fs_data_t *ffd = fs->fsap_data;  fs_fs_shared_data_t *ffsd = ffd->shared;  apr_status_t apr_err;  apr_err = apr_thread_mutex_lock(ffsd->txn_list_lock);  if (apr_err)    return svn_error_wrap_apr(apr_err, _("Can't grab FSFS txn list mutex"));#endif  err = body(fs, baton, pool);#if APR_HAS_THREADS  apr_err = apr_thread_mutex_unlock(ffsd->txn_list_lock);  if (apr_err && !err)    return svn_error_wrap_apr(apr_err, _("Can't ungrab FSFS txn list mutex"));#endif  return err;}/* A structure used by unlock_proto_rev() and unlock_proto_rev_body(),   which see. */struct unlock_proto_rev_baton{  const char *txn_id;  void *lockcookie;};/* Callback used in the implementation of unlock_proto_rev(). */static svn_error_t *unlock_proto_rev_body(svn_fs_t *fs, void *baton, apr_pool_t *pool){  struct unlock_proto_rev_baton *b = baton;  const char *txn_id = b->txn_id;  apr_file_t *lockfile = b->lockcookie;  fs_fs_shared_txn_data_t *txn = get_shared_txn(fs, txn_id, FALSE);  apr_status_t apr_err;  if (!txn)    return svn_error_createf(SVN_ERR_FS_CORRUPT, NULL,                             _("Can't unlock unknown transaction '%s'"),                             txn_id);  if (!txn->being_written)    return svn_error_createf(SVN_ERR_FS_CORRUPT, NULL,                             _("Can't unlock nonlocked transaction '%s'"),                             txn_id);  apr_err = apr_file_unlock(lockfile);  if (apr_err)    return svn_error_wrap_apr      (apr_err,       _("Can't unlock prototype revision lockfile for transaction '%s'"),       txn_id);  apr_err = apr_file_close(lockfile);  if (apr_err)    return svn_error_wrap_apr      (apr_err,       _("Can't close prototype revision lockfile for transaction '%s'"),       txn_id);  txn->being_written = FALSE;  return SVN_NO_ERROR;}/* Unlock the prototype revision file for transaction TXN_ID in filesystem   FS using cookie LOCKCOOKIE.  The original prototype revision file must   have been closed _before_ calling this function.   Perform temporary allocations in POOL. */static svn_error_t *unlock_proto_rev(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 with_txnlist_lock(fs, unlock_proto_rev_body, &b, pool);}

⌨️ 快捷键说明

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