/* * Copyright 2020 Google LLC * * Use of this source code is governed by a BSD-style * license that can be found in the LICENSE file or at * https://developers.google.com/open-source/licenses/bsd */ #ifndef REFTABLE_WRITER_H #define REFTABLE_WRITER_H #include "reftable-record.h" #include #include /* ssize_t */ /* Writing single reftables */ /* reftable_write_options sets options for writing a single reftable. */ struct reftable_write_options { /* boolean: do not pad out blocks to block size. */ unsigned unpadded : 1; /* the blocksize. Should be less than 2^24. */ uint32_t block_size; /* boolean: do not generate a SHA1 => ref index. */ unsigned skip_index_objects : 1; /* how often to write complete keys in each block. */ uint16_t restart_interval; /* 4-byte identifier ("sha1", "s256") of the hash. * Defaults to SHA1 if unset */ enum reftable_hash hash_id; /* Default mode for creating files. If unset, use 0666 (+umask) */ unsigned int default_permissions; /* boolean: copy log messages exactly. If unset, check that the message * is a single line, and add '\n' if missing. */ unsigned exact_log_message : 1; /* boolean: Prevent auto-compaction of tables. */ unsigned disable_auto_compact : 1; /* * Geometric sequence factor used by auto-compaction to decide which * tables to compact. Defaults to 2 if unset. */ uint8_t auto_compaction_factor; /* * The number of milliseconds to wait when trying to lock "tables.list". * Note that this does not apply to locking individual tables, as these * should only ever be locked when already holding the "tables.list" * lock. * * Passing 0 will fail immediately when the file is locked, passing a * negative value will cause us to block indefinitely. */ long lock_timeout_ms; /* * Optional callback used to fsync files to disk. Falls back to using * fsync(3P) when unset. */ int (*fsync)(int fd); /* * Callback function to execute whenever the stack is being reloaded. * This can be used e.g. to discard cached information that relies on * the old stack's data. The payload data will be passed as argument to * the callback. */ void (*on_reload)(void *payload); void *on_reload_payload; }; /* reftable_block_stats holds statistics for a single block type */ struct reftable_block_stats { /* total number of entries written */ int entries; /* total number of key restarts */ uint32_t restarts; /* total number of blocks */ int blocks; /* total number of index blocks */ int index_blocks; /* depth of the index */ int max_index_level; /* offset of the first block for this type */ uint64_t offset; /* offset of the top level index block for this type, or 0 if not * present */ uint64_t index_offset; }; /* stats holds overall statistics for a single reftable */ struct reftable_stats { /* total number of blocks written. */ int blocks; /* stats for ref data */ struct reftable_block_stats ref_stats; /* stats for the SHA1 to ref map. */ struct reftable_block_stats obj_stats; /* stats for index blocks */ struct reftable_block_stats idx_stats; /* stats for log blocks */ struct reftable_block_stats log_stats; /* disambiguation length of shortened object IDs. */ int object_id_len; }; struct reftable_writer; /* Create a new writer. */ int reftable_writer_new(struct reftable_writer **out, ssize_t (*writer_func)(void *, const void *, size_t), int (*flush_func)(void *), void *writer_arg, const struct reftable_write_options *opts); /* * Set the range of update indices for the records we will add. When writing a * table into a stack, the min should be at least * reftable_stack_next_update_index(), or REFTABLE_API_ERROR is returned. * * For transactional updates to a stack, typically min==max, and the * update_index can be obtained by inspeciting the stack. When converting an * existing ref database into a single reftable, this would be a range of * update-index timestamps. * * The function should be called before adding any records to the writer. If not * it will fail with REFTABLE_API_ERROR. */ int reftable_writer_set_limits(struct reftable_writer *w, uint64_t min, uint64_t max); /* Add a reftable_ref_record. The record should have names that come after already added records. The update_index must be within the limits set by reftable_writer_set_limits(), or REFTABLE_API_ERROR is returned. It is an REFTABLE_API_ERROR error to write a ref record after a log record. */ int reftable_writer_add_ref(struct reftable_writer *w, struct reftable_ref_record *ref); /* Convenience function to add multiple reftable_ref_records; the function sorts the records before adding them, reordering the records array passed in. */ int reftable_writer_add_refs(struct reftable_writer *w, struct reftable_ref_record *refs, int n); /* adds reftable_log_records. Log records are keyed by (refname, decreasing update_index). The key for the record added must come after the already added log records. */ int reftable_writer_add_log(struct reftable_writer *w, struct reftable_log_record *log); /* Convenience function to add multiple reftable_log_records; the function sorts the records before adding them, reordering records array passed in. */ int reftable_writer_add_logs(struct reftable_writer *w, struct reftable_log_record *logs, int n); /* reftable_writer_close finalizes the reftable. The writer is retained so * statistics can be inspected. */ int reftable_writer_close(struct reftable_writer *w); /* writer_stats returns the statistics on the reftable being written. This struct becomes invalid when the writer is freed. */ const struct reftable_stats *reftable_writer_stats(struct reftable_writer *w); /* reftable_writer_free deallocates memory for the writer */ void reftable_writer_free(struct reftable_writer *w); #endif