mirror of
https://github.com/git/git.git
synced 2026-08-06 16:12:01 +00:00
odb/transaction: introduce ODB transaction flags
The temporary directory used by git-receive-pack(1) to write objects is
managed slightly differently than how it is done via ODB transactions:
- The temporary directory is eagerly created upfront, instead of
waiting for the first object write.
- The prefix name of the temporary directory is "incoming" instead of
"bulk-fsync".
In a subsequent commit, git-receive-pack(1) will use ODB transactions
instead of `tmp_objdir` directly. To provide a means to configure the
same transaction behavior, introduce `enum odb_transaction_flags` and
the ODB_TRANSACTION_RECEIVE flag intended as a signal for ODB
transactions using the "files" backend to be set up for
git-receive-pack(1). Transaction call sites are updated accordingly to
provide the required flag parameter.
Signed-off-by: Justin Tobler <jltobler@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
committed by
Junio C Hamano
parent
28fbc06769
commit
48d730a16a
@@ -581,7 +581,7 @@ int cmd_add(int argc,
|
||||
string_list_clear(&only_match_skip_worktree, 0);
|
||||
}
|
||||
|
||||
odb_transaction_begin_or_die(repo->objects, &transaction);
|
||||
odb_transaction_begin_or_die(repo->objects, &transaction, 0);
|
||||
|
||||
ps_matched = xcalloc(pathspec.nr, 1);
|
||||
if (add_renormalize)
|
||||
|
||||
@@ -596,7 +596,7 @@ static void unpack_all(void)
|
||||
progress = start_progress(the_repository,
|
||||
_("Unpacking objects"), nr_objects);
|
||||
CALLOC_ARRAY(obj_list, nr_objects);
|
||||
odb_transaction_begin_or_die(the_repository->objects, &transaction);
|
||||
odb_transaction_begin_or_die(the_repository->objects, &transaction, 0);
|
||||
for (i = 0; i < nr_objects; i++) {
|
||||
unpack_one(i);
|
||||
display_progress(progress, i + 1);
|
||||
|
||||
@@ -1124,7 +1124,7 @@ int cmd_update_index(int argc,
|
||||
* Allow the object layer to optimize adding multiple objects in
|
||||
* a batch.
|
||||
*/
|
||||
odb_transaction_begin_or_die(the_repository->objects, &transaction);
|
||||
odb_transaction_begin_or_die(the_repository->objects, &transaction, 0);
|
||||
while (ctx.argc) {
|
||||
if (parseopt_state != PARSE_OPT_DONE)
|
||||
parseopt_state = parse_options_step(&ctx, options,
|
||||
|
||||
@@ -492,7 +492,7 @@ int cache_tree_update(struct index_state *istate, int flags)
|
||||
trace_performance_enter();
|
||||
trace2_region_enter("cache_tree", "update", istate->repo);
|
||||
if (!inflight)
|
||||
odb_transaction_begin_or_die(the_repository->objects, &transaction);
|
||||
odb_transaction_begin_or_die(the_repository->objects, &transaction, 0);
|
||||
i = update_one(istate->cache_tree, istate->cache, istate->cache_nr,
|
||||
"", 0, &skip, flags);
|
||||
if (!inflight)
|
||||
|
||||
@@ -498,6 +498,7 @@ struct odb_transaction_files {
|
||||
|
||||
struct tmp_objdir *objdir;
|
||||
struct transaction_packfile packfile;
|
||||
const char *prefix;
|
||||
};
|
||||
|
||||
static int odb_transaction_files_prepare(struct odb_transaction *base)
|
||||
@@ -514,7 +515,7 @@ static int odb_transaction_files_prepare(struct odb_transaction *base)
|
||||
if (!transaction || transaction->objdir)
|
||||
return 0;
|
||||
|
||||
transaction->objdir = tmp_objdir_create(base->source->odb->repo, "bulk-fsync");
|
||||
transaction->objdir = tmp_objdir_create(base->source->odb->repo, transaction->prefix);
|
||||
if (!transaction->objdir)
|
||||
return error(_("unable to create temporary object directory"));
|
||||
|
||||
@@ -1357,7 +1358,7 @@ int index_fd(struct index_state *istate, struct object_id *oid,
|
||||
int inflight = !!transaction;
|
||||
|
||||
if (!inflight)
|
||||
odb_transaction_begin_or_die(odb, &transaction);
|
||||
odb_transaction_begin_or_die(odb, &transaction, 0);
|
||||
ret = odb_transaction_write_object_stream(transaction,
|
||||
&stream,
|
||||
xsize_t(st->st_size),
|
||||
@@ -1701,7 +1702,8 @@ static int odb_transaction_files_env(struct odb_transaction *base,
|
||||
}
|
||||
|
||||
int odb_transaction_files_begin(struct odb_source *source,
|
||||
struct odb_transaction **out)
|
||||
struct odb_transaction **out,
|
||||
enum odb_transaction_flags flags)
|
||||
{
|
||||
struct odb_transaction_files *transaction;
|
||||
|
||||
@@ -1710,6 +1712,27 @@ int odb_transaction_files_begin(struct odb_source *source,
|
||||
transaction->base.commit = odb_transaction_files_commit;
|
||||
transaction->base.write_object_stream = odb_transaction_files_write_object_stream;
|
||||
transaction->base.env = odb_transaction_files_env;
|
||||
|
||||
transaction->prefix = "bulk-fsync";
|
||||
if (flags & ODB_TRANSACTION_RECEIVE) {
|
||||
/*
|
||||
* ODB transactions for git-receive-pack(1) eagerly create a
|
||||
* temporary directory and use a different temporary directory
|
||||
* prefix.
|
||||
*
|
||||
* NEEDSWORK: This transaction flag is only used by the "files"
|
||||
* backend to special case temporary directory set up and
|
||||
* handling. Ideally transaction users should not have to care
|
||||
* though. To avoid this, we could eagerly create the temporary
|
||||
* directory and use the same prefix name for all transactions.
|
||||
*/
|
||||
transaction->prefix = "incoming";
|
||||
if (odb_transaction_files_prepare(&transaction->base)) {
|
||||
free(transaction);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
*out = &transaction->base;
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#include "object.h"
|
||||
#include "odb.h"
|
||||
#include "odb/source-loose.h"
|
||||
#include "odb/transaction.h"
|
||||
|
||||
/* The maximum size for an object header. */
|
||||
#define MAX_HEADER_LEN 32
|
||||
@@ -197,6 +198,7 @@ struct odb_transaction;
|
||||
* to make new objects visible.
|
||||
*/
|
||||
int odb_transaction_files_begin(struct odb_source *source,
|
||||
struct odb_transaction **out);
|
||||
struct odb_transaction **out,
|
||||
enum odb_transaction_flags flags);
|
||||
|
||||
#endif /* OBJECT_FILE_H */
|
||||
|
||||
@@ -180,9 +180,10 @@ static int odb_source_files_write_object_stream(struct odb_source *source,
|
||||
}
|
||||
|
||||
static int odb_source_files_begin_transaction(struct odb_source *source,
|
||||
struct odb_transaction **out)
|
||||
struct odb_transaction **out,
|
||||
enum odb_transaction_flags flags)
|
||||
{
|
||||
return odb_transaction_files_begin(source, out);
|
||||
return odb_transaction_files_begin(source, out, flags);
|
||||
}
|
||||
|
||||
static int odb_source_files_read_alternates(struct odb_source *source,
|
||||
|
||||
@@ -304,7 +304,8 @@ static int odb_source_inmemory_freshen_object(struct odb_source *source,
|
||||
}
|
||||
|
||||
static int odb_source_inmemory_begin_transaction(struct odb_source *source UNUSED,
|
||||
struct odb_transaction **out UNUSED)
|
||||
struct odb_transaction **out UNUSED,
|
||||
enum odb_transaction_flags flags UNUSED)
|
||||
{
|
||||
return error("in-memory source does not support transactions");
|
||||
}
|
||||
|
||||
@@ -646,7 +646,8 @@ static int odb_source_loose_write_object_stream(struct odb_source *source,
|
||||
}
|
||||
|
||||
static int odb_source_loose_begin_transaction(struct odb_source *source UNUSED,
|
||||
struct odb_transaction **out UNUSED)
|
||||
struct odb_transaction **out UNUSED,
|
||||
enum odb_transaction_flags flags UNUSED)
|
||||
{
|
||||
/* TODO: this is a known omission that we'll want to address eventually. */
|
||||
return error("loose source does not support transactions");
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
|
||||
#include "object.h"
|
||||
#include "odb.h"
|
||||
#include "odb/transaction.h"
|
||||
|
||||
enum odb_source_type {
|
||||
/*
|
||||
@@ -228,7 +229,8 @@ struct odb_source {
|
||||
* negative error code otherwise.
|
||||
*/
|
||||
int (*begin_transaction)(struct odb_source *source,
|
||||
struct odb_transaction **out);
|
||||
struct odb_transaction **out,
|
||||
enum odb_transaction_flags flags);
|
||||
|
||||
/*
|
||||
* This callback is expected to read the list of alternate object
|
||||
@@ -467,9 +469,10 @@ static inline int odb_source_write_alternate(struct odb_source *source,
|
||||
* Returns 0 on success, a negative error code otherwise.
|
||||
*/
|
||||
static inline int odb_source_begin_transaction(struct odb_source *source,
|
||||
struct odb_transaction **out)
|
||||
struct odb_transaction **out,
|
||||
enum odb_transaction_flags flags)
|
||||
{
|
||||
return source->begin_transaction(source, out);
|
||||
return source->begin_transaction(source, out, flags);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -4,14 +4,15 @@
|
||||
#include "odb/transaction.h"
|
||||
|
||||
int odb_transaction_begin(struct object_database *odb,
|
||||
struct odb_transaction **out)
|
||||
struct odb_transaction **out,
|
||||
enum odb_transaction_flags flags)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (odb->transaction)
|
||||
return error(_("object database transaction already pending"));
|
||||
|
||||
ret = odb_source_begin_transaction(odb->sources, out);
|
||||
ret = odb_source_begin_transaction(odb->sources, out, flags);
|
||||
if (!ret)
|
||||
odb->transaction = *out;
|
||||
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
|
||||
#include "gettext.h"
|
||||
#include "odb.h"
|
||||
#include "odb/source.h"
|
||||
|
||||
/*
|
||||
* A transaction may be started for an object database prior to writing new
|
||||
@@ -44,6 +43,12 @@ struct odb_transaction {
|
||||
int (*env)(struct odb_transaction *transaction, struct strvec *env);
|
||||
};
|
||||
|
||||
/* Flags used to configure an ODB transaction. */
|
||||
enum odb_transaction_flags {
|
||||
/* Configures the transaction for use with git-receive-pack(1). */
|
||||
ODB_TRANSACTION_RECEIVE = (1 << 0),
|
||||
};
|
||||
|
||||
/*
|
||||
* Starts an ODB transaction and returns it via `out`. Subsequent objects are
|
||||
* written to the transaction and not committed until odb_transaction_commit()
|
||||
@@ -52,12 +57,14 @@ struct odb_transaction {
|
||||
* ODB already has an inflight transaction pending.
|
||||
*/
|
||||
int odb_transaction_begin(struct object_database *odb,
|
||||
struct odb_transaction **out);
|
||||
struct odb_transaction **out,
|
||||
enum odb_transaction_flags flags);
|
||||
|
||||
static inline void odb_transaction_begin_or_die(struct object_database *odb,
|
||||
struct odb_transaction **out)
|
||||
struct odb_transaction **out,
|
||||
enum odb_transaction_flags flags)
|
||||
{
|
||||
if (odb_transaction_begin(odb, out))
|
||||
if (odb_transaction_begin(odb, out, flags))
|
||||
die(_("failed to start ODB transaction"));
|
||||
}
|
||||
|
||||
|
||||
@@ -4044,7 +4044,7 @@ int add_files_to_cache(struct repository *repo, const char *prefix,
|
||||
* may not have their own transaction active.
|
||||
*/
|
||||
if (!inflight)
|
||||
odb_transaction_begin_or_die(repo->objects, &transaction);
|
||||
odb_transaction_begin_or_die(repo->objects, &transaction, 0);
|
||||
run_diff_files(&rev, DIFF_RACY_IS_MODIFIED);
|
||||
if (!inflight)
|
||||
odb_transaction_commit(transaction);
|
||||
|
||||
Reference in New Issue
Block a user