1
/* -*- mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; -*-
2
* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
4
* Copyright (C) 2010 Brian Aker
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.
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.
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
23
#include <sys/types.h>
28
#include "drizzled/identifier/table.h"
29
#include "drizzled/table.h"
30
#include "drizzled/session.h"
31
#include "drizzled/table/concurrent.h"
33
#include "drizzled/table/cache.h"
34
#include "drizzled/table/unused.h"
36
#include "drizzled/pthread_globals.h"
46
CacheMap &getCache(void)
48
return Cache::singleton().getCache();
52
Remove table from the open table cache
59
We need to have a lock on LOCK_open when calling this
62
static void free_cache_entry(table::Concurrent *table)
64
table->intern_close_table();
65
if (not table->in_use)
67
getUnused().unlink(table);
73
void remove_table(table::Concurrent *arg)
76
ppp= getCache().equal_range(arg->getShare()->getCacheKey());
78
for (CacheMap::const_iterator iter= ppp.first;
79
iter != ppp.second; ++iter)
81
table::Concurrent *found_table= (*iter).second;
83
if (found_table == arg)
85
free_cache_entry(arg);
86
getCache().erase(iter);
93
Wait until all threads has closed the tables in the list
94
We have also to wait if there is thread that has a lock on this table even
95
if the table is closed
98
bool Cache::areTablesUsed(Table *table, bool wait_for_name_lock)
102
const TableIdentifier::Key &key(table->getShare()->getCacheKey());
104
table::CacheRange ppp= table::getCache().equal_range(key);
106
for (table::CacheMap::const_iterator iter= ppp.first; iter != ppp.second; ++iter)
108
Table *search= (*iter).second;
109
if (search->in_use == table->in_use)
110
continue; // Name locked by this thread
112
We can't use the table under any of the following conditions:
113
- There is an name lock on it (Table is to be deleted or altered)
114
- If we are in flush table and we didn't execute the flush
115
- If the table engine is open and it's an old version
116
(We must wait until all engines are shut down to use the table)
118
if ( (search->locked_by_name && wait_for_name_lock) ||
119
(search->is_name_opened() && search->needs_reopen_or_name_lock()))
122
} while ((table=table->getNext()));
127
Invalidate any cache entries that are for some DB
131
db Database name. This will be in lower case if
132
lower_case_table_name is set
135
We can't use hash_delete when looping hash_elements. We mark them first
136
and afterwards delete those marked unused.
139
void Cache::removeSchema(const SchemaIdentifier &schema_identifier)
141
//safe_mutex_assert_owner(LOCK_open.native_handle());
143
for (table::CacheMap::const_iterator iter= table::getCache().begin();
144
iter != table::getCache().end();
147
table::Concurrent *table= (*iter).second;
149
if (not schema_identifier.getPath().compare(table->getShare()->getSchemaName()))
151
table->getMutableShare()->resetVersion(); /* Free when thread is ready */
152
if (not table->in_use)
153
table::getUnused().relink(table);
157
table::getUnused().cullByVersion();
161
Mark all entries with the table as deleted to force an reopen of the table
163
The table will be closed (not stored in cache) by the current thread when
164
close_thread_tables() is called.
170
0 This thread now have exclusive access to this table and no other thread
171
can access the table until close_thread_tables() is called.
172
1 Table is in use by another thread
175
bool Cache::removeTable(Session *session, TableIdentifier &identifier, uint32_t flags)
177
const TableIdentifier::Key &key(identifier.getKey());
179
bool signalled= false;
183
result= signalled= false;
185
table::CacheRange ppp;
186
ppp= table::getCache().equal_range(key);
188
for (table::CacheMap::const_iterator iter= ppp.first;
189
iter != ppp.second; ++iter)
191
table::Concurrent *table= (*iter).second;
194
table->getMutableShare()->resetVersion(); /* Free when thread is ready */
195
if (not (in_use= table->in_use))
197
table::getUnused().relink(table);
199
else if (in_use != session)
202
Mark that table is going to be deleted from cache. This will
203
force threads that are in mysql_lock_tables() (but not yet
204
in thr_multi_lock()) to abort it's locks, close all tables and retry
206
in_use->some_tables_deleted= true;
207
if (table->is_name_opened())
212
Now we must abort all tables locks used by this thread
213
as the thread may be waiting to get a lock for another table.
214
Note that we need to hold LOCK_open while going through the
215
list. So that the other thread cannot change it. The other
216
thread must also hold LOCK_open whenever changing the
217
open_tables list. Aborting the MERGE lock after a child was
218
closed and before the parent is closed would be fatal.
220
for (Table *session_table= in_use->open_tables;
222
session_table= session_table->getNext())
224
/* Do not handle locks of MERGE children. */
225
if (session_table->db_stat) // If table is open
226
signalled|= mysql_lock_abort_for_thread(session, session_table);
231
result= result || (flags & RTFC_OWNED_BY_Session_FLAG);
235
table::getUnused().cullByVersion();
237
/* Remove table from table definition cache if it's not in use */
238
TableShare::release(identifier);
240
if (result && (flags & RTFC_WAIT_OTHER_THREAD_FLAG))
243
Signal any thread waiting for tables to be freed to
247
if (!(flags & RTFC_CHECK_KILLED_FLAG) || !session->killed)
250
if (likely(signalled))
252
boost_unique_lock_t scoped(LOCK_open, boost::adopt_lock_t());
253
COND_refresh.wait(scoped);
259
It can happen that another thread has opened the
260
table but has not yet locked any table at all. Since
261
it can be locked waiting for a table that our thread
262
has done LOCK Table x WRITE on previously, we need to
263
ensure that the thread actually hears our signal
264
before we go to sleep. Thus we wait for a short time
265
and then we retry another loop in the
266
table::Cache::singleton().removeTable routine.
269
xtime_get(&xt, boost::TIME_UTC);
271
boost_unique_lock_t scoped(LOCK_open, boost::adopt_lock_t());
272
COND_refresh.timed_wait(scoped, xt);
285
} /* namespace table */
286
} /* namespace drizzled */