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 lock_wait_callback _lock_wait_needed_callback; 206 uint64_t (*_loader_memory_size_callback)(void); 207 208 uint32_t _cachesize_gbytes; 209 uint32_t _cachesize_bytes; 210 uint32_t _cachetable_bucket_mutexes; 211 212 std::string _product_name; 213 214 std::string _lg_dir; 215 std::string _tmp_dir; 216 217 bool _direct_io; 218 bool _compress_buffers; 219 220 public: DBEnvBuilder()221 DBEnvBuilder() 222 : _bt_compare(nullptr), 223 _update_function(nullptr), 224 _generate_row_for_put(nullptr), 225 _generate_row_for_del(nullptr), 226 _cleaner_period(0), 227 _cleaner_iterations(0), 228 _checkpointing_period(0), 229 _fsync_log_period_msec(0), 230 _fs_redzone(0), 231 _lk_max_memory(0), 232 _lock_wait_time_msec(0), 233 _get_lock_wait_time_cb(nullptr), 234 _lock_timeout_callback(nullptr), 235 _lock_wait_needed_callback(nullptr), 236 _loader_memory_size_callback(nullptr), 237 _cachesize_gbytes(0), 238 _cachesize_bytes(0), 239 _cachetable_bucket_mutexes(0), 240 _product_name(""), 241 _lg_dir(""), 242 _tmp_dir(""), 243 _direct_io(false), 244 _compress_buffers(true) 245 {} 246 open(const char * env_dir,uint32_t flags,int mode) const247 DBEnv open(const char *env_dir, uint32_t flags, int mode) const { 248 db_env_set_direct_io(_direct_io); 249 db_env_set_compress_buffers_before_eviction(_compress_buffers); 250 if (_cachetable_bucket_mutexes) { 251 db_env_set_num_bucket_mutexes(_cachetable_bucket_mutexes); 252 } 253 254 if (!_product_name.empty()) { 255 db_env_set_toku_product_name(_product_name.c_str()); 256 } 257 258 DB_ENV *env; 259 int r = db_env_create(&env, 0); 260 handle_ft_retval(r); 261 262 if (_bt_compare) { 263 r = env->set_default_bt_compare(env, _bt_compare); 264 handle_ft_retval(r); 265 } 266 267 if (_update_function) { 268 env->set_update(env, _update_function); 269 } 270 271 if (_generate_row_for_put) { 272 r = env->set_generate_row_callback_for_put(env, _generate_row_for_put); 273 handle_ft_retval(r); 274 } 275 276 if (_generate_row_for_del) { 277 r = env->set_generate_row_callback_for_del(env, _generate_row_for_del); 278 handle_ft_retval(r); 279 } 280 281 if (_lk_max_memory) { 282 r = env->set_lk_max_memory(env, _lk_max_memory); 283 handle_ft_retval(r); 284 } 285 286 if (_lock_wait_time_msec || _get_lock_wait_time_cb) { 287 uint64_t wait_time = _lock_wait_time_msec; 288 if (!wait_time) { 289 r = env->get_lock_timeout(env, &wait_time); 290 handle_ft_retval(r); 291 } 292 r = env->set_lock_timeout(env, wait_time, _get_lock_wait_time_cb); 293 handle_ft_retval(r); 294 } 295 296 if (_lock_timeout_callback) { 297 r = env->set_lock_timeout_callback(env, _lock_timeout_callback); 298 handle_ft_retval(r); 299 } 300 301 if (_lock_wait_needed_callback) { 302 r = env->set_lock_wait_callback(env, _lock_wait_needed_callback); 303 handle_ft_retval(r); 304 } 305 306 if (_loader_memory_size_callback) { 307 env->set_loader_memory_size(env, _loader_memory_size_callback); 308 } 309 310 if (_cachesize_gbytes || _cachesize_bytes) { 311 r = env->set_cachesize(env, _cachesize_gbytes, _cachesize_bytes, 1); 312 handle_ft_retval(r); 313 } 314 315 if (_fs_redzone) { 316 env->set_redzone(env, _fs_redzone); 317 } 318 319 if (!_lg_dir.empty()) { 320 r = env->set_lg_dir(env, _lg_dir.c_str()); 321 handle_ft_retval(r); 322 } 323 324 if (!_tmp_dir.empty()) { 325 r = env->set_tmp_dir(env, _tmp_dir.c_str()); 326 handle_ft_retval(r); 327 } 328 329 r = env->open(env, env_dir, flags, mode); 330 handle_ft_retval(r); 331 332 if (_cleaner_period) { 333 r = env->cleaner_set_period(env, _cleaner_period); 334 handle_ft_retval(r); 335 } 336 337 if (_cleaner_iterations) { 338 r = env->cleaner_set_iterations(env, _cleaner_iterations); 339 handle_ft_retval(r); 340 } 341 342 if (_checkpointing_period) { 343 r = env->checkpointing_set_period(env, _checkpointing_period); 344 handle_ft_retval(r); 345 } 346 347 if (_fsync_log_period_msec) { 348 env->change_fsync_log_period(env, _fsync_log_period_msec); 349 } 350 351 return DBEnv(env, true); 352 } 353 set_direct_io(bool direct_io)354 DBEnvBuilder& set_direct_io(bool direct_io) { 355 _direct_io = direct_io; 356 return *this; 357 } 358 set_compress_buffers_before_eviction(bool compress_buffers)359 DBEnvBuilder& set_compress_buffers_before_eviction(bool compress_buffers) { 360 _compress_buffers = compress_buffers; 361 return *this; 362 } 363 set_default_bt_compare(bt_compare_func bt_compare)364 DBEnvBuilder& set_default_bt_compare(bt_compare_func bt_compare) { 365 _bt_compare = bt_compare; 366 return *this; 367 } 368 set_update(update_func update_function)369 DBEnvBuilder& set_update(update_func update_function) { 370 _update_function = update_function; 371 return *this; 372 } 373 set_generate_row_callback_for_put(generate_row_for_put_func generate_row_for_put)374 DBEnvBuilder& set_generate_row_callback_for_put(generate_row_for_put_func generate_row_for_put) { 375 _generate_row_for_put = generate_row_for_put; 376 return *this; 377 } 378 set_generate_row_callback_for_del(generate_row_for_del_func generate_row_for_del)379 DBEnvBuilder& set_generate_row_callback_for_del(generate_row_for_del_func generate_row_for_del) { 380 _generate_row_for_del = generate_row_for_del; 381 return *this; 382 } 383 cleaner_set_period(uint32_t period)384 DBEnvBuilder& cleaner_set_period(uint32_t period) { 385 _cleaner_period = period; 386 return *this; 387 } 388 cleaner_set_iterations(uint32_t iterations)389 DBEnvBuilder& cleaner_set_iterations(uint32_t iterations) { 390 _cleaner_iterations = iterations; 391 return *this; 392 } 393 checkpointing_set_period(uint32_t period)394 DBEnvBuilder& checkpointing_set_period(uint32_t period) { 395 _checkpointing_period = period; 396 return *this; 397 } 398 change_fsync_log_period(uint32_t period)399 DBEnvBuilder& change_fsync_log_period(uint32_t period) { 400 _fsync_log_period_msec = period; 401 return *this; 402 } 403 set_fs_redzone(int fs_redzone)404 DBEnvBuilder& set_fs_redzone(int fs_redzone) { 405 _fs_redzone = fs_redzone; 406 return *this; 407 } 408 set_lk_max_memory(uint64_t sz)409 DBEnvBuilder& set_lk_max_memory(uint64_t sz) { 410 _lk_max_memory = sz; 411 return *this; 412 } 413 set_lock_wait_time_msec(uint64_t lock_wait_time_msec)414 DBEnvBuilder& set_lock_wait_time_msec(uint64_t lock_wait_time_msec) { 415 _lock_wait_time_msec = lock_wait_time_msec; 416 return *this; 417 } 418 set_lock_wait_time_cb(get_lock_wait_time_cb_func get_lock_wait_time_cb)419 DBEnvBuilder& set_lock_wait_time_cb(get_lock_wait_time_cb_func get_lock_wait_time_cb) { 420 _get_lock_wait_time_cb = get_lock_wait_time_cb; 421 return *this; 422 } 423 set_lock_timeout_callback(lock_timeout_callback callback)424 DBEnvBuilder& set_lock_timeout_callback(lock_timeout_callback callback) { 425 _lock_timeout_callback = callback; 426 return *this; 427 } 428 set_lock_wait_callback(lock_wait_callback callback)429 DBEnvBuilder& set_lock_wait_callback(lock_wait_callback callback) { 430 _lock_wait_needed_callback = callback; 431 return *this; 432 } 433 set_loader_memory_size(uint64_t (* callback)(void))434 DBEnvBuilder& set_loader_memory_size(uint64_t (*callback)(void)) { 435 _loader_memory_size_callback = callback; 436 return *this; 437 } 438 set_cachesize(uint32_t gbytes,uint32_t bytes)439 DBEnvBuilder& set_cachesize(uint32_t gbytes, uint32_t bytes) { 440 _cachesize_gbytes = gbytes; 441 _cachesize_bytes = bytes; 442 return *this; 443 } 444 set_cachetable_bucket_mutexes(uint32_t mutexes)445 DBEnvBuilder& set_cachetable_bucket_mutexes(uint32_t mutexes) { 446 _cachetable_bucket_mutexes = mutexes; 447 return *this; 448 } 449 set_product_name(const char * product_name)450 DBEnvBuilder& set_product_name(const char *product_name) { 451 _product_name = std::string(product_name); 452 return *this; 453 } 454 set_lg_dir(const char * lg_dir)455 DBEnvBuilder& set_lg_dir(const char *lg_dir) { 456 _lg_dir = std::string(lg_dir); 457 return *this; 458 } 459 set_tmp_dir(const char * tmp_dir)460 DBEnvBuilder& set_tmp_dir(const char *tmp_dir) { 461 _tmp_dir = std::string(tmp_dir); 462 return *this; 463 } 464 }; 465 466 } // namespace ftcxx 467