1877.2.6
by Brian Aker
Fixed header/etc. |
1 |
/* -*- mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; -*-
|
2 |
* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
|
|
3 |
*
|
|
4 |
* Copyright (C) 2010 Brian Aker
|
|
5 |
*
|
|
6 |
* This program is free software; you can redistribute it and/or modify
|
|
7 |
* it under the terms of the GNU General Public License as published by
|
|
8 |
* the Free Software Foundation; either version 2 of the License, or
|
|
9 |
* (at your option) any later version.
|
|
10 |
*
|
|
11 |
* This program is distributed in the hope that it will be useful,
|
|
12 |
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
13 |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
14 |
* GNU General Public License for more details.
|
|
15 |
*
|
|
16 |
* You should have received a copy of the GNU General Public License
|
|
17 |
* along with this program; if not, write to the Free Software
|
|
18 |
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
19 |
*/
|
|
20 |
||
2173.2.1
by Monty Taylor
Fixes incorrect usage of include |
21 |
#include <config.h> |
2275.3.2
by Olaf van der Spek
Session Cache |
22 |
#include <drizzled/table/cache.h> |
1877.2.6
by Brian Aker
Fixed header/etc. |
23 |
|
24 |
#include <sys/types.h> |
|
25 |
#include <sys/stat.h> |
|
26 |
#include <fcntl.h> |
|
27 |
||
2318.6.116
by Olaf van der Spek
Add copyright |
28 |
#include <drizzled/identifier.h> |
29 |
#include <drizzled/open_tables_state.h> |
|
30 |
#include <drizzled/pthread_globals.h> |
|
31 |
#include <drizzled/session.h> |
|
32 |
#include <drizzled/sql_base.h> |
|
33 |
#include <drizzled/sys_var.h> |
|
34 |
#include <drizzled/table.h> |
|
35 |
#include <drizzled/table/concurrent.h> |
|
36 |
#include <drizzled/table/unused.h> |
|
1877.2.8
by Brian Aker
Additional encapsulation |
37 |
|
2241.2.14
by Olaf van der Spek
Refactor |
38 |
namespace drizzled { |
39 |
namespace table { |
|
1877.2.6
by Brian Aker
Fixed header/etc. |
40 |
|
2272.1.3
by Olaf van der Spek
Table Cache |
41 |
CacheMap Cache::cache; |
42 |
boost::mutex Cache::_mutex; |
|
43 |
||
44 |
CacheMap& getCache() |
|
1877.2.6
by Brian Aker
Fixed header/etc. |
45 |
{
|
2275.3.1
by Olaf van der Spek
Remove table::Cache::singleton() |
46 |
return Cache::getCache(); |
1877.2.6
by Brian Aker
Fixed header/etc. |
47 |
}
|
48 |
||
49 |
/*
|
|
50 |
Remove table from the open table cache
|
|
51 |
||
52 |
SYNOPSIS
|
|
53 |
free_cache_entry()
|
|
54 |
entry Table to remove
|
|
55 |
||
56 |
NOTE
|
|
2275.3.1
by Olaf van der Spek
Remove table::Cache::singleton() |
57 |
We need to have a lock on table::Cache::mutex() when calling this
|
1877.2.6
by Brian Aker
Fixed header/etc. |
58 |
*/
|
59 |
||
60 |
static void free_cache_entry(table::Concurrent *table) |
|
61 |
{
|
|
62 |
table->intern_close_table(); |
|
63 |
if (not table->in_use) |
|
64 |
{
|
|
65 |
getUnused().unlink(table); |
|
66 |
}
|
|
67 |
||
2069.4.1
by Brian Aker
A little on the paranoid side, but not the worst plan ever to check our |
68 |
boost::checked_delete(table); |
1877.2.6
by Brian Aker
Fixed header/etc. |
69 |
}
|
70 |
||
71 |
void remove_table(table::Concurrent *arg) |
|
72 |
{
|
|
73 |
CacheRange ppp; |
|
74 |
ppp= getCache().equal_range(arg->getShare()->getCacheKey()); |
|
75 |
||
76 |
for (CacheMap::const_iterator iter= ppp.first; |
|
77 |
iter != ppp.second; ++iter) |
|
78 |
{
|
|
2192.4.7
by Olaf van der Spek
Use "iter->" instead of "(*iter)." |
79 |
table::Concurrent *found_table= iter->second; |
1877.2.6
by Brian Aker
Fixed header/etc. |
80 |
|
81 |
if (found_table == arg) |
|
82 |
{
|
|
83 |
free_cache_entry(arg); |
|
84 |
getCache().erase(iter); |
|
85 |
return; |
|
86 |
}
|
|
87 |
}
|
|
88 |
}
|
|
89 |
||
1877.2.7
by Brian Aker
Encapsulate more of the table cache. |
90 |
/*
|
91 |
Wait until all threads has closed the tables in the list
|
|
92 |
We have also to wait if there is thread that has a lock on this table even
|
|
93 |
if the table is closed
|
|
94 |
*/
|
|
95 |
||
96 |
bool Cache::areTablesUsed(Table *table, bool wait_for_name_lock) |
|
97 |
{
|
|
98 |
do
|
|
99 |
{
|
|
2087.4.2
by Brian Aker
Modify TableIdentifier to fit with the rest of the identifiers. |
100 |
const identifier::Table::Key &key(table->getShare()->getCacheKey()); |
1877.2.7
by Brian Aker
Encapsulate more of the table cache. |
101 |
|
102 |
table::CacheRange ppp= table::getCache().equal_range(key); |
|
103 |
||
104 |
for (table::CacheMap::const_iterator iter= ppp.first; iter != ppp.second; ++iter) |
|
105 |
{
|
|
2192.4.7
by Olaf van der Spek
Use "iter->" instead of "(*iter)." |
106 |
Table *search= iter->second; |
1877.2.7
by Brian Aker
Encapsulate more of the table cache. |
107 |
if (search->in_use == table->in_use) |
108 |
continue; // Name locked by this thread |
|
109 |
/*
|
|
110 |
We can't use the table under any of the following conditions:
|
|
111 |
- There is an name lock on it (Table is to be deleted or altered)
|
|
112 |
- If we are in flush table and we didn't execute the flush
|
|
113 |
- If the table engine is open and it's an old version
|
|
114 |
(We must wait until all engines are shut down to use the table)
|
|
115 |
*/
|
|
116 |
if ( (search->locked_by_name && wait_for_name_lock) || |
|
117 |
(search->is_name_opened() && search->needs_reopen_or_name_lock())) |
|
118 |
return 1; |
|
119 |
}
|
|
120 |
} while ((table=table->getNext())); |
|
121 |
return 0; |
|
122 |
}
|
|
123 |
||
1877.2.8
by Brian Aker
Additional encapsulation |
124 |
/*
|
125 |
Invalidate any cache entries that are for some DB
|
|
126 |
||
127 |
SYNOPSIS
|
|
1887.2.5
by Brian Aker
OSX found a reference to a function that was no longer declared. |
128 |
removeSchema()
|
1877.2.8
by Brian Aker
Additional encapsulation |
129 |
db Database name. This will be in lower case if
|
130 |
lower_case_table_name is set
|
|
131 |
||
132 |
NOTE:
|
|
133 |
We can't use hash_delete when looping hash_elements. We mark them first
|
|
134 |
and afterwards delete those marked unused.
|
|
135 |
*/
|
|
136 |
||
2087.4.1
by Brian Aker
Merge in schema identifier. |
137 |
void Cache::removeSchema(const identifier::Schema &schema_identifier) |
1877.2.8
by Brian Aker
Additional encapsulation |
138 |
{
|
1938.4.11
by Brian Aker
Scoped locks a bit better. |
139 |
boost::mutex::scoped_lock scopedLock(_mutex); |
1877.2.8
by Brian Aker
Additional encapsulation |
140 |
|
141 |
for (table::CacheMap::const_iterator iter= table::getCache().begin(); |
|
142 |
iter != table::getCache().end(); |
|
143 |
iter++) |
|
144 |
{
|
|
2192.4.7
by Olaf van der Spek
Use "iter->" instead of "(*iter)." |
145 |
table::Concurrent *table= iter->second; |
1877.2.8
by Brian Aker
Additional encapsulation |
146 |
|
147 |
if (not schema_identifier.getPath().compare(table->getShare()->getSchemaName())) |
|
148 |
{
|
|
149 |
table->getMutableShare()->resetVersion(); /* Free when thread is ready */ |
|
150 |
if (not table->in_use) |
|
151 |
table::getUnused().relink(table); |
|
152 |
}
|
|
153 |
}
|
|
154 |
||
155 |
table::getUnused().cullByVersion(); |
|
156 |
}
|
|
157 |
||
158 |
/*
|
|
159 |
Mark all entries with the table as deleted to force an reopen of the table
|
|
160 |
||
161 |
The table will be closed (not stored in cache) by the current thread when
|
|
162 |
close_thread_tables() is called.
|
|
163 |
||
164 |
PREREQUISITES
|
|
2275.3.1
by Olaf van der Spek
Remove table::Cache::singleton() |
165 |
Lock on table::Cache::mutex()()
|
1877.2.8
by Brian Aker
Additional encapsulation |
166 |
|
167 |
RETURN
|
|
168 |
0 This thread now have exclusive access to this table and no other thread
|
|
169 |
can access the table until close_thread_tables() is called.
|
|
170 |
1 Table is in use by another thread
|
|
171 |
*/
|
|
172 |
||
2272.1.2
by Olaf van der Spek
Table Cache |
173 |
bool Cache::removeTable(Session& session, const identifier::Table &identifier, uint32_t flags) |
1877.2.8
by Brian Aker
Additional encapsulation |
174 |
{
|
2087.4.2
by Brian Aker
Modify TableIdentifier to fit with the rest of the identifiers. |
175 |
const identifier::Table::Key &key(identifier.getKey()); |
2227.4.3
by Olaf van der Spek
Remove unnecessary statement.h include |
176 |
bool result= false; |
1877.2.8
by Brian Aker
Additional encapsulation |
177 |
bool signalled= false; |
178 |
||
179 |
for (;;) |
|
180 |
{
|
|
181 |
result= signalled= false; |
|
182 |
||
183 |
table::CacheRange ppp; |
|
184 |
ppp= table::getCache().equal_range(key); |
|
185 |
||
186 |
for (table::CacheMap::const_iterator iter= ppp.first; |
|
187 |
iter != ppp.second; ++iter) |
|
188 |
{
|
|
2192.4.7
by Olaf van der Spek
Use "iter->" instead of "(*iter)." |
189 |
table::Concurrent *table= iter->second; |
1877.2.8
by Brian Aker
Additional encapsulation |
190 |
Session *in_use; |
191 |
||
192 |
table->getMutableShare()->resetVersion(); /* Free when thread is ready */ |
|
193 |
if (not (in_use= table->in_use)) |
|
194 |
{
|
|
195 |
table::getUnused().relink(table); |
|
196 |
}
|
|
2272.1.2
by Olaf van der Spek
Table Cache |
197 |
else if (in_use != &session) |
1877.2.8
by Brian Aker
Additional encapsulation |
198 |
{
|
199 |
/*
|
|
200 |
Mark that table is going to be deleted from cache. This will
|
|
1910.2.7
by Brian Aker
Rename lock methods to be style + well make sense. |
201 |
force threads that are in lockTables() (but not yet
|
1877.2.8
by Brian Aker
Additional encapsulation |
202 |
in thr_multi_lock()) to abort it's locks, close all tables and retry
|
203 |
*/
|
|
204 |
if (table->is_name_opened()) |
|
205 |
{
|
|
206 |
result= true; |
|
207 |
}
|
|
208 |
/*
|
|
209 |
Now we must abort all tables locks used by this thread
|
|
210 |
as the thread may be waiting to get a lock for another table.
|
|
2275.3.1
by Olaf van der Spek
Remove table::Cache::singleton() |
211 |
Note that we need to hold table::Cache::mutex() while going through the
|
1877.2.8
by Brian Aker
Additional encapsulation |
212 |
list. So that the other thread cannot change it. The other
|
2275.3.1
by Olaf van der Spek
Remove table::Cache::singleton() |
213 |
thread must also hold table::Cache::mutex() whenever changing the
|
1877.2.8
by Brian Aker
Additional encapsulation |
214 |
open_tables list. Aborting the MERGE lock after a child was
|
215 |
closed and before the parent is closed would be fatal.
|
|
216 |
*/
|
|
2263.3.3
by Olaf van der Spek
Use open_tables |
217 |
for (Table *session_table= in_use->open_tables.open_tables_; |
1877.2.8
by Brian Aker
Additional encapsulation |
218 |
session_table ; |
219 |
session_table= session_table->getNext()) |
|
220 |
{
|
|
221 |
/* Do not handle locks of MERGE children. */
|
|
222 |
if (session_table->db_stat) // If table is open |
|
2272.1.2
by Olaf van der Spek
Table Cache |
223 |
signalled|= session.abortLockForThread(session_table); |
1877.2.8
by Brian Aker
Additional encapsulation |
224 |
}
|
225 |
}
|
|
226 |
else
|
|
227 |
{
|
|
228 |
result= result || (flags & RTFC_OWNED_BY_Session_FLAG); |
|
229 |
}
|
|
230 |
}
|
|
231 |
||
232 |
table::getUnused().cullByVersion(); |
|
233 |
||
234 |
/* Remove table from table definition cache if it's not in use */
|
|
2069.4.4
by Brian Aker
Create a shared form of the instance which is a bit more heavier weight then |
235 |
table::instance::release(identifier); |
1877.2.8
by Brian Aker
Additional encapsulation |
236 |
|
237 |
if (result && (flags & RTFC_WAIT_OTHER_THREAD_FLAG)) |
|
238 |
{
|
|
239 |
/*
|
|
240 |
Signal any thread waiting for tables to be freed to
|
|
241 |
reopen their tables
|
|
242 |
*/
|
|
1910.2.5
by Brian Aker
Merge in changes such that lock is now broken out into its own directory. |
243 |
locking::broadcast_refresh(); |
2272.1.2
by Olaf van der Spek
Table Cache |
244 |
if (not (flags & RTFC_CHECK_KILLED_FLAG) || not session.getKilled()) |
1877.2.8
by Brian Aker
Additional encapsulation |
245 |
{
|
246 |
dropping_tables++; |
|
247 |
if (likely(signalled)) |
|
248 |
{
|
|
2275.3.4
by Olaf van der Spek
Thread |
249 |
boost::mutex::scoped_lock scoped(table::Cache::mutex(), boost::adopt_lock_t()); |
1877.2.8
by Brian Aker
Additional encapsulation |
250 |
COND_refresh.wait(scoped); |
251 |
scoped.release(); |
|
252 |
}
|
|
253 |
else
|
|
254 |
{
|
|
255 |
/*
|
|
256 |
It can happen that another thread has opened the
|
|
257 |
table but has not yet locked any table at all. Since
|
|
258 |
it can be locked waiting for a table that our thread
|
|
259 |
has done LOCK Table x WRITE on previously, we need to
|
|
260 |
ensure that the thread actually hears our signal
|
|
261 |
before we go to sleep. Thus we wait for a short time
|
|
262 |
and then we retry another loop in the
|
|
2275.3.1
by Olaf van der Spek
Remove table::Cache::singleton() |
263 |
table::Cache::removeTable routine.
|
1877.2.8
by Brian Aker
Additional encapsulation |
264 |
*/
|
2227.4.3
by Olaf van der Spek
Remove unnecessary statement.h include |
265 |
boost::xtime xt; |
266 |
xtime_get(&xt, boost::TIME_UTC); |
|
267 |
xt.sec += 10; |
|
2275.3.4
by Olaf van der Spek
Thread |
268 |
boost::mutex::scoped_lock scoped(table::Cache::mutex(), boost::adopt_lock_t()); |
1877.2.8
by Brian Aker
Additional encapsulation |
269 |
COND_refresh.timed_wait(scoped, xt); |
270 |
scoped.release(); |
|
271 |
}
|
|
272 |
dropping_tables--; |
|
273 |
continue; |
|
274 |
}
|
|
275 |
}
|
|
276 |
break; |
|
277 |
}
|
|
278 |
||
279 |
return result; |
|
280 |
}
|
|
281 |
||
1903.1.1
by Brian Aker
Merge of partial set of patches for locks. |
282 |
|
2263.3.12
by Olaf van der Spek
Refactor constant return |
283 |
void Cache::insert(table::Concurrent* arg) |
1903.1.1
by Brian Aker
Merge of partial set of patches for locks. |
284 |
{
|
285 |
CacheMap::iterator returnable= cache.insert(std::make_pair(arg->getShare()->getCacheKey(), arg)); |
|
2241.3.12
by Olaf van der Spek
Refactor Session |
286 |
assert(returnable != cache.end()); |
1903.1.1
by Brian Aker
Merge of partial set of patches for locks. |
287 |
}
|
288 |
||
1877.2.6
by Brian Aker
Fixed header/etc. |
289 |
} /* namespace table */ |
290 |
} /* namespace drizzled */ |