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 | |
36 | namespace myrocks { |
37 | |
38 | /* Check if ColumnFamily name says it's a reverse-ordered CF */ |
39 | bool 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 | |
45 | void 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 | |
63 | void 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 | */ |
78 | rocksdb::ColumnFamilyHandle * |
79 | Rdb_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 | |
132 | rocksdb::ColumnFamilyHandle * |
133 | Rdb_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 | |
153 | rocksdb::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 | |
165 | std::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 | |
177 | std::vector<rocksdb::ColumnFamilyHandle *> |
178 | Rdb_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 | |