1/*
2 Copyright (c) 2014, SkySQL Ab
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; version 2 of the License.
7
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
12
13 You should have received a copy of the GNU General Public License
14 along with this program; if not, write to the Free Software
15 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
16
17#ifdef USE_PRAGMA_IMPLEMENTATION
18#pragma implementation // gcc: Class implementation
19#endif
20
21/* For use of 'PRIu64': */
22#define __STDC_FORMAT_MACROS
23
24#include <my_global.h>
25
26#include <inttypes.h>
27
28/* This C++ files header file */
29#include "./rdb_cf_manager.h"
30
31/* MyRocks header files */
32#include "./ha_rocksdb.h"
33#include "./ha_rocksdb_proto.h"
34#include "./rdb_psi.h"
35
36namespace myrocks {
37
38/* Check if ColumnFamily name says it's a reverse-ordered CF */
39bool Rdb_cf_manager::is_cf_name_reverse(const char *const name) {
40 /* nullptr means the default CF is used.. (TODO: can the default CF be
41 * reverse?) */
42 return (name && !strncmp(name, "rev:", 4));
43}
44
45void Rdb_cf_manager::init(
46 std::unique_ptr<Rdb_cf_options> cf_options,
47 std::vector<rocksdb::ColumnFamilyHandle *> *const handles) {
48 mysql_mutex_init(rdb_cfm_mutex_key, &m_mutex, MY_MUTEX_INIT_FAST);
49
50 DBUG_ASSERT(cf_options != nullptr);
51 DBUG_ASSERT(handles != nullptr);
52 DBUG_ASSERT(handles->size() > 0);
53
54 m_cf_options = std::move(cf_options);
55
56 for (auto cfh : *handles) {
57 DBUG_ASSERT(cfh != nullptr);
58 m_cf_name_map[cfh->GetName()] = cfh;
59 m_cf_id_map[cfh->GetID()] = cfh;
60 }
61}
62
63void Rdb_cf_manager::cleanup() {
64 for (auto it : m_cf_name_map) {
65 delete it.second;
66 }
67 mysql_mutex_destroy(&m_mutex);
68 m_cf_options = nullptr;
69}
70
71/*
72 @brief
73 Find column family by name. If it doesn't exist, create it
74
75 @detail
76 See Rdb_cf_manager::get_cf
77*/
78rocksdb::ColumnFamilyHandle *
79Rdb_cf_manager::get_or_create_cf(rocksdb::DB *const rdb,
80 const std::string &cf_name_arg) {
81 DBUG_ASSERT(rdb != nullptr);
82
83 rocksdb::ColumnFamilyHandle *cf_handle = nullptr;
84
85 if (cf_name_arg == PER_INDEX_CF_NAME) {
86 // per-index column families is no longer supported.
87 my_error(ER_PER_INDEX_CF_DEPRECATED, MYF(0));
88 return nullptr;
89 }
90
91 const std::string &cf_name =
92 cf_name_arg.empty() ? DEFAULT_CF_NAME : cf_name_arg;
93
94 RDB_MUTEX_LOCK_CHECK(m_mutex);
95
96 const auto it = m_cf_name_map.find(cf_name);
97
98 if (it != m_cf_name_map.end()) {
99 cf_handle = it->second;
100 } else {
101 /* Create a Column Family. */
102 rocksdb::ColumnFamilyOptions opts;
103 m_cf_options->get_cf_options(cf_name, &opts);
104
105 // NO_LINT_DEBUG
106 sql_print_information("RocksDB: creating a column family %s",
107 cf_name.c_str());
108 sql_print_information(" write_buffer_size=%ld", opts.write_buffer_size);
109 sql_print_information(" target_file_size_base=%" PRIu64,
110 opts.target_file_size_base);
111
112 const rocksdb::Status s =
113 rdb->CreateColumnFamily(opts, cf_name, &cf_handle);
114
115 if (s.ok()) {
116 m_cf_name_map[cf_handle->GetName()] = cf_handle;
117 m_cf_id_map[cf_handle->GetID()] = cf_handle;
118 } else {
119 cf_handle = nullptr;
120 }
121 }
122
123 RDB_MUTEX_UNLOCK_CHECK(m_mutex);
124
125 return cf_handle;
126}
127
128/*
129 Find column family by its cf_name.
130*/
131
132rocksdb::ColumnFamilyHandle *
133Rdb_cf_manager::get_cf(const std::string &cf_name_arg) const {
134 rocksdb::ColumnFamilyHandle *cf_handle;
135
136 RDB_MUTEX_LOCK_CHECK(m_mutex);
137
138 std::string cf_name = cf_name_arg.empty() ? DEFAULT_CF_NAME : cf_name_arg;
139
140 const auto it = m_cf_name_map.find(cf_name);
141 cf_handle = (it != m_cf_name_map.end()) ? it->second : nullptr;
142
143 if (!cf_handle) {
144 // NO_LINT_DEBUG
145 sql_print_warning("Column family '%s' not found.", cf_name.c_str());
146 }
147
148 RDB_MUTEX_UNLOCK_CHECK(m_mutex);
149
150 return cf_handle;
151}
152
153rocksdb::ColumnFamilyHandle *Rdb_cf_manager::get_cf(const uint32_t &id) const {
154 rocksdb::ColumnFamilyHandle *cf_handle = nullptr;
155
156 RDB_MUTEX_LOCK_CHECK(m_mutex);
157 const auto it = m_cf_id_map.find(id);
158 if (it != m_cf_id_map.end())
159 cf_handle = it->second;
160 RDB_MUTEX_UNLOCK_CHECK(m_mutex);
161
162 return cf_handle;
163}
164
165std::vector<std::string> Rdb_cf_manager::get_cf_names(void) const {
166 std::vector<std::string> names;
167
168 RDB_MUTEX_LOCK_CHECK(m_mutex);
169 for (auto it : m_cf_name_map) {
170 names.push_back(it.first);
171 }
172 RDB_MUTEX_UNLOCK_CHECK(m_mutex);
173
174 return names;
175}
176
177std::vector<rocksdb::ColumnFamilyHandle *>
178Rdb_cf_manager::get_all_cf(void) const {
179 std::vector<rocksdb::ColumnFamilyHandle *> list;
180
181 RDB_MUTEX_LOCK_CHECK(m_mutex);
182
183 for (auto it : m_cf_id_map) {
184 DBUG_ASSERT(it.second != nullptr);
185 list.push_back(it.second);
186 }
187
188 RDB_MUTEX_UNLOCK_CHECK(m_mutex);
189
190 return list;
191}
192
193} // namespace myrocks
194