#ifndef ODB_SOURCE_H #define ODB_SOURCE_H #include "hashmap.h" #include "object.h" #include "odb.h" #include "odb/transaction.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, /* The "loose" backend that uses loose objects, only. */ ODB_SOURCE_LOOSE, /* The "packed" backend that uses packfiles. */ ODB_SOURCE_PACKED, /* The "in-memory" backend that stores objects in memory. */ ODB_SOURCE_INMEMORY, }; /* * Convert between the enum and its name. Returns the equivalent of "unknown" * for unknown types. */ const char *odb_source_type_to_name(enum odb_source_type type); struct object_id; struct odb_stream; struct strbuf; struct strvec; struct odb_create_on_disk_options { /* * Alternates that shall be written into the newly created object * database. Whether or not this option can be handled is specific to * the backend. */ const struct strvec *alternates; }; /* * 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; /* * Entry in the object database's map of sources, keyed by this * source's path. */ struct hashmap_entry by_path_entry; /* 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 create on-disk data structures that are * required for this source to operate. * * The callback is expected to return 0 on success, a negative error * code otherwise. * * This callback may be NULL in case the source does not need any * on-disk setup. */ int (*create_on_disk)(struct odb_source *source, const struct odb_create_on_disk_options *opts); /* * This callback is expected to prepare the source so that it becomes * ready for use. It optionally clears underlying caches of the object * database source. */ void (*prepare)(struct odb_source *source, enum odb_prepare_flags flags); /* * 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 an `enum odb_read_status`. Please * refer to the individual values that can be returned. In case reading * the object has failed with a generic error and `errmsg` is non-NULL, * the callback is expected to populate it with a human-readable * message that describes the failure. */ enum odb_read_status (*read_object_info)(struct odb_source *source, const struct object_id *oid, struct object_info *oi, enum object_info_flags flags, struct strbuf *errmsg); /* * 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_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, const struct odb_for_each_object_options *opts); /* * This callback is expected to count objects in the given object * database source. The callback function does not have to guarantee * that only unique objects are counted. The result shall be assigned * to the `out` pointer. * * Accepts `enum odb_count_objects_flag` flags to alter the behaviour. * * The callback is expected to return 0 on success, or a negative error * code otherwise. */ int (*count_objects)(struct odb_source *source, enum odb_count_objects_flags flags, unsigned long *out); /* * This callback is expected to find the minimum required length to * make the given object ID unique. * * The callback is expected to return a negative error code in case it * failed, 0 otherwise. */ int (*find_abbrev_len)(struct odb_source *source, const struct object_id *oid, unsigned min_length, unsigned *out); /* * 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, const time_t *mtime); /* * 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, size_t len, enum object_type type, const struct object_id *oid, const struct object_id *compat_oid, const time_t *mtime, enum odb_write_object_flags 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_stream *stream, 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, enum odb_transaction_flags flags); /* * 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 optimize the object database source. * Returns 0 on success, a negative error code otherwise. */ int (*optimize)(struct odb_source *source, const struct odb_optimize_options *opts); /* * This callback is expected to check whether optimization of the * object database source is required given the provided options. * Returns true if optimization should be performed, false otherwise. */ bool (*optimize_required)(struct odb_source *source, const struct odb_optimize_options *opts); /* * This callback is expected to start generating a packfile with the * given options. The pack shall be generated asynchronously so that * the caller can consume the pack data and progress output while the * pack is being generated. * * This callback is optional. Sources that cannot generate packfiles * shall leave it unset. * * The callback is expected to return 0 on success and populate the * `out` pointer with the pack generator, a negative error code * otherwise. */ int (*generate_pack)(struct odb_source *source, struct odb_pack_generator **out, const struct odb_generate_pack_options *opts); }; /* * 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); } /* * Create on-disk data structures that are required for this source to operate * correctly. Returns 0 on success, a negative error code otherwise. */ static inline int odb_source_create_on_disk(struct odb_source *source, const struct odb_create_on_disk_options *opts) { if (!source->create_on_disk) return 0; return source->create_on_disk(source, opts); } /* * Prepare 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_prepare(struct odb_source *source, enum odb_prepare_flags flags) { source->prepare(source, flags); } /* * Read an object from the object database source identified by its object ID. * Please refer to `enum odb_read_status` for the individual error codes. * * In case reading the object has failed with a generic error and `errmsg` is * non-NULL it will be populated with a human-readable message that describes * the failure. */ static inline enum odb_read_status odb_source_read_object_info(struct odb_source *source, const struct object_id *oid, struct object_info *oi, enum object_info_flags flags, struct strbuf *errmsg) { return source->read_object_info(source, oid, oi, flags, errmsg); } /* * 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_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 individual 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, const struct odb_for_each_object_options *opts) { return source->for_each_object(source, request, cb, cb_data, opts); } /* * Count the number of objects in the given object database source. * * Returns 0 on success, a negative error code otherwise. */ static inline int odb_source_count_objects(struct odb_source *source, enum odb_count_objects_flags flags, unsigned long *out) { return source->count_objects(source, flags, out); } /* * Determine the minimum required length to make the given object ID unique in * the given source. Returns 0 on success, a negative error code otherwise. */ static inline int odb_source_find_abbrev_len(struct odb_source *source, const struct object_id *oid, unsigned min_len, unsigned *out) { return source->find_abbrev_len(source, oid, min_len, out); } /* * 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, const time_t *mtime) { return source->freshen_object(source, oid, mtime); } /* * 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, const struct object_id *oid, const struct object_id *compat_oid, const time_t *mtime, enum odb_write_object_flags flags) { return source->write_object(source, buf, len, type, oid, compat_oid, mtime, 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_stream *stream, struct object_id *oid) { return source->write_object_stream(source, stream, 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); } /* * 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, enum odb_transaction_flags flags) { return source->begin_transaction(source, out, flags); } /* * Optimize the object database source. Returns 0 on success, a negative error * code otherwise. */ static inline int odb_source_optimize(struct odb_source *source, const struct odb_optimize_options *opts) { return source->optimize(source, opts); } /* * Check whether optimization of the object database source is required given * the provided options. Returns true if optimization should be performed, * false otherwise. */ static inline bool odb_source_optimize_required(struct odb_source *source, const struct odb_optimize_options *opts) { return source->optimize_required(source, opts); } /* * Start generating a packfile from the given source with the given options. * The pack is generated asynchronously; the caller is expected to consume the * file descriptors exposed via the pack generator and to then wait for * completion via `odb_pack_generator_finish()`. * * Returns 0 on success and populates the `out` pointer with the pack * generator, a negative error code otherwise. */ static inline int odb_source_generate_pack(struct odb_source *source, struct odb_pack_generator **out, const struct odb_generate_pack_options *opts) { return source->generate_pack(source, out, opts); } #endif