git/list[1] front-page[2] threads[3] people[4] search[5] about
 

[PATCH v2 0/4] odb: support ODB source specific transaction handling

From
Justin Tobler <jltobler@gmail.com>
Date
Feb 3, 2026, 00:09 UTC
Message-ID
<20260203001002.2500198-1-jltobler@gmail.com>
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
Previous: Patrick SteinhardtNext: Justin Tobler
Message 15 of 32 in “odb: support ODB source specific transaction handling”
  1. 0/4 odb: support ODB source specific transaction handlingJustin Tobler, Jan 28, 2026
  2. 1/4 odb: store ODB source in `struct odb_transaction`Justin Tobler, Jan 28, 2026
  3. Patrick SteinhardtJan 29, 2026
  4. Junio C HamanoJan 29, 2026
  5. Justin ToblerJan 29, 2026
  6. Junio C HamanoJan 29, 2026
  7. Justin ToblerJan 29, 2026
  8. Justin ToblerJan 29, 2026
  9. 2/4 object-file: rename transaction functionsJustin Tobler, Jan 28, 2026
  10. 3/4 odb: prepare `struct odb_transaction` to support more sourcesJustin Tobler, Jan 28, 2026
  11. Patrick SteinhardtJan 29, 2026
  12. Justin ToblerJan 29, 2026
  13. 4/4 odb: transparently handle common transaction behaviorJustin Tobler, Jan 28, 2026
  14. Patrick SteinhardtJan 29, 2026
  15. 0/4 odb: support ODB source specific transaction handlingJustin Tobler, Feb 3, 2026
  16. 1/4 odb: store ODB source in `struct odb_transaction`Justin Tobler, Feb 3, 2026
  17. 2/4 object-file: rename transaction functionsJustin Tobler, Feb 3, 2026
  18. 3/4 odb: prepare `struct odb_transaction` to become genericJustin Tobler, Feb 3, 2026
  19. Toon ClaesFeb 3, 2026
  20. Justin ToblerFeb 3, 2026
  21. Junio C HamanoFeb 3, 2026
  22. Patrick SteinhardtFeb 4, 2026
  23. Justin ToblerFeb 4, 2026
  24. Karthik NayakFeb 4, 2026
  25. Justin ToblerFeb 4, 2026
  26. Karthik NayakFeb 5, 2026
  27. 4/4 odb: transparently handle common transaction behaviorJustin Tobler, Feb 3, 2026
  28. Karthik NayakFeb 4, 2026
  29. Justin ToblerFeb 4, 2026
  30. Karthik NayakFeb 5, 2026
  31. Junio C HamanoFeb 3, 2026
  32. Patrick SteinhardtFeb 4, 2026

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.