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 #pragma once
7 
8 #include <memory>
9 #include <unordered_map>
10 #include <utility>
11 
12 #include "rocksdb/env.h"
13 #include "rocksdb/options.h"
14 #include "rocksdb/trace_reader_writer.h"
15 
16 namespace ROCKSDB_NAMESPACE {
17 
18 // This file contains Tracer and Replayer classes that enable capturing and
19 // replaying RocksDB traces.
20 
21 class ColumnFamilyHandle;
22 class ColumnFamilyData;
23 class DB;
24 class DBImpl;
25 class Slice;
26 class WriteBatch;
27 
28 extern const std::string kTraceMagic;
29 const unsigned int kTraceTimestampSize = 8;
30 const unsigned int kTraceTypeSize = 1;
31 const unsigned int kTracePayloadLengthSize = 4;
32 const unsigned int kTraceMetadataSize =
33     kTraceTimestampSize + kTraceTypeSize + kTracePayloadLengthSize;
34 
35 // Supported Trace types.
36 enum TraceType : char {
37   kTraceBegin = 1,
38   kTraceEnd = 2,
39   kTraceWrite = 3,
40   kTraceGet = 4,
41   kTraceIteratorSeek = 5,
42   kTraceIteratorSeekForPrev = 6,
43   // Block cache related types.
44   kBlockTraceIndexBlock = 7,
45   kBlockTraceFilterBlock = 8,
46   kBlockTraceDataBlock = 9,
47   kBlockTraceUncompressionDictBlock = 10,
48   kBlockTraceRangeDeletionBlock = 11,
49   // All trace types should be added before kTraceMax
50   kTraceMax,
51 };
52 
53 // TODO: This should also be made part of public interface to help users build
54 // custom TracerReaders and TraceWriters.
55 //
56 // The data structure that defines a single trace.
57 struct Trace {
58   uint64_t ts;  // timestamp
59   TraceType type;
60   std::string payload;
61 
resetTrace62   void reset() {
63     ts = 0;
64     type = kTraceMax;
65     payload.clear();
66   }
67 };
68 
69 class TracerHelper {
70  public:
71   // Encode a trace object into the given string.
72   static void EncodeTrace(const Trace& trace, std::string* encoded_trace);
73 
74   // Decode a string into the given trace object.
75   static Status DecodeTrace(const std::string& encoded_trace, Trace* trace);
76 };
77 
78 // Tracer captures all RocksDB operations using a user-provided TraceWriter.
79 // Every RocksDB operation is written as a single trace. Each trace will have a
80 // timestamp and type, followed by the trace payload.
81 class Tracer {
82  public:
83   Tracer(Env* env, const TraceOptions& trace_options,
84          std::unique_ptr<TraceWriter>&& trace_writer);
85   ~Tracer();
86 
87   // Trace all write operations -- Put, Merge, Delete, SingleDelete, Write
88   Status Write(WriteBatch* write_batch);
89 
90   // Trace Get operations.
91   Status Get(ColumnFamilyHandle* cfname, const Slice& key);
92 
93   // Trace Iterators.
94   Status IteratorSeek(const uint32_t& cf_id, const Slice& key);
95   Status IteratorSeekForPrev(const uint32_t& cf_id, const Slice& key);
96 
97   // Returns true if the trace is over the configured max trace file limit.
98   // False otherwise.
99   bool IsTraceFileOverMax();
100 
101   // Writes a trace footer at the end of the tracing
102   Status Close();
103 
104  private:
105   // Write a trace header at the beginning, typically on initiating a trace,
106   // with some metadata like a magic number, trace version, RocksDB version, and
107   // trace format.
108   Status WriteHeader();
109 
110   // Write a trace footer, typically on ending a trace, with some metadata.
111   Status WriteFooter();
112 
113   // Write a single trace using the provided TraceWriter to the underlying
114   // system, say, a filesystem or a streaming service.
115   Status WriteTrace(const Trace& trace);
116 
117   // Helps in filtering and sampling of traces.
118   // Returns true if a trace should be skipped, false otherwise.
119   bool ShouldSkipTrace(const TraceType& type);
120 
121   Env* env_;
122   TraceOptions trace_options_;
123   std::unique_ptr<TraceWriter> trace_writer_;
124   uint64_t trace_request_count_;
125 };
126 
127 // Replayer helps to replay the captured RocksDB operations, using a user
128 // provided TraceReader.
129 // The Replayer is instantiated via db_bench today, on using "replay" benchmark.
130 class Replayer {
131  public:
132   Replayer(DB* db, const std::vector<ColumnFamilyHandle*>& handles,
133            std::unique_ptr<TraceReader>&& reader);
134   ~Replayer();
135 
136   // Replay all the traces from the provided trace stream, taking the delay
137   // between the traces into consideration.
138   Status Replay();
139 
140   // Replay the provide trace stream, which is the same as Replay(), with
141   // multi-threads. Queries are scheduled in the thread pool job queue.
142   // User can set the number of threads in the thread pool.
143   Status MultiThreadReplay(uint32_t threads_num);
144 
145   // Enables fast forwarding a replay by reducing the delay between the ingested
146   // traces.
147   // fast_forward : Rate of replay speedup.
148   //   If 1, replay the operations at the same rate as in the trace stream.
149   //   If > 1, speed up the replay by this amount.
150   Status SetFastForward(uint32_t fast_forward);
151 
152  private:
153   Status ReadHeader(Trace* header);
154   Status ReadFooter(Trace* footer);
155   Status ReadTrace(Trace* trace);
156 
157   // The background function for MultiThreadReplay to execute Get query
158   // based on the trace records.
159   static void BGWorkGet(void* arg);
160 
161   // The background function for MultiThreadReplay to execute WriteBatch
162   // (Put, Delete, SingleDelete, DeleteRange) based on the trace records.
163   static void BGWorkWriteBatch(void* arg);
164 
165   // The background function for MultiThreadReplay to execute Iterator (Seek)
166   // based on the trace records.
167   static void BGWorkIterSeek(void* arg);
168 
169   // The background function for MultiThreadReplay to execute Iterator
170   // (SeekForPrev) based on the trace records.
171   static void BGWorkIterSeekForPrev(void* arg);
172 
173   DBImpl* db_;
174   Env* env_;
175   std::unique_ptr<TraceReader> trace_reader_;
176   std::unordered_map<uint32_t, ColumnFamilyHandle*> cf_map_;
177   uint32_t fast_forward_;
178 };
179 
180 // The passin arg of MultiThreadRepkay for each trace record.
181 struct ReplayerWorkerArg {
182   DB* db;
183   Trace trace_entry;
184   std::unordered_map<uint32_t, ColumnFamilyHandle*>* cf_map;
185   WriteOptions woptions;
186   ReadOptions roptions;
187 };
188 
189 }  // namespace ROCKSDB_NAMESPACE
190