~drizzle-trunk/drizzle/development

1 by brian
clean slate
1
/* Copyright (C) 2000-2004 MySQL AB
2
   This program is free software; you can redistribute it and/or modify
3
   it under the terms of the GNU General Public License as published by
4
   the Free Software Foundation; version 2 of the License.
5
6
   This program is distributed in the hope that it will be useful,
7
   but WITHOUT ANY WARRANTY; without even the implied warranty of
8
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
9
   GNU General Public License for more details.
10
11
   You should have received a copy of the GNU General Public License
12
   along with this program; if not, write to the Free Software
13
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
14
15
16
/* HANDLER ... commands - direct access to ISAM */
17
18
/* TODO:
19
  HANDLER blabla OPEN [ AS foobar ] [ (column-list) ]
20
21
  the most natural (easiest, fastest) way to do it is to
22
  compute List<Item> field_list not in mysql_ha_read
23
  but in mysql_ha_open, and then store it in TABLE structure.
24
25
  The problem here is that mysql_parse calls free_item to free all the
26
  items allocated at the end of every query. The workaround would to
27
  keep two item lists per THD - normal free_list and handler_items.
28
  The second is to be freeed only on thread end. mysql_ha_open should
29
  then do { handler_items=concat(handler_items, free_list); free_list=0; }
30
31
  But !!! do_command calls free_root at the end of every query and frees up
32
  all the sql_alloc'ed memory. It's harder to work around...
33
*/
34
35
/*
36
  There are two containers holding information about open handler tables.
37
  The first is 'thd->handler_tables'. It is a linked list of TABLE objects.
38
  It is used like 'thd->open_tables' in the table cache. The trick is to
39
  exchange these two lists during open and lock of tables. Thus the normal
40
  table cache code can be used.
41
  The second container is a HASH. It holds objects of the type TABLE_LIST.
42
  Despite its name, no lists of tables but only single structs are hashed
43
  (the 'next' pointer is always NULL). The reason for theis second container
44
  is, that we want handler tables to survive FLUSH TABLE commands. A table
45
  affected by FLUSH TABLE must be closed so that other threads are not
46
  blocked by handler tables still in use. Since we use the normal table cache
47
  functions with 'thd->handler_tables', the closed tables are removed from
48
  this list. Hence we need the original open information for the handler
49
  table in the case that it is used again. This information is handed over
50
  to mysql_ha_open() as a TABLE_LIST. So we store this information in the
51
  second container, where it is not affected by FLUSH TABLE. The second
52
  container is implemented as a hash for performance reasons. Consequently,
53
  we use it not only for re-opening a handler table, but also for the
54
  HANDLER ... READ commands. For this purpose, we store a pointer to the
55
  TABLE structure (in the first container) in the TBALE_LIST object in the
56
  second container. When the table is flushed, the pointer is cleared.
57
*/
58
59
#include "mysql_priv.h"
60
#include "sql_select.h"
61
#include <assert.h>
62
63
#define HANDLER_TABLES_HASH_SIZE 120
64
65
/**
66
  Close a HANDLER table.
67
68
  @param thd Thread identifier.
69
  @param tables A list of tables with the first entry to close.
70
  @param is_locked If LOCK_open is locked.
71
72
  @note Though this function takes a list of tables, only the first list entry
73
  will be closed.
74
  @note Broadcasts refresh if it closed a table with old version.
75
*/
76
77
static void mysql_ha_close_table(THD *thd, TABLE_LIST *tables,
78
                                 bool is_locked)
79
{
80
  TABLE **table_ptr;
81
82
  /*
83
    Though we could take the table pointer from hash_tables->table,
84
    we must follow the thd->handler_tables chain anyway, as we need the
85
    address of the 'next' pointer referencing this table
86
    for close_thread_table().
87
  */
88
  for (table_ptr= &(thd->handler_tables);
89
       *table_ptr && (*table_ptr != tables->table);
90
         table_ptr= &(*table_ptr)->next)
91
    ;
92
93
  if (*table_ptr)
94
  {
95
    (*table_ptr)->file->ha_index_or_rnd_end();
96
    if (! is_locked)
97
      VOID(pthread_mutex_lock(&LOCK_open));
98
    if (close_thread_table(thd, table_ptr))
99
    {
100
      /* Tell threads waiting for refresh that something has happened */
101
      broadcast_refresh();
102
    }
103
    if (! is_locked)
104
      VOID(pthread_mutex_unlock(&LOCK_open));
105
  }
106
  else if (tables->table)
107
  {
108
    /* Must be a temporary table */
109
    TABLE *table= tables->table;
110
    table->file->ha_index_or_rnd_end();
111
    table->query_id= thd->query_id;
112
    table->open_by_handler= 0;
113
  }
114
}
115
116
117
/*
118
  Close a HANDLER table by alias or table name
119
120
  SYNOPSIS
121
    mysql_ha_close()
122
    thd                         Thread identifier.
123
    tables                      A list of tables with the first entry to close.
124
125
  DESCRIPTION
126
    Closes the table that is associated (on the handler tables hash) with the
127
    name (table->alias) of the specified table.
128
129
  RETURN
51.1.52 by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE
130
    false ok
131
    true  error
1 by brian
clean slate
132
*/
133
134
bool mysql_ha_close(THD *thd, TABLE_LIST *tables)
135
{
136
  TABLE_LIST    *hash_tables;
137
138
  if ((hash_tables= (TABLE_LIST*) hash_search(&thd->handler_tables_hash,
139
                                              (uchar*) tables->alias,
140
                                              strlen(tables->alias) + 1)))
141
  {
51.1.52 by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE
142
    mysql_ha_close_table(thd, hash_tables, false);
1 by brian
clean slate
143
    hash_delete(&thd->handler_tables_hash, (uchar*) hash_tables);
144
  }
145
  else
146
  {
147
    my_error(ER_UNKNOWN_TABLE, MYF(0), tables->alias, "HANDLER");
51.1.52 by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE
148
    return(true);
1 by brian
clean slate
149
  }
150
151
  my_ok(thd);
51.1.52 by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE
152
  return(false);
1 by brian
clean slate
153
}
154
155
156
/**
157
  Scan the handler tables hash for matching tables.
158
159
  @param thd Thread identifier.
160
  @param tables The list of tables to remove.
161
162
  @return Pointer to head of linked list (TABLE_LIST::next_local) of matching
163
          TABLE_LIST elements from handler_tables_hash. Otherwise, NULL if no
164
          table was matched.
165
*/
166
167
static TABLE_LIST *mysql_ha_find(THD *thd, TABLE_LIST *tables)
168
{
169
  TABLE_LIST *hash_tables, *head= NULL, *first= tables;
170
171
  /* search for all handlers with matching table names */
172
  for (uint i= 0; i < thd->handler_tables_hash.records; i++)
173
  {
174
    hash_tables= (TABLE_LIST*) hash_element(&thd->handler_tables_hash, i);
175
    for (tables= first; tables; tables= tables->next_local)
176
    {
177
      if ((! *tables->db ||
178
          ! my_strcasecmp(&my_charset_latin1, hash_tables->db, tables->db)) &&
179
          ! my_strcasecmp(&my_charset_latin1, hash_tables->table_name,
180
                          tables->table_name))
181
        break;
182
    }
183
    if (tables)
184
    {
185
      hash_tables->next_local= head;
186
      head= hash_tables;
187
    }
188
  }
189
51.1.52 by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE
190
  return(head);
1 by brian
clean slate
191
}
192
193
194
/**
195
  Remove matching tables from the HANDLER's hash table.
196
197
  @param thd Thread identifier.
198
  @param tables The list of tables to remove.
199
  @param is_locked If LOCK_open is locked.
200
201
  @note Broadcasts refresh if it closed a table with old version.
202
*/
203
204
void mysql_ha_rm_tables(THD *thd, TABLE_LIST *tables, bool is_locked)
205
{
206
  TABLE_LIST *hash_tables, *next;
207
51.1.52 by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE
208
  assert(tables);
1 by brian
clean slate
209
210
  hash_tables= mysql_ha_find(thd, tables);
211
212
  while (hash_tables)
213
  {
214
    next= hash_tables->next_local;
215
    if (hash_tables->table)
216
      mysql_ha_close_table(thd, hash_tables, is_locked);
217
    hash_delete(&thd->handler_tables_hash, (uchar*) hash_tables);
218
    hash_tables= next;
219
  }
220
51.1.52 by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE
221
  return;
1 by brian
clean slate
222
}
223
224
225
/**
226
  Flush (close and mark for re-open) all tables that should be should
227
  be reopen.
228
229
  @param thd Thread identifier.
230
231
  @note Broadcasts refresh if it closed a table with old version.
232
*/
233
234
void mysql_ha_flush(THD *thd)
235
{
236
  TABLE_LIST *hash_tables;
237
238
  safe_mutex_assert_owner(&LOCK_open);
239
240
  for (uint i= 0; i < thd->handler_tables_hash.records; i++)
241
  {
242
    hash_tables= (TABLE_LIST*) hash_element(&thd->handler_tables_hash, i);
243
    if (hash_tables->table && hash_tables->table->needs_reopen_or_name_lock())
244
    {
51.1.52 by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE
245
      mysql_ha_close_table(thd, hash_tables, true);
1 by brian
clean slate
246
      /* Mark table as closed, ready for re-open. */
247
      hash_tables->table= NULL;
248
    }
249
  }
250
51.1.52 by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE
251
  return;
1 by brian
clean slate
252
}
253
254
255
/**
256
  Close all HANDLER's tables.
257
258
  @param thd Thread identifier.
259
260
  @note Broadcasts refresh if it closed a table with old version.
261
*/
262
263
void mysql_ha_cleanup(THD *thd)
264
{
265
  TABLE_LIST *hash_tables;
266
267
  for (uint i= 0; i < thd->handler_tables_hash.records; i++)
268
  {
269
    hash_tables= (TABLE_LIST*) hash_element(&thd->handler_tables_hash, i);
270
    if (hash_tables->table)
51.1.52 by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE
271
      mysql_ha_close_table(thd, hash_tables, false);
1 by brian
clean slate
272
   }
273
274
  hash_free(&thd->handler_tables_hash);
275
51.1.52 by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE
276
  return;
1 by brian
clean slate
277
}