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 <string>
9 
10 #include "monitoring/thread_status_updater.h"
11 #include "rocksdb/db.h"
12 #include "rocksdb/env.h"
13 #include "rocksdb/thread_status.h"
14 
15 namespace ROCKSDB_NAMESPACE {
16 
17 class ColumnFamilyData;
18 
19 // The static utility class for updating thread-local status.
20 //
21 // The thread-local status is updated via the thread-local cached
22 // pointer thread_updater_local_cache_.  During each function call,
23 // when ThreadStatusUtil finds thread_updater_local_cache_ is
24 // left uninitialized (determined by thread_updater_initialized_),
25 // it will tries to initialize it using the return value of
26 // Env::GetThreadStatusUpdater().  When thread_updater_local_cache_
27 // is initialized by a non-null pointer, each function call will
28 // then update the status of the current thread.  Otherwise,
29 // all function calls to ThreadStatusUtil will be no-op.
30 class ThreadStatusUtil {
31  public:
32   // Register the current thread for tracking.
33   static void RegisterThread(
34       const Env* env, ThreadStatus::ThreadType thread_type);
35 
36   // Unregister the current thread.
37   static void UnregisterThread();
38 
39   // Create an entry in the global ColumnFamilyInfo table for the
40   // specified column family.  This function should be called only
41   // when the current thread does not hold db_mutex.
42   static void NewColumnFamilyInfo(const DB* db, const ColumnFamilyData* cfd,
43                                   const std::string& cf_name, const Env* env);
44 
45   // Erase the ConstantColumnFamilyInfo that is associated with the
46   // specified ColumnFamilyData.  This function should be called only
47   // when the current thread does not hold db_mutex.
48   static void EraseColumnFamilyInfo(const ColumnFamilyData* cfd);
49 
50   // Erase all ConstantColumnFamilyInfo that is associated with the
51   // specified db instance.  This function should be called only when
52   // the current thread does not hold db_mutex.
53   static void EraseDatabaseInfo(const DB* db);
54 
55   // Update the thread status to indicate the current thread is doing
56   // something related to the specified column family.
57   static void SetColumnFamily(const ColumnFamilyData* cfd, const Env* env,
58                               bool enable_thread_tracking);
59 
60   static void SetThreadOperation(ThreadStatus::OperationType type);
61 
62   static ThreadStatus::OperationStage SetThreadOperationStage(
63       ThreadStatus::OperationStage stage);
64 
65   static void SetThreadOperationProperty(
66       int code, uint64_t value);
67 
68   static void IncreaseThreadOperationProperty(
69       int code, uint64_t delta);
70 
71   static void SetThreadState(ThreadStatus::StateType type);
72 
73   static void ResetThreadStatus();
74 
75 #ifndef NDEBUG
76   static void TEST_SetStateDelay(
77       const ThreadStatus::StateType state, int micro);
78   static void TEST_StateDelay(const ThreadStatus::StateType state);
79 #endif
80 
81  protected:
82   // Initialize the thread-local ThreadStatusUpdater when it finds
83   // the cached value is nullptr.  Returns true if it has cached
84   // a non-null pointer.
85   static bool MaybeInitThreadLocalUpdater(const Env* env);
86 
87 #ifdef ROCKSDB_USING_THREAD_STATUS
88   // A boolean flag indicating whether thread_updater_local_cache_
89   // is initialized.  It is set to true when an Env uses any
90   // ThreadStatusUtil functions using the current thread other
91   // than UnregisterThread().  It will be set to false when
92   // UnregisterThread() is called.
93   //
94   // When this variable is set to true, thread_updater_local_cache_
95   // will not be updated until this variable is again set to false
96   // in UnregisterThread().
97   static  __thread bool thread_updater_initialized_;
98 
99   // The thread-local cached ThreadStatusUpdater that caches the
100   // thread_status_updater_ of the first Env that uses any ThreadStatusUtil
101   // function other than UnregisterThread().  This variable will
102   // be cleared when UnregisterThread() is called.
103   //
104   // When this variable is set to a non-null pointer, then the status
105   // of the current thread will be updated when a function of
106   // ThreadStatusUtil is called.  Otherwise, all functions of
107   // ThreadStatusUtil will be no-op.
108   //
109   // When thread_updater_initialized_ is set to true, this variable
110   // will not be updated until this thread_updater_initialized_ is
111   // again set to false in UnregisterThread().
112   static __thread ThreadStatusUpdater* thread_updater_local_cache_;
113 #else
114   static bool thread_updater_initialized_;
115   static ThreadStatusUpdater* thread_updater_local_cache_;
116 #endif
117 };
118 
119 // A helper class for updating thread state.  It will set the
120 // thread state according to the input parameter in its constructor
121 // and set the thread state to the previous state in its destructor.
122 class AutoThreadOperationStageUpdater {
123  public:
124   explicit AutoThreadOperationStageUpdater(
125       ThreadStatus::OperationStage stage);
126   ~AutoThreadOperationStageUpdater();
127 
128 #ifdef ROCKSDB_USING_THREAD_STATUS
129  private:
130   ThreadStatus::OperationStage prev_stage_;
131 #endif
132 };
133 
134 }  // namespace ROCKSDB_NAMESPACE
135