1 // Copyright (c) 2014 The LevelDB Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. See the AUTHORS file for names of contributors.
4 //
5 // Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved.
6 
7 #pragma once
8 
9 #include <chrono>
10 #include <memory>
11 #include <string>
12 #include <unordered_map>
13 #include <vector>
14 #include "rocksdb/compaction_job_stats.h"
15 #include "rocksdb/status.h"
16 #include "rocksdb/table_properties.h"
17 
18 namespace ROCKSDB_NAMESPACE {
19 
20 typedef std::unordered_map<std::string, std::shared_ptr<const TableProperties>>
21     TablePropertiesCollection;
22 
23 class DB;
24 class ColumnFamilyHandle;
25 class Status;
26 struct CompactionJobStats;
27 enum CompressionType : unsigned char;
28 
29 enum class TableFileCreationReason {
30   kFlush,
31   kCompaction,
32   kRecovery,
33   kMisc,
34 };
35 
36 struct TableFileCreationBriefInfo {
37   // the name of the database where the file was created
38   std::string db_name;
39   // the name of the column family where the file was created.
40   std::string cf_name;
41   // the path to the created file.
42   std::string file_path;
43   // the id of the job (which could be flush or compaction) that
44   // created the file.
45   int job_id;
46   // reason of creating the table.
47   TableFileCreationReason reason;
48 };
49 
50 struct TableFileCreationInfo : public TableFileCreationBriefInfo {
51   TableFileCreationInfo() = default;
TableFileCreationInfoTableFileCreationInfo52   explicit TableFileCreationInfo(TableProperties&& prop)
53       : table_properties(prop) {}
54   // the size of the file.
55   uint64_t file_size;
56   // Detailed properties of the created file.
57   TableProperties table_properties;
58   // The status indicating whether the creation was successful or not.
59   Status status;
60 };
61 
62 enum class CompactionReason : int {
63   kUnknown = 0,
64   // [Level] number of L0 files > level0_file_num_compaction_trigger
65   kLevelL0FilesNum,
66   // [Level] total size of level > MaxBytesForLevel()
67   kLevelMaxLevelSize,
68   // [Universal] Compacting for size amplification
69   kUniversalSizeAmplification,
70   // [Universal] Compacting for size ratio
71   kUniversalSizeRatio,
72   // [Universal] number of sorted runs > level0_file_num_compaction_trigger
73   kUniversalSortedRunNum,
74   // [FIFO] total size > max_table_files_size
75   kFIFOMaxSize,
76   // [FIFO] reduce number of files.
77   kFIFOReduceNumFiles,
78   // [FIFO] files with creation time < (current_time - interval)
79   kFIFOTtl,
80   // Manual compaction
81   kManualCompaction,
82   // DB::SuggestCompactRange() marked files for compaction
83   kFilesMarkedForCompaction,
84   // [Level] Automatic compaction within bottommost level to cleanup duplicate
85   // versions of same user key, usually due to a released snapshot.
86   kBottommostFiles,
87   // Compaction based on TTL
88   kTtl,
89   // According to the comments in flush_job.cc, RocksDB treats flush as
90   // a level 0 compaction in internal stats.
91   kFlush,
92   // Compaction caused by external sst file ingestion
93   kExternalSstIngestion,
94   // Compaction due to SST file being too old
95   kPeriodicCompaction,
96   // total number of compaction reasons, new reasons must be added above this.
97   kNumOfReasons,
98 };
99 
100 enum class FlushReason : int {
101   kOthers = 0x00,
102   kGetLiveFiles = 0x01,
103   kShutDown = 0x02,
104   kExternalFileIngestion = 0x03,
105   kManualCompaction = 0x04,
106   kWriteBufferManager = 0x05,
107   kWriteBufferFull = 0x06,
108   kTest = 0x07,
109   kDeleteFiles = 0x08,
110   kAutoCompaction = 0x09,
111   kManualFlush = 0x0a,
112   kErrorRecovery = 0xb,
113 };
114 
115 enum class BackgroundErrorReason {
116   kFlush,
117   kCompaction,
118   kWriteCallback,
119   kMemTable,
120 };
121 
122 enum class WriteStallCondition {
123   kNormal,
124   kDelayed,
125   kStopped,
126 };
127 
128 struct WriteStallInfo {
129   // the name of the column family
130   std::string cf_name;
131   // state of the write controller
132   struct {
133     WriteStallCondition cur;
134     WriteStallCondition prev;
135   } condition;
136 };
137 
138 #ifndef ROCKSDB_LITE
139 
140 struct TableFileDeletionInfo {
141   // The name of the database where the file was deleted.
142   std::string db_name;
143   // The path to the deleted file.
144   std::string file_path;
145   // The id of the job which deleted the file.
146   int job_id;
147   // The status indicating whether the deletion was successful or not.
148   Status status;
149 };
150 
151 struct FileOperationInfo {
152   using TimePoint = std::chrono::time_point<std::chrono::system_clock,
153                                             std::chrono::nanoseconds>;
154 
155   const std::string& path;
156   uint64_t offset;
157   size_t length;
158   const TimePoint& start_timestamp;
159   const TimePoint& finish_timestamp;
160   Status status;
FileOperationInfoFileOperationInfo161   FileOperationInfo(const std::string& _path, const TimePoint& start,
162                     const TimePoint& finish)
163       : path(_path), start_timestamp(start), finish_timestamp(finish) {}
164 };
165 
166 struct FlushJobInfo {
167   // the id of the column family
168   uint32_t cf_id;
169   // the name of the column family
170   std::string cf_name;
171   // the path to the newly created file
172   std::string file_path;
173   // the file number of the newly created file
174   uint64_t file_number;
175   // the oldest blob file referenced by the newly created file
176   uint64_t oldest_blob_file_number;
177   // the id of the thread that completed this flush job.
178   uint64_t thread_id;
179   // the job id, which is unique in the same thread.
180   int job_id;
181   // If true, then rocksdb is currently slowing-down all writes to prevent
182   // creating too many Level 0 files as compaction seems not able to
183   // catch up the write request speed.  This indicates that there are
184   // too many files in Level 0.
185   bool triggered_writes_slowdown;
186   // If true, then rocksdb is currently blocking any writes to prevent
187   // creating more L0 files.  This indicates that there are too many
188   // files in level 0.  Compactions should try to compact L0 files down
189   // to lower levels as soon as possible.
190   bool triggered_writes_stop;
191   // The smallest sequence number in the newly created file
192   SequenceNumber smallest_seqno;
193   // The largest sequence number in the newly created file
194   SequenceNumber largest_seqno;
195   // Table properties of the table being flushed
196   TableProperties table_properties;
197 
198   FlushReason flush_reason;
199 };
200 
201 struct CompactionFileInfo {
202   // The level of the file.
203   int level;
204 
205   // The file number of the file.
206   uint64_t file_number;
207 
208   // The file number of the oldest blob file this SST file references.
209   uint64_t oldest_blob_file_number;
210 };
211 
212 struct CompactionJobInfo {
213   // the id of the column family where the compaction happened.
214   uint32_t cf_id;
215   // the name of the column family where the compaction happened.
216   std::string cf_name;
217   // the status indicating whether the compaction was successful or not.
218   Status status;
219   // the id of the thread that completed this compaction job.
220   uint64_t thread_id;
221   // the job id, which is unique in the same thread.
222   int job_id;
223   // the smallest input level of the compaction.
224   int base_input_level;
225   // the output level of the compaction.
226   int output_level;
227 
228   // The following variables contain information about compaction inputs
229   // and outputs. A file may appear in both the input and output lists
230   // if it was simply moved to a different level. The order of elements
231   // is the same across input_files and input_file_infos; similarly, it is
232   // the same across output_files and output_file_infos.
233 
234   // The names of the compaction input files.
235   std::vector<std::string> input_files;
236 
237   // Additional information about the compaction input files.
238   std::vector<CompactionFileInfo> input_file_infos;
239 
240   // The names of the compaction output files.
241   std::vector<std::string> output_files;
242 
243   // Additional information about the compaction output files.
244   std::vector<CompactionFileInfo> output_file_infos;
245 
246   // Table properties for input and output tables.
247   // The map is keyed by values from input_files and output_files.
248   TablePropertiesCollection table_properties;
249 
250   // Reason to run the compaction
251   CompactionReason compaction_reason;
252 
253   // Compression algorithm used for output files
254   CompressionType compression;
255 
256   // If non-null, this variable stores detailed information
257   // about this compaction.
258   CompactionJobStats stats;
259 };
260 
261 struct MemTableInfo {
262   // the name of the column family to which memtable belongs
263   std::string cf_name;
264   // Sequence number of the first element that was inserted
265   // into the memtable.
266   SequenceNumber first_seqno;
267   // Sequence number that is guaranteed to be smaller than or equal
268   // to the sequence number of any key that could be inserted into this
269   // memtable. It can then be assumed that any write with a larger(or equal)
270   // sequence number will be present in this memtable or a later memtable.
271   SequenceNumber earliest_seqno;
272   // Total number of entries in memtable
273   uint64_t num_entries;
274   // Total number of deletes in memtable
275   uint64_t num_deletes;
276 };
277 
278 struct ExternalFileIngestionInfo {
279   // the name of the column family
280   std::string cf_name;
281   // Path of the file outside the DB
282   std::string external_file_path;
283   // Path of the file inside the DB
284   std::string internal_file_path;
285   // The global sequence number assigned to keys in this file
286   SequenceNumber global_seqno;
287   // Table properties of the table being flushed
288   TableProperties table_properties;
289 };
290 
291 // EventListener class contains a set of callback functions that will
292 // be called when specific RocksDB event happens such as flush.  It can
293 // be used as a building block for developing custom features such as
294 // stats-collector or external compaction algorithm.
295 //
296 // Note that callback functions should not run for an extended period of
297 // time before the function returns, otherwise RocksDB may be blocked.
298 // For example, it is not suggested to do DB::CompactFiles() (as it may
299 // run for a long while) or issue many of DB::Put() (as Put may be blocked
300 // in certain cases) in the same thread in the EventListener callback.
301 // However, doing DB::CompactFiles() and DB::Put() in another thread is
302 // considered safe.
303 //
304 // [Threading] All EventListener callback will be called using the
305 // actual thread that involves in that specific event.   For example, it
306 // is the RocksDB background flush thread that does the actual flush to
307 // call EventListener::OnFlushCompleted().
308 //
309 // [Locking] All EventListener callbacks are designed to be called without
310 // the current thread holding any DB mutex. This is to prevent potential
311 // deadlock and performance issue when using EventListener callback
312 // in a complex way.
313 class EventListener {
314  public:
315   // A callback function to RocksDB which will be called whenever a
316   // registered RocksDB flushes a file.  The default implementation is
317   // no-op.
318   //
319   // Note that the this function must be implemented in a way such that
320   // it should not run for an extended period of time before the function
321   // returns.  Otherwise, RocksDB may be blocked.
OnFlushCompleted(DB *,const FlushJobInfo &)322   virtual void OnFlushCompleted(DB* /*db*/,
323                                 const FlushJobInfo& /*flush_job_info*/) {}
324 
325   // A callback function to RocksDB which will be called before a
326   // RocksDB starts to flush memtables.  The default implementation is
327   // no-op.
328   //
329   // Note that the this function must be implemented in a way such that
330   // it should not run for an extended period of time before the function
331   // returns.  Otherwise, RocksDB may be blocked.
OnFlushBegin(DB *,const FlushJobInfo &)332   virtual void OnFlushBegin(DB* /*db*/,
333                             const FlushJobInfo& /*flush_job_info*/) {}
334 
335   // A callback function for RocksDB which will be called whenever
336   // a SST file is deleted.  Different from OnCompactionCompleted and
337   // OnFlushCompleted, this callback is designed for external logging
338   // service and thus only provide string parameters instead
339   // of a pointer to DB.  Applications that build logic basic based
340   // on file creations and deletions is suggested to implement
341   // OnFlushCompleted and OnCompactionCompleted.
342   //
343   // Note that if applications would like to use the passed reference
344   // outside this function call, they should make copies from the
345   // returned value.
OnTableFileDeleted(const TableFileDeletionInfo &)346   virtual void OnTableFileDeleted(const TableFileDeletionInfo& /*info*/) {}
347 
348   // A callback function to RocksDB which will be called before a
349   // RocksDB starts to compact.  The default implementation is
350   // no-op.
351   //
352   // Note that the this function must be implemented in a way such that
353   // it should not run for an extended period of time before the function
354   // returns.  Otherwise, RocksDB may be blocked.
OnCompactionBegin(DB *,const CompactionJobInfo &)355   virtual void OnCompactionBegin(DB* /*db*/, const CompactionJobInfo& /*ci*/) {}
356 
357   // A callback function for RocksDB which will be called whenever
358   // a registered RocksDB compacts a file. The default implementation
359   // is a no-op.
360   //
361   // Note that this function must be implemented in a way such that
362   // it should not run for an extended period of time before the function
363   // returns. Otherwise, RocksDB may be blocked.
364   //
365   // @param db a pointer to the rocksdb instance which just compacted
366   //   a file.
367   // @param ci a reference to a CompactionJobInfo struct. 'ci' is released
368   //  after this function is returned, and must be copied if it is needed
369   //  outside of this function.
OnCompactionCompleted(DB *,const CompactionJobInfo &)370   virtual void OnCompactionCompleted(DB* /*db*/,
371                                      const CompactionJobInfo& /*ci*/) {}
372 
373   // A callback function for RocksDB which will be called whenever
374   // a SST file is created.  Different from OnCompactionCompleted and
375   // OnFlushCompleted, this callback is designed for external logging
376   // service and thus only provide string parameters instead
377   // of a pointer to DB.  Applications that build logic basic based
378   // on file creations and deletions is suggested to implement
379   // OnFlushCompleted and OnCompactionCompleted.
380   //
381   // Historically it will only be called if the file is successfully created.
382   // Now it will also be called on failure case. User can check info.status
383   // to see if it succeeded or not.
384   //
385   // Note that if applications would like to use the passed reference
386   // outside this function call, they should make copies from these
387   // returned value.
OnTableFileCreated(const TableFileCreationInfo &)388   virtual void OnTableFileCreated(const TableFileCreationInfo& /*info*/) {}
389 
390   // A callback function for RocksDB which will be called before
391   // a SST file is being created. It will follow by OnTableFileCreated after
392   // the creation finishes.
393   //
394   // Note that if applications would like to use the passed reference
395   // outside this function call, they should make copies from these
396   // returned value.
OnTableFileCreationStarted(const TableFileCreationBriefInfo &)397   virtual void OnTableFileCreationStarted(
398       const TableFileCreationBriefInfo& /*info*/) {}
399 
400   // A callback function for RocksDB which will be called before
401   // a memtable is made immutable.
402   //
403   // Note that the this function must be implemented in a way such that
404   // it should not run for an extended period of time before the function
405   // returns.  Otherwise, RocksDB may be blocked.
406   //
407   // Note that if applications would like to use the passed reference
408   // outside this function call, they should make copies from these
409   // returned value.
OnMemTableSealed(const MemTableInfo &)410   virtual void OnMemTableSealed(const MemTableInfo& /*info*/) {}
411 
412   // A callback function for RocksDB which will be called before
413   // a column family handle is deleted.
414   //
415   // Note that the this function must be implemented in a way such that
416   // it should not run for an extended period of time before the function
417   // returns.  Otherwise, RocksDB may be blocked.
418   // @param handle is a pointer to the column family handle to be deleted
419   // which will become a dangling pointer after the deletion.
OnColumnFamilyHandleDeletionStarted(ColumnFamilyHandle *)420   virtual void OnColumnFamilyHandleDeletionStarted(
421       ColumnFamilyHandle* /*handle*/) {}
422 
423   // A callback function for RocksDB which will be called after an external
424   // file is ingested using IngestExternalFile.
425   //
426   // Note that the this function will run on the same thread as
427   // IngestExternalFile(), if this function is blocked, IngestExternalFile()
428   // will be blocked from finishing.
OnExternalFileIngested(DB *,const ExternalFileIngestionInfo &)429   virtual void OnExternalFileIngested(
430       DB* /*db*/, const ExternalFileIngestionInfo& /*info*/) {}
431 
432   // A callback function for RocksDB which will be called before setting the
433   // background error status to a non-OK value. The new background error status
434   // is provided in `bg_error` and can be modified by the callback. E.g., a
435   // callback can suppress errors by resetting it to Status::OK(), thus
436   // preventing the database from entering read-only mode. We do not provide any
437   // guarantee when failed flushes/compactions will be rescheduled if the user
438   // suppresses an error.
439   //
440   // Note that this function can run on the same threads as flush, compaction,
441   // and user writes. So, it is extremely important not to perform heavy
442   // computations or blocking calls in this function.
OnBackgroundError(BackgroundErrorReason,Status *)443   virtual void OnBackgroundError(BackgroundErrorReason /* reason */,
444                                  Status* /* bg_error */) {}
445 
446   // A callback function for RocksDB which will be called whenever a change
447   // of superversion triggers a change of the stall conditions.
448   //
449   // Note that the this function must be implemented in a way such that
450   // it should not run for an extended period of time before the function
451   // returns.  Otherwise, RocksDB may be blocked.
OnStallConditionsChanged(const WriteStallInfo &)452   virtual void OnStallConditionsChanged(const WriteStallInfo& /*info*/) {}
453 
454   // A callback function for RocksDB which will be called whenever a file read
455   // operation finishes.
OnFileReadFinish(const FileOperationInfo &)456   virtual void OnFileReadFinish(const FileOperationInfo& /* info */) {}
457 
458   // A callback function for RocksDB which will be called whenever a file write
459   // operation finishes.
OnFileWriteFinish(const FileOperationInfo &)460   virtual void OnFileWriteFinish(const FileOperationInfo& /* info */) {}
461 
462   // If true, the OnFileReadFinish and OnFileWriteFinish will be called. If
463   // false, then they won't be called.
ShouldBeNotifiedOnFileIO()464   virtual bool ShouldBeNotifiedOnFileIO() { return false; }
465 
466   // A callback function for RocksDB which will be called just before
467   // starting the automatic recovery process for recoverable background
468   // errors, such as NoSpace(). The callback can suppress the automatic
469   // recovery by setting *auto_recovery to false. The database will then
470   // have to be transitioned out of read-only mode by calling DB::Resume()
OnErrorRecoveryBegin(BackgroundErrorReason,Status,bool *)471   virtual void OnErrorRecoveryBegin(BackgroundErrorReason /* reason */,
472                                     Status /* bg_error */,
473                                     bool* /* auto_recovery */) {}
474 
475   // A callback function for RocksDB which will be called once the database
476   // is recovered from read-only mode after an error. When this is called, it
477   // means normal writes to the database can be issued and the user can
478   // initiate any further recovery actions needed
OnErrorRecoveryCompleted(Status)479   virtual void OnErrorRecoveryCompleted(Status /* old_bg_error */) {}
480 
~EventListener()481   virtual ~EventListener() {}
482 };
483 
484 #else
485 
486 class EventListener {};
487 struct FlushJobInfo {};
488 
489 #endif  // ROCKSDB_LITE
490 
491 }  // namespace ROCKSDB_NAMESPACE
492