1 /* -*- mode: C++; c-basic-offset: 4; indent-tabs-mode: nil -*- */ 2 #ident "$Id$" 3 /*====== 4 This file is part of PerconaFT. 5 6 7 Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved. 8 9 PerconaFT is free software: you can redistribute it and/or modify 10 it under the terms of the GNU General Public License, version 2, 11 as published by the Free Software Foundation. 12 13 PerconaFT is distributed in the hope that it will be useful, 14 but WITHOUT ANY WARRANTY; without even the implied warranty of 15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 GNU General Public License for more details. 17 18 You should have received a copy of the GNU General Public License 19 along with PerconaFT. If not, see <http://www.gnu.org/licenses/>. 20 21 ---------------------------------------- 22 23 PerconaFT is free software: you can redistribute it and/or modify 24 it under the terms of the GNU Affero General Public License, version 3, 25 as published by the Free Software Foundation. 26 27 PerconaFT is distributed in the hope that it will be useful, 28 but WITHOUT ANY WARRANTY; without even the implied warranty of 29 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 30 GNU Affero General Public License for more details. 31 32 You should have received a copy of the GNU Affero General Public License 33 along with PerconaFT. If not, see <http://www.gnu.org/licenses/>. 34 ======= */ 35 36 #ident "Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved." 37 38 #pragma once 39 40 #include <errno.h> 41 42 #include <map> 43 #include <string> 44 45 #include <db.h> 46 47 #include "exceptions.hpp" 48 #include "slice.hpp" 49 50 namespace ftcxx { 51 52 template<class Comparator, class Handler> 53 class CallbackCursor; 54 template<class Comparator, class Predicate> 55 class BufferedCursor; 56 template<class Comparator> 57 class SimpleCursor; 58 59 class DBTxn; 60 61 class DBEnv { 62 public: DBEnv(DB_ENV * e,bool close_on_destroy=false)63 explicit DBEnv(DB_ENV *e, bool close_on_destroy=false) 64 : _env(e), 65 _close_on_destroy(close_on_destroy) 66 {} 67 ~DBEnv()68 ~DBEnv() { 69 if (_env && _close_on_destroy) { 70 close(); 71 } 72 } 73 74 DBEnv(const DBEnv &) = delete; 75 DBEnv& operator=(const DBEnv &) = delete; 76 DBEnv(DBEnv && o)77 DBEnv(DBEnv &&o) 78 : _env(nullptr), 79 _close_on_destroy(false) 80 { 81 std::swap(_env, o._env); 82 std::swap(_close_on_destroy, o._close_on_destroy); 83 } 84 operator =(DBEnv && o)85 DBEnv& operator=(DBEnv &&o) { 86 std::swap(_env, o._env); 87 std::swap(_close_on_destroy, o._close_on_destroy); 88 return *this; 89 } 90 env() const91 DB_ENV *env() const { return _env; } 92 close()93 void close() { 94 int r = _env->close(_env, 0); 95 handle_ft_retval(r); 96 _env = nullptr; 97 } 98 99 typedef std::map<std::string, TOKU_ENGINE_STATUS_ROW_S> Status; 100 void get_status(Status &status, fs_redzone_state &redzone_state, uint64_t &env_panic, std::string &panic_string) const; 101 log_flush()102 void log_flush() { 103 int r = _env->log_flush(_env, NULL); 104 handle_ft_retval(r); 105 } 106 checkpointing_set_period(uint32_t period)107 int checkpointing_set_period(uint32_t period) { 108 if (!_env) { 109 return EINVAL; 110 } 111 _env->checkpointing_set_period(_env, period); 112 return 0; 113 } 114 cleaner_set_iterations(uint32_t iterations)115 int cleaner_set_iterations(uint32_t iterations) { 116 if (!_env) { 117 return EINVAL; 118 } 119 _env->cleaner_set_iterations(_env, iterations); 120 return 0; 121 } 122 cleaner_set_period(uint32_t period)123 int cleaner_set_period(uint32_t period) { 124 if (!_env) { 125 return EINVAL; 126 } 127 _env->cleaner_set_period(_env, period); 128 return 0; 129 } 130 change_fsync_log_period(uint32_t period)131 int change_fsync_log_period(uint32_t period) { 132 if (!_env) { 133 return EINVAL; 134 } 135 _env->change_fsync_log_period(_env, period); 136 return 0; 137 } 138 get_engine_status_num_rows()139 uint64_t get_engine_status_num_rows() { 140 if (!_env) { 141 handle_ft_retval(EINVAL); // throws 142 } 143 uint64_t ret; 144 int r = _env->get_engine_status_num_rows(_env, &ret); 145 handle_ft_retval(r); 146 return ret; 147 } 148 get_engine_status(TOKU_ENGINE_STATUS_ROW_S * rows,uint64_t max_rows,uint64_t & num_rows,uint64_t & panic,std::string & panic_string,toku_engine_status_include_type include_type)149 void get_engine_status(TOKU_ENGINE_STATUS_ROW_S *rows, uint64_t max_rows, uint64_t &num_rows, 150 uint64_t &panic, std::string &panic_string, 151 toku_engine_status_include_type include_type) { 152 if (!_env) { 153 handle_ft_retval(EINVAL); 154 } 155 fs_redzone_state dummy; // this is duplicated in the actual engine status output 156 const size_t panic_string_len = 1024; 157 char panic_string_buf[panic_string_len]; 158 panic_string_buf[0] = '\0'; 159 int r = _env->get_engine_status(_env, rows, max_rows, &num_rows, 160 &dummy, &panic, panic_string_buf, panic_string_len, 161 include_type); 162 handle_ft_retval(r); 163 panic_string = panic_string_buf; 164 } 165 166 /** 167 * Constructs a Cursor over this DBEnv's directory. 168 */ 169 template<class Comparator, class Handler> 170 CallbackCursor<Comparator, Handler> cursor(const DBTxn &txn, Comparator &&cmp, Handler &&handler) const; 171 172 template<class Comparator, class Predicate> 173 BufferedCursor<Comparator, Predicate> buffered_cursor(const DBTxn &txn, Comparator &&cmp, Predicate &&filter) const; 174 175 template<class Comparator> 176 SimpleCursor<Comparator> simple_cursor(const DBTxn &txn, Comparator &&cmp, Slice &key, Slice &val) const; 177 178 private: 179 DB_ENV *_env; 180 bool _close_on_destroy; 181 }; 182 183 class DBEnvBuilder { 184 typedef int (*bt_compare_func)(DB *, const DBT *, const DBT *); 185 bt_compare_func _bt_compare; 186 187 typedef int (*update_func)(DB *, const DBT *, const DBT *, const DBT *, void (*)(const DBT *, void *), void *); 188 update_func _update_function; 189 190 generate_row_for_put_func _generate_row_for_put; 191 generate_row_for_del_func _generate_row_for_del; 192 193 uint32_t _cleaner_period; 194 uint32_t _cleaner_iterations; 195 uint32_t _checkpointing_period; 196 uint32_t _fsync_log_period_msec; 197 int _fs_redzone; 198 199 uint64_t _lk_max_memory; 200 uint64_t _lock_wait_time_msec; 201 202 typedef uint64_t (*get_lock_wait_time_cb_func)(uint64_t); 203 get_lock_wait_time_cb_func _get_lock_wait_time_cb; 204 lock_timeout_callback _lock_timeout_callback; 205 uint64_t (*_loader_memory_size_callback)(void); 206 207 uint32_t _cachesize_gbytes; 208 uint32_t _cachesize_bytes; 209 uint32_t _cachetable_bucket_mutexes; 210 211 std::string _product_name; 212 213 std::string _lg_dir; 214 std::string _tmp_dir; 215 216 bool _direct_io; 217 bool _compress_buffers; 218 219 public: DBEnvBuilder()220 DBEnvBuilder() 221 : _bt_compare(nullptr), 222 _update_function(nullptr), 223 _generate_row_for_put(nullptr), 224 _generate_row_for_del(nullptr), 225 _cleaner_period(0), 226 _cleaner_iterations(0), 227 _checkpointing_period(0), 228 _fsync_log_period_msec(0), 229 _fs_redzone(0), 230 _lk_max_memory(0), 231 _lock_wait_time_msec(0), 232 _get_lock_wait_time_cb(nullptr), 233 _lock_timeout_callback(nullptr), 234 _loader_memory_size_callback(nullptr), 235 _cachesize_gbytes(0), 236 _cachesize_bytes(0), 237 _cachetable_bucket_mutexes(0), 238 _product_name(""), 239 _lg_dir(""), 240 _tmp_dir(""), 241 _direct_io(false), 242 _compress_buffers(true) 243 {} 244 open(const char * env_dir,uint32_t flags,int mode) const245 DBEnv open(const char *env_dir, uint32_t flags, int mode) const { 246 db_env_set_direct_io(_direct_io); 247 db_env_set_compress_buffers_before_eviction(_compress_buffers); 248 if (_cachetable_bucket_mutexes) { 249 db_env_set_num_bucket_mutexes(_cachetable_bucket_mutexes); 250 } 251 252 if (!_product_name.empty()) { 253 db_env_set_toku_product_name(_product_name.c_str()); 254 } 255 256 DB_ENV *env; 257 int r = db_env_create(&env, 0); 258 handle_ft_retval(r); 259 260 if (_bt_compare) { 261 r = env->set_default_bt_compare(env, _bt_compare); 262 handle_ft_retval(r); 263 } 264 265 if (_update_function) { 266 env->set_update(env, _update_function); 267 } 268 269 if (_generate_row_for_put) { 270 r = env->set_generate_row_callback_for_put(env, _generate_row_for_put); 271 handle_ft_retval(r); 272 } 273 274 if (_generate_row_for_del) { 275 r = env->set_generate_row_callback_for_del(env, _generate_row_for_del); 276 handle_ft_retval(r); 277 } 278 279 if (_lk_max_memory) { 280 r = env->set_lk_max_memory(env, _lk_max_memory); 281 handle_ft_retval(r); 282 } 283 284 if (_lock_wait_time_msec || _get_lock_wait_time_cb) { 285 uint64_t wait_time = _lock_wait_time_msec; 286 if (!wait_time) { 287 r = env->get_lock_timeout(env, &wait_time); 288 handle_ft_retval(r); 289 } 290 r = env->set_lock_timeout(env, wait_time, _get_lock_wait_time_cb); 291 handle_ft_retval(r); 292 } 293 294 if (_lock_timeout_callback) { 295 r = env->set_lock_timeout_callback(env, _lock_timeout_callback); 296 handle_ft_retval(r); 297 } 298 299 if (_loader_memory_size_callback) { 300 env->set_loader_memory_size(env, _loader_memory_size_callback); 301 } 302 303 if (_cachesize_gbytes || _cachesize_bytes) { 304 r = env->set_cachesize(env, _cachesize_gbytes, _cachesize_bytes, 1); 305 handle_ft_retval(r); 306 } 307 308 if (_fs_redzone) { 309 env->set_redzone(env, _fs_redzone); 310 } 311 312 if (!_lg_dir.empty()) { 313 r = env->set_lg_dir(env, _lg_dir.c_str()); 314 handle_ft_retval(r); 315 } 316 317 if (!_tmp_dir.empty()) { 318 r = env->set_tmp_dir(env, _tmp_dir.c_str()); 319 handle_ft_retval(r); 320 } 321 322 r = env->open(env, env_dir, flags, mode); 323 handle_ft_retval(r); 324 325 if (_cleaner_period) { 326 r = env->cleaner_set_period(env, _cleaner_period); 327 handle_ft_retval(r); 328 } 329 330 if (_cleaner_iterations) { 331 r = env->cleaner_set_iterations(env, _cleaner_iterations); 332 handle_ft_retval(r); 333 } 334 335 if (_checkpointing_period) { 336 r = env->checkpointing_set_period(env, _checkpointing_period); 337 handle_ft_retval(r); 338 } 339 340 if (_fsync_log_period_msec) { 341 env->change_fsync_log_period(env, _fsync_log_period_msec); 342 } 343 344 return DBEnv(env, true); 345 } 346 set_direct_io(bool direct_io)347 DBEnvBuilder& set_direct_io(bool direct_io) { 348 _direct_io = direct_io; 349 return *this; 350 } 351 set_compress_buffers_before_eviction(bool compress_buffers)352 DBEnvBuilder& set_compress_buffers_before_eviction(bool compress_buffers) { 353 _compress_buffers = compress_buffers; 354 return *this; 355 } 356 set_default_bt_compare(bt_compare_func bt_compare)357 DBEnvBuilder& set_default_bt_compare(bt_compare_func bt_compare) { 358 _bt_compare = bt_compare; 359 return *this; 360 } 361 set_update(update_func update_function)362 DBEnvBuilder& set_update(update_func update_function) { 363 _update_function = update_function; 364 return *this; 365 } 366 set_generate_row_callback_for_put(generate_row_for_put_func generate_row_for_put)367 DBEnvBuilder& set_generate_row_callback_for_put(generate_row_for_put_func generate_row_for_put) { 368 _generate_row_for_put = generate_row_for_put; 369 return *this; 370 } 371 set_generate_row_callback_for_del(generate_row_for_del_func generate_row_for_del)372 DBEnvBuilder& set_generate_row_callback_for_del(generate_row_for_del_func generate_row_for_del) { 373 _generate_row_for_del = generate_row_for_del; 374 return *this; 375 } 376 cleaner_set_period(uint32_t period)377 DBEnvBuilder& cleaner_set_period(uint32_t period) { 378 _cleaner_period = period; 379 return *this; 380 } 381 cleaner_set_iterations(uint32_t iterations)382 DBEnvBuilder& cleaner_set_iterations(uint32_t iterations) { 383 _cleaner_iterations = iterations; 384 return *this; 385 } 386 checkpointing_set_period(uint32_t period)387 DBEnvBuilder& checkpointing_set_period(uint32_t period) { 388 _checkpointing_period = period; 389 return *this; 390 } 391 change_fsync_log_period(uint32_t period)392 DBEnvBuilder& change_fsync_log_period(uint32_t period) { 393 _fsync_log_period_msec = period; 394 return *this; 395 } 396 set_fs_redzone(int fs_redzone)397 DBEnvBuilder& set_fs_redzone(int fs_redzone) { 398 _fs_redzone = fs_redzone; 399 return *this; 400 } 401 set_lk_max_memory(uint64_t sz)402 DBEnvBuilder& set_lk_max_memory(uint64_t sz) { 403 _lk_max_memory = sz; 404 return *this; 405 } 406 set_lock_wait_time_msec(uint64_t lock_wait_time_msec)407 DBEnvBuilder& set_lock_wait_time_msec(uint64_t lock_wait_time_msec) { 408 _lock_wait_time_msec = lock_wait_time_msec; 409 return *this; 410 } 411 set_lock_wait_time_cb(get_lock_wait_time_cb_func get_lock_wait_time_cb)412 DBEnvBuilder& set_lock_wait_time_cb(get_lock_wait_time_cb_func get_lock_wait_time_cb) { 413 _get_lock_wait_time_cb = get_lock_wait_time_cb; 414 return *this; 415 } 416 set_lock_timeout_callback(lock_timeout_callback callback)417 DBEnvBuilder& set_lock_timeout_callback(lock_timeout_callback callback) { 418 _lock_timeout_callback = callback; 419 return *this; 420 } 421 set_loader_memory_size(uint64_t (* callback)(void))422 DBEnvBuilder& set_loader_memory_size(uint64_t (*callback)(void)) { 423 _loader_memory_size_callback = callback; 424 return *this; 425 } 426 set_cachesize(uint32_t gbytes,uint32_t bytes)427 DBEnvBuilder& set_cachesize(uint32_t gbytes, uint32_t bytes) { 428 _cachesize_gbytes = gbytes; 429 _cachesize_bytes = bytes; 430 return *this; 431 } 432 set_cachetable_bucket_mutexes(uint32_t mutexes)433 DBEnvBuilder& set_cachetable_bucket_mutexes(uint32_t mutexes) { 434 _cachetable_bucket_mutexes = mutexes; 435 return *this; 436 } 437 set_product_name(const char * product_name)438 DBEnvBuilder& set_product_name(const char *product_name) { 439 _product_name = std::string(product_name); 440 return *this; 441 } 442 set_lg_dir(const char * lg_dir)443 DBEnvBuilder& set_lg_dir(const char *lg_dir) { 444 _lg_dir = std::string(lg_dir); 445 return *this; 446 } 447 set_tmp_dir(const char * tmp_dir)448 DBEnvBuilder& set_tmp_dir(const char *tmp_dir) { 449 _tmp_dir = std::string(tmp_dir); 450 return *this; 451 } 452 }; 453 454 } // namespace ftcxx 455