/src/rocksdb/db/log_writer.h
Line | Count | Source (jump to first uncovered line) |
1 | | // Copyright (c) 2011-present, Facebook, Inc. All rights reserved. |
2 | | // This source code is licensed under both the GPLv2 (found in the |
3 | | // COPYING file in the root directory) and Apache 2.0 License |
4 | | // (found in the LICENSE.Apache file in the root directory). |
5 | | // |
6 | | // Copyright (c) 2011 The LevelDB Authors. All rights reserved. |
7 | | // Use of this source code is governed by a BSD-style license that can be |
8 | | // found in the LICENSE file. See the AUTHORS file for names of contributors. |
9 | | #pragma once |
10 | | |
11 | | #include <cstdint> |
12 | | #include <memory> |
13 | | #include <unordered_map> |
14 | | #include <vector> |
15 | | |
16 | | #include "db/log_format.h" |
17 | | #include "rocksdb/compression_type.h" |
18 | | #include "rocksdb/env.h" |
19 | | #include "rocksdb/io_status.h" |
20 | | #include "rocksdb/slice.h" |
21 | | #include "rocksdb/status.h" |
22 | | #include "util/compression.h" |
23 | | #include "util/hash_containers.h" |
24 | | |
25 | | namespace ROCKSDB_NAMESPACE { |
26 | | |
27 | | class WritableFileWriter; |
28 | | |
29 | | namespace log { |
30 | | |
31 | | /** |
32 | | * Writer is a general purpose log stream writer. It provides an append-only |
33 | | * abstraction for writing data. The details of the how the data is written is |
34 | | * handled by the WritableFile sub-class implementation. |
35 | | * |
36 | | * File format: |
37 | | * |
38 | | * File is broken down into variable sized records. The format of each record |
39 | | * is described below. |
40 | | * +-----+-------------+--+----+----------+------+-- ... ----+ |
41 | | * File | r0 | r1 |P | r2 | r3 | r4 | | |
42 | | * +-----+-------------+--+----+----------+------+-- ... ----+ |
43 | | * <--- kBlockSize ------>|<-- kBlockSize ------>| |
44 | | * rn = variable size records |
45 | | * P = Padding |
46 | | * |
47 | | * Data is written out in kBlockSize chunks. If next record does not fit |
48 | | * into the space left, the leftover space will be padded with \0. |
49 | | * |
50 | | * Legacy record format: |
51 | | * |
52 | | * +---------+-----------+-----------+--- ... ---+ |
53 | | * |CRC (4B) | Size (2B) | Type (1B) | Payload | |
54 | | * +---------+-----------+-----------+--- ... ---+ |
55 | | * |
56 | | * CRC = 32bit hash computed over the record type and payload using CRC |
57 | | * Size = Length of the payload data |
58 | | * Type = Type of record |
59 | | * (kZeroType, kFullType, kFirstType, kLastType, kMiddleType ) |
60 | | * The type is used to group a bunch of records together to represent |
61 | | * blocks that are larger than kBlockSize |
62 | | * Payload = Byte stream as long as specified by the payload size |
63 | | * |
64 | | * Recyclable record format: |
65 | | * |
66 | | * +---------+-----------+-----------+----------------+--- ... ---+ |
67 | | * |CRC (4B) | Size (2B) | Type (1B) | Log number (4B)| Payload | |
68 | | * +---------+-----------+-----------+----------------+--- ... ---+ |
69 | | * |
70 | | * Same as above, with the addition of |
71 | | * Log number = 32bit log file number, so that we can distinguish between |
72 | | * records written by the most recent log writer vs a previous one. |
73 | | */ |
74 | | class Writer { |
75 | | public: |
76 | | // Create a writer that will append data to "*dest". |
77 | | // "*dest" must be initially empty. |
78 | | // "*dest" must remain live while this Writer is in use. |
79 | | explicit Writer(std::unique_ptr<WritableFileWriter>&& dest, |
80 | | uint64_t log_number, bool recycle_log_files, |
81 | | bool manual_flush = false, |
82 | | CompressionType compressionType = kNoCompression); |
83 | | // No copying allowed |
84 | | Writer(const Writer&) = delete; |
85 | | void operator=(const Writer&) = delete; |
86 | | |
87 | | ~Writer(); |
88 | | |
89 | | IOStatus AddRecord(const WriteOptions& write_options, const Slice& slice); |
90 | | IOStatus AddCompressionTypeRecord(const WriteOptions& write_options); |
91 | | |
92 | | // If there are column families in `cf_to_ts_sz` not included in |
93 | | // `recorded_cf_to_ts_sz_` and its user-defined timestamp size is non-zero, |
94 | | // adds a record of type kUserDefinedTimestampSizeType or |
95 | | // kRecyclableUserDefinedTimestampSizeType for these column families. |
96 | | // This timestamp size record applies to all subsequent records. |
97 | | IOStatus MaybeAddUserDefinedTimestampSizeRecord( |
98 | | const WriteOptions& write_options, |
99 | | const UnorderedMap<uint32_t, size_t>& cf_to_ts_sz); |
100 | | |
101 | 112k | WritableFileWriter* file() { return dest_.get(); } |
102 | 0 | const WritableFileWriter* file() const { return dest_.get(); } |
103 | | |
104 | 23.0k | uint64_t get_log_number() const { return log_number_; } |
105 | | |
106 | | IOStatus WriteBuffer(const WriteOptions& write_options); |
107 | | |
108 | | IOStatus Close(const WriteOptions& write_options); |
109 | | |
110 | | // If closing the writer through file(), call this afterwards to modify |
111 | | // this object's state to reflect that. Returns true if the destination file |
112 | | // has been closed. If it hasn't been closed, returns false with no change. |
113 | | bool PublishIfClosed(); |
114 | | |
115 | | bool BufferIsEmpty(); |
116 | | |
117 | 0 | size_t TEST_block_offset() const { return block_offset_; } |
118 | | |
119 | | private: |
120 | | std::unique_ptr<WritableFileWriter> dest_; |
121 | | size_t block_offset_; // Current offset in block |
122 | | uint64_t log_number_; |
123 | | bool recycle_log_files_; |
124 | | int header_size_; |
125 | | |
126 | | // crc32c values for all supported record types. These are |
127 | | // pre-computed to reduce the overhead of computing the crc of the |
128 | | // record type stored in the header. |
129 | | uint32_t type_crc_[kMaxRecordType + 1]; |
130 | | |
131 | | IOStatus EmitPhysicalRecord(const WriteOptions& write_options, |
132 | | RecordType type, const char* ptr, size_t length); |
133 | | |
134 | | // If true, it does not flush after each write. Instead it relies on the upper |
135 | | // layer to manually does the flush by calling ::WriteBuffer() |
136 | | bool manual_flush_; |
137 | | |
138 | | // Compression Type |
139 | | CompressionType compression_type_; |
140 | | StreamingCompress* compress_; |
141 | | // Reusable compressed output buffer |
142 | | std::unique_ptr<char[]> compressed_buffer_; |
143 | | |
144 | | // The recorded user-defined timestamp size that have been written so far. |
145 | | // Since the user-defined timestamp size cannot be changed while the DB is |
146 | | // running, existing entry in this map cannot be updated. |
147 | | UnorderedMap<uint32_t, size_t> recorded_cf_to_ts_sz_; |
148 | | }; |
149 | | |
150 | | } // namespace log |
151 | | } // namespace ROCKSDB_NAMESPACE |