summaryrefslogtreecommitdiff
path: root/subversion/libsvn_fs_fs
diff options
context:
space:
mode:
Diffstat (limited to 'subversion/libsvn_fs_fs')
-rw-r--r--subversion/libsvn_fs_fs/fs_fs.c57
-rw-r--r--subversion/libsvn_fs_fs/rep-cache-db.h2
-rw-r--r--subversion/libsvn_fs_fs/tree.c37
3 files changed, 83 insertions, 13 deletions
diff --git a/subversion/libsvn_fs_fs/fs_fs.c b/subversion/libsvn_fs_fs/fs_fs.c
index 0354a1f5ffe94..c6074acee0738 100644
--- a/subversion/libsvn_fs_fs/fs_fs.c
+++ b/subversion/libsvn_fs_fs/fs_fs.c
@@ -1467,6 +1467,12 @@ delete_revprops_shard(const char *shard_path,
apr_pool_t *scratch_pool);
/* In the filesystem FS, pack all revprop shards up to min_unpacked_rev.
+ *
+ * NOTE: Keep the old non-packed shards around until after the format bump.
+ * Otherwise, re-running upgrade will drop the packed revprop shard but
+ * have no unpacked data anymore. Call upgrade_cleanup_pack_revprops after
+ * the bump.
+ *
* Use SCRATCH_POOL for temporary allocations.
*/
static svn_error_t *
@@ -1507,6 +1513,29 @@ upgrade_pack_revprops(svn_fs_t *fs,
svn_pool_clear(iterpool);
}
+ svn_pool_destroy(iterpool);
+
+ return SVN_NO_ERROR;
+}
+
+/* In the filesystem FS, remove all non-packed revprop shards up to
+ * min_unpacked_rev. Use SCRATCH_POOL for temporary allocations.
+ * See upgrade_pack_revprops for more info.
+ */
+static svn_error_t *
+upgrade_cleanup_pack_revprops(svn_fs_t *fs,
+ apr_pool_t *scratch_pool)
+{
+ fs_fs_data_t *ffd = fs->fsap_data;
+ const char *revprops_shard_path;
+ apr_int64_t shard;
+ apr_int64_t first_unpacked_shard
+ = ffd->min_unpacked_rev / ffd->max_files_per_dir;
+
+ apr_pool_t *iterpool = svn_pool_create(scratch_pool);
+ const char *revsprops_dir = svn_dirent_join(fs->path, PATH_REVPROPS_DIR,
+ scratch_pool);
+
/* delete the non-packed revprops shards afterwards */
for (shard = 0; shard < first_unpacked_shard; ++shard)
{
@@ -1531,6 +1560,7 @@ upgrade_body(void *baton, apr_pool_t *pool)
int format, max_files_per_dir;
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));
@@ -1582,15 +1612,28 @@ upgrade_body(void *baton, apr_pool_t *pool)
if (format < SVN_FS_FS__MIN_PACKED_FORMAT)
SVN_ERR(svn_io_file_create(path_min_unpacked_rev(fs, pool), "0\n", pool));
- /* If the file system supports revision packing but not revprop packing,
- pack the revprops up to the point that revision data has been packed. */
+ /* If the file system supports revision packing but not revprop packing
+ *and* the FS has been sharded, pack the revprops up to the point that
+ revision data has been packed. However, keep the non-packed revprop
+ files around until after the format bump */
if ( format >= SVN_FS_FS__MIN_PACKED_FORMAT
- && format < SVN_FS_FS__MIN_PACKED_REVPROP_FORMAT)
- SVN_ERR(upgrade_pack_revprops(fs, pool));
+ && format < SVN_FS_FS__MIN_PACKED_REVPROP_FORMAT
+ && max_files_per_dir > 0)
+ {
+ needs_revprop_shard_cleanup = TRUE;
+ SVN_ERR(upgrade_pack_revprops(fs, pool));
+ }
/* Bump the format file. */
- return write_format(format_path, SVN_FS_FS__FORMAT_NUMBER, max_files_per_dir,
- TRUE, pool);
+ SVN_ERR(write_format(format_path, SVN_FS_FS__FORMAT_NUMBER,
+ max_files_per_dir, TRUE, pool));
+
+ /* Now, it is safe to remove the redundant revprop files. */
+ if (needs_revprop_shard_cleanup)
+ SVN_ERR(upgrade_cleanup_pack_revprops(fs, pool));
+
+ /* Done */
+ return SVN_NO_ERROR;
}
@@ -3664,7 +3707,7 @@ parse_packed_revprops(svn_fs_t *fs,
svn_string_t *compressed
= svn_stringbuf__morph_into_string(revprops->packed_revprops);
svn_stringbuf_t *uncompressed = svn_stringbuf_create_empty(pool);
- SVN_ERR(svn__decompress(compressed, uncompressed, 0x1000000));
+ SVN_ERR(svn__decompress(compressed, uncompressed, APR_SIZE_MAX));
/* read first revision number and number of revisions in the pack */
stream = svn_stream_from_stringbuf(uncompressed, scratch_pool);
diff --git a/subversion/libsvn_fs_fs/rep-cache-db.h b/subversion/libsvn_fs_fs/rep-cache-db.h
index fb44c617192db..9f64e8234c8f7 100644
--- a/subversion/libsvn_fs_fs/rep-cache-db.h
+++ b/subversion/libsvn_fs_fs/rep-cache-db.h
@@ -1,4 +1,4 @@
-/* This file is automatically generated from rep-cache-db.sql and .dist_sandbox/subversion-1.8.0/subversion/libsvn_fs_fs/token-map.h.
+/* This file is automatically generated from rep-cache-db.sql and .dist_sandbox/subversion-1.8.1/subversion/libsvn_fs_fs/token-map.h.
* Do not edit this file -- edit the source and rerun gen-make.py */
#define STMT_CREATE_SCHEMA 0
diff --git a/subversion/libsvn_fs_fs/tree.c b/subversion/libsvn_fs_fs/tree.c
index c14955d737b8c..64c8395295a81 100644
--- a/subversion/libsvn_fs_fs/tree.c
+++ b/subversion/libsvn_fs_fs/tree.c
@@ -151,7 +151,7 @@ typedef struct cache_entry_t
{
/* hash value derived from PATH, REVISION.
Used to short-circuit failed lookups. */
- long int hash_value;
+ apr_uint32_t hash_value;
/* revision to which the NODE belongs */
svn_revnum_t revision;
@@ -340,7 +340,12 @@ cache_lookup( fs_fs_dag_cache_t *cache
{
apr_size_t i, bucket_index;
apr_size_t path_len = strlen(path);
- long int hash_value = revision;
+ apr_uint32_t hash_value = (apr_uint32_t)revision;
+
+#if SVN_UNALIGNED_ACCESS_IS_OK
+ /* "randomizing" / distributing factor used in our hash function */
+ const apr_uint32_t factor = 0xd1f3da69;
+#endif
/* optimistic lookup: hit the same bucket again? */
cache_entry_t *result = &cache->buckets[cache->last_hit];
@@ -353,11 +358,25 @@ cache_lookup( fs_fs_dag_cache_t *cache
/* need to do a full lookup. Calculate the hash value
(HASH_VALUE has been initialized to REVISION). */
- for (i = 0; i + 4 <= path_len; i += 4)
- hash_value = hash_value * 0xd1f3da69 + *(const apr_uint32_t*)(path + i);
+ i = 0;
+#if SVN_UNALIGNED_ACCESS_IS_OK
+ /* We relax the dependency chain between iterations by processing
+ two chunks from the input per hash_value self-multiplication.
+ The HASH_VALUE update latency is now 1 MUL latency + 1 ADD latency
+ per 2 chunks instead of 1 chunk.
+ */
+ for (; i + 8 <= path_len; i += 8)
+ hash_value = hash_value * factor * factor
+ + ( *(const apr_uint32_t*)(path + i) * factor
+ + *(const apr_uint32_t*)(path + i + 4));
+#endif
for (; i < path_len; ++i)
- hash_value = hash_value * 33 + path[i];
+ /* Help GCC to minimize the HASH_VALUE update latency by splitting the
+ MUL 33 of the naive implementation: h = h * 33 + path[i]. This
+ shortens the dependency chain from 1 shift + 2 ADDs to 1 shift + 1 ADD.
+ */
+ hash_value = hash_value * 32 + (hash_value + (unsigned char)path[i]);
bucket_index = hash_value + (hash_value >> 16);
bucket_index = (bucket_index + (bucket_index >> 8)) % BUCKET_COUNT;
@@ -3364,6 +3383,14 @@ fs_node_origin_rev(svn_revnum_t *revision,
return SVN_NO_ERROR;
}
+ /* The root node always has ID 0, created in revision 0 and will never
+ use the new-style ID format. */
+ if (strcmp(node_id, "0") == 0)
+ {
+ *revision = 0;
+ return SVN_NO_ERROR;
+ }
+
/* OK, it's an old-style ID? Maybe it's cached. */
SVN_ERR(svn_fs_fs__get_node_origin(&cached_origin_id,
fs,