~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/table_share.cc

  • Committer: Monty Taylor
  • Date: 2009-04-25 20:45:19 UTC
  • mto: (997.2.5 mordred)
  • mto: This revision was merged to the branch mainline in revision 1003.
  • Revision ID: mordred@inaugust.com-20090425204519-lgrl7mz2r66v0jby
Blackhole.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* -*- mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; -*-
2
 
 *  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
3
 
 *
4
 
 *  Copyright (C) 2009 Sun Microsystems
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
 
/*
22
 
  This class is shared between different table objects. There is one
23
 
  instance of table share per one table in the database.
24
 
*/
25
 
 
26
 
/* Basic functions needed by many modules */
27
 
#include "config.h"
28
 
 
29
 
#include <pthread.h>
30
 
 
31
 
#include <cassert>
32
 
 
33
 
#include "drizzled/error.h"
34
 
#include "drizzled/gettext.h"
35
 
#include "drizzled/sql_base.h"
36
 
#include "drizzled/hash.h"
37
 
#include "drizzled/pthread_globals.h"
38
 
#include "drizzled/internal/my_pthread.h"
39
 
 
40
 
using namespace std;
41
 
 
42
 
namespace drizzled
43
 
{
44
 
 
45
 
extern size_t table_def_size;
46
 
TableDefinitionCache table_def_cache;
47
 
static pthread_mutex_t LOCK_table_share;
48
 
bool table_def_inited= false;
49
 
 
50
 
/*****************************************************************************
51
 
  Functions to handle table definition cach (TableShare)
52
 
 *****************************************************************************/
53
 
 
54
 
 
55
 
void TableShare::cacheStart(void)
56
 
{
57
 
  pthread_mutex_init(&LOCK_table_share, MY_MUTEX_INIT_FAST);
58
 
  table_def_inited= true;
59
 
  /* 
60
 
   * This is going to overalloc a bit - as rehash sets the number of
61
 
   * buckets, not the number of elements. BUT, it'll allow us to not need
62
 
   * to rehash later on as the hash_map grows.
63
 
   */
64
 
  table_def_cache.rehash(table_def_size);
65
 
}
66
 
 
67
 
 
68
 
void TableShare::cacheStop(void)
69
 
{
70
 
  if (table_def_inited)
71
 
  {
72
 
    table_def_inited= false;
73
 
    pthread_mutex_destroy(&LOCK_table_share);
74
 
  }
75
 
}
76
 
 
77
 
 
78
 
/**
79
 
 * @TODO: This should return size_t
80
 
 */
81
 
uint32_t cached_table_definitions(void)
82
 
{
83
 
  return static_cast<uint32_t>(table_def_cache.size());
84
 
}
85
 
 
86
 
 
87
 
/*
88
 
  Mark that we are not using table share anymore.
89
 
 
90
 
  SYNOPSIS
91
 
  release()
92
 
  share         Table share
93
 
 
94
 
  IMPLEMENTATION
95
 
  If ref_count goes to zero and (we have done a refresh or if we have
96
 
  already too many open table shares) then delete the definition.
97
 
*/
98
 
 
99
 
void TableShare::release(TableShare *share)
100
 
{
101
 
  bool to_be_deleted= false;
102
 
  safe_mutex_assert_owner(&LOCK_open);
103
 
 
104
 
  pthread_mutex_lock(&share->mutex);
105
 
  if (!--share->ref_count)
106
 
    to_be_deleted= true;
107
 
 
108
 
  if (to_be_deleted)
109
 
  {
110
 
    const string key_string(share->table_cache_key.str,
111
 
                            share->table_cache_key.length);
112
 
    TableDefinitionCache::iterator iter= table_def_cache.find(key_string);
113
 
    if (iter != table_def_cache.end())
114
 
    {
115
 
      (*iter).second->free_table_share();
116
 
      table_def_cache.erase(iter);
117
 
    }
118
 
    return;
119
 
  }
120
 
  pthread_mutex_unlock(&share->mutex);
121
 
}
122
 
 
123
 
void TableShare::release(const char *key, uint32_t key_length)
124
 
{
125
 
  const string key_string(key, key_length);
126
 
 
127
 
  TableDefinitionCache::iterator iter= table_def_cache.find(key_string);
128
 
  if (iter != table_def_cache.end())
129
 
  {
130
 
    TableShare *share= (*iter).second;
131
 
    share->version= 0;                          // Mark for delete
132
 
    if (share->ref_count == 0)
133
 
    {
134
 
      pthread_mutex_lock(&share->mutex);
135
 
      share->free_table_share();
136
 
      table_def_cache.erase(key_string);
137
 
    }
138
 
  }
139
 
}
140
 
 
141
 
 
142
 
static TableShare *foundTableShare(TableShare *share)
143
 
{
144
 
  /*
145
 
    We found an existing table definition. Return it if we didn't get
146
 
    an error when reading the table definition from file.
147
 
  */
148
 
 
149
 
  /* We must do a lock to ensure that the structure is initialized */
150
 
  (void) pthread_mutex_lock(&share->mutex);
151
 
  if (share->error)
152
 
  {
153
 
    /* Table definition contained an error */
154
 
    share->open_table_error(share->error, share->open_errno, share->errarg);
155
 
    (void) pthread_mutex_unlock(&share->mutex);
156
 
 
157
 
    return NULL;
158
 
  }
159
 
 
160
 
  share->ref_count++;
161
 
  (void) pthread_mutex_unlock(&share->mutex);
162
 
 
163
 
  return share;
164
 
}
165
 
 
166
 
/*
167
 
  Get TableShare for a table.
168
 
 
169
 
  get_table_share()
170
 
  session                       Thread handle
171
 
  table_list            Table that should be opened
172
 
  key                   Table cache key
173
 
  key_length            Length of key
174
 
  error                 out: Error code from open_table_def()
175
 
 
176
 
  IMPLEMENTATION
177
 
  Get a table definition from the table definition cache.
178
 
  If it doesn't exist, create a new from the table definition file.
179
 
 
180
 
  NOTES
181
 
  We must have wrlock on LOCK_open when we come here
182
 
  (To be changed later)
183
 
 
184
 
  RETURN
185
 
  0  Error
186
 
#  Share for table
187
 
*/
188
 
 
189
 
TableShare *TableShare::getShare(Session *session, 
190
 
                                 TableList *table_list, char *key,
191
 
                                 uint32_t key_length, uint32_t, int *error)
192
 
{
193
 
  const string key_string(key, key_length);
194
 
  TableShare *share= NULL;
195
 
 
196
 
  *error= 0;
197
 
 
198
 
  /* Read table definition from cache */
199
 
  TableDefinitionCache::iterator iter= table_def_cache.find(key_string);
200
 
  if (iter != table_def_cache.end())
201
 
  {
202
 
    share= (*iter).second;
203
 
    return foundTableShare(share);
204
 
  }
205
 
 
206
 
  if (not (share= alloc_table_share(table_list, key, key_length)))
207
 
  {
208
 
    return NULL;
209
 
  }
210
 
 
211
 
  /*
212
 
    Lock mutex to be able to read table definition from file without
213
 
    conflicts
214
 
  */
215
 
  (void) pthread_mutex_lock(&share->mutex);
216
 
 
217
 
  /**
218
 
   * @TODO: we need to eject something if we exceed table_def_size
219
 
   */
220
 
  pair<TableDefinitionCache::iterator, bool> ret=
221
 
    table_def_cache.insert(make_pair(key_string, share));
222
 
  if (ret.second == false)
223
 
  {
224
 
    share->free_table_share();
225
 
    return NULL;
226
 
  }
227
 
  
228
 
  TableIdentifier identifier(share->getSchemaName(), share->getTableName());
229
 
  if (open_table_def(*session, identifier, share))
230
 
  {
231
 
    *error= share->error;
232
 
    table_def_cache.erase(key_string);
233
 
    share->free_table_share();
234
 
    return NULL;
235
 
  }
236
 
  share->ref_count++;                           // Mark in use
237
 
  (void) pthread_mutex_unlock(&share->mutex);
238
 
 
239
 
  return share;
240
 
}
241
 
 
242
 
 
243
 
/*
244
 
  Check if table definition exits in cache
245
 
 
246
 
  SYNOPSIS
247
 
  get_cached_table_share()
248
 
  db                    Database name
249
 
  table_name            Table name
250
 
 
251
 
  RETURN
252
 
  0  Not cached
253
 
#  TableShare for table
254
 
*/
255
 
TableShare *TableShare::getShare(TableIdentifier &identifier)
256
 
{
257
 
  char key[MAX_DBKEY_LENGTH];
258
 
  uint32_t key_length;
259
 
  safe_mutex_assert_owner(&LOCK_open);
260
 
 
261
 
  key_length= TableShare::createKey(key, identifier);
262
 
 
263
 
  const string key_string(key, key_length);
264
 
 
265
 
  TableDefinitionCache::iterator iter= table_def_cache.find(key_string);
266
 
  if (iter != table_def_cache.end())
267
 
  {
268
 
    return (*iter).second;
269
 
  }
270
 
  else
271
 
  {
272
 
    return NULL;
273
 
  }
274
 
}
275
 
 
276
 
/**
277
 
 * @todo
278
 
 *
279
 
 * Precache this stuff....
280
 
 */
281
 
bool TableShare::fieldInPrimaryKey(Field *in_field) const
282
 
{
283
 
  assert(table_proto != NULL);
284
 
  
285
 
  size_t num_indexes= table_proto->indexes_size();
286
 
 
287
 
  for (size_t x= 0; x < num_indexes; ++x)
288
 
  {
289
 
    const message::Table::Index &index= table_proto->indexes(x);
290
 
    if (index.is_primary())
291
 
    {
292
 
      size_t num_parts= index.index_part_size();
293
 
      for (size_t y= 0; y < num_parts; ++y)
294
 
      {
295
 
        if (index.index_part(y).fieldnr() == in_field->field_index)
296
 
          return true;
297
 
      }
298
 
    }
299
 
  }
300
 
  return false;
301
 
}
302
 
 
303
 
TableDefinitionCache &TableShare::getCache()
304
 
{
305
 
  return table_def_cache;
306
 
}
307
 
 
308
 
} /* namespace drizzled */