Index: subversion/libsvn_fs_fs/fs.h =================================================================== --- subversion/libsvn_fs_fs/fs.h (revision 28646) +++ subversion/libsvn_fs_fs/fs.h (working copy) @@ -45,6 +45,7 @@ extern "C" { #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_TXN_PROTOS_DIR "txn-protorevs" /* Directory of proto-revs */ #define PATH_TXN_CURRENT "transaction-current" /* File with next txn key */ #define PATH_TXN_CURRENT_LOCK "txn-current-lock" /* Lock for txn-current */ #define PATH_LOCKS_DIR "locks" /* Directory of locks */ @@ -53,13 +54,16 @@ extern "C" { #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_TXN_MERGEINFO "mergeinfo" /* Transaction mergeinfo props */ #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 */ +#define PATH_EXT_REV ".rev" /* Extension of protorev file */ +#define PATH_EXT_REV_LOCK ".rev-lock" /* Extension of protorev lock file */ +/* Names of files in legacy FS formats */ +#define PATH_REV "rev" /* Proto rev file */ +#define PATH_REV_LOCK "rev-lock" /* Proto rev (write) lock file */ /* The format number of this filesystem. This is independent of the repository format number, and @@ -77,6 +81,9 @@ extern "C" { format option. */ #define SVN_FS_FS__MIN_LAYOUT_FORMAT_OPTION_FORMAT 3 +/* The minimum format number that stores protorevs in a separate directory. */ +#define SVN_FS_FS__MIN_PROTOREVS_DIR_FORMAT 3 + /* Maximum number of directories to cache dirents for. This *must* be a power of 2 for DIR_CACHE_ENTRIES_MASK to work. */ Index: subversion/libsvn_fs_fs/fs_fs.c =================================================================== --- subversion/libsvn_fs_fs/fs_fs.c (revision 28646) +++ subversion/libsvn_fs_fs/fs_fs.c (working copy) @@ -256,13 +256,26 @@ path_txn_next_ids(svn_fs_t *fs, const ch static APR_INLINE 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); + fs_fs_data_t *ffd = fs->fsap_data; + if (ffd->format >= SVN_FS_FS__MIN_PROTOREVS_DIR_FORMAT) + return svn_path_join_many(pool, fs->path, PATH_TXN_PROTOS_DIR, + apr_pstrcat(pool, txn_id, PATH_EXT_REV, NULL), + NULL); + else + return svn_path_join(path_txn_dir(fs, txn_id, pool), PATH_REV, pool); } static APR_INLINE 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); + fs_fs_data_t *ffd = fs->fsap_data; + if (ffd->format >= SVN_FS_FS__MIN_PROTOREVS_DIR_FORMAT) + return svn_path_join_many(pool, fs->path, PATH_TXN_PROTOS_DIR, + apr_pstrcat(pool, txn_id, PATH_EXT_REV_LOCK, + NULL), + NULL); + else + return svn_path_join(path_txn_dir(fs, txn_id, pool), PATH_REV_LOCK, pool); } static const char * @@ -1178,6 +1191,11 @@ svn_fs_fs__hotcopy(const char *src_path, developed.*/ dst_subdir = svn_path_join(dst_path, PATH_TXNS_DIR, pool); SVN_ERR(svn_io_make_dir_recursively(dst_subdir, pool)); + if (format >= SVN_FS_FS__MIN_PROTOREVS_DIR_FORMAT) + { + dst_subdir = svn_path_join(dst_path, PATH_TXN_PROTOS_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); @@ -3796,11 +3814,40 @@ svn_fs_fs__purge_txn(svn_fs_t *fs, const char *txn_id, apr_pool_t *pool) { + fs_fs_data_t *ffd = fs->fsap_data; + /* Remove the shared transaction object associated with this transaction. */ SVN_ERR(purge_shared_txn(fs, txn_id, pool)); /* Remove the directory associated with this transaction. */ - return svn_io_remove_dir2(path_txn_dir(fs, txn_id, pool), FALSE, - NULL, NULL, pool); + SVN_ERR(svn_io_remove_dir2(path_txn_dir(fs, txn_id, pool), FALSE, + NULL, NULL, pool)); + if (ffd->format >= SVN_FS_FS__MIN_PROTOREVS_DIR_FORMAT) + { + /* Delete protorev and its lock, which aren't in the txn + directory. It's OK if they don't exist (for example, if this + is post-commit and the proto-rev has been moved into + place). */ + svn_error_t *err = svn_io_remove_file(path_txn_proto_rev(fs, txn_id, + pool), pool); + if (err && APR_STATUS_IS_ENOENT(err->apr_err)) + { + svn_error_clear(err); + err = NULL; + } + if (err) + return err; + + err = svn_io_remove_file(path_txn_proto_rev_lock(fs, txn_id, pool), + pool); + if (err && APR_STATUS_IS_ENOENT(err->apr_err)) + { + svn_error_clear(err); + err = NULL; + } + if (err) + return err; + } + return SVN_NO_ERROR; } @@ -5198,6 +5245,11 @@ svn_fs_fs__create(svn_fs_t *fs, pool), pool)); + if (format >= SVN_FS_FS__MIN_PROTOREVS_DIR_FORMAT) + SVN_ERR(svn_io_make_dir_recursively(svn_path_join(path, PATH_TXN_PROTOS_DIR, + pool), + pool)); + SVN_ERR(svn_io_file_create(svn_fs_fs__path_current(fs, pool), "0 1 1\n", pool)); SVN_ERR(svn_io_file_create(path_lock(fs, pool), "", pool)); Index: subversion/libsvn_fs_fs/structure =================================================================== --- subversion/libsvn_fs_fs/structure (revision 28646) +++ subversion/libsvn_fs_fs/structure (working copy) @@ -40,6 +40,9 @@ repository) is: indexes.sqlite SQLite database containing index for svn:mergeinfo props transactions/ Subdirectory containing transactions .txn/ Directory containing transaction + txn-protorevs/ Subdirectory containing transaction proto-revision files + .rev Proto-revision file for transaction + .rev-lock Write lock for proto-rev file transaction-current File containing the next transaction key locks/ Subdirectory containing locks / Subdirectory named for first 3 letters of an MD5 digest @@ -102,13 +105,15 @@ Format 1: (understood by Subversion 1.1+ Delta representations in revision files must contain only svndiff0 data. No format options are permitted. No SQLite index is present. No mechanism is provided to prevent transaction name - reuse. + reuse. Proto-rev and its lock are stored in transactions//rev + and transactions//rev-lock. Format 2: (understood by Subversion 1.4+) Delta representations in revision files may contain either svndiff0 or svndiff1 data. No format options are permitted. No SQLite index is present. No mechanism is provided to prevent transaction - name reuse. + name reuse. Proto-rev and its lock are stored in transactions//rev + and transactions//rev-lock. Format 3: (understood by Subversion 1.5+) Delta representations in revision files may contain either svndiff0 @@ -116,7 +121,8 @@ Format 3: (understood by Subversion 1.5+ index is present, and should be updated whenever the svn:mergeinfo property is set on a node. To prevent transaction name reuse, transaction names should be generated using the transaction sequence number stored in the - transaction-current file. + transaction-current file. Proto-rev and its lock are stored in + txn-protorevs/.rev and txn-protorevs/.rev-lock. Filesystem format options ------------------------- @@ -311,8 +317,6 @@ Transaction layout A transaction directory has the following layout: - rev Prototype rev file with new text reps - rev-lock Lockfile for writing to the above props Transaction props mergeinfo Transaction mergeinfo props, if any next-ids Next temporary node-ID and copy-ID @@ -321,6 +325,13 @@ A transaction directory has the followin node...props Props for new node-rev, if changed node...children Directory contents for node-rev +In FS formats 1 and 2, it also contains: + + rev Prototype rev file with new text reps + rev-lock Lockfile for writing to the above + +In newer formats, these files are in the txn-protorevs/ directory. + The prototype rev file is used to store the text representations as they are received from the client. To ensure that only one client is writing to the file at a given time, the "rev-lock" file is locked for