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 14 #include "db/log_format.h" 15 #include "rocksdb/io_status.h" 16 #include "rocksdb/slice.h" 17 #include "rocksdb/status.h" 18 19 namespace ROCKSDB_NAMESPACE { 20 21 class WritableFileWriter; 22 23 namespace log { 24 25 /** 26 * Writer is a general purpose log stream writer. It provides an append-only 27 * abstraction for writing data. The details of the how the data is written is 28 * handled by the WriteableFile sub-class implementation. 29 * 30 * File format: 31 * 32 * File is broken down into variable sized records. The format of each record 33 * is described below. 34 * +-----+-------------+--+----+----------+------+-- ... ----+ 35 * File | r0 | r1 |P | r2 | r3 | r4 | | 36 * +-----+-------------+--+----+----------+------+-- ... ----+ 37 * <--- kBlockSize ------>|<-- kBlockSize ------>| 38 * rn = variable size records 39 * P = Padding 40 * 41 * Data is written out in kBlockSize chunks. If next record does not fit 42 * into the space left, the leftover space will be padded with \0. 43 * 44 * Legacy record format: 45 * 46 * +---------+-----------+-----------+--- ... ---+ 47 * |CRC (4B) | Size (2B) | Type (1B) | Payload | 48 * +---------+-----------+-----------+--- ... ---+ 49 * 50 * CRC = 32bit hash computed over the record type and payload using CRC 51 * Size = Length of the payload data 52 * Type = Type of record 53 * (kZeroType, kFullType, kFirstType, kLastType, kMiddleType ) 54 * The type is used to group a bunch of records together to represent 55 * blocks that are larger than kBlockSize 56 * Payload = Byte stream as long as specified by the payload size 57 * 58 * Recyclable record format: 59 * 60 * +---------+-----------+-----------+----------------+--- ... ---+ 61 * |CRC (4B) | Size (2B) | Type (1B) | Log number (4B)| Payload | 62 * +---------+-----------+-----------+----------------+--- ... ---+ 63 * 64 * Same as above, with the addition of 65 * Log number = 32bit log file number, so that we can distinguish between 66 * records written by the most recent log writer vs a previous one. 67 */ 68 class Writer { 69 public: 70 // Create a writer that will append data to "*dest". 71 // "*dest" must be initially empty. 72 // "*dest" must remain live while this Writer is in use. 73 explicit Writer(std::unique_ptr<WritableFileWriter>&& dest, 74 uint64_t log_number, bool recycle_log_files, 75 bool manual_flush = false); 76 // No copying allowed 77 Writer(const Writer&) = delete; 78 void operator=(const Writer&) = delete; 79 80 ~Writer(); 81 82 IOStatus AddRecord(const Slice& slice); 83 file()84 WritableFileWriter* file() { return dest_.get(); } file()85 const WritableFileWriter* file() const { return dest_.get(); } 86 get_log_number()87 uint64_t get_log_number() const { return log_number_; } 88 89 IOStatus WriteBuffer(); 90 91 IOStatus Close(); 92 93 bool TEST_BufferIsEmpty(); 94 95 private: 96 std::unique_ptr<WritableFileWriter> dest_; 97 size_t block_offset_; // Current offset in block 98 uint64_t log_number_; 99 bool recycle_log_files_; 100 101 // crc32c values for all supported record types. These are 102 // pre-computed to reduce the overhead of computing the crc of the 103 // record type stored in the header. 104 uint32_t type_crc_[kMaxRecordType + 1]; 105 106 IOStatus EmitPhysicalRecord(RecordType type, const char* ptr, size_t length); 107 108 // If true, it does not flush after each write. Instead it relies on the upper 109 // layer to manually does the flush by calling ::WriteBuffer() 110 bool manual_flush_; 111 }; 112 113 } // namespace log 114 } // namespace ROCKSDB_NAMESPACE 115