diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-04 18:07:14 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-04 18:07:14 +0000 |
commit | a175314c3e5827eb193872241446f2f8f5c9d33c (patch) | |
tree | cd3d60ca99ae00829c52a6ca79150a5b6e62528b /storage/tokudb/tokudb_status.h | |
parent | Initial commit. (diff) | |
download | mariadb-10.5-9e4947182e0b875da38088fdd168e775f473b8ad.tar.xz mariadb-10.5-9e4947182e0b875da38088fdd168e775f473b8ad.zip |
Adding upstream version 1:10.5.12.upstream/1%10.5.12upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'storage/tokudb/tokudb_status.h')
-rw-r--r-- | storage/tokudb/tokudb_status.h | 416 |
1 files changed, 416 insertions, 0 deletions
diff --git a/storage/tokudb/tokudb_status.h b/storage/tokudb/tokudb_status.h new file mode 100644 index 00000000..07772bdc --- /dev/null +++ b/storage/tokudb/tokudb_status.h @@ -0,0 +1,416 @@ +/* -*- mode: C++; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +// vim: ft=cpp:expandtab:ts=8:sw=4:softtabstop=4: +#ident "$Id$" +/*====== +This file is part of TokuDB + + +Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved. + + TokuDBis is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License, version 2, + as published by the Free Software Foundation. + + TokuDB is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with TokuDB. If not, see <http://www.gnu.org/licenses/>. + +======= */ + +#ident "Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved." + +#ifndef _TOKUDB_STATUS_H +#define _TOKUDB_STATUS_H + +// These are keys that will be used for retrieving metadata in status.tokudb +// To get the version, one looks up the value associated with key hatoku_version +// in status.tokudb +typedef ulonglong HA_METADATA_KEY; +#define hatoku_old_version 0 +#define hatoku_capabilities 1 +#define hatoku_max_ai 2 //maximum auto increment value found so far +#define hatoku_ai_create_value 3 +#define hatoku_key_name 4 +#define hatoku_frm_data 5 +#define hatoku_new_version 6 +#define hatoku_cardinality 7 + +// use a very small pagesize for the status dictionary +#define status_dict_pagesize 1024 + +namespace tokudb { +namespace metadata { + +// get the value for a given key in the status dictionary. +// copy the value to the supplied buffer. +// returns 0 if successful. +int read( + DB* status_db, + DB_TXN* txn, + HA_METADATA_KEY k, + void* p, + size_t s, + size_t* sp) { + + DBT key = {}; + key.data = &k; + key.size = sizeof(k); + DBT val = {}; + val.data = p; + val.ulen = (uint32_t)s; + val.flags = DB_DBT_USERMEM; + int error = status_db->get(status_db, txn, &key, &val, 0); + if (error == 0) { + *sp = val.size; + } + return error; +} + +// get the value for a given key in the status dictionary. +// put the value in a realloced buffer. +// returns 0 if successful. +int read_realloc( + DB* status_db, + DB_TXN* txn, + HA_METADATA_KEY k, + void** pp, + size_t* sp) { + + DBT key = {}; + key.data = &k; + key.size = sizeof(k); + DBT val = {}; + val.data = *pp; + val.size = (uint32_t)*sp; + val.flags = DB_DBT_REALLOC; + int error = status_db->get(status_db, txn, &key, &val, 0); + if (error == 0) { + *pp = val.data; + *sp = val.size; + } + return error; +} + +// write a key value pair into the status dictionary, +// overwriting the previous value if any. +// auto create a txn if necessary. +// returns 0 if successful. +int write_low( + DB* status_db, + void* key_data, + uint key_size, + void* val_data, + uint val_size, + DB_TXN *txn) { + + DBT key = {}; + key.data = key_data; + key.size = key_size; + DBT value = {}; + value.data = val_data; + value.size = val_size; + int error = status_db->put(status_db, txn, &key, &value, 0); + return error; +} + +// write a key value pair into the status dictionary, +// overwriting the previous value if any. +// the key must be a HA_METADATA_KEY. +// returns 0 if successful. +int write( + DB* status_db, + HA_METADATA_KEY curr_key_data, + void* val, + size_t val_size, + DB_TXN* txn) { + + return + tokudb::metadata::write_low( + status_db, + &curr_key_data, + sizeof(curr_key_data), + val, + val_size, + txn); +} + +// remove a key from the status dictionary. +// auto create a txn if necessary. +// returns 0 if successful. +int remove_low( + DB* status_db, + void* key_data, + uint key_size, + DB_TXN* txn) { + + DBT key = {}; + key.data = key_data; + key.size = key_size; + int error = status_db->del(status_db, txn, &key, DB_DELETE_ANY); + return error; +} + +// remove a key from the status dictionary. +// the key must be a HA_METADATA_KEY +// returns 0 if successful. +int remove( + DB* status_db, + HA_METADATA_KEY curr_key_data, + DB_TXN* txn) { + return + tokudb::metadata::remove_low( + status_db, + &curr_key_data, + sizeof(curr_key_data), + txn); +} + +int close(DB** status_db_ptr) { + int error = 0; + DB* status_db = *status_db_ptr; + if (status_db) { + error = status_db->close(status_db, 0); + if (error == 0) + *status_db_ptr = NULL; + } + return error; +} + +int create( + DB_ENV* env, + DB** status_db_ptr, + const char* name, + DB_TXN* txn) { + + int error; + DB *status_db = NULL; + + error = db_create(&status_db, env, 0); + if (error == 0) { + error = status_db->set_pagesize(status_db, status_dict_pagesize); + } + if (error == 0) { + error = + status_db->open( + status_db, + txn, + name, + NULL, + DB_BTREE, DB_CREATE | DB_EXCL, + S_IWUSR); + } + if (error == 0) { + *status_db_ptr = status_db; + } else { + int r = tokudb::metadata::close(&status_db); + assert_always(r == 0); + } + return error; +} + +int open( + DB_ENV* env, + DB** status_db_ptr, + const char* name, + DB_TXN* txn) { + + int error = 0; + DB* status_db = NULL; + error = db_create(&status_db, env, 0); + if (error == 0) { + error = + status_db->open( + status_db, + txn, + name, + NULL, + DB_BTREE, + DB_THREAD, + S_IWUSR); + } + if (error == 0) { + uint32_t pagesize = 0; + error = status_db->get_pagesize(status_db, &pagesize); + if (error == 0 && pagesize > status_dict_pagesize) { + error = + status_db->change_pagesize(status_db, status_dict_pagesize); + } + } + if (error == 0) { + *status_db_ptr = status_db; + } else { + int r = tokudb::metadata::close(&status_db); + assert_always(r == 0); + } + return error; +} + +int strip_frm_data(DB_ENV* env) { + int r; + DB_TXN* txn = NULL; + + fprintf(stderr, "TokuDB strip_frm_data : Beginning stripping process.\n"); + + r = db_env->txn_begin(env, NULL, &txn, 0); + assert_always(r == 0); + + DBC* c = NULL; + r = env->get_cursor_for_directory(env, txn, &c); + assert_always(r == 0); + + DBT key = { }; + key.flags = DB_DBT_REALLOC; + + DBT val = { }; + val.flags = DB_DBT_REALLOC; + while (1) { + r = c->c_get(c, &key, &val, DB_NEXT); + if (r == DB_NOTFOUND) + break; + const char* dname = (const char*) key.data; + const char* iname = (const char*) val.data; + assert_always(r == 0); + + if (strstr(iname, "_status_")) { + fprintf( + stderr, + "TokuDB strip_frm_data : stripping from dname=%s iname=%s\n", + dname, + iname); + + DB* status_db; + r = tokudb::metadata::open(db_env, &status_db, dname, txn); + if (r != 0) { + fprintf( + stderr, + "TokuDB strip_frm_data : unable to open status file %s, " + "error = %d\n", + dname, + r); + continue; + } + + // GOL : this is a godawful hack. The inventors of this did not + // think it would be a good idea to use some kind of magic + // identifier k/v pair so that you can in fact tell a proper status + // file from any other file that might have the string _status_ in + // it. Out in ha_tokudb::create, when the status file is initially + // created, it is immediately populated with: + // uint hatoku_new_version=HA_TOKU_VERSION=4 and + // uint hatoku_capabilities=HA_TOKU_CAP=0 + // Since I can't count on the fact that these values are/were + // _always_ 4 and 0, I can count on the fact that they _must_ be + // there and the _must_ be sizeof(uint). That will at least give us + // a much better idea that these are in fact status files. + void* p = NULL; + size_t sz; + r = + tokudb::metadata::read_realloc( + status_db, + txn, + hatoku_new_version, + &p, + &sz); + if (r != 0) { + fprintf( + stderr, + "TokuDB strip_frm_data : does not look like a real TokuDB " + "status file, new_verion is missing, leaving alone %s \n", + dname); + + r = tokudb::metadata::close(&status_db); + assert_always(r == 0); + continue; + } else if (sz != sizeof(uint)) { + fprintf( + stderr, + "TokuDB strip_frm_data : does not look like a real TokuDB " + "status file, new_verion is the wrong size, " + "leaving alone %s \n", + dname); + + tokudb::memory::free(p); + r = tokudb::metadata::close(&status_db); + assert_always(r == 0); + continue; + } + tokudb::memory::free(p); + p = NULL; + + r = + tokudb::metadata::read_realloc( + status_db, + txn, + hatoku_capabilities, + &p, + &sz); + if (r != 0) { + fprintf( + stderr, + "TokuDB strip_frm_data : does not look like a real TokuDB " + "status file, capabilities is missing, leaving alone %s \n", + dname); + + r = tokudb::metadata::close(&status_db); + assert_always(r == 0); + continue; + } else if (sz != sizeof(uint)) { + fprintf( + stderr, + "TokuDB strip_frm_data : does not look like a real TokuDB " + "status file, capabilities is the wrong size, " + "leaving alone %s \n", + dname); + + tokudb::memory::free(p); + r = tokudb::metadata::close(&status_db); + assert_always(r == 0); + continue; + } + tokudb::memory::free(p); + + // OK, st this point, it is probably a status file, not 100% but + // it looks like it :( + r = tokudb::metadata::remove(status_db, hatoku_frm_data, txn); + if (r != 0) { + fprintf( + stderr, + "TokuDB strip_frm_data : unable to find/strip frm data " + "from status file %s, error = %d\n", + dname, + r); + } + + r = tokudb::metadata::close(&status_db); + assert_always(r == 0); + } + } + tokudb::memory::free(key.data); + tokudb::memory::free(val.data); + + fprintf( + stderr, + "TokuDB strip_frm_data : Stripping process complete, beginning " + "commit, this may take some time.\n"); + + r = c->c_close(c); + assert_always(r == 0); + + r = txn->commit(txn, 0); + assert_always(r == 0); + + fprintf( + stderr, + "TokuDB strip_frm_data : Commit complete, resuming server init " + "process."); + + return 0; +} + +} // namespace metadata +} // namespace tokudb +#endif |