Modified: subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_fs_fs/caching.c URL: http://svn.apache.org/viewvc/subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_fs_fs/caching.c?rev=1549081&r1=1549080&r2=1549081&view=diff ============================================================================== --- subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_fs_fs/caching.c (original) +++ subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_fs_fs/caching.c Sun Dec 8 17:56:46 2013 @@ -25,6 +25,7 @@ #include "id.h" #include "dag.h" #include "tree.h" +#include "index.h" #include "temp_serializer.h" #include "../libsvn_fs/fs-loader.h" @@ -89,7 +90,7 @@ read_config(svn_memcache_t **memcache_p, fs_fs_data_t *ffd = fs->fsap_data; SVN_ERR(svn_cache__make_memcache_from_config(memcache_p, ffd->config, - fs->pool)); + fs->pool)); /* No cache namespace by default. I.e. all FS instances share the * cached data. If you specify different namespaces, the data will @@ -143,8 +144,8 @@ read_config(svn_memcache_t **memcache_p, ""), "2")) *cache_revprops = svn_hash__get_bool(fs->config, - SVN_FS_CONFIG_FSFS_CACHE_REVPROPS, - FALSE); + SVN_FS_CONFIG_FSFS_CACHE_REVPROPS, + FALSE); else *cache_revprops = svn_named_atomic__is_efficient(); @@ -403,7 +404,7 @@ svn_fs_fs__initialize_caches(svn_fs_t *f * - Data that can be reconstructed from other elements has low prio * (e.g. fulltexts, directories etc.) * - Index data required to find any of the other data has high prio - * (e.g. noderevs) + * (e.g. noderevs, L2P and P2L index pages) * - everthing else should use default prio */ @@ -492,7 +493,7 @@ svn_fs_fs__initialize_caches(svn_fs_t *f SVN_ERR(create_cache(&(ffd->node_revision_cache), NULL, membuffer, - 0, 0, /* Do not use inprocess cache */ + 32, 32, /* ~200 byte / entry; 1k entries total */ svn_fs_fs__serialize_node_revision, svn_fs_fs__deserialize_node_revision, sizeof(pair_cache_key_t), @@ -506,7 +507,7 @@ svn_fs_fs__initialize_caches(svn_fs_t *f SVN_ERR(create_cache(&(ffd->rep_header_cache), NULL, membuffer, - 0, 0, /* Do not use inprocess cache */ + 1, 1000, /* ~8 bytes / entry; 1k entries total */ svn_fs_fs__serialize_rep_header, svn_fs_fs__deserialize_rep_header, sizeof(representation_cache_key_t), @@ -520,7 +521,7 @@ svn_fs_fs__initialize_caches(svn_fs_t *f SVN_ERR(create_cache(&(ffd->changes_cache), NULL, membuffer, - 0, 0, /* Do not use inprocess cache */ + 1, 8, /* 1k / entry; 8 entries total, rarely used */ svn_fs_fs__serialize_changes, svn_fs_fs__deserialize_changes, sizeof(svn_revnum_t), @@ -655,6 +656,71 @@ svn_fs_fs__initialize_caches(svn_fs_t *f ffd->combined_window_cache = NULL; } + if (ffd->format >= SVN_FS_FS__MIN_LOG_ADDRESSING_FORMAT) + { + SVN_ERR(create_cache(&(ffd->l2p_header_cache), + NULL, + membuffer, + 64, 16, /* entry size varies but we must cover + a reasonable number of revisions (1k) */ + svn_fs_fs__serialize_l2p_header, + svn_fs_fs__deserialize_l2p_header, + sizeof(pair_cache_key_t), + apr_pstrcat(pool, prefix, "L2P_HEADER", + (char *)NULL), + SVN_CACHE__MEMBUFFER_HIGH_PRIORITY, + fs, + no_handler, + fs->pool)); + SVN_ERR(create_cache(&(ffd->l2p_page_cache), + NULL, + membuffer, + 64, 16, /* entry size varies but we must cover + a reasonable number of revisions (1k) */ + svn_fs_fs__serialize_l2p_page, + svn_fs_fs__deserialize_l2p_page, + sizeof(svn_fs_fs__page_cache_key_t), + apr_pstrcat(pool, prefix, "L2P_PAGE", + (char *)NULL), + SVN_CACHE__MEMBUFFER_HIGH_PRIORITY, + fs, + no_handler, + fs->pool)); + SVN_ERR(create_cache(&(ffd->p2l_header_cache), + NULL, + membuffer, + 4, 1, /* Large entries. Rarely used. */ + svn_fs_fs__serialize_p2l_header, + svn_fs_fs__deserialize_p2l_header, + sizeof(pair_cache_key_t), + apr_pstrcat(pool, prefix, "P2L_HEADER", + (char *)NULL), + SVN_CACHE__MEMBUFFER_HIGH_PRIORITY, + fs, + no_handler, + fs->pool)); + SVN_ERR(create_cache(&(ffd->p2l_page_cache), + NULL, + membuffer, + 4, 16, /* Variably sized entries. Rarely used. */ + svn_fs_fs__serialize_p2l_page, + svn_fs_fs__deserialize_p2l_page, + sizeof(svn_fs_fs__page_cache_key_t), + apr_pstrcat(pool, prefix, "P2L_PAGE", + (char *)NULL), + SVN_CACHE__MEMBUFFER_HIGH_PRIORITY, + fs, + no_handler, + fs->pool)); + } + else + { + ffd->l2p_header_cache = NULL; + ffd->l2p_page_cache = NULL; + ffd->p2l_header_cache = NULL; + ffd->p2l_page_cache = NULL; + } + return SVN_NO_ERROR; }
Modified: subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_fs_fs/fs.c URL: http://svn.apache.org/viewvc/subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_fs_fs/fs.c?rev=1549081&r1=1549080&r2=1549081&view=diff ============================================================================== --- subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_fs_fs/fs.c (original) +++ subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_fs_fs/fs.c Sun Dec 8 17:56:46 2013 @@ -221,6 +221,8 @@ static svn_error_t * initialize_fs_struct(svn_fs_t *fs) { fs_fs_data_t *ffd = apr_pcalloc(fs->pool, sizeof(*ffd)); + ffd->min_log_addressing_rev = SVN_INVALID_REVNUM; + fs->vtable = &fs_vtable; fs->fsap_data = ffd; return SVN_NO_ERROR; Modified: subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_fs_fs/fs.h URL: http://svn.apache.org/viewvc/subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_fs_fs/fs.h?rev=1549081&r1=1549080&r2=1549081&view=diff ============================================================================== --- subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_fs_fs/fs.h (original) +++ subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_fs_fs/fs.h Sun Dec 8 17:56:46 2013 @@ -71,6 +71,10 @@ extern "C" { #define PATH_PACKED "pack" /* Packed revision data file */ #define PATH_EXT_PACKED_SHARD ".pack" /* Extension for packed shards */ +#define PATH_EXT_L2P_INDEX ".l2p" /* extension of the log- + to-phys index */ +#define PATH_EXT_P2L_INDEX ".p2l" /* extension of the phys- + to-log index */ /* If you change this, look at tests/svn_test_fs.c(maybe_install_fsfs_conf) */ #define PATH_CONFIG "fsfs.conf" /* Configuration */ @@ -84,6 +88,10 @@ extern "C" { #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 */ +#define PATH_TXN_ITEM_INDEX "itemidx" /* File containing the current item + index number */ +#define PATH_INDEX "index" /* name of index files w/o ext */ + /* 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 */ @@ -101,11 +109,19 @@ extern "C" { #define CONFIG_SECTION_PACKED_REVPROPS "packed-revprops" #define CONFIG_OPTION_REVPROP_PACK_SIZE "revprop-pack-size" #define CONFIG_OPTION_COMPRESS_PACKED_REVPROPS "compress-packed-revprops" +#define CONFIG_SECTION_IO "io" +#define CONFIG_OPTION_BLOCK_SIZE "block-size" +#define CONFIG_OPTION_L2P_PAGE_SIZE "l2p-page-size" +#define CONFIG_OPTION_P2L_PAGE_SIZE "p2l-page-size" /* The format number of this filesystem. This is independent of the repository format number, and - independent of any other FS back ends. */ -#define SVN_FS_FS__FORMAT_NUMBER 6 + independent of any other FS back ends. + + Note: If you bump this, please update the switch statement in + svn_fs_fs__create() as well. + */ +#define SVN_FS_FS__FORMAT_NUMBER 7 /* The minimum format number that supports svndiff version 1. */ #define SVN_FS_FS__MIN_SVNDIFF1_FORMAT 2 @@ -148,6 +164,9 @@ extern "C" { /* The minimum format number that supports packed revprops. */ #define SVN_FS_FS__MIN_PACKED_REVPROP_FORMAT 6 +/* The minimum format number that supports packed revprops. */ +#define SVN_FS_FS__MIN_LOG_ADDRESSING_FORMAT 7 + /* Minimum format number that will record moves */ #define SVN_FS_FS__MIN_MOVE_SUPPORT_FORMAT 7 @@ -244,8 +263,8 @@ typedef struct representation_cache_key_ /* Packed or non-packed representation? */ svn_boolean_t is_packed; - /* Item offset of the representation */ - apr_uint64_t offset; + /* Item index of the representation */ + apr_uint64_t item_index; } representation_cache_key_t; /* Key type that identifies a txdelta window. */ @@ -257,8 +276,8 @@ typedef struct window_cache_key_t /* Window number within that representation */ apr_int32_t chunk_index; - /* Offset of the representation within REVISION */ - apr_uint64_t offset; + /* Item index of the representation */ + apr_uint64_t item_index; } window_cache_key_t; /* Private (non-shared) FSFS-specific data for each svn_fs_t object. @@ -267,10 +286,26 @@ typedef struct fs_fs_data_t { /* The format number of this FS. */ int format; + /* The maximum number of files to store per directory (for sharded layouts) or zero (for linear layouts). */ int max_files_per_dir; + /* The first revision that uses logical addressing. SVN_INVALID_REVNUM + if there is no such revision (pre-f7 or non-sharded). May be a + future revision if the current shard started with physical addressing + and is not complete, yet. */ + svn_revnum_t min_log_addressing_rev; + + /* Rev / pack file read granularity. */ + apr_int64_t block_size; + + /* Capacity in entries of log-to-phys index pages */ + apr_int64_t l2p_page_size; + + /* Rev / pack file granularity covered by phys-to-log index pages */ + apr_int64_t p2l_page_size; + /* The revision that was youngest, last time we checked. */ svn_revnum_t youngest_rev_cache; @@ -332,7 +367,7 @@ typedef struct fs_fs_data_t the key is window_cache_key_t */ svn_cache__t *combined_window_cache; - /* Cache for node_revision_t objects; the key is (revision, id offset) */ + /* Cache for node_revision_t objects; the key is (revision, item_index) */ svn_cache__t *node_revision_cache; /* Cache for change lists as APR arrays of change_t * objects; the key @@ -340,7 +375,7 @@ typedef struct fs_fs_data_t svn_cache__t *changes_cache; /* Cache for svn_fs_fs__rep_header_t objects; the key is a - (revision, is_packed, offset) set */ + (revision, item index) pair */ svn_cache__t *rep_header_cache; /* Cache for svn_mergeinfo_t objects; the key is a combination of @@ -352,6 +387,23 @@ typedef struct fs_fs_data_t if the node has mergeinfo, "0" if it doesn't. */ svn_cache__t *mergeinfo_existence_cache; + /* Cache for l2p_header_t objects; the key is (revision, is-packed). + Will be NULL for pre-format7 repos */ + svn_cache__t *l2p_header_cache; + + /* Cache for l2p_page_t objects; the key is svn_fs_fs__page_cache_key_t. + Will be NULL for pre-format7 repos */ + svn_cache__t *l2p_page_cache; + + /* Cache for p2l_header_t objects; the key is (revision, is-packed). + Will be NULL for pre-format7 repos */ + svn_cache__t *p2l_header_cache; + + /* Cache for apr_array_header_t objects containing svn_fs_fs__p2l_entry_t + elements; the key is svn_fs_fs__page_cache_key_t. + Will be NULL for pre-format7 repos */ + svn_cache__t *p2l_page_cache; + /* TRUE while the we hold a lock on the write lock file. */ svn_boolean_t has_write_lock; @@ -449,8 +501,8 @@ typedef struct representation_t /* Revision where this representation is located. */ svn_revnum_t revision; - /* Offset into the revision file where it is located. */ - svn_filesize_t offset; + /* Item index with the the revision. */ + apr_uint64_t item_index; /* The size of the representation in bytes as seen in the revision file. */ Modified: subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_fs_fs/fs_fs.c URL: http://svn.apache.org/viewvc/subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_fs_fs/fs_fs.c?rev=1549081&r1=1549080&r2=1549081&view=diff ============================================================================== --- subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_fs_fs/fs_fs.c (original) +++ subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_fs_fs/fs_fs.c Sun Dec 8 17:56:46 2013 @@ -42,7 +42,6 @@ #include "private/svn_fs_util.h" #include "private/svn_string_private.h" -#include "private/svn_subr_private.h" #include "../libsvn_fs/fs-loader.h" /* The default maximum number of files per directory to store in the @@ -271,16 +270,21 @@ check_format(int format) } /* Read the format number and maximum number of files per directory - from PATH and return them in *PFORMAT and *MAX_FILES_PER_DIR - respectively. + from PATH and return them in *PFORMAT, *MAX_FILES_PER_DIR and + MIN_LOG_ADDRESSING_REV respectively. *MAX_FILES_PER_DIR is obtained from the 'layout' format option, and will be set to zero if a linear scheme should be used. + *MIN_LOG_ADDRESSING_REV is obtained from the 'addressing' format option, + and will be set to SVN_INVALID_REVNUM for physical addressing. Use POOL for temporary allocation. */ static svn_error_t * -read_format(int *pformat, int *max_files_per_dir, - const char *path, apr_pool_t *pool) +read_format(int *pformat, + int *max_files_per_dir, + svn_revnum_t *min_log_addressing_rev, + const char *path, + apr_pool_t *pool) { svn_error_t *err; svn_stream_t *stream; @@ -325,6 +329,7 @@ read_format(int *pformat, int *max_files /* Set the default values for anything that can be set via an option. */ *max_files_per_dir = 0; + *min_log_addressing_rev = SVN_INVALID_REVNUM; /* Read any options. */ while (!eos) @@ -351,17 +356,47 @@ read_format(int *pformat, int *max_files } } + if (*pformat >= SVN_FS_FS__MIN_LOG_ADDRESSING_FORMAT && + strncmp(buf->data, "addressing ", 11) == 0) + { + if (strcmp(buf->data + 11, "physical") == 0) + { + *min_log_addressing_rev = SVN_INVALID_REVNUM; + continue; + } + + if (strncmp(buf->data + 11, "logical ", 8) == 0) + { + int value; + + /* Check that the argument is numeric. */ + SVN_ERR(check_format_file_buffer_numeric(buf->data, 19, path, pool)); + SVN_ERR(svn_cstring_atoi(&value, buf->data + 19)); + *min_log_addressing_rev = value; + continue; + } + } + return svn_error_createf(SVN_ERR_BAD_VERSION_FILE_FORMAT, NULL, _("'%s' contains invalid filesystem format option '%s'"), svn_dirent_local_style(path, pool), buf->data); } + /* Non-sharded repositories never use logical addressing. + * If the format file is inconsistent in that respect, something + * probably went wrong. + */ + if (*min_log_addressing_rev != SVN_INVALID_REVNUM && !*max_files_per_dir) + return svn_error_createf(SVN_ERR_BAD_VERSION_FILE_FORMAT, NULL, + _("'%s' specifies logical addressing for a non-sharded repository"), + svn_dirent_local_style(path, pool)); + return SVN_NO_ERROR; } -/* Write the format number and maximum number of files per directory - to a new format file in PATH, possibly expecting to overwrite a - previously existing file. +/* Write the format number, maximum number of files per directory and + the addressing scheme to a new format file in PATH, possibly expecting + to overwrite a previously existing file. Use POOL for temporary allocation. */ svn_error_t * @@ -387,6 +422,17 @@ svn_fs_fs__write_format(svn_fs_t *fs, svn_stringbuf_appendcstr(sb, "layout linear\n"); } + if (ffd->format >= SVN_FS_FS__MIN_LOG_ADDRESSING_FORMAT) + { + if (ffd->min_log_addressing_rev == SVN_INVALID_REVNUM) + svn_stringbuf_appendcstr(sb, "addressing physical\n"); + else + svn_stringbuf_appendcstr(sb, + apr_psprintf(pool, + "addressing logical %ld\n", + ffd->min_log_addressing_rev)); + } + /* svn_io_write_version_file() does a load of magic to allow it to replace version files that already exist. We only need to do that when we're allowed to overwrite an existing file. */ @@ -482,6 +528,32 @@ read_config(fs_fs_data_t *ffd, ffd->compress_packed_revprops = FALSE; } + if (ffd->format >= SVN_FS_FS__MIN_LOG_ADDRESSING_FORMAT) + { + SVN_ERR(svn_config_get_int64(ffd->config, &ffd->block_size, + CONFIG_SECTION_IO, + CONFIG_OPTION_BLOCK_SIZE, + 64)); + SVN_ERR(svn_config_get_int64(ffd->config, &ffd->l2p_page_size, + CONFIG_SECTION_IO, + CONFIG_OPTION_L2P_PAGE_SIZE, + 0x2000)); + SVN_ERR(svn_config_get_int64(ffd->config, &ffd->p2l_page_size, + CONFIG_SECTION_IO, + CONFIG_OPTION_P2L_PAGE_SIZE, + 64)); + + ffd->block_size *= 0x400; + ffd->p2l_page_size *= 0x400; + } + else + { + /* should be irrelevant but we initialize them anyway */ + ffd->block_size = 0x1000; + ffd->l2p_page_size = 0x2000; + ffd->p2l_page_size = 0x1000; + } + return SVN_NO_ERROR; } @@ -616,6 +688,58 @@ write_config(svn_fs_t *fs, "### unless you often modify revprops after packing." NL "### Compressing packed revprops is disabled by default." NL "# " CONFIG_OPTION_COMPRESS_PACKED_REVPROPS " = false" NL +"" NL +"[" CONFIG_SECTION_IO "]" NL +"### Parameters in this section control the data access granularity in" NL +"### format 7 repositories and later. The defaults should translate into" NL +"### decent performance over a wide range of setups." NL +"###" NL +"### When a specific piece of information needs to be read from disk, a" NL +"### data block is being read at once and its contents are being cached." NL +"### If the repository is being stored on a RAID, the block size should" NL +"### be either 50% or 100% of RAID block size / granularity. Also, your" NL +"### file system (clusters) should be properly aligned and sized. In that" NL +"### setup, each access will hit only one disk (minimizes I/O load) but" NL +"### uses all the data provided by the disk in a single access." NL +"### For SSD-based storage systems, slightly lower values around 16 kB" NL +"### may improve latency while still maximizing throughput." NL +"### Can be changed at any time but must be a power of 2." NL +"### block-size is 64 kBytes by default." NL +"# " CONFIG_OPTION_BLOCK_SIZE " = 64" NL +"###" NL +"### The log-to-phys index maps data item numbers to offsets within the" NL +"### rev or pack file. A revision typically contains 2 .. 5 such items" NL +"### per changed path. For each revision, at least one page is being" NL +"### allocated in the l2p index with unused parts resulting in no wasted" NL +"### space." NL +"### Changing this parameter only affects larger revisions with thousands" NL +"### of changed paths. A smaller value means that more pages need to be" NL +"### allocated for such revisions, increasing the size of the page table" NL +"### meaning it takes longer to read that table (once). Access to each" NL +"### page is then faster because less data has to read. So, if you have" NL +"### several extremely large revisions (approaching 1 mio changes), think" NL +"### about increasing this setting. Reducing the value will rarely result" NL +"### in a net speedup." NL +"### This is an expert setting. Any non-zero value is possible." NL +"### l2p-page-size is 8192 entries by default." NL +"# " CONFIG_OPTION_L2P_PAGE_SIZE " = 8192" NL +"###" NL +"### The phys-to-log index maps positions within the rev or pack file to" NL +"### to data items, i.e. describes what piece of information is being" NL +"### stored at that particular offset. The index describes the rev file" NL +"### in chunks (pages) and keeps a global list of all those pages. Large" NL +"### pages mean a shorter page table but a larger per-page description of" NL +"### data items in it. The latency sweetspot depends on the change size" NL +"### distribution but is relatively wide." NL +"### If the repository contains very large files, i.e. individual changes" NL +"### of tens of MB each, increasing the page size will shorten the index" NL +"### file at the expense of a slightly increased latency in sections with" NL +"### smaller changes." NL +"### For practical reasons, this should match block-size. Differing" NL +"### values are perfectly legal but may result in some processing overhead." NL +"### Must be a power of 2." NL +"### p2l-page-size is 64 kBytes by default." NL +"# " CONFIG_OPTION_P2L_PAGE_SIZE " = 64" NL ; #undef NL return svn_io_file_create(svn_dirent_join(fs->path, PATH_CONFIG, pool), @@ -628,18 +752,20 @@ svn_fs_fs__open(svn_fs_t *fs, const char fs_fs_data_t *ffd = fs->fsap_data; apr_file_t *uuid_file; int format, max_files_per_dir; + svn_revnum_t min_log_addressing_rev; char buf[APR_UUID_FORMATTED_LENGTH + 2]; apr_size_t limit; fs->path = apr_pstrdup(fs->pool, path); /* Read the FS format number. */ - SVN_ERR(read_format(&format, &max_files_per_dir, + SVN_ERR(read_format(&format, &max_files_per_dir, &min_log_addressing_rev, path_format(fs, pool), pool)); /* Now we've got a format number no matter what. */ ffd->format = format; ffd->max_files_per_dir = max_files_per_dir; + ffd->min_log_addressing_rev = min_log_addressing_rev; /* Read in and cache the repository uuid. */ SVN_ERR(svn_io_file_open(&uuid_file, path_uuid(fs, pool), @@ -694,12 +820,14 @@ upgrade_body(void *baton, apr_pool_t *po svn_fs_t *fs = upgrade_baton->fs; fs_fs_data_t *ffd = fs->fsap_data; int format, max_files_per_dir; + svn_revnum_t min_log_addressing_rev; const char *format_path = path_format(fs, pool); svn_node_kind_t kind; svn_boolean_t needs_revprop_shard_cleanup = FALSE; /* Read the FS format number and max-files-per-dir setting. */ - SVN_ERR(read_format(&format, &max_files_per_dir, format_path, pool)); + SVN_ERR(read_format(&format, &max_files_per_dir, &min_log_addressing_rev, + format_path, pool)); /* If the config file does not exist, create one. */ SVN_ERR(svn_io_check_path(svn_dirent_join(fs->path, PATH_CONFIG, pool), @@ -723,7 +851,7 @@ upgrade_body(void *baton, apr_pool_t *po if (format == SVN_FS_FS__FORMAT_NUMBER) return SVN_NO_ERROR; - /* If our filesystem predates the existance of the 'txn-current + /* If our filesystem predates the existence of the 'txn-current file', make that file and its corresponding lock file. */ if (format < SVN_FS_FS__MIN_TXN_CURRENT_FORMAT) { @@ -735,7 +863,7 @@ upgrade_body(void *baton, apr_pool_t *po pool)); } - /* If our filesystem predates the existance of the 'txn-protorevs' + /* If our filesystem predates the existence of the 'txn-protorevs' dir, make that directory. */ if (format < SVN_FS_FS__MIN_PROTOREVS_DIR_FORMAT) { @@ -767,9 +895,19 @@ upgrade_body(void *baton, apr_pool_t *po pool)); } + if ( format < SVN_FS_FS__MIN_LOG_ADDRESSING_FORMAT + && max_files_per_dir > 0) + { + min_log_addressing_rev + = (ffd->youngest_rev_cache / max_files_per_dir + 1) + * max_files_per_dir; + } + /* Bump the format file. */ ffd->format = SVN_FS_FS__FORMAT_NUMBER; ffd->max_files_per_dir = max_files_per_dir; + ffd->min_log_addressing_rev = min_log_addressing_rev; + SVN_ERR(svn_fs_fs__write_format(fs, TRUE, pool)); if (upgrade_baton->notify_func) SVN_ERR(upgrade_baton->notify_func(upgrade_baton->notify_baton, @@ -892,7 +1030,7 @@ svn_fs_fs__noderev_same_rep_key(represen if (a == NULL || b == NULL) return FALSE; - if (a->offset != b->offset) + if (a->item_index != b->item_index) return FALSE; if (a->revision != b->revision) @@ -957,17 +1095,58 @@ write_revision_zero(svn_fs_t *fs) svn_string_t date; /* Write out a rev file for revision 0. */ - SVN_ERR(svn_io_file_create(path_revision_zero, - "PLAIN\nEND\nENDREP\n" - "id: 0.0.r0/17\n" - "type: dir\n" - "count: 0\n" - "text: 0 0 4 4 " - "2d2977d1c96f487abe4a1e202dd03b4e\n" - "cpath: /\n" - "\n\n17 107\n", fs->pool)); + if (svn_fs_fs__use_log_addressing(fs, 0)) + SVN_ERR(svn_io_file_create(path_revision_zero, + "PLAIN\nEND\nENDREP\n" + "id: 0.0.r0/2\n" + "type: dir\n" + "count: 0\n" + "text: 0 3 4 4 " + "2d2977d1c96f487abe4a1e202dd03b4e\n" + "cpath: /\n" + "\n\n", fs->pool)); + else + SVN_ERR(svn_io_file_create(path_revision_zero, + "PLAIN\nEND\nENDREP\n" + "id: 0.0.r0/17\n" + "type: dir\n" + "count: 0\n" + "text: 0 0 4 4 " + "2d2977d1c96f487abe4a1e202dd03b4e\n" + "cpath: /\n" + "\n\n17 107\n", fs->pool)); + SVN_ERR(svn_io_set_file_read_only(path_revision_zero, FALSE, fs->pool)); + if (svn_fs_fs__use_log_addressing(fs, 0)) + { + const char *path = svn_fs_fs__path_l2p_index(fs, 0, FALSE, fs->pool); + SVN_ERR(svn_io_file_create_binary + (path, + "\0\x80\x40" /* rev 0, 8k entries per page */ + "\1\1\1" /* 1 rev, 1 page, 1 page in 1st rev */ + "\6\4" /* page size: bytes, count */ + "\0\xd6\1\xb1\1\x21", /* phys offsets + 1 */ + 14, + fs->pool)); + SVN_ERR(svn_io_set_file_read_only(path, FALSE, fs->pool)); + + path = svn_fs_fs__path_p2l_index(fs, 0, FALSE, fs->pool); + SVN_ERR(svn_io_file_create_binary + (path, + "\0\x6b" /* start rev, rev file size */ + "\x80\x80\4\1\x1D" /* 64k pages, 1 page using 29 bytes */ + "\0" /* offset entry 0 page 1 */ + /* len, item & type, rev, checksum */ + "\x11\x34\0\xe0\xc6\xac\xa9\x07" + "\x59\x09\0\xc0\xfa\xf8\xc5\x04" + "\1\x0d\0\xf2\x95\xbe\xea\x01" + "\x95\xff\3\x1b\0\0", /* last entry fills up 64k page */ + 38, + fs->pool)); + SVN_ERR(svn_io_set_file_read_only(path, FALSE, fs->pool)); + } + /* Set a date on revision 0. */ date.data = svn_time_to_cstring(apr_time_now(), fs->pool); date.len = strlen(date.data); @@ -988,14 +1167,36 @@ svn_fs_fs__create(svn_fs_t *fs, /* See if compatibility with older versions was explicitly requested. */ if (fs->config) { - if (svn_hash_gets(fs->config, SVN_FS_CONFIG_PRE_1_4_COMPATIBLE)) - format = 1; - else if (svn_hash_gets(fs->config, SVN_FS_CONFIG_PRE_1_5_COMPATIBLE)) - format = 2; - else if (svn_hash_gets(fs->config, SVN_FS_CONFIG_PRE_1_6_COMPATIBLE)) - format = 3; - else if (svn_hash_gets(fs->config, SVN_FS_CONFIG_PRE_1_8_COMPATIBLE)) - format = 4; + svn_version_t *compatible_version; + SVN_ERR(svn_fs__compatible_version(&compatible_version, fs->config, + pool)); + + /* select format number */ + switch(compatible_version->minor) + { + case 0: return svn_error_create(SVN_ERR_FS_UNSUPPORTED_FORMAT, NULL, + _("FSFS is not compatible with Subversion prior to 1.1")); + + case 1: + case 2: + case 3: format = 1; + break; + + case 4: format = 2; + break; + + case 5: format = 3; + break; + + case 6: + case 7: format = 4; + break; + + case 8: format = 6; + break; + + default:format = SVN_FS_FS__FORMAT_NUMBER; + } } ffd->format = format; @@ -1003,6 +1204,12 @@ svn_fs_fs__create(svn_fs_t *fs, if (format >= SVN_FS_FS__MIN_LAYOUT_FORMAT_OPTION_FORMAT) ffd->max_files_per_dir = SVN_FS_FS_DEFAULT_MAX_FILES_PER_DIR; + /* Select the addressing mode depending on the format. */ + if (format >= SVN_FS_FS__MIN_LOG_ADDRESSING_FORMAT) + ffd->min_log_addressing_rev = 0; + else + ffd->min_log_addressing_rev = SVN_INVALID_REVNUM; + /* Create the revision data directories. */ if (ffd->max_files_per_dir) SVN_ERR(svn_io_make_dir_recursively(svn_fs_fs__path_rev_shard(fs, 0, @@ -1045,7 +1252,12 @@ svn_fs_fs__create(svn_fs_t *fs, SVN_ERR(write_revision_zero(fs)); - SVN_ERR(write_config(fs, pool)); + /* Create the fsfs.conf file if supported. Older server versions would + simply ignore the file but that might result in a different behavior + than with the later releases. Also, hotcopy would ignore, i.e. not + copy, a fsfs.conf with old formats. */ + if (ffd->format >= SVN_FS_FS__MIN_CONFIG_FILE) + SVN_ERR(write_config(fs, pool)); SVN_ERR(read_config(ffd, fs->path, pool)); @@ -1379,8 +1591,11 @@ svn_fs_fs__info_format(int *fs_format, case 6: (*supports_version)->minor = 8; break; + case 7: + (*supports_version)->minor = 9; + break; #ifdef SVN_DEBUG -# if SVN_FS_FS__FORMAT_NUMBER != 6 +# if SVN_FS_FS__FORMAT_NUMBER != 7 # error "Need to add a 'case' statement here" # endif #endif Modified: subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_fs_fs/hotcopy.c URL: http://svn.apache.org/viewvc/subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_fs_fs/hotcopy.c?rev=1549081&r1=1549080&r2=1549081&view=diff ============================================================================== --- subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_fs_fs/hotcopy.c (original) +++ subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_fs_fs/hotcopy.c Sun Dec 8 17:56:46 2013 @@ -228,12 +228,14 @@ hotcopy_io_copy_dir_recursively(const ch /* Copy an un-packed revision or revprop file for revision REV from SRC_SUBDIR * to DST_SUBDIR. Assume a sharding layout based on MAX_FILES_PER_DIR. + * If INCLUDE_INDEXES is set, copy rev index files as well. * Use SCRATCH_POOL for temporary allocations. */ static svn_error_t * hotcopy_copy_shard_file(const char *src_subdir, const char *dst_subdir, svn_revnum_t rev, int max_files_per_dir, + svn_boolean_t include_indexes, apr_pool_t *scratch_pool) { const char *src_subdir_shard = src_subdir, @@ -257,6 +259,19 @@ hotcopy_copy_shard_file(const char *src_ SVN_ERR(hotcopy_io_dir_file_copy(src_subdir_shard, dst_subdir_shard, apr_psprintf(scratch_pool, "%ld", rev), scratch_pool)); + + if (include_indexes) + { + SVN_ERR(hotcopy_io_dir_file_copy(src_subdir_shard, dst_subdir_shard, + apr_psprintf(scratch_pool, "%ld.l2p", + rev), + scratch_pool)); + SVN_ERR(hotcopy_io_dir_file_copy(src_subdir_shard, dst_subdir_shard, + apr_psprintf(scratch_pool, "%ld.p2l", + rev), + scratch_pool)); + } + return SVN_NO_ERROR; } @@ -312,7 +327,7 @@ hotcopy_copy_packed_shard(svn_revnum_t * SVN_ERR(hotcopy_copy_shard_file(src_subdir, dst_subdir, revprop_rev, max_files_per_dir, - iterpool)); + FALSE, iterpool)); } svn_pool_destroy(iterpool); } @@ -321,7 +336,7 @@ hotcopy_copy_packed_shard(svn_revnum_t * /* revprop for revision 0 will never be packed */ if (rev == 0) SVN_ERR(hotcopy_copy_shard_file(src_subdir, dst_subdir, - 0, max_files_per_dir, + 0, max_files_per_dir, FALSE, scratch_pool)); /* packed revprops folder */ @@ -379,17 +394,33 @@ hotcopy_update_current(svn_revnum_t *dst return SVN_NO_ERROR; } +/* Remove FILE in SHARD folder. Use POOL for temporary allocations. */ +static svn_error_t * +hotcopy_remove_file(const char *shard, + const char *file, + apr_pool_t *pool) +{ + const char *rev_path = svn_dirent_join(shard, file, pool); + + /* Make the rev file writable and remove it. */ + SVN_ERR(svn_io_set_file_read_write(rev_path, TRUE, pool)); + SVN_ERR(svn_io_remove_file2(rev_path, TRUE, pool)); + + return SVN_NO_ERROR; +} + /* Remove revision or revprop files between START_REV (inclusive) and - * END_REV (non-inclusive) from folder DST_SUBDIR in DST_FS. Assume - * sharding as per MAX_FILES_PER_DIR. - * Use SCRATCH_POOL for temporary allocations. */ + * END_REV (non-inclusive) from folder DST_SUBDIR in DST_FS. Also, + * remove index files if REMOVE_INDEXES is set. Assume sharding as per + * MAX_FILES_PER_DIR. Use SCRATCH_POOL for temporary allocations. */ static svn_error_t * hotcopy_remove_files(svn_fs_t *dst_fs, const char *dst_subdir, svn_revnum_t start_rev, svn_revnum_t end_rev, int max_files_per_dir, + svn_boolean_t remove_indexes, apr_pool_t *scratch_pool) { const char *shard; @@ -404,7 +435,6 @@ hotcopy_remove_files(svn_fs_t *dst_fs, iterpool = svn_pool_create(scratch_pool); for (rev = start_rev; rev < end_rev; rev++) { - const char *path; svn_pool_clear(iterpool); /* If necessary, update paths for shard. */ @@ -415,13 +445,18 @@ hotcopy_remove_files(svn_fs_t *dst_fs, } /* remove files for REV */ - path = svn_dirent_join(dst_subdir_shard, - apr_psprintf(iterpool, "%ld", rev), - iterpool); - - /* Make the rev file writable and remove it. */ - SVN_ERR(svn_io_set_file_read_write(path, TRUE, iterpool)); - SVN_ERR(svn_io_remove_file2(path, TRUE, iterpool)); + SVN_ERR(hotcopy_remove_file(dst_subdir_shard, + apr_psprintf(iterpool, "%ld", rev), + iterpool)); + if (remove_indexes && svn_fs_fs__use_log_addressing(dst_fs, rev)) + { + SVN_ERR(hotcopy_remove_file(dst_subdir_shard, + apr_psprintf(iterpool, "%ld.p2l", rev), + iterpool)); + SVN_ERR(hotcopy_remove_file(dst_subdir_shard, + apr_psprintf(iterpool, "%ld.l2p", rev), + iterpool)); + } } svn_pool_destroy(iterpool); @@ -445,7 +480,7 @@ hotcopy_remove_rev_files(svn_fs_t *dst_f PATH_REVS_DIR, scratch_pool), start_rev, end_rev, - max_files_per_dir, scratch_pool)); + max_files_per_dir, TRUE, scratch_pool)); return SVN_NO_ERROR; } @@ -469,7 +504,7 @@ hotcopy_remove_revprop_files(svn_fs_t *d PATH_REVPROPS_DIR, scratch_pool), start_rev ? start_rev : 1, end_rev, - max_files_per_dir, scratch_pool)); + max_files_per_dir, FALSE, scratch_pool)); return SVN_NO_ERROR; } @@ -772,6 +807,7 @@ hotcopy_body(void *baton, apr_pool_t *po /* Copy the rev file. */ err = hotcopy_copy_shard_file(src_subdir, dst_subdir, rev, max_files_per_dir, + svn_fs_fs__use_log_addressing(src_fs, rev), iterpool); if (err) { @@ -822,7 +858,7 @@ hotcopy_body(void *baton, apr_pool_t *po /* Copy the revprop file. */ SVN_ERR(hotcopy_copy_shard_file(revprop_src_subdir, revprop_dst_subdir, - rev, max_files_per_dir, + rev, max_files_per_dir, FALSE, iterpool)); /* After completing a full shard, update 'current'. */ @@ -935,6 +971,7 @@ hotcopy_create_empty_dest(svn_fs_t *src_ dst_fs->path = apr_pstrdup(pool, dst_path); dst_ffd->max_files_per_dir = src_ffd->max_files_per_dir; + dst_ffd->min_log_addressing_rev = src_ffd->min_log_addressing_rev; dst_ffd->config = src_ffd->config; dst_ffd->format = src_ffd->format; Modified: subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_fs_fs/id.c URL: http://svn.apache.org/viewvc/subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_fs_fs/id.c?rev=1549081&r1=1549080&r2=1549081&view=diff ============================================================================== --- subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_fs_fs/id.c (original) +++ subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_fs_fs/id.c Sun Dec 8 17:56:46 2013 @@ -24,6 +24,7 @@ #include <stdlib.h> #include "id.h" +#include "index.h" #include "../libsvn_fs/fs-loader.h" #include "private/svn_temp_serializer.h" @@ -41,7 +42,7 @@ typedef struct fs_fs__id_t svn_fs_fs__id_part_t node_id; svn_fs_fs__id_part_t copy_id; svn_fs_fs__id_part_t txn_id; - svn_fs_fs__id_part_t rev_offset; + svn_fs_fs__id_part_t rev_item; } private_id; } fs_fs__id_t; @@ -214,11 +215,11 @@ svn_fs_fs__id_txn_id(const svn_fs_id_t * const svn_fs_fs__id_part_t * -svn_fs_fs__id_rev_offset(const svn_fs_id_t *fs_id) +svn_fs_fs__id_rev_item(const svn_fs_id_t *fs_id) { fs_fs__id_t *id = (fs_fs__id_t *)fs_id; - return &id->private_id.rev_offset; + return &id->private_id.rev_item; } svn_revnum_t @@ -226,15 +227,15 @@ svn_fs_fs__id_rev(const svn_fs_id_t *fs_ { fs_fs__id_t *id = (fs_fs__id_t *)fs_id; - return id->private_id.rev_offset.revision; + return id->private_id.rev_item.revision; } apr_uint64_t -svn_fs_fs__id_offset(const svn_fs_id_t *fs_id) +svn_fs_fs__id_item(const svn_fs_id_t *fs_id) { fs_fs__id_t *id = (fs_fs__id_t *)fs_id; - return id->private_id.rev_offset.number; + return id->private_id.rev_item.number; } svn_boolean_t @@ -265,9 +266,9 @@ svn_fs_fs__id_unparse(const svn_fs_id_t else { *(p++) = 'r'; - p += svn__i64toa(p, id->private_id.rev_offset.revision); + p += svn__i64toa(p, id->private_id.rev_item.revision); *(p++) = '/'; - p += svn__i64toa(p, id->private_id.rev_offset.number); + p += svn__i64toa(p, id->private_id.rev_item.number); } return svn_string_ncreate(string, p - string, pool); @@ -355,7 +356,22 @@ svn_fs_fs__id_txn_create_root(const svn_ /* node ID and copy ID are "0" */ id->private_id.txn_id = *txn_id; - id->private_id.rev_offset.revision = SVN_INVALID_REVNUM; + id->private_id.rev_item.revision = SVN_INVALID_REVNUM; + + id->generic_id.vtable = &id_vtable; + id->generic_id.fsap_data = &id; + + return (svn_fs_id_t *)id; +} + +svn_fs_id_t *svn_fs_fs__id_create_root(const svn_revnum_t revision, + apr_pool_t *pool) +{ + fs_fs__id_t *id = apr_pcalloc(pool, sizeof(*id)); + + id->private_id.txn_id.revision = SVN_INVALID_REVNUM; + id->private_id.rev_item.revision = revision; + id->private_id.rev_item.number = SVN_FS_FS__ITEM_INDEX_ROOT_NODE; id->generic_id.vtable = &id_vtable; id->generic_id.fsap_data = &id; @@ -374,7 +390,7 @@ svn_fs_fs__id_txn_create(const svn_fs_fs id->private_id.node_id = *node_id; id->private_id.copy_id = *copy_id; id->private_id.txn_id = *txn_id; - id->private_id.rev_offset.revision = SVN_INVALID_REVNUM; + id->private_id.rev_item.revision = SVN_INVALID_REVNUM; id->generic_id.vtable = &id_vtable; id->generic_id.fsap_data = &id; @@ -386,7 +402,7 @@ svn_fs_fs__id_txn_create(const svn_fs_fs svn_fs_id_t * svn_fs_fs__id_rev_create(const svn_fs_fs__id_part_t *node_id, const svn_fs_fs__id_part_t *copy_id, - const svn_fs_fs__id_part_t *rev_offset, + const svn_fs_fs__id_part_t *rev_item, apr_pool_t *pool) { fs_fs__id_t *id = apr_pcalloc(pool, sizeof(*id)); @@ -394,7 +410,7 @@ svn_fs_fs__id_rev_create(const svn_fs_fs id->private_id.node_id = *node_id; id->private_id.copy_id = *copy_id; id->private_id.txn_id.revision = SVN_INVALID_REVNUM; - id->private_id.rev_offset = *rev_offset; + id->private_id.rev_item = *rev_item; id->generic_id.vtable = &id_vtable; id->generic_id.fsap_data = &id; @@ -471,7 +487,7 @@ svn_fs_fs__id_parse(const char *data, str = svn_cstring_tokenize("/", &data_copy); if (str == NULL) return NULL; - id->private_id.rev_offset.revision = SVN_STR_TO_REV(str); + id->private_id.rev_item.revision = SVN_STR_TO_REV(str); err = svn_cstring_atoi64(&val, data_copy); if (err) @@ -479,13 +495,13 @@ svn_fs_fs__id_parse(const char *data, svn_error_clear(err); return NULL; } - id->private_id.rev_offset.number = (apr_uint64_t)val; + id->private_id.rev_item.number = (apr_uint64_t)val; } else if (str[0] == 't') { /* This is a transaction type ID */ - id->private_id.rev_offset.revision = SVN_INVALID_REVNUM; - id->private_id.rev_offset.number = 0; + id->private_id.rev_item.revision = SVN_INVALID_REVNUM; + id->private_id.rev_item.number = 0; if (! txn_id_parse(&id->private_id.txn_id, str + 1)) return NULL; Modified: subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_fs_fs/id.h URL: http://svn.apache.org/viewvc/subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_fs_fs/id.h?rev=1549081&r1=1549080&r2=1549081&view=diff ============================================================================== --- subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_fs_fs/id.h (original) +++ subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_fs_fs/id.h Sun Dec 8 17:56:46 2013 @@ -45,7 +45,7 @@ typedef struct svn_fs_fs__id_part_t svn_revnum_t revision; /* sub-id value relative to REVISION. Its interpretation depends on - the part itself. In rev_offset, it is the offset value, in others + the part itself. In rev_item, it is the index_index value, in others it represents a unique counter value. */ apr_uint64_t number; } svn_fs_fs__id_part_t; @@ -88,16 +88,16 @@ const svn_fs_fs__id_part_t *svn_fs_fs__i /* Get the "txn id" portion of ID, or NULL if it is a permanent ID. */ const svn_fs_fs__id_part_t *svn_fs_fs__id_txn_id(const svn_fs_id_t *id); -/* Get the "rev,offset" portion of ID. */ -const svn_fs_fs__id_part_t *svn_fs_fs__id_rev_offset(const svn_fs_id_t *id); +/* Get the "rev,item" portion of ID. */ +const svn_fs_fs__id_part_t *svn_fs_fs__id_rev_item(const svn_fs_id_t *id); /* Get the "rev" portion of ID, or SVN_INVALID_REVNUM if it is a transaction ID. */ svn_revnum_t svn_fs_fs__id_rev(const svn_fs_id_t *id); -/* Access the "offset" portion of the ID, or 0 if it is a transaction +/* Access the "item" portion of the ID, or 0 if it is a transaction ID. */ -apr_uint64_t svn_fs_fs__id_offset(const svn_fs_id_t *id); +apr_uint64_t svn_fs_fs__id_item(const svn_fs_id_t *id); /* Return TRUE, if this is a transaction ID. */ svn_boolean_t svn_fs_fs__id_is_txn(const svn_fs_id_t *id); @@ -126,6 +126,11 @@ int svn_fs_fs__id_part_compare(const svn svn_fs_id_t *svn_fs_fs__id_txn_create_root(const svn_fs_fs__id_part_t *txn_id, apr_pool_t *pool); +/* Create the root ID for REVISION (logical addressing node only). + Allocate it in POOL. */ +svn_fs_id_t *svn_fs_fs__id_create_root(const svn_revnum_t revision, + apr_pool_t *pool); + /* Create an ID within a transaction based on NODE_ID, COPY_ID, and TXN_ID, allocated in POOL. */ svn_fs_id_t *svn_fs_fs__id_txn_create(const svn_fs_fs__id_part_t *node_id, @@ -133,11 +138,11 @@ svn_fs_id_t *svn_fs_fs__id_txn_create(co const svn_fs_fs__id_part_t *txn_id, apr_pool_t *pool); -/* Create a permanent ID based on NODE_ID, COPY_ID and REV_OFFSET, +/* Create a permanent ID based on NODE_ID, COPY_ID and REV_ITEM, allocated in POOL. */ svn_fs_id_t *svn_fs_fs__id_rev_create(const svn_fs_fs__id_part_t *node_id, const svn_fs_fs__id_part_t *copy_id, - const svn_fs_fs__id_part_t *rev_offset, + const svn_fs_fs__id_part_t *rev_item, apr_pool_t *pool); /* Return a copy of ID, allocated from POOL. */ Modified: subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_fs_fs/lock.c URL: http://svn.apache.org/viewvc/subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_fs_fs/lock.c?rev=1549081&r1=1549080&r2=1549081&view=diff ============================================================================== --- subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_fs_fs/lock.c (original) +++ subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_fs_fs/lock.c Sun Dec 8 17:56:46 2013 @@ -252,24 +252,23 @@ read_digest_file(apr_hash_t **children_p apr_hash_t *hash; svn_stream_t *stream; const char *val; + svn_node_kind_t kind; if (lock_p) *lock_p = NULL; if (children_p) *children_p = apr_hash_make(pool); - err = svn_stream_open_readonly(&stream, digest_path, pool, pool); - if (err && APR_STATUS_IS_ENOENT(err->apr_err)) - { - svn_error_clear(err); - return SVN_NO_ERROR; - } - SVN_ERR(err); + SVN_ERR(svn_io_check_path(digest_path, &kind, pool)); + if (kind == svn_node_none) + return SVN_NO_ERROR; /* If our caller doesn't care about anything but the presence of the file... whatever. */ - if (! (lock_p || children_p)) - return svn_stream_close(stream); + if (kind == svn_node_file && !lock_p && !children_p) + return SVN_NO_ERROR; + + SVN_ERR(svn_stream_open_readonly(&stream, digest_path, pool, pool)); hash = apr_hash_make(pool); if ((err = svn_hash_read2(hash, stream, SVN_HASH_TERMINATOR, pool))) Modified: subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_fs_fs/low_level.c URL: http://svn.apache.org/viewvc/subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_fs_fs/low_level.c?rev=1549081&r1=1549080&r2=1549081&view=diff ============================================================================== --- subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_fs_fs/low_level.c (original) +++ subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_fs_fs/low_level.c Sun Dec 8 17:56:46 2013 @@ -25,6 +25,7 @@ #include "svn_pools.h" #include "svn_sorts.h" #include "private/svn_string_private.h" +#include "private/svn_subr_private.h" #include "../libsvn_fs/fs-loader.h" @@ -482,13 +483,14 @@ read_header_block(apr_hash_t **headers, svn_stream_t *stream, apr_pool_t *pool) { - *headers = apr_hash_make(pool); + *headers = svn_hash__make(pool); while (1) { svn_stringbuf_t *header_str; const char *name, *value; - apr_size_t i = 0; + apr_ssize_t i = 0; + apr_ssize_t name_len; svn_boolean_t eof; SVN_ERR(svn_stream_readline(stream, &header_str, "\n", &eof, pool)); @@ -509,6 +511,7 @@ read_header_block(apr_hash_t **headers, /* Create a 'name' string and point to it. */ header_str->data[i] = '\0'; name = header_str->data; + name_len = i; /* Skip over the NULL byte and the space following it. */ i += 2; @@ -528,7 +531,7 @@ read_header_block(apr_hash_t **headers, /* header_str is safely in our pool, so we can use bits of it as key and value. */ - svn_hash_sets(*headers, name, value); + apr_hash_set(*headers, name, name_len, value); } return SVN_NO_ERROR; @@ -571,7 +574,7 @@ svn_fs_fs__parse_representation(represen } SVN_ERR(svn_cstring_atoi64(&val, str)); - rep->offset = (apr_off_t)val; + rep->item_index = (apr_uint64_t)val; str = svn_cstring_tokenize(" ", &string); if (str == NULL) @@ -851,17 +854,17 @@ svn_fs_fs__unparse_representation(repres if (format < SVN_FS_FS__MIN_REP_SHARING_FORMAT || !rep->has_sha1) return svn_stringbuf_createf - (pool, "%ld %" APR_OFF_T_FMT " %" SVN_FILESIZE_T_FMT + (pool, "%ld %" APR_UINT64_T_FMT " %" SVN_FILESIZE_T_FMT " %" SVN_FILESIZE_T_FMT " %s", - rep->revision, rep->offset, rep->size, + rep->revision, rep->item_index, rep->size, rep->expanded_size, format_digest(rep->md5_digest, svn_checksum_md5, FALSE, pool)); svn__ui64tobase36(buffer, rep->uniquifier.number); return svn_stringbuf_createf - (pool, "%ld %" APR_OFF_T_FMT " %" SVN_FILESIZE_T_FMT + (pool, "%ld %" APR_UINT64_T_FMT " %" SVN_FILESIZE_T_FMT " %" SVN_FILESIZE_T_FMT " %s %s %s/_%s", - rep->revision, rep->offset, rep->size, + rep->revision, rep->item_index, rep->size, rep->expanded_size, format_digest(rep->md5_digest, svn_checksum_md5, FALSE, pool), format_digest(rep->sha1_digest, svn_checksum_sha1, @@ -985,7 +988,7 @@ svn_fs_fs__read_rep_header(svn_fs_fs__re if (! str) goto error; SVN_ERR(svn_cstring_atoi64(&val, str)); - (*header)->base_offset = (apr_off_t)val; + (*header)->base_item_index = (apr_off_t)val; str = svn_cstring_tokenize(" ", &last_str); if (! str) @@ -1020,7 +1023,7 @@ svn_fs_fs__write_rep_header(svn_fs_fs__r default: text = apr_psprintf(pool, REP_DELTA " %ld %" APR_OFF_T_FMT " %" SVN_FILESIZE_T_FMT "\n", - header->base_revision, header->base_offset, + header->base_revision, header->base_item_index, header->base_length); } Modified: subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_fs_fs/low_level.h URL: http://svn.apache.org/viewvc/subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_fs_fs/low_level.h?rev=1549081&r1=1549080&r2=1549081&view=diff ============================================================================== --- subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_fs_fs/low_level.h (original) +++ subversion/branches/invoke-diff-cmd-feature/subversion/libsvn_fs_fs/low_level.h Sun Dec 8 17:56:46 2013 @@ -142,9 +142,9 @@ typedef struct svn_fs_fs__rep_header_t svn_revnum_t base_revision; /* if this rep is a delta against some other rep, that base rep can - * be found at this offset within the base rep's revision. Should + * be found at this item index within the base rep's revision. Should * be 0 if there is no base rep. */ - apr_off_t base_offset; + apr_off_t base_item_index; /* if this rep is a delta against some other rep, this is the (deltified) * size of that base rep. Should be 0 if there is no base rep. */
