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 | |