~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
327.1.5 by Brian Aker
Refactor around classes. TABLE_LIST has been factored out of table.h
23
  but in mysql_ha_open, and then store it in Table structure.
1 by brian
clean slate
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.
327.1.5 by Brian Aker
Refactor around classes. TABLE_LIST has been factored out of table.h
37
  The first is 'thd->handler_tables'. It is a linked list of Table objects.
1 by brian
clean slate
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.
327.2.4 by Brian Aker
Refactoring table.h
41
  The second container is a HASH. It holds objects of the type TableList.
1 by brian
clean slate
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
327.1.5 by Brian Aker
Refactor around classes. TABLE_LIST has been factored out of table.h
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
1 by brian
clean slate
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
327.2.4 by Brian Aker
Refactoring table.h
50
  to mysql_ha_open() as a TableList. So we store this information in the
327.1.5 by Brian Aker
Refactor around classes. TABLE_LIST has been factored out of table.h
51
  second container, where it is not affected by FLUSH Table. The second
1 by brian
clean slate
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
327.1.5 by Brian Aker
Refactor around classes. TABLE_LIST has been factored out of table.h
55
  Table structure (in the first container) in the TBALE_LIST object in the
1 by brian
clean slate
56
  second container. When the table is flushed, the pointer is cleared.
57
*/
58
243.1.17 by Jay Pipes
FINAL PHASE removal of mysql_priv.h (Bye, bye my friend.)
59
#include <drizzled/server_includes.h>
60
#include <drizzled/sql_select.h>
1 by brian
clean slate
61
62
#define HANDLER_TABLES_HASH_SIZE 120
63
64
/**
65
  Close a HANDLER table.
66
67
  @param thd Thread identifier.
68
  @param tables A list of tables with the first entry to close.
69
  @param is_locked If LOCK_open is locked.
70
71
  @note Though this function takes a list of tables, only the first list entry
72
  will be closed.
73
  @note Broadcasts refresh if it closed a table with old version.
74
*/
75
327.2.4 by Brian Aker
Refactoring table.h
76
static void mysql_ha_close_table(THD *thd, TableList *tables,
1 by brian
clean slate
77
                                 bool is_locked)
78
{
327.1.5 by Brian Aker
Refactor around classes. TABLE_LIST has been factored out of table.h
79
  Table **table_ptr;
1 by brian
clean slate
80
81
  /*
82
    Though we could take the table pointer from hash_tables->table,
83
    we must follow the thd->handler_tables chain anyway, as we need the
84
    address of the 'next' pointer referencing this table
85
    for close_thread_table().
86
  */
87
  for (table_ptr= &(thd->handler_tables);
88
       *table_ptr && (*table_ptr != tables->table);
89
         table_ptr= &(*table_ptr)->next)
90
    ;
91
92
  if (*table_ptr)
93
  {
94
    (*table_ptr)->file->ha_index_or_rnd_end();
95
    if (! is_locked)
96
      VOID(pthread_mutex_lock(&LOCK_open));
97
    if (close_thread_table(thd, table_ptr))
98
    {
99
      /* Tell threads waiting for refresh that something has happened */
100
      broadcast_refresh();
101
    }
102
    if (! is_locked)
103
      VOID(pthread_mutex_unlock(&LOCK_open));
104
  }
105
  else if (tables->table)
106
  {
107
    /* Must be a temporary table */
327.1.5 by Brian Aker
Refactor around classes. TABLE_LIST has been factored out of table.h
108
    Table *table= tables->table;
1 by brian
clean slate
109
    table->file->ha_index_or_rnd_end();
110
    table->query_id= thd->query_id;
111
    table->open_by_handler= 0;
112
  }
113
}
114
115
116
/*
117
  Close a HANDLER table by alias or table name
118
119
  SYNOPSIS
120
    mysql_ha_close()
121
    thd                         Thread identifier.
122
    tables                      A list of tables with the first entry to close.
123
124
  DESCRIPTION
125
    Closes the table that is associated (on the handler tables hash) with the
126
    name (table->alias) of the specified table.
127
128
  RETURN
51.1.52 by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE
129
    false ok
130
    true  error
1 by brian
clean slate
131
*/
132
327.2.4 by Brian Aker
Refactoring table.h
133
bool mysql_ha_close(THD *thd, TableList *tables)
1 by brian
clean slate
134
{
327.2.4 by Brian Aker
Refactoring table.h
135
  TableList    *hash_tables;
1 by brian
clean slate
136
327.2.4 by Brian Aker
Refactoring table.h
137
  if ((hash_tables= (TableList*) hash_search(&thd->handler_tables_hash,
1 by brian
clean slate
138
                                              (uchar*) tables->alias,
139
                                              strlen(tables->alias) + 1)))
140
  {
51.1.52 by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE
141
    mysql_ha_close_table(thd, hash_tables, false);
1 by brian
clean slate
142
    hash_delete(&thd->handler_tables_hash, (uchar*) hash_tables);
143
  }
144
  else
145
  {
146
    my_error(ER_UNKNOWN_TABLE, MYF(0), tables->alias, "HANDLER");
51.1.52 by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE
147
    return(true);
1 by brian
clean slate
148
  }
149
150
  my_ok(thd);
51.1.52 by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE
151
  return(false);
1 by brian
clean slate
152
}
153
154
155
/**
156
  Scan the handler tables hash for matching tables.
157
158
  @param thd Thread identifier.
159
  @param tables The list of tables to remove.
160
327.2.4 by Brian Aker
Refactoring table.h
161
  @return Pointer to head of linked list (TableList::next_local) of matching
162
          TableList elements from handler_tables_hash. Otherwise, NULL if no
1 by brian
clean slate
163
          table was matched.
164
*/
165
327.2.4 by Brian Aker
Refactoring table.h
166
static TableList *mysql_ha_find(THD *thd, TableList *tables)
1 by brian
clean slate
167
{
327.2.4 by Brian Aker
Refactoring table.h
168
  TableList *hash_tables, *head= NULL, *first= tables;
1 by brian
clean slate
169
170
  /* search for all handlers with matching table names */
171
  for (uint i= 0; i < thd->handler_tables_hash.records; i++)
172
  {
327.2.4 by Brian Aker
Refactoring table.h
173
    hash_tables= (TableList*) hash_element(&thd->handler_tables_hash, i);
1 by brian
clean slate
174
    for (tables= first; tables; tables= tables->next_local)
175
    {
176
      if ((! *tables->db ||
383.1.12 by Brian Aker
Much closer toward UTF8 being around all the time...
177
          ! my_strcasecmp(&my_charset_utf8_general_ci, hash_tables->db, tables->db)) &&
178
          ! my_strcasecmp(&my_charset_utf8_general_ci, hash_tables->table_name,
1 by brian
clean slate
179
                          tables->table_name))
180
        break;
181
    }
182
    if (tables)
183
    {
184
      hash_tables->next_local= head;
185
      head= hash_tables;
186
    }
187
  }
188
51.1.52 by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE
189
  return(head);
1 by brian
clean slate
190
}
191
192
193
/**
194
  Remove matching tables from the HANDLER's hash table.
195
196
  @param thd Thread identifier.
197
  @param tables The list of tables to remove.
198
  @param is_locked If LOCK_open is locked.
199
200
  @note Broadcasts refresh if it closed a table with old version.
201
*/
202
327.2.4 by Brian Aker
Refactoring table.h
203
void mysql_ha_rm_tables(THD *thd, TableList *tables, bool is_locked)
1 by brian
clean slate
204
{
327.2.4 by Brian Aker
Refactoring table.h
205
  TableList *hash_tables, *next;
1 by brian
clean slate
206
51.1.52 by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE
207
  assert(tables);
1 by brian
clean slate
208
209
  hash_tables= mysql_ha_find(thd, tables);
210
211
  while (hash_tables)
212
  {
213
    next= hash_tables->next_local;
214
    if (hash_tables->table)
215
      mysql_ha_close_table(thd, hash_tables, is_locked);
216
    hash_delete(&thd->handler_tables_hash, (uchar*) hash_tables);
217
    hash_tables= next;
218
  }
219
51.1.52 by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE
220
  return;
1 by brian
clean slate
221
}
222
223
224
/**
225
  Flush (close and mark for re-open) all tables that should be should
226
  be reopen.
227
228
  @param thd Thread identifier.
229
230
  @note Broadcasts refresh if it closed a table with old version.
231
*/
232
233
void mysql_ha_flush(THD *thd)
234
{
327.2.4 by Brian Aker
Refactoring table.h
235
  TableList *hash_tables;
1 by brian
clean slate
236
237
  safe_mutex_assert_owner(&LOCK_open);
238
239
  for (uint i= 0; i < thd->handler_tables_hash.records; i++)
240
  {
327.2.4 by Brian Aker
Refactoring table.h
241
    hash_tables= (TableList*) hash_element(&thd->handler_tables_hash, i);
1 by brian
clean slate
242
    if (hash_tables->table && hash_tables->table->needs_reopen_or_name_lock())
243
    {
51.1.52 by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE
244
      mysql_ha_close_table(thd, hash_tables, true);
1 by brian
clean slate
245
      /* Mark table as closed, ready for re-open. */
246
      hash_tables->table= NULL;
247
    }
248
  }
249
51.1.52 by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE
250
  return;
1 by brian
clean slate
251
}
252
253
254
/**
255
  Close all HANDLER's tables.
256
257
  @param thd Thread identifier.
258
259
  @note Broadcasts refresh if it closed a table with old version.
260
*/
261
262
void mysql_ha_cleanup(THD *thd)
263
{
327.2.4 by Brian Aker
Refactoring table.h
264
  TableList *hash_tables;
1 by brian
clean slate
265
266
  for (uint i= 0; i < thd->handler_tables_hash.records; i++)
267
  {
327.2.4 by Brian Aker
Refactoring table.h
268
    hash_tables= (TableList*) hash_element(&thd->handler_tables_hash, i);
1 by brian
clean slate
269
    if (hash_tables->table)
51.1.52 by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE
270
      mysql_ha_close_table(thd, hash_tables, false);
1 by brian
clean slate
271
   }
272
273
  hash_free(&thd->handler_tables_hash);
274
51.1.52 by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE
275
  return;
1 by brian
clean slate
276
}