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/cached_data.c26
-rw-r--r--subversion/libsvn_fs_fs/caching.c4
-rw-r--r--subversion/libsvn_fs_fs/fs.c2
-rw-r--r--subversion/libsvn_fs_fs/fs_fs.c1
-rw-r--r--subversion/libsvn_fs_fs/low_level.c16
-rw-r--r--subversion/libsvn_fs_fs/pack.c58
-rw-r--r--subversion/libsvn_fs_fs/pack.h8
-rw-r--r--subversion/libsvn_fs_fs/rep-cache-db.h2
-rw-r--r--subversion/libsvn_fs_fs/rep-cache.c26
-rw-r--r--subversion/libsvn_fs_fs/rep-cache.h4
-rw-r--r--subversion/libsvn_fs_fs/transaction.c27
-rw-r--r--subversion/libsvn_fs_fs/tree.c2
12 files changed, 141 insertions, 35 deletions
diff --git a/subversion/libsvn_fs_fs/cached_data.c b/subversion/libsvn_fs_fs/cached_data.c
index 948870e6be1a..6e61535f46a5 100644
--- a/subversion/libsvn_fs_fs/cached_data.c
+++ b/subversion/libsvn_fs_fs/cached_data.c
@@ -1571,6 +1571,17 @@ read_plain_window(svn_stringbuf_t **nwin, rep_state_t *rs,
return SVN_NO_ERROR;
}
+/* Skip SIZE bytes from the PLAIN representation RS. */
+static svn_error_t *
+skip_plain_window(rep_state_t *rs,
+ apr_size_t size)
+{
+ /* Update RS. */
+ rs->current += (apr_off_t)size;
+
+ return SVN_NO_ERROR;
+}
+
/* Get the undeltified window that is a result of combining all deltas
from the current desired representation identified in *RB with its
base representation. Store the window in *RESULT. */
@@ -1628,9 +1639,18 @@ get_combined_window(svn_stringbuf_t **result,
Also note that we may have short-cut reading the delta chain --
in which case SRC_OPS is 0 and it might not be a PLAIN rep. */
source = buf;
- if (source == NULL && rb->src_state != NULL && window->src_ops)
- SVN_ERR(read_plain_window(&source, rb->src_state, window->sview_len,
- pool, iterpool));
+ if (source == NULL && rb->src_state != NULL)
+ {
+ /* Even if we don't need the source rep now, we still must keep
+ * its read offset in sync with what we might need for the next
+ * window. */
+ if (window->src_ops)
+ SVN_ERR(read_plain_window(&source, rb->src_state,
+ window->sview_len,
+ pool, iterpool));
+ else
+ SVN_ERR(skip_plain_window(rb->src_state, window->sview_len));
+ }
/* Combine this window with the current one. */
new_pool = svn_pool_create(rb->pool);
diff --git a/subversion/libsvn_fs_fs/caching.c b/subversion/libsvn_fs_fs/caching.c
index 6775fab009f8..b54d69b3039a 100644
--- a/subversion/libsvn_fs_fs/caching.c
+++ b/subversion/libsvn_fs_fs/caching.c
@@ -430,7 +430,7 @@ svn_fs_fs__initialize_caches(svn_fs_t *fs,
svn_fs_fs__deserialize_dir_entries,
sizeof(pair_cache_key_t),
apr_pstrcat(pool, prefix, "DIR", SVN_VA_NULL),
- SVN_CACHE__MEMBUFFER_DEFAULT_PRIORITY,
+ SVN_CACHE__MEMBUFFER_HIGH_PRIORITY,
fs,
no_handler,
fs->pool, pool));
@@ -806,7 +806,7 @@ svn_fs_fs__initialize_txn_caches(svn_fs_t *fs,
APR_HASH_KEY_STRING,
apr_pstrcat(pool, prefix, "TXNDIR",
SVN_VA_NULL),
- 0,
+ SVN_CACHE__MEMBUFFER_HIGH_PRIORITY,
fs,
TRUE,
pool, pool));
diff --git a/subversion/libsvn_fs_fs/fs.c b/subversion/libsvn_fs_fs/fs.c
index 77c5d221c8e3..1978798917b9 100644
--- a/subversion/libsvn_fs_fs/fs.c
+++ b/subversion/libsvn_fs_fs/fs.c
@@ -452,7 +452,7 @@ fs_pack(svn_fs_t *fs,
apr_pool_t *common_pool)
{
SVN_ERR(fs_open(fs, path, common_pool_lock, pool, common_pool));
- return svn_fs_fs__pack(fs, notify_func, notify_baton,
+ return svn_fs_fs__pack(fs, 0, notify_func, notify_baton,
cancel_func, cancel_baton, pool);
}
diff --git a/subversion/libsvn_fs_fs/fs_fs.c b/subversion/libsvn_fs_fs/fs_fs.c
index 1d32672b87f9..103458d8ef0a 100644
--- a/subversion/libsvn_fs_fs/fs_fs.c
+++ b/subversion/libsvn_fs_fs/fs_fs.c
@@ -492,6 +492,7 @@ read_format(int *pformat,
svn_error_clear(err);
*pformat = 1;
*max_files_per_dir = 0;
+ *use_log_addressing = FALSE;
return SVN_NO_ERROR;
}
diff --git a/subversion/libsvn_fs_fs/low_level.c b/subversion/libsvn_fs_fs/low_level.c
index a27bbcc35b87..d21e312faa2e 100644
--- a/subversion/libsvn_fs_fs/low_level.c
+++ b/subversion/libsvn_fs_fs/low_level.c
@@ -764,7 +764,11 @@ svn_fs_fs__parse_representation(representation_t **rep_p,
SVN_ERR(svn_checksum_parse_hex(&checksum, svn_checksum_md5, str,
scratch_pool));
- memcpy(rep->md5_digest, checksum->digest, sizeof(rep->md5_digest));
+
+ /* If STR is a all-zero checksum, CHECKSUM will be NULL and REP already
+ contains the correct value. */
+ if (checksum)
+ memcpy(rep->md5_digest, checksum->digest, sizeof(rep->md5_digest));
/* The remaining fields are only used for formats >= 4, so check that. */
str = svn_cstring_tokenize(" ", &string);
@@ -778,8 +782,16 @@ svn_fs_fs__parse_representation(representation_t **rep_p,
SVN_ERR(svn_checksum_parse_hex(&checksum, svn_checksum_sha1, str,
scratch_pool));
+
+ /* We do have a valid SHA1 but it might be all 0.
+ We cannot be sure where that came from (Alas! legacy), so let's not
+ claim we know the SHA1 in that case. */
rep->has_sha1 = checksum != NULL;
- memcpy(rep->sha1_digest, checksum->digest, sizeof(rep->sha1_digest));
+
+ /* If STR is a all-zero checksum, CHECKSUM will be NULL and REP already
+ contains the correct value. */
+ if (checksum)
+ memcpy(rep->sha1_digest, checksum->digest, sizeof(rep->sha1_digest));
/* Read the uniquifier. */
str = svn_cstring_tokenize("/", &string);
diff --git a/subversion/libsvn_fs_fs/pack.c b/subversion/libsvn_fs_fs/pack.c
index 50b8898c43a9..8c4ef37fbaa4 100644
--- a/subversion/libsvn_fs_fs/pack.c
+++ b/subversion/libsvn_fs_fs/pack.c
@@ -335,21 +335,40 @@ static svn_error_t *
reset_pack_context(pack_context_t *context,
apr_pool_t *pool)
{
+ const char *temp_dir;
+
apr_array_clear(context->changes);
- SVN_ERR(svn_io_file_trunc(context->changes_file, 0, pool));
+ SVN_ERR(svn_io_file_close(context->changes_file, pool));
apr_array_clear(context->file_props);
- SVN_ERR(svn_io_file_trunc(context->file_props_file, 0, pool));
+ SVN_ERR(svn_io_file_close(context->file_props_file, pool));
apr_array_clear(context->dir_props);
- SVN_ERR(svn_io_file_trunc(context->dir_props_file, 0, pool));
+ SVN_ERR(svn_io_file_close(context->dir_props_file, pool));
apr_array_clear(context->rev_offsets);
apr_array_clear(context->path_order);
apr_array_clear(context->references);
apr_array_clear(context->reps);
- SVN_ERR(svn_io_file_trunc(context->reps_file, 0, pool));
+ SVN_ERR(svn_io_file_close(context->reps_file, pool));
svn_pool_clear(context->info_pool);
+ /* The new temporary files must live at least as long as any other info
+ * object in CONTEXT. */
+ SVN_ERR(svn_io_temp_dir(&temp_dir, pool));
+ SVN_ERR(svn_io_open_unique_file3(&context->changes_file, NULL, temp_dir,
+ svn_io_file_del_on_close,
+ context->info_pool, pool));
+ SVN_ERR(svn_io_open_unique_file3(&context->file_props_file, NULL, temp_dir,
+ svn_io_file_del_on_close,
+ context->info_pool, pool));
+ SVN_ERR(svn_io_open_unique_file3(&context->dir_props_file, NULL, temp_dir,
+ svn_io_file_del_on_close,
+ context->info_pool, pool));
+ SVN_ERR(svn_io_open_unique_file3(&context->reps_file, NULL, temp_dir,
+ svn_io_file_del_on_close,
+ context->info_pool, pool));
+ context->paths = svn_prefix_tree__create(context->info_pool);
+
return SVN_NO_ERROR;
}
@@ -1410,21 +1429,20 @@ append_revision(pack_context_t *context,
apr_off_t offset = 0;
apr_pool_t *iterpool = svn_pool_create(pool);
svn_fs_fs__revision_file_t *rev_file;
- apr_finfo_t finfo;
+ svn_filesize_t revdata_size;
- /* Get the size of the file. */
- const char *path = svn_dirent_join(context->shard_dir,
- apr_psprintf(iterpool, "%ld",
- context->start_rev),
- pool);
- SVN_ERR(svn_io_stat(&finfo, path, APR_FINFO_SIZE, pool));
-
- /* Copy all the bits from the rev file to the end of the pack file. */
+ /* Copy all non-index contents the rev file to the end of the pack file. */
SVN_ERR(svn_fs_fs__open_pack_or_rev_file(&rev_file, context->fs,
context->start_rev, pool,
iterpool));
+
+ SVN_ERR(svn_fs_fs__auto_read_footer(rev_file));
+ revdata_size = rev_file->l2p_offset;
+
+ SVN_ERR(svn_io_file_aligned_seek(rev_file->file, ffd->block_size, NULL, 0,
+ iterpool));
SVN_ERR(copy_file_data(context, context->pack_file, rev_file->file,
- finfo.size, iterpool));
+ revdata_size, iterpool));
/* mark the start of a new revision */
SVN_ERR(svn_fs_fs__l2p_proto_index_add_revision(context->proto_l2p_index,
@@ -1432,7 +1450,7 @@ append_revision(pack_context_t *context,
/* read the phys-to-log index file until we covered the whole rev file.
* That index contains enough info to build both target indexes from it. */
- while (offset < finfo.size)
+ while (offset < revdata_size)
{
/* read one cluster */
int i;
@@ -1456,7 +1474,7 @@ append_revision(pack_context_t *context,
/* process entry while inside the rev file */
offset = entry->offset;
- if (offset < finfo.size)
+ if (offset < revdata_size)
{
entry->offset += context->pack_offset;
offset += entry->size;
@@ -1470,7 +1488,7 @@ append_revision(pack_context_t *context,
}
svn_pool_destroy(iterpool);
- context->pack_offset += finfo.size;
+ context->pack_offset += revdata_size;
SVN_ERR(svn_fs_fs__close_revision_file(rev_file));
@@ -1534,6 +1552,7 @@ pack_log_addressed(svn_fs_t *fs,
for (i = 0; i < max_ids->nelts; ++i)
if (APR_ARRAY_IDX(max_ids, i, apr_uint64_t) + item_count <= max_items)
{
+ item_count += APR_ARRAY_IDX(max_ids, i, apr_uint64_t);
context.end_rev++;
}
else
@@ -1792,6 +1811,7 @@ struct pack_baton
void *notify_baton;
svn_cancel_func_t cancel_func;
void *cancel_baton;
+ size_t max_mem;
/* Additional entries valid when entering pack_shard(). */
const char *revs_dir;
@@ -1913,7 +1933,7 @@ pack_shard(struct pack_baton *baton,
/* pack the revision content */
SVN_ERR(pack_rev_shard(baton->fs, rev_pack_file_dir, baton->rev_shard_path,
baton->shard, ffd->max_files_per_dir,
- DEFAULT_MAX_MEM, baton->cancel_func,
+ baton->max_mem, baton->cancel_func,
baton->cancel_baton, pool));
/* For newer repo formats, we only acquired the pack lock so far.
@@ -2002,6 +2022,7 @@ pack_body(void *baton,
svn_error_t *
svn_fs_fs__pack(svn_fs_t *fs,
+ apr_size_t max_mem,
svn_fs_pack_notify_t notify_func,
void *notify_baton,
svn_cancel_func_t cancel_func,
@@ -2017,6 +2038,7 @@ svn_fs_fs__pack(svn_fs_t *fs,
pb.notify_baton = notify_baton;
pb.cancel_func = cancel_func;
pb.cancel_baton = cancel_baton;
+ pb.max_mem = max_mem ? max_mem : DEFAULT_MAX_MEM;
if (ffd->format >= SVN_FS_FS__MIN_PACK_LOCK_FORMAT)
{
diff --git a/subversion/libsvn_fs_fs/pack.h b/subversion/libsvn_fs_fs/pack.h
index ce1ceb01ee1f..b11f99951113 100644
--- a/subversion/libsvn_fs_fs/pack.h
+++ b/subversion/libsvn_fs_fs/pack.h
@@ -26,13 +26,19 @@
#include "fs.h"
/* Possibly pack the repository at PATH. This just take full shards, and
- combines all the revision files into a single one, with a manifest header.
+ combines all the revision files into a single one, with a manifest header
+ when required by the repository format.
+
+ MAX_MEM limits the size of in-memory data structures needed for reordering
+ items in format 7 repositories. 0 means use the built-in default.
+
If given, NOTIFY_FUNC will be called with NOTIFY_BATON to report progress.
Use optional CANCEL_FUNC/CANCEL_BATON for cancellation support.
Existing filesystem references need not change. */
svn_error_t *
svn_fs_fs__pack(svn_fs_t *fs,
+ apr_size_t max_mem,
svn_fs_pack_notify_t notify_func,
void *notify_baton,
svn_cancel_func_t cancel_func,
diff --git a/subversion/libsvn_fs_fs/rep-cache-db.h b/subversion/libsvn_fs_fs/rep-cache-db.h
index 56692c92e6d0..804b669d12f4 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.9.4/subversion/libsvn_fs_fs/token-map.h.
+/* This file is automatically generated from rep-cache-db.sql and .dist_sandbox/subversion-1.9.5/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/rep-cache.c b/subversion/libsvn_fs_fs/rep-cache.c
index c2b42808becc..663d11d6f09a 100644
--- a/subversion/libsvn_fs_fs/rep-cache.c
+++ b/subversion/libsvn_fs_fs/rep-cache.c
@@ -50,6 +50,13 @@ path_rep_cache_db(const char *fs_path,
return svn_dirent_join(fs_path, REP_CACHE_DB_NAME, result_pool);
}
+#define SVN_ERR_CLOSE(x, db) do \
+{ \
+ svn_error_t *svn__err = (x); \
+ if (svn__err) \
+ return svn_error_compose_create(svn__err, svn_sqlite__close(db)); \
+} while (0)
+
/** Library-private API's. **/
@@ -99,12 +106,12 @@ open_rep_cache(void *baton,
0, NULL, 0,
fs->pool, pool));
- SVN_ERR(svn_sqlite__read_schema_version(&version, sdb, pool));
+ SVN_ERR_CLOSE(svn_sqlite__read_schema_version(&version, sdb, pool), sdb);
if (version < REP_CACHE_SCHEMA_FORMAT)
{
/* Must be 0 -- an uninitialized (no schema) database. Create
the schema. Results in schema version of 1. */
- SVN_ERR(svn_sqlite__exec_statements(sdb, STMT_CREATE_SCHEMA));
+ SVN_ERR_CLOSE(svn_sqlite__exec_statements(sdb, STMT_CREATE_SCHEMA), sdb);
}
/* This is used as a flag that the database is available so don't
@@ -125,6 +132,21 @@ svn_fs_fs__open_rep_cache(svn_fs_t *fs,
}
svn_error_t *
+svn_fs_fs__close_rep_cache(svn_fs_t *fs)
+{
+ fs_fs_data_t *ffd = fs->fsap_data;
+
+ if (ffd->rep_cache_db)
+ {
+ SVN_ERR(svn_sqlite__close(ffd->rep_cache_db));
+ ffd->rep_cache_db = NULL;
+ ffd->rep_cache_db_opened = 0;
+ }
+
+ return SVN_NO_ERROR;
+}
+
+svn_error_t *
svn_fs_fs__exists_rep_cache(svn_boolean_t *exists,
svn_fs_t *fs, apr_pool_t *pool)
{
diff --git a/subversion/libsvn_fs_fs/rep-cache.h b/subversion/libsvn_fs_fs/rep-cache.h
index ce424e6ead99..75072a03eb59 100644
--- a/subversion/libsvn_fs_fs/rep-cache.h
+++ b/subversion/libsvn_fs_fs/rep-cache.h
@@ -40,6 +40,10 @@ svn_error_t *
svn_fs_fs__open_rep_cache(svn_fs_t *fs,
apr_pool_t *pool);
+/* Close the rep cache database associated with FS. */
+svn_error_t *
+svn_fs_fs__close_rep_cache(svn_fs_t *fs);
+
/* Set *EXISTS to TRUE iff the rep-cache DB file exists. */
svn_error_t *
svn_fs_fs__exists_rep_cache(svn_boolean_t *exists,
diff --git a/subversion/libsvn_fs_fs/transaction.c b/subversion/libsvn_fs_fs/transaction.c
index 3968c6fa5deb..fabfe3e3e03b 100644
--- a/subversion/libsvn_fs_fs/transaction.c
+++ b/subversion/libsvn_fs_fs/transaction.c
@@ -2334,12 +2334,17 @@ rep_write_contents_close(void *baton)
b->fnv1a_checksum_ctx,
b->scratch_pool));
- SVN_ERR(store_sha1_rep_mapping(b->fs, b->noderev, b->scratch_pool));
SVN_ERR(store_p2l_index_entry(b->fs, &rep->txn_id, &entry,
b->scratch_pool));
}
SVN_ERR(svn_io_file_close(b->file, b->scratch_pool));
+
+ /* Write the sha1->rep mapping *after* we successfully written node
+ * revision to disk. */
+ if (!old_rep)
+ SVN_ERR(store_sha1_rep_mapping(b->fs, b->noderev, b->scratch_pool));
+
SVN_ERR(unlock_proto_rev(b->fs, &rep->txn_id, b->lockcookie,
b->scratch_pool));
svn_pool_destroy(b->scratch_pool);
@@ -3623,6 +3628,8 @@ svn_fs_fs__commit(svn_revnum_t *new_rev_p,
if (ffd->rep_sharing_allowed)
{
+ svn_error_t *err;
+
SVN_ERR(svn_fs_fs__open_rep_cache(fs, pool));
/* Write new entries to the rep-sharing database.
@@ -3633,9 +3640,21 @@ svn_fs_fs__commit(svn_revnum_t *new_rev_p,
/* ### A commit that touches thousands of files will starve other
(reader/writer) commits for the duration of the below call.
Maybe write in batches? */
- SVN_SQLITE__WITH_TXN(
- write_reps_to_cache(fs, cb.reps_to_cache, pool),
- ffd->rep_cache_db);
+ SVN_ERR(svn_sqlite__begin_transaction(ffd->rep_cache_db));
+ err = write_reps_to_cache(fs, cb.reps_to_cache, pool);
+ err = svn_sqlite__finish_transaction(ffd->rep_cache_db, err);
+
+ if (svn_error_find_cause(err, SVN_SQLITE__ERR_ROLLBACK_FAILED))
+ {
+ /* Failed rollback means that our db connection is unusable, and
+ the only thing we can do is close it. The connection will be
+ reopened during the next operation with rep-cache.db. */
+ return svn_error_trace(
+ svn_error_compose_create(err,
+ svn_fs_fs__close_rep_cache(fs)));
+ }
+ else if (err)
+ return svn_error_trace(err);
}
return SVN_NO_ERROR;
diff --git a/subversion/libsvn_fs_fs/tree.c b/subversion/libsvn_fs_fs/tree.c
index 0047bef251fc..5893da22b0cb 100644
--- a/subversion/libsvn_fs_fs/tree.c
+++ b/subversion/libsvn_fs_fs/tree.c
@@ -2284,7 +2284,7 @@ svn_fs_fs__commit_txn(const char **conflict_p,
if (ffd->pack_after_commit)
{
- SVN_ERR(svn_fs_fs__pack(fs, NULL, NULL, NULL, NULL, pool));
+ SVN_ERR(svn_fs_fs__pack(fs, 0, NULL, NULL, NULL, NULL, pool));
}
return SVN_NO_ERROR;