From: Justin Tobler <jltobler@gmail.com>
To: git@vger.kernel.org
Cc: ps@pks.im, gitster@pobox.com, Justin Tobler <jltobler@gmail.com>
Subject: [PATCH v2 0/4] odb: support ODB source specific transaction handling
Date: Mon, 2 Feb 2026 18:09:58 -0600 [thread overview]
Message-ID: <20260203001002.2500198-1-jltobler@gmail.com> (raw)
In-Reply-To: <20260128234519.2721179-1-jltobler@gmail.com>
Greetings,
ODB transactions provide a mechanism for writing new objects in the
repository that are in a pending state until they are committed. With
pluggable ODBs, each source will likely need to handle transactions
differently. This patch series prepares ODB transaction handling to be
defined for each ODB source by creating a generic odb_transaction
structure that stores a callback for committing the transaction.
For now, `struct odb_transaction_files` is the only transaction
implementation and what is always returned when creating a transaction.
Additionally, this series lifts transaction logic that is common to all
backends out of the implementation layer into
`odb_transaction_{begin,commit}()` layer.
Changes since V1:
- Renamed the files transaction type to be `odb_transaction_files`.
Associated functions were also renamed accordingly.
- Updated commit messages.
- The `tmp_objdir` subsystem has been left unchange in the version. In a
followup series, I plan to couple tmpdirs directly to ODB files
transactions.
Thanks,
-Justin
Justin Tobler (4):
odb: store ODB source in `struct odb_transaction`
object-file: rename transaction functions
odb: prepare `struct odb_transaction` to become generic
odb: transparently handle common transaction behavior
object-file.c | 77 +++++++++++++++++++++++++--------------------------
object-file.h | 10 ++-----
odb.c | 19 +++++++++++--
odb.h | 17 ++++++++++++
4 files changed, 74 insertions(+), 49 deletions(-)
Range-diff against v1:
1: 525c96f5f2 = 1: 525c96f5f2 odb: store ODB source in `struct odb_transaction`
2: 5ee1085453 ! 2: 02528f49fb object-file: rename transaction functions
@@ Commit message
In a subsequent commit, ODB transactions are made more generic to
facilitate each ODB source providing its own transaction handling.
Rename `object_file_transaction_{begin,commit}()` to
- `odb_transaction_loose_{begin,commit}()` to better match the future
+ `odb_transaction_files_{begin,commit}()` to better match the future
source specific transaction implementation.
Signed-off-by: Justin Tobler <jltobler@gmail.com>
@@ object-file.c: static void prepare_loose_object_transaction(struct odb_transacti
* the first time an object might be added, since
* callers may not know whether any objects will be
- * added at the time they call object_file_transaction_begin.
-+ * added at the time they call odb_transaction_loose_begin.
++ * added at the time they call odb_transaction_files_begin.
*/
if (!transaction || transaction->objdir)
return;
@@ object-file.c: int read_loose_object(struct repository *repo,
}
-struct odb_transaction *object_file_transaction_begin(struct odb_source *source)
-+struct odb_transaction *odb_transaction_loose_begin(struct odb_source *source)
++struct odb_transaction *odb_transaction_files_begin(struct odb_source *source)
{
struct object_database *odb = source->odb;
@@ object-file.c: struct odb_transaction *object_file_transaction_begin(struct odb_
}
-void object_file_transaction_commit(struct odb_transaction *transaction)
-+void odb_transaction_loose_commit(struct odb_transaction *transaction)
++void odb_transaction_files_commit(struct odb_transaction *transaction)
{
if (!transaction)
return;
@@ object-file.h: struct odb_transaction;
/*
* Tell the object database to optimize for adding
- * multiple objects. object_file_transaction_commit must be called
-+ * multiple objects. odb_transaction_loose_commit must be called
++ * multiple objects. odb_transaction_files_commit must be called
* to make new objects visible. If a transaction is already
* pending, NULL is returned.
*/
-struct odb_transaction *object_file_transaction_begin(struct odb_source *source);
-+struct odb_transaction *odb_transaction_loose_begin(struct odb_source *source);
++struct odb_transaction *odb_transaction_files_begin(struct odb_source *source);
/*
* Tell the object database to make any objects from the
* current transaction visible.
*/
-void object_file_transaction_commit(struct odb_transaction *transaction);
-+void odb_transaction_loose_commit(struct odb_transaction *transaction);
++void odb_transaction_files_commit(struct odb_transaction *transaction);
#endif /* OBJECT_FILE_H */
@@ odb.c: void odb_reprepare(struct object_database *o)
struct odb_transaction *odb_transaction_begin(struct object_database *odb)
{
- return object_file_transaction_begin(odb->sources);
-+ return odb_transaction_loose_begin(odb->sources);
++ return odb_transaction_files_begin(odb->sources);
}
void odb_transaction_commit(struct odb_transaction *transaction)
{
- object_file_transaction_commit(transaction);
-+ odb_transaction_loose_commit(transaction);
++ odb_transaction_files_commit(transaction);
}
3: a06bfd8c55 ! 3: 081c82428b odb: prepare `struct odb_transaction` to support more sources
@@ Metadata
Author: Justin Tobler <jltobler@gmail.com>
## Commit message ##
- odb: prepare `struct odb_transaction` to support more sources
+ odb: prepare `struct odb_transaction` to become generic
- Each ODB transaction should be specific to the ODB source it pertains
- to. Update `struct odb_transaction` to store a commit callback specific
- to its object source type. For now `struct odb_transaction_loose` is the
+ An ODB transaction handles how objects are stored temporarily and
+ eventually committed. Due to object storage being implemented
+ differently for a given ODB source, the ODB transactions must be
+ implemented in a manner specific to the source the objects are being
+ written to. To provide generic transactions, `struct odb_transaction` is
+ updated to store a commit callback that can be configured to support a
+ specific ODB source. For now `struct odb_transaction_files` is the
only transaction type and what is always returned when starting a
transaction.
@@ object-file.c: struct transaction_packfile {
-struct odb_transaction {
- struct odb_source *source;
-+struct odb_transaction_loose {
++struct odb_transaction_files {
+ struct odb_transaction base;
struct tmp_objdir *objdir;
@@ object-file.c: struct transaction_packfile {
-static void prepare_loose_object_transaction(struct odb_transaction *transaction)
+static void prepare_loose_object_transaction(struct odb_transaction *base)
{
-+ struct odb_transaction_loose *transaction = (struct odb_transaction_loose *)base;
++ struct odb_transaction_files *transaction = (struct odb_transaction_files *)base;
+
/*
* We lazily create the temporary object directory
@@ object-file.c: static void prepare_loose_object_transaction(struct odb_transacti
+static void fsync_loose_object_transaction(struct odb_transaction *base,
int fd, const char *filename)
{
-+ struct odb_transaction_loose *transaction = (struct odb_transaction_loose *)base;
++ struct odb_transaction_files *transaction = (struct odb_transaction_files *)base;
+
/*
* If we have an active ODB transaction, we issue a call that
@@ object-file.c: static void fsync_loose_object_transaction(struct odb_transaction
* Cleanup after batch-mode fsync_object_files.
*/
-static void flush_loose_object_transaction(struct odb_transaction *transaction)
-+static void flush_loose_object_transaction(struct odb_transaction_loose *transaction)
++static void flush_loose_object_transaction(struct odb_transaction_files *transaction)
{
struct strbuf temp_path = STRBUF_INIT;
struct tempfile *temp;
@@ object-file.c: static int index_core(struct index_state *istate,
}
-static int already_written(struct odb_transaction *transaction,
-+static int already_written(struct odb_transaction_loose *transaction,
++static int already_written(struct odb_transaction_files *transaction,
struct object_id *oid)
{
/* The object may already exist in the repository */
@@ object-file.c: static int already_written(struct odb_transaction *transaction,
/* Lazily create backing packfile for the state */
-static void prepare_packfile_transaction(struct odb_transaction *transaction,
-+static void prepare_packfile_transaction(struct odb_transaction_loose *transaction,
++static void prepare_packfile_transaction(struct odb_transaction_files *transaction,
unsigned flags)
{
struct transaction_packfile *state = &transaction->packfile;
@@ object-file.c: static int stream_blob_to_pack(struct transaction_packfile *state
}
-static void flush_packfile_transaction(struct odb_transaction *transaction)
-+static void flush_packfile_transaction(struct odb_transaction_loose *transaction)
++static void flush_packfile_transaction(struct odb_transaction_files *transaction)
{
struct transaction_packfile *state = &transaction->packfile;
- struct repository *repo = transaction->source->odb->repo;
@@ object-file.c: static void flush_packfile_transaction(struct odb_transaction *tr
* callers should avoid this code path when filters are requested.
*/
-static int index_blob_packfile_transaction(struct odb_transaction *transaction,
-+static int index_blob_packfile_transaction(struct odb_transaction_loose *transaction,
++static int index_blob_packfile_transaction(struct odb_transaction_files *transaction,
struct object_id *result_oid, int fd,
size_t size, const char *path,
unsigned flags)
@@ object-file.c: int index_fd(struct index_state *istate, struct object_id *oid,
- transaction = odb_transaction_begin(the_repository->objects);
- ret = index_blob_packfile_transaction(the_repository->objects->transaction,
+ transaction = odb_transaction_begin(odb);
-+ ret = index_blob_packfile_transaction((struct odb_transaction_loose *)odb->transaction,
++ ret = index_blob_packfile_transaction((struct odb_transaction_files *)odb->transaction,
oid, fd,
xsize_t(st->st_size),
path, flags);
@@ object-file.c: int read_loose_object(struct repository *repo,
return ret;
}
--struct odb_transaction *odb_transaction_loose_begin(struct odb_source *source)
-+static void odb_transaction_loose_commit(struct odb_transaction *base)
+-struct odb_transaction *odb_transaction_files_begin(struct odb_source *source)
++static void odb_transaction_files_commit(struct odb_transaction *base)
{
- struct object_database *odb = source->odb;
-
@@ object-file.c: int read_loose_object(struct repository *repo,
- return odb->transaction;
-}
-
--void odb_transaction_loose_commit(struct odb_transaction *transaction)
+-void odb_transaction_files_commit(struct odb_transaction *transaction)
-{
- if (!transaction)
- return;
-+ struct odb_transaction_loose *transaction = (struct odb_transaction_loose *)base;
++ struct odb_transaction_files *transaction = (struct odb_transaction_files *)base;
/*
* Ensure the transaction ending matches the pending transaction.
@@ object-file.c: int read_loose_object(struct repository *repo,
free(transaction);
}
-+struct odb_transaction *odb_transaction_loose_begin(struct odb_source *source)
++struct odb_transaction *odb_transaction_files_begin(struct odb_source *source)
+{
-+ struct odb_transaction_loose *transaction;
++ struct odb_transaction_files *transaction;
+ struct object_database *odb = source->odb;
+
+ if (odb->transaction)
@@ object-file.c: int read_loose_object(struct repository *repo,
+
+ transaction = xcalloc(1, sizeof(*transaction));
+ transaction->base.source = source;
-+ transaction->base.commit = odb_transaction_loose_commit;
++ transaction->base.commit = odb_transaction_files_commit;
+
+ odb->transaction = &transaction->base;
+
@@ object-file.c: int read_loose_object(struct repository *repo,
## object-file.h ##
@@ object-file.h: struct odb_transaction;
*/
- struct odb_transaction *odb_transaction_loose_begin(struct odb_source *source);
+ struct odb_transaction *odb_transaction_files_begin(struct odb_source *source);
-/*
- * Tell the object database to make any objects from the
- * current transaction visible.
- */
--void odb_transaction_loose_commit(struct odb_transaction *transaction);
+-void odb_transaction_files_commit(struct odb_transaction *transaction);
-
#endif /* OBJECT_FILE_H */
@@ odb.c: struct odb_transaction *odb_transaction_begin(struct object_database *odb
void odb_transaction_commit(struct odb_transaction *transaction)
{
-- odb_transaction_loose_commit(transaction);
+- odb_transaction_files_commit(transaction);
+ if (!transaction)
+ return;
+
4: 476ed1235c ! 4: ed8164a3a3 odb: transparently handle common transaction behavior
@@ Commit message
Signed-off-by: Justin Tobler <jltobler@gmail.com>
## object-file.c ##
-@@ object-file.c: static void odb_transaction_loose_commit(struct odb_transaction *base)
+@@ object-file.c: static void odb_transaction_files_commit(struct odb_transaction *base)
{
- struct odb_transaction_loose *transaction = (struct odb_transaction_loose *)base;
+ struct odb_transaction_files *transaction = (struct odb_transaction_files *)base;
- /*
- * Ensure the transaction ending matches the pending transaction.
@@ object-file.c: static void odb_transaction_loose_commit(struct odb_transaction *
- free(transaction);
}
- struct odb_transaction *odb_transaction_loose_begin(struct odb_source *source)
-@@ object-file.c: struct odb_transaction *odb_transaction_loose_begin(struct odb_source *source)
+ struct odb_transaction *odb_transaction_files_begin(struct odb_source *source)
+@@ object-file.c: struct odb_transaction *odb_transaction_files_begin(struct odb_source *source)
transaction->base.source = source;
- transaction->base.commit = odb_transaction_loose_commit;
+ transaction->base.commit = odb_transaction_files_commit;
- odb->transaction = &transaction->base;
-
@@ odb.c: void odb_reprepare(struct object_database *o)
struct odb_transaction *odb_transaction_begin(struct object_database *odb)
{
-- return odb_transaction_loose_begin(odb->sources);
-+ struct odb_transaction *transaction;
-+
+- return odb_transaction_files_begin(odb->sources);
+ if (odb->transaction)
+ return NULL;
+
-+ transaction = odb_transaction_loose_begin(odb->sources);
-+ odb->transaction = transaction;
++ odb->transaction = odb_transaction_files_begin(odb->sources);
+
-+ return transaction;
++ return odb->transaction;
}
void odb_transaction_commit(struct odb_transaction *transaction)
base-commit: ea717645d199f6f1b66058886475db3e8c9330e9
--
2.52.0.373.g68cb7f9e92
next prev parent reply other threads:[~2026-02-03 0:10 UTC|newest]
Thread overview: 32+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-01-28 23:45 [PATCH 0/4] odb: support ODB source specific transaction handling Justin Tobler
2026-01-28 23:45 ` [PATCH 1/4] odb: store ODB source in `struct odb_transaction` Justin Tobler
2026-01-29 11:24 ` Patrick Steinhardt
2026-01-29 19:25 ` Junio C Hamano
2026-01-29 20:12 ` Justin Tobler
2026-01-29 20:28 ` Junio C Hamano
2026-01-29 21:54 ` Justin Tobler
2026-01-29 19:30 ` Justin Tobler
2026-01-28 23:45 ` [PATCH 2/4] object-file: rename transaction functions Justin Tobler
2026-01-28 23:45 ` [PATCH 3/4] odb: prepare `struct odb_transaction` to support more sources Justin Tobler
2026-01-29 11:24 ` Patrick Steinhardt
2026-01-29 19:41 ` Justin Tobler
2026-01-28 23:45 ` [PATCH 4/4] odb: transparently handle common transaction behavior Justin Tobler
2026-01-29 11:24 ` Patrick Steinhardt
2026-02-03 0:09 ` Justin Tobler [this message]
2026-02-03 0:09 ` [PATCH v2 1/4] odb: store ODB source in `struct odb_transaction` Justin Tobler
2026-02-03 0:10 ` [PATCH v2 2/4] object-file: rename transaction functions Justin Tobler
2026-02-03 0:10 ` [PATCH v2 3/4] odb: prepare `struct odb_transaction` to become generic Justin Tobler
2026-02-03 15:54 ` Toon Claes
2026-02-03 16:46 ` Justin Tobler
2026-02-03 22:54 ` Junio C Hamano
2026-02-04 6:26 ` Patrick Steinhardt
2026-02-04 17:15 ` Justin Tobler
2026-02-04 10:31 ` Karthik Nayak
2026-02-04 17:38 ` Justin Tobler
2026-02-05 11:20 ` Karthik Nayak
2026-02-03 0:10 ` [PATCH v2 4/4] odb: transparently handle common transaction behavior Justin Tobler
2026-02-04 10:34 ` Karthik Nayak
2026-02-04 17:50 ` Justin Tobler
2026-02-05 11:22 ` Karthik Nayak
2026-02-03 1:16 ` [PATCH v2 0/4] odb: support ODB source specific transaction handling Junio C Hamano
2026-02-04 6:25 ` Patrick Steinhardt
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260203001002.2500198-1-jltobler@gmail.com \
--to=jltobler@gmail.com \
--cc=git@vger.kernel.org \
--cc=gitster@pobox.com \
--cc=ps@pks.im \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox