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