~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 */
27
#include <drizzled/server_includes.h>
28
#include <assert.h>
29
30
#include <drizzled/error.h>
31
#include <drizzled/gettext.h>
32
#include <drizzled/sql_base.h>
33
34
using namespace std;
35
36
static HASH table_def_cache;
37
static pthread_mutex_t LOCK_table_share;
38
bool table_def_inited= false;
39
40
/*****************************************************************************
41
  Functions to handle table definition cach (TableShare)
42
 *****************************************************************************/
43
44
extern "C"
45
{
46
  unsigned char *table_def_key(const unsigned char *record,
47
                               size_t *length,
48
                               bool );
49
}
50
51
unsigned char *table_def_key(const unsigned char *record,
52
                             size_t *length,
53
                             bool )
54
{
55
  TableShare *entry=(TableShare*) record;
56
  *length= entry->table_cache_key.length;
57
  return (unsigned char*) entry->table_cache_key.str;
58
}
59
60
61
static void table_def_free_entry(TableShare *share)
62
{
63
  share->free_table_share();
64
}
65
66
67
bool TableShare::cacheStart(void)
68
{
69
  table_def_inited= true;
70
  pthread_mutex_init(&LOCK_table_share, MY_MUTEX_INIT_FAST);
71
72
  return hash_init(&table_def_cache, &my_charset_bin, (size_t)table_def_size,
73
                   0, 0, table_def_key,
74
                   (hash_free_key) table_def_free_entry, 0);
75
}
76
77
78
void TableShare::cacheStop(void)
79
{
80
  if (table_def_inited)
81
  {
82
    table_def_inited= 0;
83
    pthread_mutex_destroy(&LOCK_table_share);
84
    hash_free(&table_def_cache);
85
  }
86
}
87
88
89
uint32_t cached_table_definitions(void)
90
{
91
  return table_def_cache.records;
92
}
93
94
95
/*
96
  Mark that we are not using table share anymore.
97
98
  SYNOPSIS
99
  release()
100
  share		Table share
101
102
  IMPLEMENTATION
103
  If ref_count goes to zero and (we have done a refresh or if we have
104
  already too many open table shares) then delete the definition.
105
*/
106
107
void TableShare::release(TableShare *share)
108
{
109
  bool to_be_deleted= false;
110
  safe_mutex_assert_owner(&LOCK_open);
111
112
  pthread_mutex_lock(&share->mutex);
113
  if (!--share->ref_count)
114
    to_be_deleted= true;
115
116
  if (to_be_deleted)
117
  {
118
    hash_delete(&table_def_cache, (unsigned char*) share);
119
    return;
120
  }
121
  pthread_mutex_unlock(&share->mutex);
122
}
123
124
void TableShare::release(const char *key, uint32_t key_length)
125
{
126
  TableShare *share;
127
128
  if ((share= (TableShare*) hash_search(&table_def_cache,(unsigned char*) key,
129
                                        key_length)))
130
  {
131
    share->version= 0;                          // Mark for delete
132
    if (share->ref_count == 0)
133
    {
134
      pthread_mutex_lock(&share->mutex);
135
      hash_delete(&table_def_cache, (unsigned char*) share);
136
    }
137
  }
138
}
139
140
141
142
/*
143
  Get TableShare for a table.
144
145
  get_table_share()
146
  session			Thread handle
147
  table_list		Table that should be opened
148
  key			Table cache key
149
  key_length		Length of key
150
  error			out: Error code from open_table_def()
151
152
  IMPLEMENTATION
153
  Get a table definition from the table definition cache.
154
  If it doesn't exist, create a new from the table definition file.
155
156
  NOTES
157
  We must have wrlock on LOCK_open when we come here
158
  (To be changed later)
159
160
  RETURN
161
  0  Error
162
#  Share for table
163
*/
164
165
TableShare *TableShare::getShare(Session *session, 
166
                                 TableList *table_list, char *key,
167
                                 uint32_t key_length, uint32_t, int *error)
168
{
169
  TableShare *share;
170
171
  *error= 0;
172
173
  /* Read table definition from cache */
174
  if ((share= (TableShare*) hash_search(&table_def_cache,(unsigned char*) key,
175
                                        key_length)))
176
    goto found;
177
178
  if (!(share= alloc_table_share(table_list, key, key_length)))
179
  {
180
    return NULL;
181
  }
182
183
  /*
184
    Lock mutex to be able to read table definition from file without
185
    conflicts
186
  */
187
  (void) pthread_mutex_lock(&share->mutex);
188
189
  if (my_hash_insert(&table_def_cache, (unsigned char*) share))
190
  {
191
    share->free_table_share();
192
    return NULL;				// return error
193
  }
194
  if (open_table_def(session, share))
195
  {
196
    *error= share->error;
197
    (void) hash_delete(&table_def_cache, (unsigned char*) share);
198
    return NULL;
199
  }
200
  share->ref_count++;				// Mark in use
201
  (void) pthread_mutex_unlock(&share->mutex);
202
  return(share);
203
204
found:
205
  /*
206
    We found an existing table definition. Return it if we didn't get
207
    an error when reading the table definition from file.
208
  */
209
210
  /* We must do a lock to ensure that the structure is initialized */
211
  (void) pthread_mutex_lock(&share->mutex);
212
  if (share->error)
213
  {
214
    /* Table definition contained an error */
215
    share->open_table_error(share->error, share->open_errno, share->errarg);
216
    (void) pthread_mutex_unlock(&share->mutex);
217
218
    return NULL;
219
  }
220
221
  share->ref_count++;
222
  (void) pthread_mutex_unlock(&share->mutex);
223
224
  return share;
225
}
226
227
228
/*
229
  Check if table definition exits in cache
230
231
  SYNOPSIS
232
  get_cached_table_share()
233
  db			Database name
234
  table_name		Table name
235
236
  RETURN
237
  0  Not cached
238
#  TableShare for table
239
*/
240
241
TableShare *TableShare::getShare(const char *db, const char *table_name)
242
{
243
  char key[NAME_LEN*2+2];
244
  uint32_t key_length;
245
  safe_mutex_assert_owner(&LOCK_open);
246
247
  key_length= TableShare::createKey(key, db, table_name);
248
249
  return (TableShare*) hash_search(&table_def_cache,(unsigned char*) key, key_length);
250
}