| 1 | /* -*- mode: C++; c-basic-offset: 4; indent-tabs-mode: nil -*- */ |
| 2 | // vim: ft=cpp:expandtab:ts=8:sw=4:softtabstop=4: |
| 3 | #ident "$Id$" |
| 4 | /*====== |
| 5 | This file is part of TokuDB |
| 6 | |
| 7 | |
| 8 | Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved. |
| 9 | |
| 10 | TokuDB is free software: you can redistribute it and/or modify |
| 11 | it under the terms of the GNU General Public License, version 2, |
| 12 | as published by the Free Software Foundation. |
| 13 | |
| 14 | TokuDB is distributed in the hope that it will be useful, |
| 15 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 17 | GNU General Public License for more details. |
| 18 | |
| 19 | You should have received a copy of the GNU General Public License |
| 20 | along with TokuDB. If not, see <http://www.gnu.org/licenses/>. |
| 21 | |
| 22 | ======= */ |
| 23 | |
| 24 | #ident "Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved." |
| 25 | |
| 26 | #ifndef _TOKUDB_BACKGROUND_H |
| 27 | #define _TOKUDB_BACKGROUND_H |
| 28 | |
| 29 | #include "hatoku_hton.h" |
| 30 | #include <atomic> |
| 31 | #include <list> |
| 32 | |
| 33 | namespace tokudb { |
| 34 | namespace background { |
| 35 | |
| 36 | class job_manager_t { |
| 37 | public: |
| 38 | class job_t { |
| 39 | public: |
| 40 | // NO default constructor |
| 41 | job_t() = delete; |
| 42 | |
| 43 | job_t(bool user_scheduled); |
| 44 | |
| 45 | virtual ~job_t(); |
| 46 | |
| 47 | // method that runs the job |
| 48 | inline void run(); |
| 49 | |
| 50 | // method that tells the job to cancel ASAP |
| 51 | inline void cancel(); |
| 52 | |
| 53 | // method that tells the job to clean up/free resources on cancel |
| 54 | // or completion |
| 55 | inline void destroy(); |
| 56 | |
| 57 | // method that returns a 'key' string for finding a specific job |
| 58 | // (or jobs) usually used to find jobs to cancel |
| 59 | virtual const char* key() = 0; |
| 60 | |
| 61 | // method to obtain the database name the job is scheduled on |
| 62 | virtual const char* database() = 0; |
| 63 | |
| 64 | // method to obtain the table name the job is scheduled on |
| 65 | virtual const char* table() = 0; |
| 66 | |
| 67 | // method to obtain the type of job |
| 68 | virtual const char* type() = 0; |
| 69 | |
| 70 | // method to obtain a stringized list of job parameters |
| 71 | virtual const char* parameters() = 0; |
| 72 | |
| 73 | // method to obtain a sting identifying the current status of the job |
| 74 | virtual const char* status() = 0; |
| 75 | |
| 76 | inline bool running() const; |
| 77 | |
| 78 | inline bool cancelled() const; |
| 79 | |
| 80 | inline uint64_t id() const; |
| 81 | |
| 82 | inline bool user_scheduled() const; |
| 83 | |
| 84 | inline time_t scheduled_time() const; |
| 85 | |
| 86 | inline time_t started_time() const; |
| 87 | |
| 88 | protected: |
| 89 | // derived classed implement this to actually run their job |
| 90 | virtual void on_run() {}; |
| 91 | |
| 92 | // derived classes implement this to cancel their job |
| 93 | virtual void on_cancel() {}; |
| 94 | |
| 95 | // derived classes implement this to clean up/free resources |
| 96 | virtual void on_destroy() {}; |
| 97 | |
| 98 | private: |
| 99 | static std::atomic<uint64_t> _next_id; |
| 100 | std::atomic<bool> _running; |
| 101 | std::atomic<bool> _cancelled; |
| 102 | uint64_t _id; |
| 103 | bool _user_scheduled; |
| 104 | time_t _scheduled_time; |
| 105 | time_t _started_time; |
| 106 | }; |
| 107 | |
| 108 | // pfn for iterate callback |
| 109 | typedef void (*pfn_iterate_t)(class job_t*, void*); |
| 110 | |
| 111 | public: |
| 112 | void* operator new(size_t sz); |
| 113 | void operator delete(void* p); |
| 114 | |
| 115 | job_manager_t(); |
| 116 | |
| 117 | ~job_manager_t(); |
| 118 | |
| 119 | // creates/initializes a singleton bjm |
| 120 | void initialize(); |
| 121 | |
| 122 | // destroys a bjm singleton |
| 123 | // cancels all jobs abd frees all resources |
| 124 | void destroy(); |
| 125 | |
| 126 | // schedules or runs a job depending on the 'background' value |
| 127 | // job specifics all depend on the implementation od 'job' |
| 128 | // background jobs will be executed in a FIFO fashion |
| 129 | // two jobs with the same key can not run concurrently |
| 130 | // if a foreground job is attempted, any currently scheduled or running |
| 131 | // background jobs will be cancelled first |
| 132 | // if another foreground job is already running, a new foreground job with |
| 133 | // the same key will be rejected |
| 134 | bool run_job(job_t* newjob, bool background); |
| 135 | |
| 136 | // cancels any background job with a matching key |
| 137 | bool cancel_job(const char* key); |
| 138 | |
| 139 | // iterates currently pending and running background jobs, calling |
| 140 | // 'callback' with the 'extra' data provided and the original 'extra' |
| 141 | // data passed when the job was scheduled |
| 142 | void iterate_jobs(pfn_iterate_t callback, void* ) const; |
| 143 | |
| 144 | // lock the bjm, this prevents anyone from running, cancelling or iterating |
| 145 | // jobs in the bjm. |
| 146 | inline void lock(); |
| 147 | inline void unlock(); |
| 148 | |
| 149 | private: |
| 150 | static void* thread_func(void* v); |
| 151 | |
| 152 | void* real_thread_func(); |
| 153 | |
| 154 | // _mutex MUST be held on entry, will release and reaquire on exit |
| 155 | void run(job_t* job); |
| 156 | |
| 157 | // _mutex MUST be held on entry |
| 158 | void cancel(job_t* job); |
| 159 | private: |
| 160 | typedef std::list<job_t*> jobs_t; |
| 161 | |
| 162 | mutable tokudb::thread::mutex_t _mutex; |
| 163 | mutable tokudb::thread::semaphore_t _sem; |
| 164 | mutable tokudb::thread::thread_t _thread; |
| 165 | jobs_t _background_jobs; |
| 166 | jobs_t _foreground_jobs; |
| 167 | std::atomic<bool> _shutdown; |
| 168 | }; |
| 169 | |
| 170 | extern job_manager_t* _job_manager; |
| 171 | |
| 172 | bool initialize(); |
| 173 | bool destroy(); |
| 174 | |
| 175 | inline void job_manager_t::lock() { |
| 176 | assert_debug(!_mutex.is_owned_by_me()); |
| 177 | mutex_t_lock(_mutex); |
| 178 | } |
| 179 | inline void job_manager_t::unlock() { |
| 180 | assert_debug(_mutex.is_owned_by_me()); |
| 181 | mutex_t_unlock(_mutex); |
| 182 | } |
| 183 | |
| 184 | inline void job_manager_t::job_t::run() { |
| 185 | if (!_cancelled) { |
| 186 | _running = true; |
| 187 | _started_time = ::time(0); |
| 188 | on_run(); |
| 189 | _running = false; |
| 190 | } |
| 191 | } |
| 192 | inline void job_manager_t::job_t::cancel() { |
| 193 | _cancelled = true; |
| 194 | if (_running) |
| 195 | on_cancel(); |
| 196 | while (_running) tokudb::time::sleep_microsec(500000); |
| 197 | destroy(); |
| 198 | } |
| 199 | void job_manager_t::job_t::destroy() { |
| 200 | on_destroy(); |
| 201 | } |
| 202 | inline bool job_manager_t::job_t::running() const { |
| 203 | return _running; |
| 204 | } |
| 205 | inline bool job_manager_t::job_t::cancelled() const { |
| 206 | return _cancelled; |
| 207 | } |
| 208 | inline uint64_t job_manager_t::job_t::id() const { |
| 209 | return _id; |
| 210 | } |
| 211 | inline bool job_manager_t::job_t::user_scheduled() const { |
| 212 | return _user_scheduled; |
| 213 | } |
| 214 | inline time_t job_manager_t::job_t::scheduled_time() const { |
| 215 | return _scheduled_time; |
| 216 | } |
| 217 | inline time_t job_manager_t::job_t::started_time() const { |
| 218 | return _started_time; |
| 219 | } |
| 220 | } // namespace background |
| 221 | } // namespace tokudb |
| 222 | |
| 223 | #endif // _TOKUDB_BACKGROUND_H |
| 224 | |