Coverage Report

Created: 2024-07-27 06:53

/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