~drizzle-trunk/drizzle/development

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
21
#include "config.h"
22
23
#include <sys/types.h>
24
#include <sys/stat.h>
25
#include <fcntl.h>
26
27
28
#include "drizzled/identifier/table.h"
29
#include "drizzled/table.h"
1877.2.8 by Brian Aker
Additional encapsulation
30
#include "drizzled/session.h"
1877.2.6 by Brian Aker
Fixed header/etc.
31
#include "drizzled/table/concurrent.h"
32
33
#include "drizzled/table/cache.h"
34
#include "drizzled/table/unused.h"
35
1877.2.8 by Brian Aker
Additional encapsulation
36
#include "drizzled/pthread_globals.h"
37
1877.2.6 by Brian Aker
Fixed header/etc.
38
namespace drizzled
39
{
1877.2.8 by Brian Aker
Additional encapsulation
40
41
class Session;
42
1877.2.6 by Brian Aker
Fixed header/etc.
43
namespace table
44
{
45
46
CacheMap &getCache(void)
47
{
48
  return Cache::singleton().getCache();
49
}
50
51
/*
52
  Remove table from the open table cache
53
54
  SYNOPSIS
55
  free_cache_entry()
56
  entry		Table to remove
57
58
  NOTE
1938.4.10 by Brian Aker
Convert LOCK_open to lock in mutex
59
  We need to have a lock on table::Cache::singleton().mutex() when calling this
1877.2.6 by Brian Aker
Fixed header/etc.
60
*/
61
62
static void free_cache_entry(table::Concurrent *table)
63
{
64
  table->intern_close_table();
65
  if (not table->in_use)
66
  {
67
    getUnused().unlink(table);
68
  }
69
70
  delete table;
71
}
72
73
void remove_table(table::Concurrent *arg)
74
{
75
  CacheRange ppp;
76
  ppp= getCache().equal_range(arg->getShare()->getCacheKey());
77
78
  for (CacheMap::const_iterator iter= ppp.first;
79
         iter != ppp.second; ++iter)
80
  {
81
    table::Concurrent *found_table= (*iter).second;
82
83
    if (found_table == arg)
84
    {
85
      free_cache_entry(arg);
86
      getCache().erase(iter);
87
      return;
88
    }
89
  }
90
}
91
1877.2.7 by Brian Aker
Encapsulate more of the table cache.
92
/*
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
96
*/
97
98
bool Cache::areTablesUsed(Table *table, bool wait_for_name_lock)
99
{
100
  do
101
  {
102
    const TableIdentifier::Key &key(table->getShare()->getCacheKey());
103
104
    table::CacheRange ppp= table::getCache().equal_range(key);
105
106
    for (table::CacheMap::const_iterator iter= ppp.first; iter != ppp.second; ++iter)
107
    {
108
      Table *search= (*iter).second;
109
      if (search->in_use == table->in_use)
110
        continue;                               // Name locked by this thread
111
      /*
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)
117
      */
118
      if ( (search->locked_by_name && wait_for_name_lock) ||
119
           (search->is_name_opened() && search->needs_reopen_or_name_lock()))
120
        return 1;
121
    }
122
  } while ((table=table->getNext()));
123
  return 0;
124
}
125
1877.2.8 by Brian Aker
Additional encapsulation
126
/*
127
  Invalidate any cache entries that are for some DB
128
129
  SYNOPSIS
1887.2.5 by Brian Aker
OSX found a reference to a function that was no longer declared.
130
  removeSchema()
1877.2.8 by Brian Aker
Additional encapsulation
131
  db		Database name. This will be in lower case if
132
  lower_case_table_name is set
133
134
NOTE:
135
We can't use hash_delete when looping hash_elements. We mark them first
136
and afterwards delete those marked unused.
137
*/
138
139
void Cache::removeSchema(const SchemaIdentifier &schema_identifier)
140
{
1938.4.11 by Brian Aker
Scoped locks a bit better.
141
  boost::mutex::scoped_lock scopedLock(_mutex);
1877.2.8 by Brian Aker
Additional encapsulation
142
143
  for (table::CacheMap::const_iterator iter= table::getCache().begin();
144
       iter != table::getCache().end();
145
       iter++)
146
  {
147
    table::Concurrent *table= (*iter).second;
148
149
    if (not schema_identifier.getPath().compare(table->getShare()->getSchemaName()))
150
    {
151
      table->getMutableShare()->resetVersion();			/* Free when thread is ready */
152
      if (not table->in_use)
153
        table::getUnused().relink(table);
154
    }
155
  }
156
157
  table::getUnused().cullByVersion();
158
}
159
160
/*
161
  Mark all entries with the table as deleted to force an reopen of the table
162
163
  The table will be closed (not stored in cache) by the current thread when
164
  close_thread_tables() is called.
165
166
  PREREQUISITES
1938.4.10 by Brian Aker
Convert LOCK_open to lock in mutex
167
  Lock on table::Cache::singleton().mutex()()
1877.2.8 by Brian Aker
Additional encapsulation
168
169
  RETURN
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
173
*/
174
175
bool Cache::removeTable(Session *session, TableIdentifier &identifier, uint32_t flags)
176
{
177
  const TableIdentifier::Key &key(identifier.getKey());
178
  bool result= false; 
179
  bool signalled= false;
180
181
  for (;;)
182
  {
183
    result= signalled= false;
184
185
    table::CacheRange ppp;
186
    ppp= table::getCache().equal_range(key);
187
188
    for (table::CacheMap::const_iterator iter= ppp.first;
189
         iter != ppp.second; ++iter)
190
    {
191
      table::Concurrent *table= (*iter).second;
192
      Session *in_use;
193
194
      table->getMutableShare()->resetVersion();		/* Free when thread is ready */
195
      if (not (in_use= table->in_use))
196
      {
197
        table::getUnused().relink(table);
198
      }
199
      else if (in_use != session)
200
      {
201
        /*
202
          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.
203
          force threads that are in lockTables() (but not yet
1877.2.8 by Brian Aker
Additional encapsulation
204
          in thr_multi_lock()) to abort it's locks, close all tables and retry
205
        */
206
        in_use->some_tables_deleted= true;
207
        if (table->is_name_opened())
208
        {
209
          result= true;
210
        }
211
        /*
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.
1938.4.10 by Brian Aker
Convert LOCK_open to lock in mutex
214
          Note that we need to hold table::Cache::singleton().mutex() while going through the
1877.2.8 by Brian Aker
Additional encapsulation
215
          list. So that the other thread cannot change it. The other
1938.4.10 by Brian Aker
Convert LOCK_open to lock in mutex
216
          thread must also hold table::Cache::singleton().mutex() whenever changing the
1877.2.8 by Brian Aker
Additional encapsulation
217
          open_tables list. Aborting the MERGE lock after a child was
218
          closed and before the parent is closed would be fatal.
219
        */
220
        for (Table *session_table= in_use->open_tables;
221
             session_table ;
222
             session_table= session_table->getNext())
223
        {
224
          /* Do not handle locks of MERGE children. */
225
          if (session_table->db_stat)	// If table is open
1910.2.7 by Brian Aker
Rename lock methods to be style + well make sense.
226
            signalled|= session->abortLockForThread(session_table);
1877.2.8 by Brian Aker
Additional encapsulation
227
        }
228
      }
229
      else
230
      {
231
        result= result || (flags & RTFC_OWNED_BY_Session_FLAG);
232
      }
233
    }
234
235
    table::getUnused().cullByVersion();
236
237
    /* Remove table from table definition cache if it's not in use */
238
    TableShare::release(identifier);
239
240
    if (result && (flags & RTFC_WAIT_OTHER_THREAD_FLAG))
241
    {
242
      /*
243
        Signal any thread waiting for tables to be freed to
244
        reopen their tables
245
      */
1910.2.5 by Brian Aker
Merge in changes such that lock is now broken out into its own directory.
246
      locking::broadcast_refresh();
1910.2.8 by Brian Aker
Enapsulate Kill.
247
      if (not (flags & RTFC_CHECK_KILLED_FLAG) || not session->getKilled())
1877.2.8 by Brian Aker
Additional encapsulation
248
      {
249
        dropping_tables++;
250
        if (likely(signalled))
251
        {
1938.4.10 by Brian Aker
Convert LOCK_open to lock in mutex
252
          boost_unique_lock_t scoped(table::Cache::singleton().mutex(), boost::adopt_lock_t());
1877.2.8 by Brian Aker
Additional encapsulation
253
          COND_refresh.wait(scoped);
254
          scoped.release();
255
        }
256
        else
257
        {
258
          /*
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
1887.2.5 by Brian Aker
OSX found a reference to a function that was no longer declared.
266
            table::Cache::singleton().removeTable routine.
1877.2.8 by Brian Aker
Additional encapsulation
267
          */
268
          boost::xtime xt; 
269
          xtime_get(&xt, boost::TIME_UTC); 
270
          xt.sec += 10; 
1938.4.10 by Brian Aker
Convert LOCK_open to lock in mutex
271
          boost_unique_lock_t scoped(table::Cache::singleton().mutex(), boost::adopt_lock_t());
1877.2.8 by Brian Aker
Additional encapsulation
272
          COND_refresh.timed_wait(scoped, xt);
273
          scoped.release();
274
        }
275
        dropping_tables--;
276
        continue;
277
      }
278
    }
279
    break;
280
  }
281
282
  return result;
283
}
284
1903.1.1 by Brian Aker
Merge of partial set of patches for locks.
285
286
bool Cache::insert(table::Concurrent *arg)
287
{
288
  CacheMap::iterator returnable= cache.insert(std::make_pair(arg->getShare()->getCacheKey(), arg));
289
290
  return not (returnable == cache.end());
291
}
292
1877.2.6 by Brian Aker
Fixed header/etc.
293
} /* namespace table */
294
} /* namespace drizzled */