Files
git/odb/source.h
Patrick Steinhardt d80523bbf9 odb: stop including "odb/source.h"
The "odb.h" header currently includes the "odb/source.h" file. This is
somewhat roundabout though: most callers shouldn't have to care about
the `struct odb_source`, but should rather use the ODB-level functions.
Furthermore, it means that a couple of definitions have to live on the
source level even though they should be part of the generic interface.

Reverse the relation between "odb/source.h" and "odb.h" and move the
enums and typedefs that relate to the generic interfaces back into
"odb.h". Add the necessary includes to all files that rely on the
transitive include.

Suggested-by: Justin Tobler <jltobler@gmail.com>
Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2026-03-10 10:13:47 -07:00

419 lines
14 KiB
C

#ifndef ODB_SOURCE_H
#define ODB_SOURCE_H
#include "object.h"
#include "odb.h"
enum odb_source_type {
/*
* The "unknown" type, which should never be in use. This type mostly
* exists to catch cases where the type field remains zeroed out.
*/
ODB_SOURCE_UNKNOWN,
/* The "files" backend that uses loose objects and packfiles. */
ODB_SOURCE_FILES,
};
struct object_id;
struct odb_read_stream;
struct strvec;
/*
* The source is the part of the object database that stores the actual
* objects. It thus encapsulates the logic to read and write the specific
* on-disk format. An object database can have multiple sources:
*
* - The primary source, which is typically located in "$GIT_DIR/objects".
* This is where new objects are usually written to.
*
* - Alternate sources, which are configured via "objects/info/alternates" or
* via the GIT_ALTERNATE_OBJECT_DIRECTORIES environment variable. These
* alternate sources are only used to read objects.
*/
struct odb_source {
struct odb_source *next;
/* Object database that owns this object source. */
struct object_database *odb;
/* The type used by this source. */
enum odb_source_type type;
/*
* Figure out whether this is the local source of the owning
* repository, which would typically be its ".git/objects" directory.
* This local object directory is usually where objects would be
* written to.
*/
bool local;
/*
* This object store is ephemeral, so there is no need to fsync.
*/
int will_destroy;
/*
* Path to the source. If this is a relative path, it is relative to
* the current working directory.
*/
char *path;
/*
* This callback is expected to free the underlying object database source and
* all associated resources. The function will never be called with a NULL pointer.
*/
void (*free)(struct odb_source *source);
/*
* This callback is expected to close any open resources, like for
* example file descriptors or connections. The source is expected to
* still be usable after it has been closed. Closed resources may need
* to be reopened in that case.
*/
void (*close)(struct odb_source *source);
/*
* This callback is expected to clear underlying caches of the object
* database source. The function is called when the repository has for
* example just been repacked so that new objects will become visible.
*/
void (*reprepare)(struct odb_source *source);
/*
* This callback is expected to read object information from the object
* database source. The object info will be partially populated with
* pointers for each bit of information that was requested by the
* caller.
*
* The flags field is a combination of `OBJECT_INFO` flags. Only the
* following fields need to be handled by the backend:
*
* - `OBJECT_INFO_QUICK` indicates it is fine to use caches without
* re-verifying the data.
*
* - `OBJECT_INFO_SECOND_READ` indicates that the initial object
* lookup has failed and that the object sources should check
* whether any of its on-disk state has changed that may have
* caused the object to appear. Sources are free to ignore the
* second read in case they know that the first read would have
* already surfaced the object without reloading any on-disk state.
*
* The callback is expected to return a negative error code in case
* reading the object has failed, 0 otherwise.
*/
int (*read_object_info)(struct odb_source *source,
const struct object_id *oid,
struct object_info *oi,
enum object_info_flags flags);
/*
* This callback is expected to create a new read stream that can be
* used to stream the object identified by the given ID.
*
* The callback is expected to return a negative error code in case
* creating the object stream has failed, 0 otherwise.
*/
int (*read_object_stream)(struct odb_read_stream **out,
struct odb_source *source,
const struct object_id *oid);
/*
* This callback is expected to iterate over all objects stored in this
* source and invoke the callback function for each of them. It is
* valid to yield the same object multiple time. A non-zero exit code
* from the object callback shall abort iteration.
*
* The optional `request` structure should serve as a template for
* looking up object info for every individual iterated object. It
* should not be modified directly and should instead be copied into a
* separate `struct object_info` that gets passed to the callback. If
* the caller passes a `NULL` pointer then the object itself shall not
* be read.
*
* The callback is expected to return a negative error code in case the
* iteration has failed to read all objects, 0 otherwise. When the
* callback function returns a non-zero error code then that error code
* should be returned.
*/
int (*for_each_object)(struct odb_source *source,
const struct object_info *request,
odb_for_each_object_cb cb,
void *cb_data,
unsigned flags);
/*
* This callback is expected to freshen the given object so that its
* last access time is set to the current time. This is used to ensure
* that objects that are recent will not get garbage collected even if
* they were unreachable.
*
* Returns 0 in case the object does not exist, 1 in case the object
* has been freshened.
*/
int (*freshen_object)(struct odb_source *source,
const struct object_id *oid);
/*
* This callback is expected to persist the given object into the
* object source. In case the object already exists it shall be
* freshened.
*
* The flags field is a combination of `WRITE_OBJECT` flags.
*
* The resulting object ID (and optionally the compatibility object ID)
* shall be written into the out pointers. The callback is expected to
* return 0 on success, a negative error code otherwise.
*/
int (*write_object)(struct odb_source *source,
const void *buf, unsigned long len,
enum object_type type,
struct object_id *oid,
struct object_id *compat_oid,
unsigned flags);
/*
* This callback is expected to persist the given object stream into
* the object source.
*
* The resulting object ID shall be written into the out pointer. The
* callback is expected to return 0 on success, a negative error code
* otherwise.
*/
int (*write_object_stream)(struct odb_source *source,
struct odb_write_stream *stream, size_t len,
struct object_id *oid);
/*
* This callback is expected to create a new transaction that can be
* used to write objects to. The objects shall only be persisted into
* the object database when the transcation's commit function is
* called. Otherwise, the objects shall be discarded.
*
* Returns 0 on success, in which case the `*out` pointer will have
* been populated with the object database transaction. Returns a
* negative error code otherwise.
*/
int (*begin_transaction)(struct odb_source *source,
struct odb_transaction **out);
/*
* This callback is expected to read the list of alternate object
* database sources connected to it and write them into the `strvec`.
*
* The result is expected to be paths to the alternates. All paths must
* be resolved to absolute paths.
*
* The callback is expected to return 0 on success, a negative error
* code otherwise.
*/
int (*read_alternates)(struct odb_source *source,
struct strvec *out);
/*
* This callback is expected to persist the singular alternate passed
* to it into its list of alternates. Any pre-existing alternates are
* expected to remain active. Subsequent calls to `read_alternates` are
* thus expected to yield the pre-existing list of alternates plus the
* newly added alternate appended to its end.
*
* The callback is expected to return 0 on success, a negative error
* code otherwise.
*/
int (*write_alternate)(struct odb_source *source,
const char *alternate);
};
/*
* Allocate and initialize a new source for the given object database located
* at `path`. `local` indicates whether or not the source is the local and thus
* primary object source of the object database.
*/
struct odb_source *odb_source_new(struct object_database *odb,
const char *path,
bool local);
/*
* Initialize the source for the given object database located at `path`.
* `local` indicates whether or not the source is the local and thus primary
* object source of the object database.
*
* This function is only supposed to be called by specific object source
* implementations.
*/
void odb_source_init(struct odb_source *source,
struct object_database *odb,
enum odb_source_type type,
const char *path,
bool local);
/*
* Free the object database source, releasing all associated resources and
* freeing the structure itself.
*/
void odb_source_free(struct odb_source *source);
/*
* Release the object database source, releasing all associated resources.
*
* This function is only supposed to be called by specific object source
* implementations.
*/
void odb_source_release(struct odb_source *source);
/*
* Close the object database source without releasing he underlying data. The
* source can still be used going forward, but it first needs to be reopened.
* This can be useful to reduce resource usage.
*/
static inline void odb_source_close(struct odb_source *source)
{
source->close(source);
}
/*
* Reprepare the object database source and clear any caches. Depending on the
* backend used this may have the effect that concurrently-written objects
* become visible.
*/
static inline void odb_source_reprepare(struct odb_source *source)
{
source->reprepare(source);
}
/*
* Read an object from the object database source identified by its object ID.
* Returns 0 on success, a negative error code otherwise.
*/
static inline int odb_source_read_object_info(struct odb_source *source,
const struct object_id *oid,
struct object_info *oi,
enum object_info_flags flags)
{
return source->read_object_info(source, oid, oi, flags);
}
/*
* Create a new read stream for the given object ID. Returns 0 on success, a
* negative error code otherwise.
*/
static inline int odb_source_read_object_stream(struct odb_read_stream **out,
struct odb_source *source,
const struct object_id *oid)
{
return source->read_object_stream(out, source, oid);
}
/*
* Iterate through all objects contained in the given source and invoke the
* callback function for each of them. Returning a non-zero code from the
* callback function aborts iteration. There is no guarantee that objects
* are only iterated over once.
*
* The optional `request` structure serves as a template for retrieving the
* object info for each indvidual iterated object and will be populated as if
* `odb_source_read_object_info()` was called on the object. It will not be
* modified, the callback will instead be invoked with a separate `struct
* object_info` for every object. Object info will not be read when passing a
* `NULL` pointer.
*
* The flags is a bitfield of `ODB_FOR_EACH_OBJECT_*` flags. Not all flags may
* apply to a specific backend, so whether or not they are honored is defined
* by the implementation.
*
* Returns 0 when all objects have been iterated over, a negative error code in
* case iteration has failed, or a non-zero value returned from the callback.
*/
static inline int odb_source_for_each_object(struct odb_source *source,
const struct object_info *request,
odb_for_each_object_cb cb,
void *cb_data,
unsigned flags)
{
return source->for_each_object(source, request, cb, cb_data, flags);
}
/*
* Freshen an object in the object database by updating its timestamp.
* Returns 1 in case the object has been freshened, 0 in case the object does
* not exist.
*/
static inline int odb_source_freshen_object(struct odb_source *source,
const struct object_id *oid)
{
return source->freshen_object(source, oid);
}
/*
* Write an object into the object database source. Returns 0 on success, a
* negative error code otherwise. Populates the given out pointers for the
* object ID and the compatibility object ID, if non-NULL.
*/
static inline int odb_source_write_object(struct odb_source *source,
const void *buf, unsigned long len,
enum object_type type,
struct object_id *oid,
struct object_id *compat_oid,
unsigned flags)
{
return source->write_object(source, buf, len, type, oid,
compat_oid, flags);
}
/*
* Write an object into the object database source via a stream. The overall
* length of the object must be known in advance.
*
* Return 0 on success, a negative error code otherwise. Populates the given
* out pointer for the object ID.
*/
static inline int odb_source_write_object_stream(struct odb_source *source,
struct odb_write_stream *stream,
size_t len,
struct object_id *oid)
{
return source->write_object_stream(source, stream, len, oid);
}
/*
* Read the list of alternative object database sources from the given backend
* and populate the `strvec` with them. The listing is not recursive -- that
* is, if any of the yielded alternate sources has alternates itself, those
* will not be yielded as part of this function call.
*
* Return 0 on success, a negative error code otherwise.
*/
static inline int odb_source_read_alternates(struct odb_source *source,
struct strvec *out)
{
return source->read_alternates(source, out);
}
/*
* Write and persist a new alternate object database source for the given
* source. Any preexisting alternates are expected to stay valid, and the new
* alternate shall be appended to the end of the list.
*
* Returns 0 on success, a negative error code otherwise.
*/
static inline int odb_source_write_alternate(struct odb_source *source,
const char *alternate)
{
return source->write_alternate(source, alternate);
}
/*
* Create a new transaction that can be used to write objects into a temporary
* staging area. The objects will only be persisted when the transaction is
* committed.
*
* Returns 0 on success, a negative error code otherwise.
*/
static inline int odb_source_begin_transaction(struct odb_source *source,
struct odb_transaction **out)
{
return source->begin_transaction(source, out);
}
#endif