diff options
Diffstat (limited to 'subversion/libsvn_fs_fs')
-rw-r--r-- | subversion/libsvn_fs_fs/cached_data.c | 26 | ||||
-rw-r--r-- | subversion/libsvn_fs_fs/caching.c | 4 | ||||
-rw-r--r-- | subversion/libsvn_fs_fs/fs.c | 2 | ||||
-rw-r--r-- | subversion/libsvn_fs_fs/fs_fs.c | 1 | ||||
-rw-r--r-- | subversion/libsvn_fs_fs/low_level.c | 16 | ||||
-rw-r--r-- | subversion/libsvn_fs_fs/pack.c | 58 | ||||
-rw-r--r-- | subversion/libsvn_fs_fs/pack.h | 8 | ||||
-rw-r--r-- | subversion/libsvn_fs_fs/rep-cache-db.h | 2 | ||||
-rw-r--r-- | subversion/libsvn_fs_fs/rep-cache.c | 26 | ||||
-rw-r--r-- | subversion/libsvn_fs_fs/rep-cache.h | 4 | ||||
-rw-r--r-- | subversion/libsvn_fs_fs/transaction.c | 27 | ||||
-rw-r--r-- | subversion/libsvn_fs_fs/tree.c | 2 |
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; |