Modified: subversion/branches/ra-git/subversion/libsvn_fs_fs/pack.c URL: http://svn.apache.org/viewvc/subversion/branches/ra-git/subversion/libsvn_fs_fs/pack.c?rev=1764214&r1=1764213&r2=1764214&view=diff ============================================================================== --- subversion/branches/ra-git/subversion/libsvn_fs_fs/pack.c (original) +++ subversion/branches/ra-git/subversion/libsvn_fs_fs/pack.c Tue Oct 11 09:11:50 2016 @@ -221,7 +221,7 @@ typedef struct pack_context_t * to NULL that we already processed. */ apr_array_header_t *reps; - /* array of int, marking for each revision, the which offset their items + /* array of int, marking for each revision, at which offset their items * begin in REPS. Will be filled in phase 2 and be cleared after * each revision range. */ apr_array_header_t *rev_offsets; @@ -233,6 +233,9 @@ typedef struct pack_context_t /* pool used for temporary data structures that will be cleaned up when * the next range of revisions is being processed */ apr_pool_t *info_pool; + + /* ensure that all filesystem changes are written to disk. */ + svn_boolean_t flush_to_disk; } pack_context_t; /* Create and initialize a new pack context for packing shard SHARD_REV in @@ -240,7 +243,7 @@ typedef struct pack_context_t * and return the structure in *CONTEXT. * * Limit the number of items being copied per iteration to MAX_ITEMS. - * Set CANCEL_FUNC and CANCEL_BATON as well. + * Set FLUSH_TO_DISK, CANCEL_FUNC and CANCEL_BATON as well. */ static svn_error_t * initialize_pack_context(pack_context_t *context, @@ -249,6 +252,7 @@ initialize_pack_context(pack_context_t * const char *shard_dir, svn_revnum_t shard_rev, int max_items, + svn_boolean_t flush_to_disk, svn_cancel_func_t cancel_func, void *cancel_baton, apr_pool_t *pool) @@ -325,6 +329,8 @@ initialize_pack_context(pack_context_t * context->info_pool = svn_pool_create(pool); context->paths = svn_prefix_tree__create(context->info_pool); + context->flush_to_disk = flush_to_disk; + return SVN_NO_ERROR; } @@ -349,6 +355,7 @@ reset_pack_context(pack_context_t *conte SVN_ERR(svn_io_file_trunc(context->reps_file, 0, pool)); svn_pool_clear(context->info_pool); + context->paths = svn_prefix_tree__create(context->info_pool); return SVN_NO_ERROR; } @@ -385,7 +392,8 @@ close_pack_context(pack_context_t *conte SVN_ERR(svn_io_remove_file2(proto_p2l_index_path, FALSE, pool)); /* Ensure that packed file is written to disk.*/ - SVN_ERR(svn_io_file_flush_to_disk(context->pack_file, pool)); + if (context->flush_to_disk) + SVN_ERR(svn_io_file_flush_to_disk(context->pack_file, pool)); SVN_ERR(svn_io_file_close(context->pack_file, pool)); return SVN_NO_ERROR; @@ -700,7 +708,7 @@ tweak_path_for_ordering(const char *orig */ static svn_error_t * copy_node_to_temp(pack_context_t *context, - apr_file_t *rev_file, + svn_fs_fs__revision_file_t *rev_file, svn_fs_fs__p2l_entry_t *entry, apr_pool_t *pool) { @@ -708,13 +716,10 @@ copy_node_to_temp(pack_context_t *contex sizeof(*path_order)); node_revision_t *noderev; const char *sort_path; - svn_stream_t *stream; apr_off_t source_offset = entry->offset; /* read & parse noderev */ - stream = svn_stream_from_aprfile2(rev_file, TRUE, pool); - SVN_ERR(svn_fs_fs__read_noderev(&noderev, stream, pool, pool)); - SVN_ERR(svn_stream_close(stream)); + SVN_ERR(svn_fs_fs__read_noderev(&noderev, rev_file->stream, pool, pool)); /* create a copy of ENTRY, make it point to the copy destination and * store it in CONTEXT */ @@ -724,9 +729,9 @@ copy_node_to_temp(pack_context_t *contex add_item_rep_mapping(context, entry); /* copy the noderev to our temp file */ - SVN_ERR(svn_io_file_seek(rev_file, APR_SET, &source_offset, pool)); - SVN_ERR(copy_file_data(context, context->reps_file, rev_file, entry->size, - pool)); + SVN_ERR(svn_io_file_seek(rev_file->file, APR_SET, &source_offset, pool)); + SVN_ERR(copy_file_data(context, context->reps_file, rev_file->file, + entry->size, pool)); /* if the node has a data representation, make that the node's "base". * This will (often) cause the noderev to be placed right in front of @@ -803,11 +808,11 @@ compare_ref_to_item(const reference_t * /* Look for the least significant bit set in VALUE and return the smallest * number with the same property, i.e. the largest power of 2 that is a - * factor in VALUE. */ + * factor in VALUE. Edge case: roundness(0) := 0 . */ static int roundness(int value) { - return value ? value - (value & (value - 1)) : INT_MAX; + return value - (value & (value - 1)); } /* For all paths in first COUNT entries in PATH_ORDER, mark their latest @@ -896,14 +901,19 @@ sort_reps_range(pack_context_t *context, /* Class 1: * Pretty round _and_ a significant stop in the node's delta chain. * This may pick up more than one representation from the same chain - * but that's rare not a problem. Prefer simple checks here. */ + * but that's rare and not a problem. Prefer simple checks here. + * + * The divider of 4 is arbitrary but seems to work well in practice. + * Larger values increase the number of items in the "hot zone". + * Smaller values make delta chains at HEAD more likely to contain + * "cold zone" representations. */ svn_boolean_t likely_target = (round >= ffd->max_linear_deltification) - && (4 * round >= path_order[i]->predecessor_count); + && (round >= path_order[i]->predecessor_count / 4); /* Class 2: * Anything from short node chains. The default of 16 is generous - * but we'd rather include to many than to few nodes here to keep + * but we'd rather include too many than too few nodes here to keep * seeks between different regions of this pack file at a minimum. */ svn_boolean_t likely_head = path_order[i]->predecessor_count @@ -1046,7 +1056,7 @@ sort_items(apr_array_header_t *entries) /* Return the remaining unused bytes in the current block in CONTEXT's * pack file. */ -static apr_ssize_t +static apr_off_t get_block_left(pack_context_t *context) { fs_fs_data_t *ffd = context->fs->fsap_data; @@ -1379,7 +1389,7 @@ pack_range(pack_context_t *context, SVN_ERR(copy_rep_to_temp(context, rev_file->file, entry, iterpool2)); else if (entry->type == SVN_FS_FS__ITEM_TYPE_NODEREV) - SVN_ERR(copy_node_to_temp(context, rev_file->file, entry, + SVN_ERR(copy_node_to_temp(context, rev_file, entry, iterpool2)); else SVN_ERR_ASSERT(entry->type == SVN_FS_FS__ITEM_TYPE_UNUSED); @@ -1438,17 +1448,19 @@ 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; - svn_filesize_t revfile_size; + svn_filesize_t revdata_size; - /* 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)); - /* Get the size of the file. */ - SVN_ERR(svn_io_file_size_get(&revfile_size, rev_file->file, pool)); + 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, - revfile_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, @@ -1456,7 +1468,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 < revfile_size) + while (offset < revdata_size) { /* read one cluster */ int i; @@ -1480,7 +1492,7 @@ append_revision(pack_context_t *context, /* process entry while inside the rev file */ offset = entry->offset; - if (offset < revfile_size) + if (offset < revdata_size) { entry->offset += context->pack_offset; offset += entry->size; @@ -1494,7 +1506,7 @@ append_revision(pack_context_t *context, } svn_pool_destroy(iterpool); - context->pack_offset += revfile_size; + context->pack_offset += revdata_size; SVN_ERR(svn_fs_fs__close_revision_file(rev_file)); @@ -1505,8 +1517,9 @@ append_revision(pack_context_t *context, * * Pack the revision shard starting at SHARD_REV in filesystem FS from * SHARD_DIR into the PACK_FILE_DIR, using POOL for allocations. Limit - * the extra memory consumption to MAX_MEM bytes. CANCEL_FUNC and - * CANCEL_BATON are what you think they are. + * the extra memory consumption to MAX_MEM bytes. If FLUSH_TO_DISK is + * non-zero, do not return until the data has actually been written on + * the disk. CANCEL_FUNC and CANCEL_BATON are what you think they are. */ static svn_error_t * pack_log_addressed(svn_fs_t *fs, @@ -1514,6 +1527,7 @@ pack_log_addressed(svn_fs_t *fs, const char *shard_dir, svn_revnum_t shard_rev, apr_size_t max_mem, + svn_boolean_t flush_to_disk, svn_cancel_func_t cancel_func, void *cancel_baton, apr_pool_t *pool) @@ -1546,8 +1560,8 @@ pack_log_addressed(svn_fs_t *fs, /* set up a pack context */ SVN_ERR(initialize_pack_context(&context, fs, pack_file_dir, shard_dir, - shard_rev, max_items, cancel_func, - cancel_baton, pool)); + shard_rev, max_items, flush_to_disk, + cancel_func, cancel_baton, pool)); /* phase 1: determine the size of the revisions to pack */ SVN_ERR(svn_fs_fs__l2p_get_max_ids(&max_ids, fs, shard_rev, @@ -1559,6 +1573,7 @@ pack_log_addressed(svn_fs_t *fs, if ( APR_ARRAY_IDX(max_ids, i, apr_uint64_t) <= (apr_uint64_t)max_items - item_count) { + item_count += APR_ARRAY_IDX(max_ids, i, apr_uint64_t); context.end_rev++; } else @@ -1670,14 +1685,16 @@ svn_fs_fs__get_packed_offset(apr_off_t * * * Pack the revision shard starting at SHARD_REV containing exactly * MAX_FILES_PER_DIR revisions from SHARD_PATH into the PACK_FILE_DIR, - * using POOL for allocations. CANCEL_FUNC and CANCEL_BATON are what you - * think they are. + * using POOL for allocations. If FLUSH_TO_DISK is non-zero, do not + * return until the data has actually been written on the disk. + * CANCEL_FUNC and CANCEL_BATON are what you think they are. */ static svn_error_t * pack_phys_addressed(const char *pack_file_dir, const char *shard_path, svn_revnum_t start_rev, int max_files_per_dir, + svn_boolean_t flush_to_disk, svn_cancel_func_t cancel_func, void *cancel_baton, apr_pool_t *pool) @@ -1715,6 +1732,7 @@ pack_phys_addressed(const char *pack_fil svn_stream_t *rev_stream; const char *path; apr_off_t offset; + apr_file_t *rev_file; svn_pool_clear(iterpool); @@ -1728,10 +1746,15 @@ pack_phys_addressed(const char *pack_fil SVN_ERR(svn_stream_printf(manifest_stream, iterpool, "%" APR_OFF_T_FMT "\n", offset)); - /* Copy all the bits from the rev file to the end of the pack file. */ - SVN_ERR(svn_stream_open_readonly(&rev_stream, path, iterpool, iterpool)); + /* Copy all the bits from the rev file to the end of the pack file. + * Use unbuffered apr_file_t since we're going to write using 16kb + * chunks. */ + SVN_ERR(svn_io_file_open(&rev_file, path, APR_READ, APR_OS_DEFAULT, + iterpool)); + rev_stream = svn_stream_from_aprfile2(rev_file, FALSE, iterpool); SVN_ERR(svn_stream_copy3(rev_stream, - svn_stream_from_aprfile2(pack_file, TRUE, pool), + svn_stream_from_aprfile2(pack_file, TRUE, + iterpool), cancel_func, cancel_baton, iterpool)); } @@ -1739,14 +1762,16 @@ pack_phys_addressed(const char *pack_fil SVN_ERR(svn_stream_close(manifest_stream)); /* Ensure that pack file is written to disk. */ - SVN_ERR(svn_io_file_flush_to_disk(manifest_file, pool)); + if (flush_to_disk) + SVN_ERR(svn_io_file_flush_to_disk(manifest_file, pool)); SVN_ERR(svn_io_file_close(manifest_file, pool)); /* disallow write access to the manifest file */ SVN_ERR(svn_io_set_file_read_only(manifest_file_path, FALSE, iterpool)); /* Ensure that pack file is written to disk. */ - SVN_ERR(svn_io_file_flush_to_disk(pack_file, pool)); + if (flush_to_disk) + SVN_ERR(svn_io_file_flush_to_disk(pack_file, pool)); SVN_ERR(svn_io_file_close(pack_file, pool)); svn_pool_destroy(iterpool); @@ -1757,8 +1782,9 @@ pack_phys_addressed(const char *pack_fil /* In filesystem FS, pack the revision SHARD containing exactly * MAX_FILES_PER_DIR revisions from SHARD_PATH into the PACK_FILE_DIR, * using POOL for allocations. Try to limit the amount of temporary - * memory needed to MAX_MEM bytes. CANCEL_FUNC and CANCEL_BATON are what - * you think they are. + * memory needed to MAX_MEM bytes. If FLUSH_TO_DISK is non-zero, do + * not return until the data has actually been written on the disk. + * CANCEL_FUNC and CANCEL_BATON are what you think they are. * * If for some reason we detect a partial packing already performed, we * remove the pack file and start again. @@ -1772,6 +1798,7 @@ pack_rev_shard(svn_fs_t *fs, apr_int64_t shard, int max_files_per_dir, apr_size_t max_mem, + svn_boolean_t flush_to_disk, svn_cancel_func_t cancel_func, void *cancel_baton, apr_pool_t *pool) @@ -1791,12 +1818,13 @@ pack_rev_shard(svn_fs_t *fs, /* Index information files */ if (svn_fs_fs__use_log_addressing(fs)) - SVN_ERR(pack_log_addressed(fs, pack_file_dir, shard_path, shard_rev, - max_mem, cancel_func, cancel_baton, pool)); + SVN_ERR(pack_log_addressed(fs, pack_file_dir, shard_path, + shard_rev, max_mem, flush_to_disk, + cancel_func, cancel_baton, pool)); else SVN_ERR(pack_phys_addressed(pack_file_dir, shard_path, shard_rev, - max_files_per_dir, cancel_func, - cancel_baton, pool)); + max_files_per_dir, flush_to_disk, + cancel_func, cancel_baton, pool)); SVN_ERR(svn_io_copy_perms(shard_path, pack_file_dir, pool)); SVN_ERR(svn_io_set_file_read_only(pack_file_path, FALSE, pool)); @@ -1815,6 +1843,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; @@ -1862,6 +1891,7 @@ synced_pack_shard(void *baton, ffd->compress_packed_revprops ? SVN__COMPRESSION_ZLIB_DEFAULT : SVN__COMPRESSION_NONE, + ffd->flush_to_disk, pb->cancel_func, pb->cancel_baton, pool)); @@ -1938,8 +1968,8 @@ 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->cancel_baton, pool)); + baton->max_mem, ffd->flush_to_disk, + baton->cancel_func, baton->cancel_baton, pool)); /* For newer repo formats, we only acquired the pack lock so far. Before modifying the repo state by switching over to the packed @@ -2048,6 +2078,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, @@ -2093,6 +2124,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) {
Modified: subversion/branches/ra-git/subversion/libsvn_fs_fs/pack.h URL: http://svn.apache.org/viewvc/subversion/branches/ra-git/subversion/libsvn_fs_fs/pack.h?rev=1764214&r1=1764213&r2=1764214&view=diff ============================================================================== --- subversion/branches/ra-git/subversion/libsvn_fs_fs/pack.h (original) +++ subversion/branches/ra-git/subversion/libsvn_fs_fs/pack.h Tue Oct 11 09:11:50 2016 @@ -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, Modified: subversion/branches/ra-git/subversion/libsvn_fs_fs/rep-cache.c URL: http://svn.apache.org/viewvc/subversion/branches/ra-git/subversion/libsvn_fs_fs/rep-cache.c?rev=1764214&r1=1764213&r2=1764214&view=diff ============================================================================== --- subversion/branches/ra-git/subversion/libsvn_fs_fs/rep-cache.c (original) +++ subversion/branches/ra-git/subversion/libsvn_fs_fs/rep-cache.c Tue Oct 11 09:11:50 2016 @@ -100,12 +100,15 @@ open_rep_cache(void *baton, 0, NULL, 0, fs->pool, pool)); - SVN_ERR(svn_sqlite__read_schema_version(&version, sdb, pool)); + SVN_SQLITE__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_SQLITE__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 @@ -126,6 +129,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) { @@ -239,7 +257,7 @@ svn_fs_fs__walk_rep_reference(svn_fs_t * If you extend this function, check the callsite to see if you have to make it not-ignore additional error codes. */ svn_error_t * -svn_fs_fs__get_rep_reference(representation_t **rep, +svn_fs_fs__get_rep_reference(representation_t **rep_p, svn_fs_t *fs, svn_checksum_t *checksum, apr_pool_t *pool) @@ -247,6 +265,7 @@ svn_fs_fs__get_rep_reference(representat fs_fs_data_t *ffd = fs->fsap_data; svn_sqlite__stmt_t *stmt; svn_boolean_t have_row; + representation_t *rep; SVN_ERR_ASSERT(ffd->rep_sharing_allowed); if (! ffd->rep_cache_db) @@ -265,28 +284,28 @@ svn_fs_fs__get_rep_reference(representat SVN_ERR(svn_sqlite__step(&have_row, stmt)); if (have_row) { - *rep = apr_pcalloc(pool, sizeof(**rep)); - svn_fs_fs__id_txn_reset(&(*rep)->txn_id); - memcpy((*rep)->sha1_digest, checksum->digest, - sizeof((*rep)->sha1_digest)); - (*rep)->has_sha1 = TRUE; - (*rep)->revision = svn_sqlite__column_revnum(stmt, 0); - (*rep)->item_index = svn_sqlite__column_int64(stmt, 1); - (*rep)->size = svn_sqlite__column_int64(stmt, 2); - (*rep)->expanded_size = svn_sqlite__column_int64(stmt, 3); - - SVN_ERR(svn_fs_fs__fixup_expanded_size(fs, *rep, pool)); + rep = apr_pcalloc(pool, sizeof(*rep)); + svn_fs_fs__id_txn_reset(&(rep->txn_id)); + memcpy(rep->sha1_digest, checksum->digest, sizeof(rep->sha1_digest)); + rep->has_sha1 = TRUE; + rep->revision = svn_sqlite__column_revnum(stmt, 0); + rep->item_index = svn_sqlite__column_int64(stmt, 1); + rep->size = svn_sqlite__column_int64(stmt, 2); + rep->expanded_size = svn_sqlite__column_int64(stmt, 3); } else - *rep = NULL; + rep = NULL; SVN_ERR(svn_sqlite__reset(stmt)); - if (*rep) + if (rep) { + svn_error_t *err; + + SVN_ERR(svn_fs_fs__fixup_expanded_size(fs, rep, pool)); + /* Check that REP refers to a revision that exists in FS. */ - svn_error_t *err = svn_fs_fs__ensure_revision_exists((*rep)->revision, - fs, pool); + err = svn_fs_fs__ensure_revision_exists(rep->revision, fs, pool); if (err) return svn_error_createf(SVN_ERR_FS_CORRUPT, err, "Checksum '%s' in rep-cache is beyond HEAD", @@ -294,6 +313,7 @@ svn_fs_fs__get_rep_reference(representat pool)); } + *rep_p = rep; return SVN_NO_ERROR; } Modified: subversion/branches/ra-git/subversion/libsvn_fs_fs/rep-cache.h URL: http://svn.apache.org/viewvc/subversion/branches/ra-git/subversion/libsvn_fs_fs/rep-cache.h?rev=1764214&r1=1764213&r2=1764214&view=diff ============================================================================== --- subversion/branches/ra-git/subversion/libsvn_fs_fs/rep-cache.h (original) +++ subversion/branches/ra-git/subversion/libsvn_fs_fs/rep-cache.h Tue Oct 11 09:11:50 2016 @@ -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, @@ -60,11 +64,11 @@ svn_fs_fs__walk_rep_reference(svn_fs_t * apr_pool_t *pool); /* Return the representation REP in FS which has fulltext CHECKSUM. - REP is allocated in POOL. If the rep cache database has not been - opened, just set *REP to NULL. Returns SVN_ERR_FS_CORRUPT if + *REP_P is allocated in POOL. If the rep cache database has not been + opened, just set *REP_P to NULL. Returns SVN_ERR_FS_CORRUPT if a reference beyond HEAD is detected. */ svn_error_t * -svn_fs_fs__get_rep_reference(representation_t **rep, +svn_fs_fs__get_rep_reference(representation_t **rep_p, svn_fs_t *fs, svn_checksum_t *checksum, apr_pool_t *pool); Modified: subversion/branches/ra-git/subversion/libsvn_fs_fs/revprops.c URL: http://svn.apache.org/viewvc/subversion/branches/ra-git/subversion/libsvn_fs_fs/revprops.c?rev=1764214&r1=1764213&r2=1764214&view=diff ============================================================================== --- subversion/branches/ra-git/subversion/libsvn_fs_fs/revprops.c (original) +++ subversion/branches/ra-git/subversion/libsvn_fs_fs/revprops.c Tue Oct 11 09:11:50 2016 @@ -79,6 +79,7 @@ svn_fs_fs__upgrade_pack_revprops(svn_fs_ shard, ffd->max_files_per_dir, (int)(0.9 * ffd->revprop_pack_size), compression_level, + ffd->flush_to_disk, cancel_func, cancel_baton, iterpool)); if (notify_func) @@ -738,6 +739,7 @@ write_non_packed_revprop(const char **fi apr_hash_t *proplist, apr_pool_t *pool) { + fs_fs_data_t *ffd = fs->fsap_data; apr_file_t *file; svn_stream_t *stream; *final_path = svn_fs_fs__path_revprops(fs, rev, pool); @@ -752,7 +754,8 @@ write_non_packed_revprop(const char **fi SVN_ERR(svn_stream_close(stream)); /* Flush temporary file to disk and close it. */ - SVN_ERR(svn_io_file_flush_to_disk(file, pool)); + if (ffd->flush_to_disk) + SVN_ERR(svn_io_file_flush_to_disk(file, pool)); SVN_ERR(svn_io_file_close(file, pool)); return SVN_NO_ERROR; @@ -775,8 +778,10 @@ switch_to_new_revprop(svn_fs_t *fs, apr_array_header_t *files_to_delete, apr_pool_t *pool) { + fs_fs_data_t *ffd = fs->fsap_data; + SVN_ERR(svn_fs_fs__move_into_place(tmp_path, final_path, perms_reference, - pool)); + ffd->flush_to_disk, pool)); /* Clean up temporary files, if necessary. */ if (files_to_delete) @@ -831,7 +836,7 @@ serialize_revprops_header(svn_stream_t * } /* the double newline char indicates the end of the header */ - SVN_ERR(svn_stream_printf(stream, iterpool, "\n")); + SVN_ERR(svn_stream_puts(stream, "\n")); svn_pool_destroy(iterpool); return SVN_NO_ERROR; @@ -904,7 +909,8 @@ repack_revprops(svn_fs_t *fs, /* finally, write the content to the target file, flush and close it */ SVN_ERR(svn_io_file_write_full(file, compressed->data, compressed->len, NULL, pool)); - SVN_ERR(svn_io_file_flush_to_disk(file, pool)); + if (ffd->flush_to_disk) + SVN_ERR(svn_io_file_flush_to_disk(file, pool)); SVN_ERR(svn_io_file_close(file, pool)); return SVN_NO_ERROR; @@ -927,7 +933,7 @@ repack_file_open(apr_file_t **file, { apr_int64_t tag; const char *tag_string; - svn_string_t *new_filename; + const char *new_filename; int i; int manifest_offset = (int)(revprops->start_revision - revprops->manifest_start); @@ -951,18 +957,18 @@ repack_file_open(apr_file_t **file, old_filename); SVN_ERR(svn_cstring_atoi64(&tag, tag_string + 1)); - new_filename = svn_string_createf(pool, "%ld.%" APR_INT64_T_FMT, - revprops->start_revision + start, - ++tag); + new_filename = apr_psprintf(pool, "%ld.%" APR_INT64_T_FMT, + revprops->start_revision + start, + ++tag); /* update the manifest to point to the new file */ for (i = start; i < end; ++i) APR_ARRAY_IDX(revprops->manifest, i + manifest_offset, const char*) - = new_filename->data; + = new_filename; /* open the file */ SVN_ERR(svn_io_file_open(file, svn_dirent_join(revprops->folder, - new_filename->data, + new_filename, pool), APR_WRITE | APR_CREATE, APR_OS_DEFAULT, pool)); @@ -1111,7 +1117,8 @@ write_packed_revprop(const char **final_ SVN_ERR(svn_stream_printf(stream, pool, "%s\n", filename)); } SVN_ERR(svn_stream_close(stream)); - SVN_ERR(svn_io_file_flush_to_disk(file, pool)); + if (ffd->flush_to_disk) + SVN_ERR(svn_io_file_flush_to_disk(file, pool)); SVN_ERR(svn_io_file_close(file, pool)); } @@ -1246,6 +1253,7 @@ svn_fs_fs__copy_revprops(const char *pac apr_array_header_t *sizes, apr_size_t total_size, int compression_level, + svn_boolean_t flush_to_disk, svn_cancel_func_t cancel_func, void *cancel_baton, apr_pool_t *scratch_pool) @@ -1278,6 +1286,7 @@ svn_fs_fs__copy_revprops(const char *pac { const char *path; svn_stream_t *stream; + apr_file_t *file; svn_pool_clear(iterpool); @@ -1286,8 +1295,11 @@ svn_fs_fs__copy_revprops(const char *pac iterpool); /* Copy all the bits from the non-packed revprop file to the end of - * the pack file. */ - SVN_ERR(svn_stream_open_readonly(&stream, path, iterpool, iterpool)); + * the pack file. Use unbuffered apr_file_t since we're going to + * write using 16kb chunks. */ + SVN_ERR(svn_io_file_open(&file, path, APR_READ, APR_OS_DEFAULT, + iterpool)); + stream = svn_stream_from_aprfile2(file, FALSE, iterpool); SVN_ERR(svn_stream_copy3(stream, pack_stream, cancel_func, cancel_baton, iterpool)); } @@ -1302,7 +1314,8 @@ svn_fs_fs__copy_revprops(const char *pac /* write the pack file content to disk */ SVN_ERR(svn_io_file_write_full(pack_file, compressed->data, compressed->len, NULL, scratch_pool)); - SVN_ERR(svn_io_file_flush_to_disk(pack_file, scratch_pool)); + if (flush_to_disk) + SVN_ERR(svn_io_file_flush_to_disk(pack_file, scratch_pool)); SVN_ERR(svn_io_file_close(pack_file, scratch_pool)); svn_pool_destroy(iterpool); @@ -1317,6 +1330,7 @@ svn_fs_fs__pack_revprops_shard(const cha int max_files_per_dir, apr_int64_t max_pack_size, int compression_level, + svn_boolean_t flush_to_disk, svn_cancel_func_t cancel_func, void *cancel_baton, apr_pool_t *scratch_pool) @@ -1388,8 +1402,9 @@ svn_fs_fs__pack_revprops_shard(const cha SVN_ERR(svn_fs_fs__copy_revprops(pack_file_dir, pack_filename, shard_path, start_rev, rev-1, sizes, total_size, - compression_level, cancel_func, - cancel_baton, iterpool)); + compression_level, flush_to_disk, + cancel_func, cancel_baton, + iterpool)); /* next pack file starts empty again */ apr_array_clear(sizes); @@ -1415,12 +1430,13 @@ svn_fs_fs__pack_revprops_shard(const cha SVN_ERR(svn_fs_fs__copy_revprops(pack_file_dir, pack_filename, shard_path, start_rev, rev-1, sizes, (apr_size_t)total_size, - compression_level, cancel_func, - cancel_baton, iterpool)); + compression_level, flush_to_disk, + cancel_func, cancel_baton, iterpool)); /* flush the manifest file to disk and update permissions */ SVN_ERR(svn_stream_close(manifest_stream)); - SVN_ERR(svn_io_file_flush_to_disk(manifest_file, iterpool)); + if (flush_to_disk) + SVN_ERR(svn_io_file_flush_to_disk(manifest_file, iterpool)); SVN_ERR(svn_io_file_close(manifest_file, iterpool)); SVN_ERR(svn_io_copy_perms(shard_path, pack_file_dir, iterpool)); Modified: subversion/branches/ra-git/subversion/libsvn_fs_fs/revprops.h URL: http://svn.apache.org/viewvc/subversion/branches/ra-git/subversion/libsvn_fs_fs/revprops.h?rev=1764214&r1=1764213&r2=1764214&view=diff ============================================================================== --- subversion/branches/ra-git/subversion/libsvn_fs_fs/revprops.h (original) +++ subversion/branches/ra-git/subversion/libsvn_fs_fs/revprops.h Tue Oct 11 09:11:50 2016 @@ -111,8 +111,9 @@ svn_fs_fs__packed_revprop_available(svn_ * a hint on which initial buffer size we should use to hold the pack file * content. * - * CANCEL_FUNC and CANCEL_BATON are used as usual. Temporary allocations - * are done in SCRATCH_POOL. + * If FLUSH_TO_DISK is non-zero, do not return until the data has actually + * been written on the disk. CANCEL_FUNC and CANCEL_BATON are used as usual. + * Temporary allocations are done in SCRATCH_POOL. */ svn_error_t * svn_fs_fs__copy_revprops(const char *pack_file_dir, @@ -123,6 +124,7 @@ svn_fs_fs__copy_revprops(const char *pac apr_array_header_t *sizes, apr_size_t total_size, int compression_level, + svn_boolean_t flush_to_disk, svn_cancel_func_t cancel_func, void *cancel_baton, apr_pool_t *scratch_pool); @@ -134,8 +136,9 @@ svn_fs_fs__copy_revprops(const char *pac * have no unpacked data anymore. Call upgrade_cleanup_pack_revprops after * the bump. * - * NOTIFY_FUNC and NOTIFY_BATON as well as CANCEL_FUNC and CANCEL_BATON are - * used in the usual way. Temporary allocations are done in SCRATCH_POOL. + * If FLUSH_TO_DISK is non-zero, do not return until the data has actually + * been written on the disk. CANCEL_FUNC and CANCEL_BATON areused in the + * usual way. Temporary allocations are done in SCRATCH_POOL. */ svn_error_t * svn_fs_fs__pack_revprops_shard(const char *pack_file_dir, @@ -144,6 +147,7 @@ svn_fs_fs__pack_revprops_shard(const cha int max_files_per_dir, apr_int64_t max_pack_size, int compression_level, + svn_boolean_t flush_to_disk, svn_cancel_func_t cancel_func, void *cancel_baton, apr_pool_t *scratch_pool); Modified: subversion/branches/ra-git/subversion/libsvn_fs_fs/stats.c URL: http://svn.apache.org/viewvc/subversion/branches/ra-git/subversion/libsvn_fs_fs/stats.c?rev=1764214&r1=1764213&r2=1764214&view=diff ============================================================================== --- subversion/branches/ra-git/subversion/libsvn_fs_fs/stats.c (original) +++ subversion/branches/ra-git/subversion/libsvn_fs_fs/stats.c Tue Oct 11 09:11:50 2016 @@ -681,19 +681,25 @@ get_phys_change_count(query_t *query, revision_info_t *revision_info, apr_pool_t *scratch_pool) { - /* We are going to use our own sub-pool here because the changes object - * may well be >100MB and SCRATCH_POOL may not get cleared until all other - * info has been read by read_phys_revision(). Therefore, tidy up early. - */ - apr_pool_t *subpool = svn_pool_create(scratch_pool); - apr_array_header_t *changes; + apr_pool_t *iterpool = svn_pool_create(scratch_pool); + svn_fs_fs__changes_context_t *context; - SVN_ERR(svn_fs_fs__get_changes(&changes, query->fs, - revision_info->revision, subpool)); - revision_info->change_count = changes->nelts; + /* Fetch the first block of data. */ + SVN_ERR(svn_fs_fs__create_changes_context(&context, query->fs, + revision_info->revision, + scratch_pool)); - /* Release potentially tons of memory. */ - svn_pool_destroy(subpool); + revision_info->change_count = 0; + while (!context->eol) + { + apr_array_header_t *changes; + + svn_pool_clear(iterpool); + SVN_ERR(svn_fs_fs__get_changes(&changes, context, iterpool, iterpool)); + revision_info->change_count = changes->nelts; + } + + svn_pool_destroy(iterpool); return SVN_NO_ERROR; } Modified: subversion/branches/ra-git/subversion/libsvn_fs_fs/temp_serializer.c URL: http://svn.apache.org/viewvc/subversion/branches/ra-git/subversion/libsvn_fs_fs/temp_serializer.c?rev=1764214&r1=1764213&r2=1764214&view=diff ============================================================================== --- subversion/branches/ra-git/subversion/libsvn_fs_fs/temp_serializer.c (original) +++ subversion/branches/ra-git/subversion/libsvn_fs_fs/temp_serializer.c Tue Oct 11 09:11:50 2016 @@ -788,16 +788,18 @@ svn_fs_fs__deserialize_node_revision(voi } /* Utility function that returns the directory serialized inside CONTEXT - * to DATA and DATA_LEN. */ + * to DATA and DATA_LEN. If OVERPROVISION is set, allocate some extra + * room for future in-place changes by svn_fs_fs__replace_dir_entry. */ static svn_error_t * return_serialized_dir_context(svn_temp_serializer__context_t *context, void **data, - apr_size_t *data_len) + apr_size_t *data_len, + svn_boolean_t overprovision) { svn_stringbuf_t *serialized = svn_temp_serializer__get(context); *data = serialized->data; - *data_len = serialized->blocksize; + *data_len = overprovision ? serialized->blocksize : serialized->len; ((dir_data_t *)serialized->data)->len = serialized->len; return SVN_NO_ERROR; @@ -815,7 +817,24 @@ svn_fs_fs__serialize_dir_entries(void ** * and return the serialized data */ return return_serialized_dir_context(serialize_dir(dir, pool), data, - data_len); + data_len, + FALSE); +} + +svn_error_t * +svn_fs_fs__serialize_txndir_entries(void **data, + apr_size_t *data_len, + void *in, + apr_pool_t *pool) +{ + svn_fs_fs__dir_data_t *dir = in; + + /* serialize the dir content into a new serialization context + * and return the serialized data */ + return return_serialized_dir_context(serialize_dir(dir, pool), + data, + data_len, + TRUE); } svn_error_t * @@ -916,7 +935,7 @@ svn_fs_fs__extract_dir_entry(void **out, apr_pool_t *pool) { const dir_data_t *dir_data = data; - const extract_dir_entry_baton_t *entry_baton = baton; + extract_dir_entry_baton_t *entry_baton = baton; svn_boolean_t found; /* resolve the reference to the entries array */ @@ -935,8 +954,11 @@ svn_fs_fs__extract_dir_entry(void **out, /* de-serialize that entry or return NULL, if no match has been found. * Be sure to check that the directory contents is still up-to-date. */ + entry_baton->out_of_date + = dir_data->txn_filesize != entry_baton->txn_filesize; + *out = NULL; - if (found && dir_data->txn_filesize == entry_baton->txn_filesize) + if (found && !entry_baton->out_of_date) { const svn_fs_dirent_t *source = svn_temp_deserializer__ptr(entries, (const void *const *)&entries[pos]); @@ -1097,9 +1119,7 @@ svn_fs_fs__replace_dir_entry(void **data serialize_dir_entry(context, &entries[pos], &length); /* return the updated serialized data */ - SVN_ERR (return_serialized_dir_context(context, - data, - data_len)); + SVN_ERR(return_serialized_dir_context(context, data, data_len, TRUE)); /* since the previous call may have re-allocated the buffer, the lengths * pointer may no longer point to the entry in that buffer. Therefore, @@ -1204,47 +1224,29 @@ deserialize_change(void *buffer, change_ svn_temp_deserializer__resolve(change, (void **)&change->info.copyfrom_path); } -/* Auxiliary structure representing the content of a change_t array. - This structure is much easier to (de-)serialize than an APR array. - */ -typedef struct changes_data_t -{ - /* number of entries in the array */ - int count; - - /* reference to the changes */ - change_t **changes; -} changes_data_t; - svn_error_t * svn_fs_fs__serialize_changes(void **data, apr_size_t *data_len, void *in, apr_pool_t *pool) { - apr_array_header_t *array = in; - changes_data_t changes; + svn_fs_fs__changes_list_t *changes = in; svn_temp_serializer__context_t *context; svn_stringbuf_t *serialized; int i; - /* initialize our auxiliary data structure and link it to the - * array elements */ - changes.count = array->nelts; - changes.changes = (change_t **)array->elts; - /* serialize it and all its elements */ - context = svn_temp_serializer__init(&changes, - sizeof(changes), - changes.count * 250, + context = svn_temp_serializer__init(changes, + sizeof(*changes), + changes->count * 250, pool); svn_temp_serializer__push(context, - (const void * const *)&changes.changes, - changes.count * sizeof(change_t*)); + (const void * const *)&changes->changes, + changes->count * sizeof(*changes->changes)); - for (i = 0; i < changes.count; ++i) - serialize_change(context, &changes.changes[i]); + for (i = 0; i < changes->count; ++i) + serialize_change(context, &changes->changes[i]); svn_temp_serializer__pop(context); @@ -1264,8 +1266,7 @@ svn_fs_fs__deserialize_changes(void **ou apr_pool_t *pool) { int i; - changes_data_t *changes = (changes_data_t *)data; - apr_array_header_t *array = apr_array_make(pool, 0, sizeof(change_t *)); + svn_fs_fs__changes_list_t *changes = (svn_fs_fs__changes_list_t *)data; /* de-serialize our auxiliary data structure */ svn_temp_deserializer__resolve(changes, (void**)&changes->changes); @@ -1275,14 +1276,8 @@ svn_fs_fs__deserialize_changes(void **ou deserialize_change(changes->changes, (change_t **)&changes->changes[i]); - /* Use the changes buffer as the array's data buffer - * (DATA remains valid for at least as long as POOL). */ - array->elts = (char *)changes->changes; - array->nelts = changes->count; - array->nalloc = changes->count; - /* done */ - *out = array; + *out = changes; return SVN_NO_ERROR; } Modified: subversion/branches/ra-git/subversion/libsvn_fs_fs/temp_serializer.h URL: http://svn.apache.org/viewvc/subversion/branches/ra-git/subversion/libsvn_fs_fs/temp_serializer.h?rev=1764214&r1=1764213&r2=1764214&view=diff ============================================================================== --- subversion/branches/ra-git/subversion/libsvn_fs_fs/temp_serializer.h (original) +++ subversion/branches/ra-git/subversion/libsvn_fs_fs/temp_serializer.h Tue Oct 11 09:11:50 2016 @@ -221,6 +221,16 @@ svn_fs_fs__serialize_dir_entries(void ** apr_pool_t *pool); /** + * Same as svn_fs_fs__serialize_dir_entries but allocates extra room for + * in-place modification. + */ +svn_error_t * +svn_fs_fs__serialize_txndir_entries(void **data, + apr_size_t *data_len, + void *in, + apr_pool_t *pool); + +/** * Implements #svn_cache__deserialize_func_t for a #svn_fs_fs__dir_data_t */ svn_error_t * @@ -264,6 +274,12 @@ typedef struct extract_dir_entry_baton_t /** Current length of the in-txn in-disk representation of the directory. * SVN_INVALID_FILESIZE if unknown. */ svn_filesize_t txn_filesize; + + /** Will be set by the callback. If FALSE, the cached data is out of date. + * We need this indicator because the svn_cache__t interface will always + * report the lookup as a success (FOUND==TRUE) if the generic lookup was + * successful -- regardless of what the entry extraction callback does. */ + svn_boolean_t out_of_date; } extract_dir_entry_baton_t; @@ -343,9 +359,34 @@ svn_fs_fs__deserialize_rep_header(void * apr_size_t data_len, apr_pool_t *pool); +/*** Block of changes in a changed paths list. */ +typedef struct svn_fs_fs__changes_list_t +{ + /* Offset of the first element in CHANGES within the changed paths list + on disk. */ + apr_off_t start_offset; + + /* Offset of the first element behind CHANGES within the changed paths + list on disk. */ + apr_off_t end_offset; + + /* End of list reached? This may have false negatives in case the number + of elements in the list is a multiple of our block / range size. */ + svn_boolean_t eol; + + /* Array of #svn_fs_x__change_t * representing a consecutive sub-range of + elements in a changed paths list. */ + + /* number of entries in the array */ + int count; + + /* reference to the changes */ + change_t **changes; + +} svn_fs_fs__changes_list_t; + /** - * Implements #svn_cache__serialize_func_t for an #apr_array_header_t of - * #change_t *. + * Implements #svn_cache__serialize_func_t for a #svn_fs_fs__changes_list_t. */ svn_error_t * svn_fs_fs__serialize_changes(void **data, @@ -354,8 +395,7 @@ svn_fs_fs__serialize_changes(void **data apr_pool_t *pool); /** - * Implements #svn_cache__deserialize_func_t for an #apr_array_header_t of - * #change_t *. + * Implements #svn_cache__deserialize_func_t for a #svn_fs_fs__changes_list_t. */ svn_error_t * svn_fs_fs__deserialize_changes(void **out, Modified: subversion/branches/ra-git/subversion/libsvn_fs_fs/transaction.c URL: http://svn.apache.org/viewvc/subversion/branches/ra-git/subversion/libsvn_fs_fs/transaction.c?rev=1764214&r1=1764213&r2=1764214&view=diff ============================================================================== --- subversion/branches/ra-git/subversion/libsvn_fs_fs/transaction.c (original) +++ subversion/branches/ra-git/subversion/libsvn_fs_fs/transaction.c Tue Oct 11 09:11:50 2016 @@ -442,7 +442,7 @@ get_writable_proto_rev(apr_file_t **file /* Now open the prototype revision file and seek to the end. */ err = svn_io_file_open(file, svn_fs_fs__path_txn_proto_rev(fs, txn_id, pool), - APR_READ | APR_WRITE | APR_BUFFERED, APR_OS_DEFAULT, + APR_WRITE | APR_BUFFERED, APR_OS_DEFAULT, pool); /* You might expect that we could dispense with the following seek @@ -932,20 +932,36 @@ svn_fs_fs__paths_changed(apr_hash_t **ch svn_revnum_t rev, apr_pool_t *pool) { - apr_hash_t *changed_paths; - apr_array_header_t *changes; - int i; + apr_hash_t *changed_paths = svn_hash__make(pool); + svn_fs_fs__changes_context_t *context; - SVN_ERR(svn_fs_fs__get_changes(&changes, fs, rev, pool)); + apr_pool_t *iterpool = svn_pool_create(pool); - changed_paths = svn_hash__make(pool); - for (i = 0; i < changes->nelts; ++i) + /* Fetch all data block-by-block. */ + SVN_ERR(svn_fs_fs__create_changes_context(&context, fs, rev, pool)); + while (!context->eol) { - change_t *change = APR_ARRAY_IDX(changes, i, change_t *); - apr_hash_set(changed_paths, change->path.data, change->path.len, - &change->info); + apr_array_header_t *changes; + int i; + + svn_pool_clear(iterpool); + + /* Be sure to allocate the changes in the result POOL, even though + we don't need the array itself afterwards. Copying the entries + from a temp pool to the result POOL would be expensive and saves + use less then 10% memory. */ + SVN_ERR(svn_fs_fs__get_changes(&changes, context, pool, iterpool)); + + for (i = 0; i < changes->nelts; ++i) + { + change_t *change = APR_ARRAY_IDX(changes, i, change_t *); + apr_hash_set(changed_paths, change->path.data, change->path.len, + &change->info); + } } + svn_pool_destroy(iterpool); + *changed_paths_p = changed_paths; return SVN_NO_ERROR; @@ -997,6 +1013,7 @@ static svn_error_t * get_and_increment_txn_key_body(void *baton, apr_pool_t *pool) { struct get_and_increment_txn_key_baton *cb = baton; + fs_fs_data_t *ffd = cb->fs->fsap_data; const char *txn_current_filename = svn_fs_fs__path_txn_current(cb->fs, pool); char new_id_str[SVN_INT64_BUFFER_SIZE + 1]; /* add space for a newline */ @@ -1017,7 +1034,7 @@ get_and_increment_txn_key_body(void *bat SVN_ERR(svn_io_write_atomic2(txn_current_filename, new_id_str, line_length + 1, txn_current_filename /* copy_perms path */, - TRUE, pool)); + ffd->flush_to_disk, pool)); return SVN_NO_ERROR; } @@ -1714,9 +1731,11 @@ svn_fs_fs__add_change(svn_fs_t *fs, return svn_io_file_close(file, pool); } -/* If the transaction TXN_ID in FS uses logical addressing, store the - * (ITEM_INDEX, OFFSET) pair in the txn's log-to-phys proto index file. +/* Store the (ITEM_INDEX, OFFSET) pair in the txn's log-to-phys proto + * index file. * Use POOL for allocations. + * This function assumes that transaction TXN_ID in FS uses logical + * addressing. */ static svn_error_t * store_l2p_index_entry(svn_fs_t *fs, @@ -1725,37 +1744,40 @@ store_l2p_index_entry(svn_fs_t *fs, apr_uint64_t item_index, apr_pool_t *pool) { - if (svn_fs_fs__use_log_addressing(fs)) - { - const char *path = svn_fs_fs__path_l2p_proto_index(fs, txn_id, pool); - apr_file_t *file; - SVN_ERR(svn_fs_fs__l2p_proto_index_open(&file, path, pool)); - SVN_ERR(svn_fs_fs__l2p_proto_index_add_entry(file, offset, - item_index, pool)); - SVN_ERR(svn_io_file_close(file, pool)); - } + const char *path; + apr_file_t *file; + + SVN_ERR_ASSERT(svn_fs_fs__use_log_addressing(fs)); + + path = svn_fs_fs__path_l2p_proto_index(fs, txn_id, pool); + SVN_ERR(svn_fs_fs__l2p_proto_index_open(&file, path, pool)); + SVN_ERR(svn_fs_fs__l2p_proto_index_add_entry(file, offset, + item_index, pool)); + SVN_ERR(svn_io_file_close(file, pool)); return SVN_NO_ERROR; } -/* If the transaction TXN_ID in FS uses logical addressing, store ENTRY - * in the phys-to-log proto index file of transaction TXN_ID. +/* Store ENTRY in the phys-to-log proto index file of transaction TXN_ID. * Use POOL for allocations. + * This function assumes that transaction TXN_ID in FS uses logical + * addressing. */ static svn_error_t * store_p2l_index_entry(svn_fs_t *fs, const svn_fs_fs__id_part_t *txn_id, - svn_fs_fs__p2l_entry_t *entry, + const svn_fs_fs__p2l_entry_t *entry, apr_pool_t *pool) { - if (svn_fs_fs__use_log_addressing(fs)) - { - const char *path = svn_fs_fs__path_p2l_proto_index(fs, txn_id, pool); - apr_file_t *file; - SVN_ERR(svn_fs_fs__p2l_proto_index_open(&file, path, pool)); - SVN_ERR(svn_fs_fs__p2l_proto_index_add_entry(file, entry, pool)); - SVN_ERR(svn_io_file_close(file, pool)); - } + const char *path; + apr_file_t *file; + + SVN_ERR_ASSERT(svn_fs_fs__use_log_addressing(fs)); + + path = svn_fs_fs__path_p2l_proto_index(fs, txn_id, pool); + SVN_ERR(svn_fs_fs__p2l_proto_index_open(&file, path, pool)); + SVN_ERR(svn_fs_fs__p2l_proto_index_add_entry(file, entry, pool)); + SVN_ERR(svn_io_file_close(file, pool)); return SVN_NO_ERROR; } @@ -2174,10 +2196,10 @@ rep_write_get_baton(struct rep_write_bat b->scratch_pool)); b->file = file; - b->rep_stream = fnv1a_wrap_stream(&b->fnv1a_checksum_ctx, - svn_stream_from_aprfile2(file, TRUE, - b->scratch_pool), - b->scratch_pool); + b->rep_stream = svn_stream_from_aprfile2(file, TRUE, b->scratch_pool); + if (svn_fs_fs__use_log_addressing(fs)) + b->rep_stream = fnv1a_wrap_stream(&b->fnv1a_checksum_ctx, b->rep_stream, + b->scratch_pool); SVN_ERR(svn_io_file_get_offset(&b->rep_offset, file, b->scratch_pool)); @@ -2454,7 +2476,7 @@ rep_write_contents_close(void *baton) /* Write out the new node-rev information. */ SVN_ERR(svn_fs_fs__put_node_revision(b->fs, b->noderev->id, b->noderev, FALSE, b->scratch_pool)); - if (!old_rep) + if (!old_rep && svn_fs_fs__use_log_addressing(b->fs)) { svn_fs_fs__p2l_entry_t entry; @@ -2468,12 +2490,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); @@ -2676,10 +2703,12 @@ write_container_rep(representation_t *re whb = apr_pcalloc(scratch_pool, sizeof(*whb)); - whb->stream = fnv1a_wrap_stream(&fnv1a_checksum_ctx, - svn_stream_from_aprfile2(file, TRUE, - scratch_pool), - scratch_pool); + whb->stream = svn_stream_from_aprfile2(file, TRUE, scratch_pool); + if (svn_fs_fs__use_log_addressing(fs)) + whb->stream = fnv1a_wrap_stream(&fnv1a_checksum_ctx, whb->stream, + scratch_pool); + else + fnv1a_checksum_ctx = NULL; whb->size = 0; whb->md5_ctx = svn_checksum_ctx_create(svn_checksum_md5, scratch_pool); if (item_type != SVN_FS_FS__ITEM_TYPE_DIR_REP) @@ -2708,16 +2737,18 @@ write_container_rep(representation_t *re /* Use the old rep for this content. */ memcpy(rep, old_rep, sizeof (*rep)); + return SVN_NO_ERROR; } - else - { - svn_fs_fs__p2l_entry_t entry; - /* Write out our cosmetic end marker. */ - SVN_ERR(svn_stream_puts(whb->stream, "ENDREP\n")); + /* Write out our cosmetic end marker. */ + SVN_ERR(svn_stream_puts(whb->stream, "ENDREP\n")); - SVN_ERR(allocate_item_index(&rep->item_index, fs, &rep->txn_id, - offset, scratch_pool)); + SVN_ERR(allocate_item_index(&rep->item_index, fs, &rep->txn_id, + offset, scratch_pool)); + + if (svn_fs_fs__use_log_addressing(fs)) + { + svn_fs_fs__p2l_entry_t entry; entry.offset = offset; SVN_ERR(svn_io_file_get_offset(&offset, file, scratch_pool)); @@ -2730,11 +2761,11 @@ write_container_rep(representation_t *re scratch_pool)); SVN_ERR(store_p2l_index_entry(fs, &rep->txn_id, &entry, scratch_pool)); - - /* update the representation */ - rep->size = whb->size; } + /* update the representation */ + rep->size = whb->size; + return SVN_NO_ERROR; } @@ -2802,10 +2833,12 @@ write_container_delta_rep(representation header.type = svn_fs_fs__rep_self_delta; } - file_stream = fnv1a_wrap_stream(&fnv1a_checksum_ctx, - svn_stream_from_aprfile2(file, TRUE, - scratch_pool), - scratch_pool); + file_stream = svn_stream_from_aprfile2(file, TRUE, scratch_pool); + if (svn_fs_fs__use_log_addressing(fs)) + file_stream = fnv1a_wrap_stream(&fnv1a_checksum_ctx, file_stream, + scratch_pool); + else + fnv1a_checksum_ctx = NULL; SVN_ERR(svn_fs_fs__write_rep_header(&header, file_stream, scratch_pool)); SVN_ERR(svn_io_file_get_offset(&delta_start, file, scratch_pool)); @@ -2848,17 +2881,19 @@ write_container_delta_rep(representation /* Use the old rep for this content. */ memcpy(rep, old_rep, sizeof (*rep)); + return SVN_NO_ERROR; } - else - { - svn_fs_fs__p2l_entry_t entry; - /* Write out our cosmetic end marker. */ - SVN_ERR(svn_io_file_get_offset(&rep_end, file, scratch_pool)); - SVN_ERR(svn_stream_puts(file_stream, "ENDREP\n")); + /* Write out our cosmetic end marker. */ + SVN_ERR(svn_io_file_get_offset(&rep_end, file, scratch_pool)); + SVN_ERR(svn_stream_puts(file_stream, "ENDREP\n")); + + SVN_ERR(allocate_item_index(&rep->item_index, fs, &rep->txn_id, + offset, scratch_pool)); - SVN_ERR(allocate_item_index(&rep->item_index, fs, &rep->txn_id, - offset, scratch_pool)); + if (svn_fs_fs__use_log_addressing(fs)) + { + svn_fs_fs__p2l_entry_t entry; entry.offset = offset; SVN_ERR(svn_io_file_get_offset(&offset, file, scratch_pool)); @@ -2871,11 +2906,11 @@ write_container_delta_rep(representation scratch_pool)); SVN_ERR(store_p2l_index_entry(fs, &rep->txn_id, &entry, scratch_pool)); - - /* update the representation */ - rep->size = rep_end - delta_start; } + /* update the representation */ + rep->size = rep_end - delta_start; + return SVN_NO_ERROR; } @@ -2922,9 +2957,8 @@ validate_root_noderev(svn_fs_t *fs, to a repository that has triggered the bug somewhere in its root noderev's history. */ - if (root_noderev->predecessor_count != -1 - && (root_noderev->predecessor_count - head_predecessor_count) - != (rev - head_revnum)) + if ( (root_noderev->predecessor_count - head_predecessor_count) + != (rev - head_revnum)) { return svn_error_createf(SVN_ERR_FS_CORRUPT, NULL, _("predecessor count for " @@ -3207,9 +3241,12 @@ write_final_rev(const svn_fs_id_t **new_ if (at_root) SVN_ERR(validate_root_noderev(fs, noderev, rev, pool)); - file_stream = fnv1a_wrap_stream(&fnv1a_checksum_ctx, - svn_stream_from_aprfile2(file, TRUE, pool), - pool); + file_stream = svn_stream_from_aprfile2(file, TRUE, pool); + if (svn_fs_fs__use_log_addressing(fs)) + file_stream = fnv1a_wrap_stream(&fnv1a_checksum_ctx, file_stream, pool); + else + fnv1a_checksum_ctx = NULL; + SVN_ERR(svn_fs_fs__write_noderev(file_stream, noderev, ffd->format, svn_fs_fs__fs_supports_mergeinfo(fs), pool)); @@ -3256,10 +3293,13 @@ write_final_changed_path_info(apr_off_t SVN_ERR(svn_io_file_get_offset(&offset, file, pool)); - /* write to target file & calculate checksum */ - stream = fnv1a_wrap_stream(&fnv1a_checksum_ctx, - svn_stream_from_aprfile2(file, TRUE, pool), - pool); + /* write to target file & calculate checksum if needed */ + stream = svn_stream_from_aprfile2(file, TRUE, pool); + if (svn_fs_fs__use_log_addressing(fs)) + stream = fnv1a_wrap_stream(&fnv1a_checksum_ctx, stream, pool); + else + fnv1a_checksum_ctx = NULL; + SVN_ERR(svn_fs_fs__write_changes(stream, fs, changed_paths, TRUE, pool)); *offset_p = offset; @@ -3441,6 +3481,7 @@ static svn_error_t * write_final_revprop(const char *path, const char *perms_reference, svn_fs_txn_t *txn, + svn_boolean_t flush_to_disk, apr_pool_t *pool) { apr_hash_t *txnprops; @@ -3480,7 +3521,8 @@ write_final_revprop(const char *path, SVN_ERR(svn_hash_write2(txnprops, stream, SVN_HASH_TERMINATOR, pool)); SVN_ERR(svn_stream_close(stream)); - SVN_ERR(svn_io_file_flush_to_disk(revprop_file, pool)); + if (flush_to_disk) + SVN_ERR(svn_io_file_flush_to_disk(revprop_file, pool)); SVN_ERR(svn_io_file_close(revprop_file, pool)); SVN_ERR(svn_io_copy_perms(perms_reference, path, pool)); @@ -3677,7 +3719,8 @@ commit_body(void *baton, apr_pool_t *poo NULL, pool)); } - SVN_ERR(svn_io_file_flush_to_disk(proto_file, pool)); + if (ffd->flush_to_disk) + SVN_ERR(svn_io_file_flush_to_disk(proto_file, pool)); SVN_ERR(svn_io_file_close(proto_file, pool)); /* We don't unlock the prototype revision file immediately to avoid a @@ -3730,7 +3773,8 @@ commit_body(void *baton, apr_pool_t *poo rev_filename = svn_fs_fs__path_rev(cb->fs, new_rev, pool); proto_filename = svn_fs_fs__path_txn_proto_rev(cb->fs, txn_id, pool); SVN_ERR(svn_fs_fs__move_into_place(proto_filename, rev_filename, - old_rev_filename, pool)); + old_rev_filename, ffd->flush_to_disk, + pool)); /* Now that we've moved the prototype revision file out of the way, we can unlock it (since further attempts to write to the file @@ -3742,7 +3786,7 @@ commit_body(void *baton, apr_pool_t *poo SVN_ERR_ASSERT(! svn_fs_fs__is_packed_revprop(cb->fs, new_rev)); revprop_filename = svn_fs_fs__path_revprops(cb->fs, new_rev, pool); SVN_ERR(write_final_revprop(revprop_filename, old_rev_filename, - cb->txn, pool)); + cb->txn, ffd->flush_to_disk, pool)); /* Update the 'current' file. */ SVN_ERR(verify_as_revision_before_current_plus_plus(cb->fs, new_rev, pool)); @@ -3820,6 +3864,8 @@ svn_fs_fs__commit(svn_revnum_t *new_rev_ 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. @@ -3830,9 +3876,21 @@ svn_fs_fs__commit(svn_revnum_t *new_rev_ /* ### 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_ERR_SQLITE_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; Modified: subversion/branches/ra-git/subversion/libsvn_fs_fs/tree.c URL: http://svn.apache.org/viewvc/subversion/branches/ra-git/subversion/libsvn_fs_fs/tree.c?rev=1764214&r1=1764213&r2=1764214&view=diff ============================================================================== --- subversion/branches/ra-git/subversion/libsvn_fs_fs/tree.c (original) +++ subversion/branches/ra-git/subversion/libsvn_fs_fs/tree.c Tue Oct 11 09:11:50 2016 @@ -1474,29 +1474,6 @@ fs_node_created_path(const char **create return SVN_NO_ERROR; } - -/* Set *KIND_P to the type of node located at PATH under ROOT. - Perform temporary allocations in POOL. */ -static svn_error_t * -node_kind(svn_node_kind_t *kind_p, - svn_fs_root_t *root, - const char *path, - apr_pool_t *pool) -{ - const svn_fs_id_t *node_id; - dag_node_t *node; - - /* Get the node id. */ - SVN_ERR(svn_fs_fs__node_id(&node_id, root, path, pool)); - - /* Use the node id to get the real kind. */ - SVN_ERR(svn_fs_fs__dag_get_node(&node, root->fs, node_id, pool)); - *kind_p = svn_fs_fs__dag_node_kind(node); - - return SVN_NO_ERROR; -} - - /* Set *KIND_P to the type of node present at PATH under ROOT. If PATH does not exist under ROOT, set *KIND_P to svn_node_none. Use POOL for temporary allocation. */ @@ -1506,17 +1483,23 @@ svn_fs_fs__check_path(svn_node_kind_t *k const char *path, apr_pool_t *pool) { - svn_error_t *err = node_kind(kind_p, root, path, pool); + dag_node_t *node; + svn_error_t *err; + + err = get_dag(&node, root, path, pool); if (err && ((err->apr_err == SVN_ERR_FS_NOT_FOUND) || (err->apr_err == SVN_ERR_FS_NOT_DIRECTORY))) { svn_error_clear(err); - err = SVN_NO_ERROR; *kind_p = svn_node_none; + return SVN_NO_ERROR; } + else if (err) + return svn_error_trace(err); - return svn_error_trace(err); + *kind_p = svn_fs_fs__dag_node_kind(node); + return SVN_NO_ERROR; } /* Set *VALUE_P to the value of the property named PROPNAME of PATH in @@ -2331,7 +2314,7 @@ svn_fs_fs__commit_txn(const char **confl 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; @@ -3298,6 +3281,187 @@ fs_paths_changed(apr_hash_t **changed_pa } +/* Copy the contents of ENTRY at PATH with LEN to OUTPUT. */ +static void +convert_path_change(svn_fs_path_change3_t *output, + const char *path, + size_t path_len, + svn_fs_path_change2_t *entry) +{ + output->path.data = path; + output->path.len = path_len; + output->change_kind = entry->change_kind; + output->node_kind = entry->node_kind; + output->text_mod = entry->text_mod; + output->prop_mod = entry->prop_mod; + output->mergeinfo_mod = entry->mergeinfo_mod; + output->copyfrom_known = entry->copyfrom_known; + output->copyfrom_rev = entry->copyfrom_rev; + output->copyfrom_path = entry->copyfrom_path; +} + +/* FSAP data structure for in-txn changes list iterators. */ +typedef struct fs_txn_changes_iterator_data_t +{ + /* Current iterator position. */ + apr_hash_index_t *hi; + + /* For efficiency such that we don't need to dynamically allocate + yet another copy of that data. */ + svn_fs_path_change3_t change; +} fs_txn_changes_iterator_data_t; + +/* Implement changes_iterator_vtable_t.get for in-txn change lists. */ +static svn_error_t * +fs_txn_changes_iterator_get(svn_fs_path_change3_t **change, + svn_fs_path_change_iterator_t *iterator) +{ + fs_txn_changes_iterator_data_t *data = iterator->fsap_data; + + if (data->hi) + { + const void *key; + apr_ssize_t length; + void *value; + apr_hash_this(data->hi, &key, &length, &value); + + convert_path_change(&data->change, key, length, value); + + *change = &data->change; + data->hi = apr_hash_next(data->hi); + } + else + { + *change = NULL; + } + + return SVN_NO_ERROR; +} + +static changes_iterator_vtable_t txn_changes_iterator_vtable = +{ + fs_txn_changes_iterator_get +}; + +/* FSAP data structure for in-revision changes list iterators. */ +typedef struct fs_revision_changes_iterator_data_t +{ + /* Context that tells the lower layers from where to fetch the next + block of changes. */ + svn_fs_fs__changes_context_t *context; + + /* Changes to send. */ + apr_array_header_t *changes; + + /* Current indexes within CHANGES. */ + int idx; + + /* For efficiency such that we don't need to dynamically allocate + yet another copy of that data. */ + svn_fs_path_change3_t change; + + /* A cleanable scratch pool in case we need one. + No further sub-pool creation necessary. */ + apr_pool_t *scratch_pool; +} fs_revision_changes_iterator_data_t; + +/* Implement changes_iterator_vtable_t.get for in-revision change lists. */ +static svn_error_t * +fs_revision_changes_iterator_get(svn_fs_path_change3_t **change, + svn_fs_path_change_iterator_t *iterator) +{ + fs_revision_changes_iterator_data_t *data = iterator->fsap_data; + + /* If we exhausted our block of changes and did not reach the end of the + list, yet, fetch the next block. Note that that block may be empty. */ + if ((data->idx >= data->changes->nelts) && !data->context->eol) + { + apr_pool_t *changes_pool = data->changes->pool; + + /* Drop old changes block, read new block. */ + svn_pool_clear(changes_pool); + SVN_ERR(svn_fs_fs__get_changes(&data->changes, data->context, + changes_pool, data->scratch_pool)); + data->idx = 0; + + /* Immediately release any temporary data. */ + svn_pool_clear(data->scratch_pool); + } + + if (data->idx < data->changes->nelts) + { + change_t *entry = APR_ARRAY_IDX(data->changes, data->idx, change_t *); + convert_path_change(&data->change, entry->path.data, entry->path.len, + &entry->info); + + *change = &data->change; + ++data->idx; + } + else + { + *change = NULL; + } + + return SVN_NO_ERROR; +} + +static changes_iterator_vtable_t rev_changes_iterator_vtable = +{ + fs_revision_changes_iterator_get +}; + +static svn_error_t * +fs_report_changes(svn_fs_path_change_iterator_t **iterator, + svn_fs_root_t *root, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool) +{ + svn_fs_path_change_iterator_t *result = apr_pcalloc(result_pool, + sizeof(*result)); + if (root->is_txn_root) + { + fs_txn_changes_iterator_data_t *data = apr_pcalloc(result_pool, + sizeof(*data)); + apr_hash_t *changed_paths; + SVN_ERR(svn_fs_fs__txn_changes_fetch(&changed_paths, root->fs, + root_txn_id(root), result_pool)); + + data->hi = apr_hash_first(result_pool, changed_paths); + result->fsap_data = data; + result->vtable = &txn_changes_iterator_vtable; + } + else + { + /* The block of changes that we retrieve need to live in a separately + cleanable pool. */ + apr_pool_t *changes_pool = svn_pool_create(result_pool); + + /* Our iteration context info. */ + fs_revision_changes_iterator_data_t *data = apr_pcalloc(result_pool, + sizeof(*data)); + + /* This pool must remain valid as long as ITERATOR lives but will + be used only for temporary allocations and will be cleaned up + frequently. So, this must be a sub-pool of RESULT_POOL. */ + data->scratch_pool = svn_pool_create(result_pool); + + /* Fetch the first block of data. */ + SVN_ERR(svn_fs_fs__create_changes_context(&data->context, + root->fs, root->rev, + result_pool)); + SVN_ERR(svn_fs_fs__get_changes(&data->changes, data->context, + changes_pool, scratch_pool)); + + /* Return the fully initialized object. */ + result->fsap_data = data; + result->vtable = &rev_changes_iterator_vtable; + } + + *iterator = result; + + return SVN_NO_ERROR; +} + /* Our coolio opaque history object. */ typedef struct fs_history_data_t @@ -4342,6 +4506,7 @@ fs_get_mergeinfo(svn_mergeinfo_catalog_t /* The vtable associated with root objects. */ static root_vtable_t root_vtable = { fs_paths_changed, + fs_report_changes, svn_fs_fs__check_path, fs_node_history, svn_fs_fs__node_id, Modified: subversion/branches/ra-git/subversion/libsvn_fs_fs/util.c URL: http://svn.apache.org/viewvc/subversion/branches/ra-git/subversion/libsvn_fs_fs/util.c?rev=1764214&r1=1764213&r2=1764214&view=diff ============================================================================== --- subversion/branches/ra-git/subversion/libsvn_fs_fs/util.c (original) +++ subversion/branches/ra-git/subversion/libsvn_fs_fs/util.c Tue Oct 11 09:11:50 2016 @@ -428,6 +428,7 @@ svn_fs_fs__write_min_unpacked_rev(svn_fs svn_revnum_t revnum, apr_pool_t *scratch_pool) { + fs_fs_data_t *ffd = fs->fsap_data; const char *final_path; char buf[SVN_INT64_BUFFER_SIZE]; apr_size_t len = svn__i64toa(buf, revnum); @@ -436,8 +437,8 @@ svn_fs_fs__write_min_unpacked_rev(svn_fs final_path = svn_fs_fs__path_min_unpacked_rev(fs, scratch_pool); SVN_ERR(svn_io_write_atomic2(final_path, buf, len + 1, - final_path /* copy_perms */, TRUE, - scratch_pool)); + final_path /* copy_perms */, + ffd->flush_to_disk, scratch_pool)); return SVN_NO_ERROR; } @@ -519,7 +520,8 @@ svn_fs_fs__write_current(svn_fs_t *fs, name = svn_fs_fs__path_current(fs, pool); SVN_ERR(svn_io_write_atomic2(name, buf, strlen(buf), - name /* copy_perms_path */, TRUE, pool)); + name /* copy_perms_path */, + ffd->flush_to_disk, pool)); return SVN_NO_ERROR; } @@ -619,6 +621,7 @@ svn_error_t * svn_fs_fs__move_into_place(const char *old_filename, const char *new_filename, const char *perms_reference, + svn_boolean_t flush_to_disk, apr_pool_t *pool) { svn_error_t *err; @@ -628,7 +631,7 @@ svn_fs_fs__move_into_place(const char *o SVN_ERR(svn_io_copy_perms(perms_reference, old_filename, pool)); /* Move the file into place. */ - err = svn_io_file_rename2(old_filename, new_filename, TRUE, pool); + err = svn_io_file_rename2(old_filename, new_filename, flush_to_disk, pool); if (err && APR_STATUS_IS_EXDEV(err->apr_err)) { /* Can't rename across devices; fall back to copying. */ @@ -639,25 +642,29 @@ svn_fs_fs__move_into_place(const char *o ### The code below is duplicates svn_io_file_rename2(), because currently we don't have the svn_io_copy_file2() function with a flush_to_disk argument. */ - SVN_ERR(svn_io_file_open(&file, new_filename, APR_WRITE, - APR_OS_DEFAULT, pool)); - SVN_ERR(svn_io_file_flush_to_disk(file, pool)); - SVN_ERR(svn_io_file_close(file, pool)); + if (flush_to_disk) + { + SVN_ERR(svn_io_file_open(&file, new_filename, APR_WRITE, + APR_OS_DEFAULT, pool)); + SVN_ERR(svn_io_file_flush_to_disk(file, pool)); + SVN_ERR(svn_io_file_close(file, pool)); + } #ifdef SVN_ON_POSIX - { - /* On POSIX, the file name is stored in the file's directory entry. - Hence, we need to fsync() that directory as well. - On other operating systems, we'd only be asking for trouble - by trying to open and fsync a directory. */ - const char *dirname; - - dirname = svn_dirent_dirname(new_filename, pool); - SVN_ERR(svn_io_file_open(&file, dirname, APR_READ, APR_OS_DEFAULT, - pool)); - SVN_ERR(svn_io_file_flush_to_disk(file, pool)); - SVN_ERR(svn_io_file_close(file, pool)); - } + if (flush_to_disk) + { + /* On POSIX, the file name is stored in the file's directory entry. + Hence, we need to fsync() that directory as well. + On other operating systems, we'd only be asking for trouble + by trying to open and fsync a directory. */ + const char *dirname; + + dirname = svn_dirent_dirname(new_filename, pool); + SVN_ERR(svn_io_file_open(&file, dirname, APR_READ, APR_OS_DEFAULT, + pool)); + SVN_ERR(svn_io_file_flush_to_disk(file, pool)); + SVN_ERR(svn_io_file_close(file, pool)); + } #endif } else if (err) Modified: subversion/branches/ra-git/subversion/libsvn_fs_fs/util.h URL: http://svn.apache.org/viewvc/subversion/branches/ra-git/subversion/libsvn_fs_fs/util.h?rev=1764214&r1=1764213&r2=1764214&view=diff ============================================================================== --- subversion/branches/ra-git/subversion/libsvn_fs_fs/util.h (original) +++ subversion/branches/ra-git/subversion/libsvn_fs_fs/util.h Tue Oct 11 09:11:50 2016 @@ -388,11 +388,12 @@ svn_fs_fs__read_number_from_stream(apr_i PERMS_REFERENCE. Temporary allocations are from POOL. This function almost duplicates svn_io_file_move(), but it tries to - guarantee a flush. */ + guarantee a flush if FLUSH_TO_DISK is non-zero. */ svn_error_t * svn_fs_fs__move_into_place(const char *old_filename, const char *new_filename, const char *perms_reference, + svn_boolean_t flush_to_disk, apr_pool_t *pool); /* Return TRUE, iff FS uses logical addressing. */ Modified: subversion/branches/ra-git/subversion/libsvn_fs_util/fs-util.c URL: http://svn.apache.org/viewvc/subversion/branches/ra-git/subversion/libsvn_fs_util/fs-util.c?rev=1764214&r1=1764213&r2=1764214&view=diff ============================================================================== --- subversion/branches/ra-git/subversion/libsvn_fs_util/fs-util.c (original) +++ subversion/branches/ra-git/subversion/libsvn_fs_util/fs-util.c Tue Oct 11 09:11:50 2016 @@ -212,6 +212,21 @@ svn_fs__path_change_create_internal(cons return change; } +svn_fs_path_change3_t * +svn_fs__path_change_create_internal2(svn_fs_path_change_kind_t change_kind, + apr_pool_t *result_pool) +{ + svn_fs_path_change3_t *change; + + change = apr_pcalloc(result_pool, sizeof(*change)); + change->path.data = ""; + change->change_kind = change_kind; + change->mergeinfo_mod = svn_tristate_unknown; + change->copyfrom_rev = SVN_INVALID_REVNUM; + + return change; +} + svn_error_t * svn_fs__append_to_merged_froms(svn_mergeinfo_t *output, svn_mergeinfo_t input, Propchange: subversion/branches/ra-git/subversion/libsvn_fs_x/ ------------------------------------------------------------------------------ --- svn:mergeinfo (original) +++ svn:mergeinfo Tue Oct 11 09:11:50 2016 @@ -94,5 +94,5 @@ /subversion/branches/verify-at-commit/subversion/libsvn_fs_x:1462039-1462408 /subversion/branches/verify-keep-going/subversion/libsvn_fs_x:1439280-1492639,1546002-1546110 /subversion/branches/wc-collate-path/subversion/libsvn_fs_x:1402685-1480384 -/subversion/trunk/subversion/libsvn_fs_fs:1415133-1596500,1596567,1597414,1597989,1598273,1599140,1600872,1601633,1603485-1603487,1603499,1603605,1604128,1604188,1604413-1604414,1604416-1604417,1604421,1604442,1604700,1604717,1604720,1604726,1604755,1604794,1604802,1604824,1604836,1604844,1604902-1604903,1604911,1604925,1604933,1604947,1605059-1605060,1605064-1605065,1605068,1605071-1605073,1605075,1605123,1605188-1605189,1605191,1605197,1605444,1605633,1606132,1606142,1606144,1606514,1606526,1606528,1606551,1606554,1606564,1606598-1606599,1606656,1606658,1606662,1606744,1606840,1607085,1607572,1612407,1612810,1613339,1613872,1614611,1615348,1615351-1615352,1615356,1616338-1616339,1616613,1617586,1617688,1618138,1618151,1618153,1618226,1618641,1618653,1618662,1619068,1619358,1619413,1619769,1619774,1620602,1620909,1620912,1620928,1620930,1621275,1621635,1622931,1622937,1622942,1622946,1622959-1622960,1622963,1622987,1623007,1623368,1623373,1623377,1623379,1623381,1623398,1623402,162 4011,1624265,1624512,1626246,1626871,1626873,1626886,1627497-1627498,1627502,1627947-1627949,1627966,1628083,1628093,1628158-1628159,1628161,1628392-1628393,1628415,1628427,1628676,1628738,1628762,1628764,1629854-1629855,1629857,1629865,1629873,1629875,1629879,1630067,1630070,1631049-1631051,1631075,1631115,1631171,1631180,1631185-1631186,1631196-1631197,1631239-1631240,1631548,1631550,1631563,1631567,1631588,1631598,1632646,1632776,1632849,1632851-1632853,1632856-1632857,1632868,1632908,1632926,1633232,1633617-1633618,1634872,1634875,1634879-1634880,1634920,1636478,1636483,1636629,1636644,1637184,1637186,1637330,1637358,1637363,1637393,1639319,1639322,1639335,1639348,1639352,1639355,1639358,1639414,1639419,1639426,1639430,1639436,1639440,1639549,1640061-1640062,1640197,1640915,1640966,1641013,1643139,1643233,1645567,1646021,1646712,1646716,1647537,1647540-1647541,1647820,1647905,1648230,1648238,1648241-1648243,1648253,1648272,1648532,1648537-1648539,1648542,1648591,1648612,1649590, 1651567,1652068,1652076,1652441,1652451,1653608,1654932,1654934,1654937,1655635,1655649,1655651,1655664,1656176,1657525,1657972,1657978,1658482,1659212,1659217,1659314,1659509,1662668,1665318,1665854,1665894,1667090,1667101,1667538,1669743,1669746,1669749,1669945,1670139,1670953,1673170,1673197,1673202,1673204,1673445,1673454,1673685,1673689,1673875,1674165,1674341,1674400,1674404,1674631,1674669,1674673,1675396,1676667,1677431,1678149,1678151,1678718,1678725,1679169,1679907,1679920-1679924,1679926,1680347,1680460,1680464,1680476,1680819,1681949,1681966,1681974,1681994,1682008,1682076,1682086,1682093,1682259,1682265,1682739,1682864,1683311,1683330,1683378,1683544,1683553,1684047,1686232,1686542,1686546,1686554,1686557,1687061,1687064,1687070-1687071,1687074,1687078-1687079,1688270,1688425,1692650,1693886,1694489,1694848,1696171,1696185,1696627-1696628,1696630,1696758,1697372,1697381,1697387,1697393,1697403,1697405,1701017,1701053,1702600,1702922,1703069,1703142,1703237,1703240,17052 66,1705638,1705643,1705646,1705724,1705730,1705739,1706612,1706615,1706617,1706619,1706675-1706676,1706679,1706979-1706980,1707308,1707971-1707973,1707986,1707988-1707989,1708004,1709799,1710017,1710359,1711582,1711672,1712927,1715793,1715947,1716047,1716067,1716784,1716973-1716974,1717332,1717334 -/subversion/trunk/subversion/libsvn_fs_x:1414756-1509914,1583624-1719651 +/subversion/trunk/subversion/libsvn_fs_fs:1415133-1596500,1596567,1597414,1597989,1598273,1599140,1600872,1601633,1603485-1603487,1603499,1603605,1604128,1604188,1604413-1604414,1604416-1604417,1604421,1604442,1604700,1604717,1604720,1604726,1604755,1604794,1604802,1604824,1604836,1604844,1604902-1604903,1604911,1604925,1604933,1604947,1605059-1605060,1605064-1605065,1605068,1605071-1605073,1605075,1605123,1605188-1605189,1605191,1605197,1605444,1605633,1606132,1606142,1606144,1606514,1606526,1606528,1606551,1606554,1606564,1606598-1606599,1606656,1606658,1606662,1606744,1606840,1607085,1607572,1612407,1612810,1613339,1613872,1614611,1615348,1615351-1615352,1615356,1616338-1616339,1616613,1617586,1617688,1618138,1618151,1618153,1618226,1618641,1618653,1618662,1619068,1619358,1619413,1619769,1619774,1620602,1620909,1620912,1620928,1620930,1621275,1621635,1622931,1622937,1622942,1622946,1622959-1622960,1622963,1622987,1623007,1623368,1623373,1623377,1623379,1623381,1623398,1623402,162 4011,1624265,1624512,1626246,1626871,1626873,1626886,1627497-1627498,1627502,1627947-1627949,1627966,1628083,1628093,1628158-1628159,1628161,1628392-1628393,1628415,1628427,1628676,1628738,1628762,1628764,1629854-1629855,1629857,1629865,1629873,1629875,1629879,1630067,1630070,1631049-1631051,1631075,1631115,1631171,1631180,1631185-1631186,1631196-1631197,1631239-1631240,1631548,1631550,1631563,1631567,1631588,1631598,1632646,1632776,1632849,1632851-1632853,1632856-1632857,1632868,1632908,1632926,1633232,1633617-1633618,1634872,1634875,1634879-1634880,1634920,1636478,1636483,1636629,1636644,1637184,1637186,1637330,1637358,1637363,1637393,1639319,1639322,1639335,1639348,1639352,1639355,1639358,1639414,1639419,1639426,1639430,1639436,1639440,1639549,1640061-1640062,1640197,1640915,1640966,1641013,1643139,1643233,1645567,1646021,1646712,1646716,1647537,1647540-1647541,1647820,1647905,1648230,1648238,1648241-1648243,1648253,1648272,1648532,1648537-1648539,1648542,1648591,1648612,1649590, 1651567,1652068,1652076,1652441,1652451,1653608,1654932,1654934,1654937,1655635,1655649,1655651,1655664,1656176,1657525,1657972,1657978,1658482,1659212,1659217,1659314,1659509,1662668,1665318,1665854,1665894,1667090,1667101,1667538,1669743,1669746,1669749,1669945,1670139,1670953,1673170,1673197,1673202,1673204,1673445,1673454,1673685,1673689,1673875,1674165,1674341,1674400,1674404,1674631,1674669,1674673,1675396,1676667,1677431,1678149,1678151,1678718,1678725,1679169,1679907,1679920-1679924,1679926,1680347,1680460,1680464,1680476,1680819,1681949,1681966,1681974,1681994,1682008,1682076,1682086,1682093,1682259,1682265,1682739,1682864,1683311,1683330,1683378,1683544,1683553,1684047,1686232,1686542,1686546,1686554,1686557,1687061,1687064,1687070-1687071,1687074,1687078-1687079,1688270,1688425,1692650,1693886,1694489,1694848,1696171,1696185,1696627-1696628,1696630,1696758,1697372,1697381,1697387,1697393,1697403,1697405,1701017,1701053,1702600,1702922,1703069,1703142,1703237,1703240,17052 66,1705638,1705643,1705646,1705724,1705730,1705739,1706612,1706615,1706617,1706619,1706675-1706676,1706679,1706979-1706980,1707308,1707971-1707973,1707986,1707988-1707989,1708004,1709388,1709799,1710017,1710359,1710368,1710370,1711507,1711582,1711672,1712927,1715793,1715947,1716047,1716067,1716784,1716973-1716974,1717332,1717334,1717864,1719269,1719336,1719413,1719730,1720015,1721285,1723715,1723720,1723834,1723839,1725179-1725180,1726004,1726099,1726116,1726897,1726995,1727006-1727007,1727028,1727040,1727707,1727822,1730491,1735916,1736357,1736359,1737355-1737356,1740721-1740722,1741096,1741200,1741206,1741214,1741224,1742540,1745055,1745107,1745852,1746006,1746012,1746026 +/subversion/trunk/subversion/libsvn_fs_x:1414756-1509914,1583624-1764213