~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/sql_base.cc

  • Committer: Brian Aker
  • Date: 2009-07-27 04:14:30 UTC
  • mfrom: (1093.6.2 table_share)
  • Revision ID: brian@gaz-20090727041430-kmxsnb2ep1cqsy05
Merge

Show diffs side-by-side

added added

removed removed

Lines of Context:
57
57
*/
58
58
Table *unused_tables;                           /* Used by mysql_test */
59
59
HASH open_cache;                                /* Used by mysql_test */
60
 
static HASH table_def_cache;
61
 
static pthread_mutex_t LOCK_table_share;
62
 
static bool table_def_inited= 0;
63
 
 
64
60
static int open_unireg_entry(Session *session, Table *entry, TableList *table_list,
65
61
                             const char *alias,
66
62
                             char *cache_key, uint32_t cache_key_length);
97
93
 
98
94
void table_cache_free(void)
99
95
{
100
 
  if (table_def_inited)
101
 
  {
102
 
    close_cached_tables(NULL, NULL, false, false);
103
 
    if (!open_cache.records)                    // Safety first
104
 
      hash_free(&open_cache);
105
 
  }
 
96
  close_cached_tables(NULL, NULL, false, false);
 
97
  if (!open_cache.records)                      // Safety first
 
98
    hash_free(&open_cache);
106
99
}
107
100
 
108
101
uint32_t cached_open_tables(void)
111
104
}
112
105
 
113
106
 
114
 
 
115
 
/*****************************************************************************
116
 
  Functions to handle table definition cach (TableShare)
117
 
 *****************************************************************************/
118
 
 
119
 
unsigned char *table_def_key(const unsigned char *record,
120
 
                             size_t *length,
121
 
                             bool )
122
 
{
123
 
  TableShare *entry=(TableShare*) record;
124
 
  *length= entry->table_cache_key.length;
125
 
  return (unsigned char*) entry->table_cache_key.str;
126
 
}
127
 
 
128
 
 
129
 
static void table_def_free_entry(TableShare *share)
130
 
{
131
 
  share->free_table_share();
132
 
}
133
 
 
134
 
 
135
 
bool table_def_init(void)
136
 
{
137
 
  table_def_inited= 1;
138
 
  pthread_mutex_init(&LOCK_table_share, MY_MUTEX_INIT_FAST);
139
 
 
140
 
  return hash_init(&table_def_cache, &my_charset_bin, (size_t)table_def_size,
141
 
                   0, 0, table_def_key,
142
 
                   (hash_free_key) table_def_free_entry, 0);
143
 
}
144
 
 
145
 
 
146
 
void table_def_free(void)
147
 
{
148
 
  if (table_def_inited)
149
 
  {
150
 
    table_def_inited= 0;
151
 
    pthread_mutex_destroy(&LOCK_table_share);
152
 
    hash_free(&table_def_cache);
153
 
  }
154
 
}
155
 
 
156
 
 
157
 
uint32_t cached_table_definitions(void)
158
 
{
159
 
  return table_def_cache.records;
160
 
}
161
 
 
162
 
 
163
 
/*
164
 
  Get TableShare for a table.
165
 
 
166
 
  get_table_share()
167
 
  session                       Thread handle
168
 
  table_list            Table that should be opened
169
 
  key                   Table cache key
170
 
  key_length            Length of key
171
 
  error                 out: Error code from open_table_def()
172
 
 
173
 
  IMPLEMENTATION
174
 
  Get a table definition from the table definition cache.
175
 
  If it doesn't exist, create a new from the table definition file.
176
 
 
177
 
  NOTES
178
 
  We must have wrlock on LOCK_open when we come here
179
 
  (To be changed later)
180
 
 
181
 
  RETURN
182
 
  0  Error
183
 
#  Share for table
184
 
*/
185
 
 
186
 
TableShare *get_table_share(Session *session, TableList *table_list, char *key,
187
 
                            uint32_t key_length, uint32_t, int *error)
188
 
{
189
 
  TableShare *share;
190
 
 
191
 
  *error= 0;
192
 
 
193
 
  /* Read table definition from cache */
194
 
  if ((share= (TableShare*) hash_search(&table_def_cache,(unsigned char*) key,
195
 
                                        key_length)))
196
 
    goto found;
197
 
 
198
 
  if (!(share= alloc_table_share(table_list, key, key_length)))
199
 
  {
200
 
    return NULL;
201
 
  }
202
 
 
203
 
  /*
204
 
    Lock mutex to be able to read table definition from file without
205
 
    conflicts
206
 
  */
207
 
  (void) pthread_mutex_lock(&share->mutex);
208
 
 
209
 
  if (my_hash_insert(&table_def_cache, (unsigned char*) share))
210
 
  {
211
 
    share->free_table_share();
212
 
    return NULL;                                // return error
213
 
  }
214
 
  if (open_table_def(session, share))
215
 
  {
216
 
    *error= share->error;
217
 
    (void) hash_delete(&table_def_cache, (unsigned char*) share);
218
 
    return NULL;
219
 
  }
220
 
  share->ref_count++;                           // Mark in use
221
 
  (void) pthread_mutex_unlock(&share->mutex);
222
 
  return(share);
223
 
 
224
 
found:
225
 
  /*
226
 
    We found an existing table definition. Return it if we didn't get
227
 
    an error when reading the table definition from file.
228
 
  */
229
 
 
230
 
  /* We must do a lock to ensure that the structure is initialized */
231
 
  (void) pthread_mutex_lock(&share->mutex);
232
 
  if (share->error)
233
 
  {
234
 
    /* Table definition contained an error */
235
 
    share->open_table_error(share->error, share->open_errno, share->errarg);
236
 
    (void) pthread_mutex_unlock(&share->mutex);
237
 
 
238
 
    return NULL;
239
 
  }
240
 
 
241
 
  share->ref_count++;
242
 
  (void) pthread_mutex_unlock(&share->mutex);
243
 
 
244
 
  return share;
245
 
}
246
 
 
247
 
 
248
 
/*
249
 
  Mark that we are not using table share anymore.
250
 
 
251
 
  SYNOPSIS
252
 
  release_table_share()
253
 
  share         Table share
254
 
 
255
 
  IMPLEMENTATION
256
 
  If ref_count goes to zero and (we have done a refresh or if we have
257
 
  already too many open table shares) then delete the definition.
258
 
 
259
 
  If type == RELEASE_WAIT_FOR_DROP then don't return until we get a signal
260
 
  that the table is deleted or the thread is killed.
261
 
*/
262
 
 
263
 
void release_table_share(TableShare *share)
264
 
{
265
 
  bool to_be_deleted= false;
266
 
 
267
 
  safe_mutex_assert_owner(&LOCK_open);
268
 
 
269
 
  pthread_mutex_lock(&share->mutex);
270
 
  if (!--share->ref_count)
271
 
    to_be_deleted= true;
272
 
 
273
 
  if (to_be_deleted)
274
 
  {
275
 
    hash_delete(&table_def_cache, (unsigned char*) share);
276
 
    return;
277
 
  }
278
 
  pthread_mutex_unlock(&share->mutex);
279
 
}
280
 
 
281
 
 
282
 
/*
283
 
  Check if table definition exits in cache
284
 
 
285
 
  SYNOPSIS
286
 
  get_cached_table_share()
287
 
  db                    Database name
288
 
  table_name            Table name
289
 
 
290
 
  RETURN
291
 
  0  Not cached
292
 
#  TableShare for table
293
 
*/
294
 
 
295
 
TableShare *get_cached_table_share(const char *db, const char *table_name)
296
 
{
297
 
  char key[NAME_LEN*2+2];
298
 
  uint32_t key_length;
299
 
  safe_mutex_assert_owner(&LOCK_open);
300
 
 
301
 
  key_length= TableShare::createKey(key, db, table_name);
302
 
 
303
 
  return (TableShare*) hash_search(&table_def_cache,(unsigned char*) key, key_length);
304
 
}
305
 
 
306
 
 
307
107
/*
308
108
  Close file handle, but leave the table in the table cache
309
109
 
348
148
 
349
149
  table->file->close();
350
150
  table->db_stat= 0;                            // Mark file closed
351
 
  release_table_share(table->s);
 
151
  TableShare::release(table->s);
352
152
  table->s= share;
353
153
  table->file->change_table_ptr(table, table->s);
354
154
}
368
168
  a lock on LOCK_open when traversing the return list.
369
169
 
370
170
  RETURN VALUES
371
 
  NULL  Error (Probably OOM)
372
 
#               Pointer to list of names of open tables.
 
171
  true  Error 
373
172
*/
374
173
 
375
 
OPEN_TableList *list_open_tables(const char *db, const char *wild)
 
174
bool list_open_tables(const char *db, const char *wild, bool(*func)(Table *table, open_table_list_st& open_list), Table *display)
376
175
{
377
 
  int result = 0;
378
 
  OPEN_TableList **start_list, *open_list;
379
 
  TableList table_list;
 
176
  vector<open_table_list_st> open_list;
 
177
  vector<open_table_list_st>::iterator it;
 
178
  open_table_list_st table;
 
179
 
 
180
  /* What we really need is an optimization for knowing unique tables */
 
181
  if (db && wild)
 
182
    open_list.reserve(sizeof(open_table_list_st) * (open_cache.records % 2));
 
183
  else
 
184
    open_list.reserve(sizeof(open_table_list_st) * open_cache.records);
380
185
 
381
186
  pthread_mutex_lock(&LOCK_open); /* List all open tables */
382
 
  memset(&table_list, 0, sizeof(table_list));
383
 
  start_list= &open_list;
384
 
  open_list=0;
385
187
 
386
 
  for (uint32_t idx=0 ; result == 0 && idx < open_cache.records; idx++)
 
188
  for (uint32_t idx= 0; idx < open_cache.records; idx++)
387
189
  {
388
 
    OPEN_TableList *table;
 
190
    bool found= false;
389
191
    Table *entry=(Table*) hash_element(&open_cache,idx);
390
 
    TableShare *share= entry->s;
391
 
 
392
 
    if (db && my_strcasecmp(system_charset_info, db, share->db.str))
393
 
      continue;
394
 
    if (wild && wild_compare(share->table_name.str, wild, 0))
395
 
      continue;
396
 
 
397
 
    /* Check if user has SELECT privilege for any column in the table */
398
 
    table_list.db=         share->db.str;
399
 
    table_list.table_name= share->table_name.str;
400
 
 
401
 
    /* need to check if we haven't already listed it */
402
 
    for (table= open_list  ; table ; table=table->next)
 
192
 
 
193
    if (db && my_strcasecmp(system_charset_info, db, entry->s->db.str))
 
194
      continue;
 
195
    if (wild && wild_compare(entry->s->table_name.str, wild, 0))
 
196
      continue;
 
197
 
 
198
    for (it= open_list.begin(); it < open_list.end(); it++)
403
199
    {
404
 
      if (!strcmp(table->table, share->table_name.str) &&
405
 
          !strcmp(table->db,    share->db.str))
 
200
      if (!(*it).table.compare(entry->s->table_name.str) &&
 
201
          !(*it).db.compare(entry->s->db.str))
406
202
      {
407
203
        if (entry->in_use)
408
 
          table->in_use++;
 
204
          (*it).in_use++;
409
205
        if (entry->locked_by_name)
410
 
          table->locked++;
 
206
          (*it).locked++;
 
207
 
 
208
        found= true;
 
209
 
411
210
        break;
412
211
      }
413
212
    }
414
 
    if (table)
 
213
 
 
214
    if (found)
415
215
      continue;
416
 
    if (!(*start_list = (OPEN_TableList *)
417
 
          sql_alloc(sizeof(**start_list)+share->table_cache_key.length)))
418
 
    {
419
 
      open_list=0;                              // Out of memory
420
 
      break;
421
 
    }
422
 
    strcpy((*start_list)->table=
423
 
           strcpy(((*start_list)->db= (char*) ((*start_list)+1)),
424
 
                  share->db.str)+share->db.length+1,
425
 
           share->table_name.str);
426
 
    (*start_list)->in_use= entry->in_use ? 1 : 0;
427
 
    (*start_list)->locked= entry->locked_by_name ? 1 : 0;
428
 
    start_list= &(*start_list)->next;
429
 
    *start_list=0;
 
216
 
 
217
    table.db= entry->s->db.str;
 
218
    table.table= entry->s->table_name.str;
 
219
    open_list.push_back(table);
430
220
  }
431
221
  pthread_mutex_unlock(&LOCK_open);
432
 
  return(open_list);
 
222
 
 
223
  for (it= open_list.begin(); it < open_list.end(); it++)
 
224
  {
 
225
    if (func(display, *it))
 
226
      return true;
 
227
  }
 
228
 
 
229
  return false;
433
230
}
434
231
 
435
232
/*****************************************************************************
2279
2076
 
2280
2077
  safe_mutex_assert_owner(&LOCK_open);
2281
2078
retry:
2282
 
  if (!(share= get_table_share(session, table_list, cache_key,
2283
 
                                           cache_key_length,
2284
 
                                           table_list->i_s_requested_object,
2285
 
                                           &error)))
 
2079
  if (!(share= TableShare::getShare(session, table_list, cache_key,
 
2080
                                    cache_key_length,
 
2081
                                    table_list->i_s_requested_object,
 
2082
                                    &error)))
2286
2083
    return 1;
2287
2084
 
2288
2085
  while ((error= open_table_from_share(session, share, alias,
2321
2118
      if (share->ref_count != 1)
2322
2119
        goto err;
2323
2120
      /* Free share and wait until it's released by all threads */
2324
 
      release_table_share(share);
 
2121
      TableShare::release(share);
 
2122
 
2325
2123
      if (!session->killed)
2326
2124
      {
2327
2125
        drizzle_reset_errors(session, 1);         // Clear warnings
2411
2209
  return 0;
2412
2210
 
2413
2211
err:
2414
 
  release_table_share(share);
 
2212
  TableShare::release(share);
2415
2213
 
2416
2214
  return 1;
2417
2215
}
5084
4882
  char *key_pos= key;
5085
4883
  uint32_t key_length;
5086
4884
  Table *table;
5087
 
  TableShare *share;
5088
4885
  bool result= false; 
5089
4886
  bool signalled= false;
5090
4887
 
5147
4944
      hash_delete(&open_cache,(unsigned char*) unused_tables);
5148
4945
 
5149
4946
    /* Remove table from table definition cache if it's not in use */
5150
 
    if ((share= (TableShare*) hash_search(&table_def_cache,(unsigned char*) key,
5151
 
                                          key_length)))
5152
 
    {
5153
 
      share->version= 0;                          // Mark for delete
5154
 
      if (share->ref_count == 0)
5155
 
      {
5156
 
        pthread_mutex_lock(&share->mutex);
5157
 
        hash_delete(&table_def_cache, (unsigned char*) share);
5158
 
      }
5159
 
    }
 
4947
    TableShare::release(key, key_length);
5160
4948
 
5161
4949
    if (result && (flags & RTFC_WAIT_OTHER_THREAD_FLAG))
5162
4950
    {