#ifndef ODB_SOURCE_H #define ODB_SOURCE_H #include "object.h" enum odb_source_type { /* * The "unknown" type, which should never be in use. This is 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, }; /* Flags that can be passed to `odb_read_object_info_extended()`. */ enum object_info_flags { /* Invoke lookup_replace_object() on the given hash. */ OBJECT_INFO_LOOKUP_REPLACE = (1 << 0), /* Do not reprepare object sources when the first lookup has failed. */ OBJECT_INFO_QUICK = (1 << 1), /* * Do not attempt to fetch the object if missing (even if fetch_is_missing is * nonzero). */ OBJECT_INFO_SKIP_FETCH_OBJECT = (1 << 2), /* Die if object corruption (not just an object being missing) was detected. */ OBJECT_INFO_DIE_IF_CORRUPT = (1 << 3), /* * We have already tried reading the object, but it couldn't be found * via any of the attached sources, and are now doing a second read. * This second read asks the individual sources to also evaluate * whether any on-disk state may have changed that may have caused the * object to appear. * * This flag is for internal use, only. The second read only occurs * when `OBJECT_INFO_QUICK` was not passed. */ OBJECT_INFO_SECOND_READ = (1 << 4), /* * This is meant for bulk prefetching of missing blobs in a partial * clone. Implies OBJECT_INFO_SKIP_FETCH_OBJECT and OBJECT_INFO_QUICK. */ OBJECT_INFO_FOR_PREFETCH = (OBJECT_INFO_SKIP_FETCH_OBJECT | OBJECT_INFO_QUICK), }; struct object_id; struct object_info; struct odb_read_stream; struct odb_transaction; struct odb_write_stream; struct strvec; /* * A callback function that can be used to iterate through objects. If given, * the optional `oi` parameter will be populated the same as if you would call * `odb_read_object_info()`. * * Returning a non-zero error code will cause iteration to abort. The error * code will be propagated. */ typedef int (*odb_for_each_object_cb)(const struct object_id *oid, struct object_info *oi, void *cb_data); /* * 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 `oi` structure shall be populated similar to how an individual * call to `odb_source_read_object_info()` would have behaved. 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 format is expected to follow the "objectStorage" extension * format with `(backend://)?payload` syntax. If the payload contains * paths, these 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 `oi` structure shall be populated similar to how an individual * call to `odb_source_read_object_info()` would have behaved. If the caller * passes a `NULL` pointer then the object itself shall not be read. * * 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