summaryrefslogtreecommitdiff
path: root/reftable/reftable-writer.h
blob: db8de197f6c42a0de203fc1fbca8174f7f4d2938 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
/*
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 <stdint.h>
#include <unistd.h> /* 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. */
	int restart_interval;

	/* 4-byte identifier ("sha1", "s256") of the hash.
	 * Defaults to SHA1 if unset
	 */
	uint32_t hash_id;

	/* Default mode for creating files. If unset, use 0666 (+umask) */
	unsigned int default_permissions;

	/* boolean: do not check ref names for validity or dir/file conflicts.
	 */
	unsigned skip_name_check : 1;

	/* 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;
};

/* 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 */
	int 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;
};

/* reftable_new_writer creates a new writer */
struct reftable_writer *
reftable_new_writer(ssize_t (*writer_func)(void *, const void *, size_t),
		    void *writer_arg, 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.
 */
void 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