~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to sql/sql_handler.cc

  • Committer: Monty Taylor
  • Date: 2008-07-05 19:00:59 UTC
  • mto: This revision was merged to the branch mainline in revision 63.
  • Revision ID: monty@inaugust.com-20080705190059-3vfbd3ebpmzaw5e5
Fixed unsigned long int, format specifiers and functions. 

Show diffs side-by-side

added added

removed removed

Lines of Context:
20
20
 
21
21
  the most natural (easiest, fastest) way to do it is to
22
22
  compute List<Item> field_list not in mysql_ha_read
23
 
  but in mysql_ha_open, and then store it in Table structure.
 
23
  but in mysql_ha_open, and then store it in TABLE structure.
24
24
 
25
25
  The problem here is that mysql_parse calls free_item to free all the
26
26
  items allocated at the end of every query. The workaround would to
27
 
  keep two item lists per Session - normal free_list and handler_items.
 
27
  keep two item lists per THD - normal free_list and handler_items.
28
28
  The second is to be freeed only on thread end. mysql_ha_open should
29
29
  then do { handler_items=concat(handler_items, free_list); free_list=0; }
30
30
 
34
34
 
35
35
/*
36
36
  There are two containers holding information about open handler tables.
37
 
  The first is 'session->handler_tables'. It is a linked list of Table objects.
38
 
  It is used like 'session->open_tables' in the table cache. The trick is to
 
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
39
  exchange these two lists during open and lock of tables. Thus the normal
40
40
  table cache code can be used.
41
 
  The second container is a HASH. It holds objects of the type TableList.
 
41
  The second container is a HASH. It holds objects of the type TABLE_LIST.
42
42
  Despite its name, no lists of tables but only single structs are hashed
43
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
 
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
46
  blocked by handler tables still in use. Since we use the normal table cache
47
 
  functions with 'session->handler_tables', the closed tables are removed from
 
47
  functions with 'thd->handler_tables', the closed tables are removed from
48
48
  this list. Hence we need the original open information for the handler
49
49
  table in the case that it is used again. This information is handed over
50
 
  to mysql_ha_open() as a TableList. So we store this information in the
51
 
  second container, where it is not affected by FLUSH Table. The second
 
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
52
  container is implemented as a hash for performance reasons. Consequently,
53
53
  we use it not only for re-opening a handler table, but also for the
54
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
 
55
  TABLE structure (in the first container) in the TBALE_LIST object in the
56
56
  second container. When the table is flushed, the pointer is cleared.
57
57
*/
58
58
 
59
 
#include <drizzled/server_includes.h>
60
 
#include <drizzled/sql_select.h>
 
59
#include "mysql_priv.h"
 
60
#include "sql_select.h"
 
61
#include <assert.h>
61
62
 
 
63
#define HANDLER_TABLES_HASH_SIZE 120
62
64
 
63
65
/**
64
66
  Close a HANDLER table.
65
67
 
66
 
  @param session Thread identifier.
 
68
  @param thd Thread identifier.
67
69
  @param tables A list of tables with the first entry to close.
68
70
  @param is_locked If LOCK_open is locked.
69
71
 
72
74
  @note Broadcasts refresh if it closed a table with old version.
73
75
*/
74
76
 
75
 
static void mysql_ha_close_table(Session *session, TableList *tables,
 
77
static void mysql_ha_close_table(THD *thd, TABLE_LIST *tables,
76
78
                                 bool is_locked)
77
79
{
78
 
  Table **table_ptr;
 
80
  TABLE **table_ptr;
79
81
 
80
82
  /*
81
83
    Though we could take the table pointer from hash_tables->table,
82
 
    we must follow the session->handler_tables chain anyway, as we need the
 
84
    we must follow the thd->handler_tables chain anyway, as we need the
83
85
    address of the 'next' pointer referencing this table
84
86
    for close_thread_table().
85
87
  */
86
 
  for (table_ptr= &(session->handler_tables);
 
88
  for (table_ptr= &(thd->handler_tables);
87
89
       *table_ptr && (*table_ptr != tables->table);
88
90
         table_ptr= &(*table_ptr)->next)
89
91
    ;
92
94
  {
93
95
    (*table_ptr)->file->ha_index_or_rnd_end();
94
96
    if (! is_locked)
95
 
      pthread_mutex_lock(&LOCK_open);
96
 
    if (close_thread_table(session, table_ptr))
 
97
      VOID(pthread_mutex_lock(&LOCK_open));
 
98
    if (close_thread_table(thd, table_ptr))
97
99
    {
98
100
      /* Tell threads waiting for refresh that something has happened */
99
101
      broadcast_refresh();
100
102
    }
101
103
    if (! is_locked)
102
 
      pthread_mutex_unlock(&LOCK_open);
 
104
      VOID(pthread_mutex_unlock(&LOCK_open));
103
105
  }
104
106
  else if (tables->table)
105
107
  {
106
108
    /* Must be a temporary table */
107
 
    Table *table= tables->table;
 
109
    TABLE *table= tables->table;
108
110
    table->file->ha_index_or_rnd_end();
109
 
    table->query_id= session->query_id;
 
111
    table->query_id= thd->query_id;
110
112
    table->open_by_handler= 0;
111
113
  }
112
114
}
117
119
 
118
120
  SYNOPSIS
119
121
    mysql_ha_close()
120
 
    session                         Thread identifier.
 
122
    thd                         Thread identifier.
121
123
    tables                      A list of tables with the first entry to close.
122
124
 
123
125
  DESCRIPTION
125
127
    name (table->alias) of the specified table.
126
128
 
127
129
  RETURN
128
 
    false ok
129
 
    true  error
 
130
    FALSE ok
 
131
    TRUE  error
130
132
*/
131
133
 
132
 
bool mysql_ha_close(Session *session, TableList *tables)
 
134
bool mysql_ha_close(THD *thd, TABLE_LIST *tables)
133
135
{
134
 
  TableList    *hash_tables;
 
136
  TABLE_LIST    *hash_tables;
 
137
  DBUG_ENTER("mysql_ha_close");
 
138
  DBUG_PRINT("enter",("'%s'.'%s' as '%s'",
 
139
                      tables->db, tables->table_name, tables->alias));
135
140
 
136
 
  if ((hash_tables= (TableList*) hash_search(&session->handler_tables_hash,
137
 
                                              (unsigned char*) tables->alias,
 
141
  if ((hash_tables= (TABLE_LIST*) hash_search(&thd->handler_tables_hash,
 
142
                                              (uchar*) tables->alias,
138
143
                                              strlen(tables->alias) + 1)))
139
144
  {
140
 
    mysql_ha_close_table(session, hash_tables, false);
141
 
    hash_delete(&session->handler_tables_hash, (unsigned char*) hash_tables);
 
145
    mysql_ha_close_table(thd, hash_tables, FALSE);
 
146
    hash_delete(&thd->handler_tables_hash, (uchar*) hash_tables);
142
147
  }
143
148
  else
144
149
  {
145
150
    my_error(ER_UNKNOWN_TABLE, MYF(0), tables->alias, "HANDLER");
146
 
    return(true);
 
151
    DBUG_PRINT("exit",("ERROR"));
 
152
    DBUG_RETURN(TRUE);
147
153
  }
148
154
 
149
 
  my_ok(session);
150
 
  return(false);
 
155
  my_ok(thd);
 
156
  DBUG_PRINT("exit", ("OK"));
 
157
  DBUG_RETURN(FALSE);
151
158
}
152
159
 
153
160
 
154
161
/**
155
162
  Scan the handler tables hash for matching tables.
156
163
 
157
 
  @param session Thread identifier.
 
164
  @param thd Thread identifier.
158
165
  @param tables The list of tables to remove.
159
166
 
160
 
  @return Pointer to head of linked list (TableList::next_local) of matching
161
 
          TableList elements from handler_tables_hash. Otherwise, NULL if no
 
167
  @return Pointer to head of linked list (TABLE_LIST::next_local) of matching
 
168
          TABLE_LIST elements from handler_tables_hash. Otherwise, NULL if no
162
169
          table was matched.
163
170
*/
164
171
 
165
 
static TableList *mysql_ha_find(Session *session, TableList *tables)
 
172
static TABLE_LIST *mysql_ha_find(THD *thd, TABLE_LIST *tables)
166
173
{
167
 
  TableList *hash_tables, *head= NULL, *first= tables;
 
174
  TABLE_LIST *hash_tables, *head= NULL, *first= tables;
 
175
  DBUG_ENTER("mysql_ha_find");
168
176
 
169
177
  /* search for all handlers with matching table names */
170
 
  for (uint32_t i= 0; i < session->handler_tables_hash.records; i++)
 
178
  for (uint i= 0; i < thd->handler_tables_hash.records; i++)
171
179
  {
172
 
    hash_tables= (TableList*) hash_element(&session->handler_tables_hash, i);
 
180
    hash_tables= (TABLE_LIST*) hash_element(&thd->handler_tables_hash, i);
173
181
    for (tables= first; tables; tables= tables->next_local)
174
182
    {
175
183
      if ((! *tables->db ||
176
 
          ! my_strcasecmp(&my_charset_utf8_general_ci, hash_tables->db, tables->db)) &&
177
 
          ! my_strcasecmp(&my_charset_utf8_general_ci, hash_tables->table_name,
 
184
          ! my_strcasecmp(&my_charset_latin1, hash_tables->db, tables->db)) &&
 
185
          ! my_strcasecmp(&my_charset_latin1, hash_tables->table_name,
178
186
                          tables->table_name))
179
187
        break;
180
188
    }
185
193
    }
186
194
  }
187
195
 
188
 
  return(head);
 
196
  DBUG_RETURN(head);
189
197
}
190
198
 
191
199
 
192
200
/**
193
201
  Remove matching tables from the HANDLER's hash table.
194
202
 
195
 
  @param session Thread identifier.
 
203
  @param thd Thread identifier.
196
204
  @param tables The list of tables to remove.
197
205
  @param is_locked If LOCK_open is locked.
198
206
 
199
207
  @note Broadcasts refresh if it closed a table with old version.
200
208
*/
201
209
 
202
 
void mysql_ha_rm_tables(Session *session, TableList *tables, bool is_locked)
 
210
void mysql_ha_rm_tables(THD *thd, TABLE_LIST *tables, bool is_locked)
203
211
{
204
 
  TableList *hash_tables, *next;
205
 
 
206
 
  assert(tables);
207
 
 
208
 
  hash_tables= mysql_ha_find(session, tables);
 
212
  TABLE_LIST *hash_tables, *next;
 
213
  DBUG_ENTER("mysql_ha_rm_tables");
 
214
 
 
215
  DBUG_ASSERT(tables);
 
216
 
 
217
  hash_tables= mysql_ha_find(thd, tables);
209
218
 
210
219
  while (hash_tables)
211
220
  {
212
221
    next= hash_tables->next_local;
213
222
    if (hash_tables->table)
214
 
      mysql_ha_close_table(session, hash_tables, is_locked);
215
 
    hash_delete(&session->handler_tables_hash, (unsigned char*) hash_tables);
 
223
      mysql_ha_close_table(thd, hash_tables, is_locked);
 
224
    hash_delete(&thd->handler_tables_hash, (uchar*) hash_tables);
216
225
    hash_tables= next;
217
226
  }
218
227
 
219
 
  return;
 
228
  DBUG_VOID_RETURN;
220
229
}
221
230
 
222
231
 
224
233
  Flush (close and mark for re-open) all tables that should be should
225
234
  be reopen.
226
235
 
227
 
  @param session Thread identifier.
 
236
  @param thd Thread identifier.
228
237
 
229
238
  @note Broadcasts refresh if it closed a table with old version.
230
239
*/
231
240
 
232
 
void mysql_ha_flush(Session *session)
 
241
void mysql_ha_flush(THD *thd)
233
242
{
234
 
  TableList *hash_tables;
 
243
  TABLE_LIST *hash_tables;
 
244
  DBUG_ENTER("mysql_ha_flush");
235
245
 
236
246
  safe_mutex_assert_owner(&LOCK_open);
237
247
 
238
 
  for (uint32_t i= 0; i < session->handler_tables_hash.records; i++)
 
248
  for (uint i= 0; i < thd->handler_tables_hash.records; i++)
239
249
  {
240
 
    hash_tables= (TableList*) hash_element(&session->handler_tables_hash, i);
 
250
    hash_tables= (TABLE_LIST*) hash_element(&thd->handler_tables_hash, i);
241
251
    if (hash_tables->table && hash_tables->table->needs_reopen_or_name_lock())
242
252
    {
243
 
      mysql_ha_close_table(session, hash_tables, true);
 
253
      mysql_ha_close_table(thd, hash_tables, TRUE);
244
254
      /* Mark table as closed, ready for re-open. */
245
255
      hash_tables->table= NULL;
246
256
    }
247
257
  }
248
258
 
249
 
  return;
 
259
  DBUG_VOID_RETURN;
250
260
}
251
261
 
252
262
 
253
263
/**
254
264
  Close all HANDLER's tables.
255
265
 
256
 
  @param session Thread identifier.
 
266
  @param thd Thread identifier.
257
267
 
258
268
  @note Broadcasts refresh if it closed a table with old version.
259
269
*/
260
270
 
261
 
void mysql_ha_cleanup(Session *session)
 
271
void mysql_ha_cleanup(THD *thd)
262
272
{
263
 
  TableList *hash_tables;
 
273
  TABLE_LIST *hash_tables;
 
274
  DBUG_ENTER("mysql_ha_cleanup");
264
275
 
265
 
  for (uint32_t i= 0; i < session->handler_tables_hash.records; i++)
 
276
  for (uint i= 0; i < thd->handler_tables_hash.records; i++)
266
277
  {
267
 
    hash_tables= (TableList*) hash_element(&session->handler_tables_hash, i);
 
278
    hash_tables= (TABLE_LIST*) hash_element(&thd->handler_tables_hash, i);
268
279
    if (hash_tables->table)
269
 
      mysql_ha_close_table(session, hash_tables, false);
 
280
      mysql_ha_close_table(thd, hash_tables, FALSE);
270
281
   }
271
282
 
272
 
  hash_free(&session->handler_tables_hash);
 
283
  hash_free(&thd->handler_tables_hash);
273
284
 
274
 
  return;
 
285
  DBUG_VOID_RETURN;
275
286
}