~drizzle-trunk/drizzle/development

1093.6.1 by Brian Aker
Refactor TableShare has to be behind class.
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 */
1241.9.36 by Monty Taylor
ZOMG. I deleted drizzled/server_includes.h.
27
#include "config.h"
1223.3.1 by Monty Taylor
Replace HASH in table_share with drizzled::hash_map
28
1241.9.57 by Monty Taylor
Oy. Bigger change than I normally like - but this stuff is all intertwined.
29
#include <pthread.h>
30
31
#include <cassert>
1093.6.1 by Brian Aker
Refactor TableShare has to be behind class.
32
1223.3.1 by Monty Taylor
Replace HASH in table_share with drizzled::hash_map
33
#include "drizzled/error.h"
34
#include "drizzled/gettext.h"
35
#include "drizzled/sql_base.h"
36
#include "drizzled/hash.h"
1241.9.57 by Monty Taylor
Oy. Bigger change than I normally like - but this stuff is all intertwined.
37
#include "drizzled/pthread_globals.h"
1241.9.64 by Monty Taylor
Moved remaining non-public portions of mysys and mystrings to drizzled/internal.
38
#include "drizzled/internal/my_pthread.h"
1093.6.1 by Brian Aker
Refactor TableShare has to be behind class.
39
40
using namespace std;
41
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
42
namespace drizzled
43
{
44
1241.9.33 by Monty Taylor
Moved most of the global vars to set_var where they belong.
45
extern size_t table_def_size;
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
46
typedef hash_map<string, TableShare *> TableDefCache;
1223.3.1 by Monty Taylor
Replace HASH in table_share with drizzled::hash_map
47
TableDefCache table_def_cache;
1093.6.1 by Brian Aker
Refactor TableShare has to be behind class.
48
static pthread_mutex_t LOCK_table_share;
49
bool table_def_inited= false;
50
51
/*****************************************************************************
52
  Functions to handle table definition cach (TableShare)
53
 *****************************************************************************/
1223.3.1 by Monty Taylor
Replace HASH in table_share with drizzled::hash_map
54
55
56
void TableShare::cacheStart(void)
57
{
58
  pthread_mutex_init(&LOCK_table_share, MY_MUTEX_INIT_FAST);
1093.6.1 by Brian Aker
Refactor TableShare has to be behind class.
59
  table_def_inited= true;
1223.3.2 by Monty Taylor
Added init-time rehash to the table_def_cache.
60
  /* 
61
   * This is going to overalloc a bit - as rehash sets the number of
62
   * buckets, not the number of elements. BUT, it'll allow us to not need
63
   * to rehash later on as the hash_map grows.
64
   */
65
  table_def_cache.rehash(table_def_size);
1093.6.1 by Brian Aker
Refactor TableShare has to be behind class.
66
}
67
68
69
void TableShare::cacheStop(void)
70
{
71
  if (table_def_inited)
72
  {
1223.3.1 by Monty Taylor
Replace HASH in table_share with drizzled::hash_map
73
    table_def_inited= false;
1093.6.1 by Brian Aker
Refactor TableShare has to be behind class.
74
    pthread_mutex_destroy(&LOCK_table_share);
75
  }
76
}
77
78
1223.3.1 by Monty Taylor
Replace HASH in table_share with drizzled::hash_map
79
/**
80
 * @TODO: This should return size_t
81
 */
1093.6.1 by Brian Aker
Refactor TableShare has to be behind class.
82
uint32_t cached_table_definitions(void)
83
{
1223.3.1 by Monty Taylor
Replace HASH in table_share with drizzled::hash_map
84
  return static_cast<uint32_t>(table_def_cache.size());
1093.6.1 by Brian Aker
Refactor TableShare has to be behind class.
85
}
86
87
88
/*
89
  Mark that we are not using table share anymore.
90
91
  SYNOPSIS
92
  release()
93
  share		Table share
94
95
  IMPLEMENTATION
96
  If ref_count goes to zero and (we have done a refresh or if we have
97
  already too many open table shares) then delete the definition.
98
*/
99
100
void TableShare::release(TableShare *share)
101
{
102
  bool to_be_deleted= false;
103
  safe_mutex_assert_owner(&LOCK_open);
104
105
  pthread_mutex_lock(&share->mutex);
106
  if (!--share->ref_count)
107
    to_be_deleted= true;
108
109
  if (to_be_deleted)
110
  {
1223.3.1 by Monty Taylor
Replace HASH in table_share with drizzled::hash_map
111
    const string key_string(share->table_cache_key.str,
112
                            share->table_cache_key.length);
113
    TableDefCache::iterator iter= table_def_cache.find(key_string);
114
    if (iter != table_def_cache.end())
115
    {
116
      (*iter).second->free_table_share();
117
      table_def_cache.erase(iter);
118
    }
1093.6.1 by Brian Aker
Refactor TableShare has to be behind class.
119
    return;
120
  }
121
  pthread_mutex_unlock(&share->mutex);
122
}
123
124
void TableShare::release(const char *key, uint32_t key_length)
125
{
1223.3.1 by Monty Taylor
Replace HASH in table_share with drizzled::hash_map
126
  const string key_string(key, key_length);
1093.6.1 by Brian Aker
Refactor TableShare has to be behind class.
127
1223.3.1 by Monty Taylor
Replace HASH in table_share with drizzled::hash_map
128
  TableDefCache::iterator iter= table_def_cache.find(key_string);
129
  if (iter != table_def_cache.end())
1093.6.1 by Brian Aker
Refactor TableShare has to be behind class.
130
  {
1223.3.1 by Monty Taylor
Replace HASH in table_share with drizzled::hash_map
131
    TableShare *share= (*iter).second;
1093.6.1 by Brian Aker
Refactor TableShare has to be behind class.
132
    share->version= 0;                          // Mark for delete
133
    if (share->ref_count == 0)
134
    {
135
      pthread_mutex_lock(&share->mutex);
1223.3.1 by Monty Taylor
Replace HASH in table_share with drizzled::hash_map
136
      share->free_table_share();
137
      table_def_cache.erase(key_string);
1093.6.1 by Brian Aker
Refactor TableShare has to be behind class.
138
    }
139
  }
140
}
141
142
1223.3.1 by Monty Taylor
Replace HASH in table_share with drizzled::hash_map
143
static TableShare *foundTableShare(TableShare *share)
144
{
145
  /*
146
    We found an existing table definition. Return it if we didn't get
147
    an error when reading the table definition from file.
148
  */
149
150
  /* We must do a lock to ensure that the structure is initialized */
151
  (void) pthread_mutex_lock(&share->mutex);
152
  if (share->error)
153
  {
154
    /* Table definition contained an error */
155
    share->open_table_error(share->error, share->open_errno, share->errarg);
156
    (void) pthread_mutex_unlock(&share->mutex);
157
158
    return NULL;
159
  }
160
161
  share->ref_count++;
162
  (void) pthread_mutex_unlock(&share->mutex);
163
164
  return share;
165
}
1093.6.1 by Brian Aker
Refactor TableShare has to be behind class.
166
167
/*
168
  Get TableShare for a table.
169
170
  get_table_share()
171
  session			Thread handle
172
  table_list		Table that should be opened
173
  key			Table cache key
174
  key_length		Length of key
175
  error			out: Error code from open_table_def()
176
177
  IMPLEMENTATION
178
  Get a table definition from the table definition cache.
179
  If it doesn't exist, create a new from the table definition file.
180
181
  NOTES
182
  We must have wrlock on LOCK_open when we come here
183
  (To be changed later)
184
185
  RETURN
186
  0  Error
187
#  Share for table
188
*/
189
190
TableShare *TableShare::getShare(Session *session, 
191
                                 TableList *table_list, char *key,
192
                                 uint32_t key_length, uint32_t, int *error)
193
{
1223.3.1 by Monty Taylor
Replace HASH in table_share with drizzled::hash_map
194
  const string key_string(key, key_length);
195
  TableShare *share= NULL;
1093.6.1 by Brian Aker
Refactor TableShare has to be behind class.
196
197
  *error= 0;
198
199
  /* Read table definition from cache */
1223.3.1 by Monty Taylor
Replace HASH in table_share with drizzled::hash_map
200
  TableDefCache::iterator iter= table_def_cache.find(key_string);
201
  if (iter != table_def_cache.end())
202
  {
203
    share= (*iter).second;
204
    return foundTableShare(share);
205
  }
1093.6.1 by Brian Aker
Refactor TableShare has to be behind class.
206
207
  if (!(share= alloc_table_share(table_list, key, key_length)))
208
  {
209
    return NULL;
210
  }
211
212
  /*
213
    Lock mutex to be able to read table definition from file without
214
    conflicts
215
  */
216
  (void) pthread_mutex_lock(&share->mutex);
217
1223.3.1 by Monty Taylor
Replace HASH in table_share with drizzled::hash_map
218
  /**
219
   * @TODO: we need to eject something if we exceed table_def_size
220
   */
221
  pair<TableDefCache::iterator, bool> ret=
222
    table_def_cache.insert(make_pair(key_string, share));
223
  if (ret.second == false)
1093.6.1 by Brian Aker
Refactor TableShare has to be behind class.
224
  {
225
    share->free_table_share();
1223.3.1 by Monty Taylor
Replace HASH in table_share with drizzled::hash_map
226
    return NULL;
1093.6.1 by Brian Aker
Refactor TableShare has to be behind class.
227
  }
1223.3.1 by Monty Taylor
Replace HASH in table_share with drizzled::hash_map
228
  
1183.1.29 by Brian Aker
Clean up interface so that Truncate sets the propper engine when
229
  if (open_table_def(*session, share))
1093.6.1 by Brian Aker
Refactor TableShare has to be behind class.
230
  {
231
    *error= share->error;
1223.3.1 by Monty Taylor
Replace HASH in table_share with drizzled::hash_map
232
    table_def_cache.erase(key_string);
233
    share->free_table_share();
1093.6.1 by Brian Aker
Refactor TableShare has to be behind class.
234
    return NULL;
235
  }
236
  share->ref_count++;				// Mark in use
237
  (void) pthread_mutex_unlock(&share->mutex);
238
  return share;
1223.3.1 by Monty Taylor
Replace HASH in table_share with drizzled::hash_map
239
1093.6.1 by Brian Aker
Refactor TableShare has to be behind class.
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
256
TableShare *TableShare::getShare(const char *db, const char *table_name)
257
{
258
  char key[NAME_LEN*2+2];
259
  uint32_t key_length;
260
  safe_mutex_assert_owner(&LOCK_open);
261
262
  key_length= TableShare::createKey(key, db, table_name);
263
1223.3.1 by Monty Taylor
Replace HASH in table_share with drizzled::hash_map
264
  const string key_string(key, key_length);
265
  TableDefCache::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
  }
1093.6.1 by Brian Aker
Refactor TableShare has to be behind class.
274
}
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
275
1308.2.2 by Jay Pipes
Fixes transaction log/replication for multi-column primary keys. Changes CREATE SCHEMA to not use statement-base RAW_SQL and instead use a derived message::Statement subclass.
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
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
303
} /* namespace drizzled */