~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/table/concurrent.cc

  • Committer: Andrew Hutchings
  • Date: 2010-10-20 15:31:27 UTC
  • mto: This revision was merged to the branch mainline in revision 1907.
  • Revision ID: andrew@linuxjedi.co.uk-20101020153127-w9djuz9omzezg2kz
Add error message for global sort buffer constraint

Show diffs side-by-side

added added

removed removed

Lines of Context:
28
28
#include "plugin/myisam/myisam.h"
29
29
#include "drizzled/plugin/transactional_storage_engine.h"
30
30
 
31
 
#include <drizzled/table/instance.h>
32
 
 
33
31
#include "drizzled/table.h"
34
32
 
35
33
namespace drizzled
38
36
namespace table
39
37
{
40
38
 
41
 
/*
42
 
  Open table which is already name-locked by this thread.
43
 
 
44
 
  SYNOPSIS
45
 
  reopen_name_locked_table()
46
 
  session         Thread handle
47
 
  table_list  TableList object for table to be open, TableList::table
48
 
  member should point to Table object which was used for
49
 
  name-locking.
50
 
  link_in     true  - if Table object for table to be opened should be
51
 
  linked into Session::open_tables list.
52
 
  false - placeholder used for name-locking is already in
53
 
  this list so we only need to preserve Table::next
54
 
  pointer.
55
 
 
56
 
  NOTE
57
 
  This function assumes that its caller already acquired table::Cache::singleton().mutex() mutex.
58
 
 
59
 
  RETURN VALUE
60
 
  false - Success
61
 
  true  - Error
62
 
*/
63
 
 
64
 
bool Concurrent::reopen_name_locked_table(TableList* table_list, Session *session)
65
 
{
66
 
  safe_mutex_assert_owner(table::Cache::singleton().mutex().native_handle());
67
 
 
68
 
  if (session->getKilled())
69
 
    return true;
70
 
 
71
 
  identifier::Table identifier(table_list->getSchemaName(), table_list->getTableName());
72
 
  if (open_unireg_entry(session, table_list->getTableName(), identifier))
73
 
  {
74
 
    intern_close_table();
75
 
    return true;
76
 
  }
77
 
 
78
 
  /*
79
 
    We want to prevent other connections from opening this table until end
80
 
    of statement as it is likely that modifications of table's metadata are
81
 
    not yet finished (for example CREATE TRIGGER have to change .TRG cursor,
82
 
    or we might want to drop table if CREATE TABLE ... SELECT fails).
83
 
    This also allows us to assume that no other connection will sneak in
84
 
    before we will get table-level lock on this table.
85
 
  */
86
 
  getMutableShare()->resetVersion();
87
 
  in_use = session;
88
 
 
89
 
  tablenr= session->current_tablenr++;
90
 
  used_fields= 0;
91
 
  const_table= 0;
92
 
  null_row= false;
93
 
  maybe_null= false;
94
 
  force_index= false;
95
 
  status= STATUS_NO_RECORD;
96
 
 
97
 
  return false;
98
 
}
99
 
 
100
 
 
101
 
/*
102
 
  Load a table definition from cursor and open unireg table
103
 
 
104
 
  SYNOPSIS
105
 
  open_unireg_entry()
106
 
  session                       Thread handle
107
 
  entry         Store open table definition here
108
 
  table_list            TableList with db, table_name
109
 
  alias         Alias name
110
 
  cache_key             Key for share_cache
111
 
  cache_key_length      length of cache_key
112
 
 
113
 
  NOTES
114
 
  Extra argument for open is taken from session->open_options
115
 
  One must have a lock on table::Cache::singleton().mutex() when calling this function
116
 
 
117
 
  RETURN
118
 
  0     ok
119
 
#       Error
120
 
*/
121
 
 
122
 
int table::Concurrent::open_unireg_entry(Session *session,
123
 
                                         const char *alias,
124
 
                                         identifier::Table &identifier)
125
 
{
126
 
  int error;
127
 
  TableShare::shared_ptr share;
128
 
  uint32_t discover_retry_count= 0;
129
 
 
130
 
  safe_mutex_assert_owner(table::Cache::singleton().mutex().native_handle());
131
 
retry:
132
 
  if (not (share= table::instance::Shared::make_shared(session,
133
 
                                                       identifier,
134
 
                                                       error)))
135
 
  {
136
 
    return 1;
137
 
  }
138
 
 
139
 
  while ((error= share->open_table_from_share(session,
140
 
                                              identifier,
141
 
                                              alias,
142
 
                                              (uint32_t) (HA_OPEN_KEYFILE |
143
 
                                                          HA_OPEN_RNDFILE |
144
 
                                                          HA_GET_INDEX |
145
 
                                                          HA_TRY_READ_ONLY),
146
 
                                              session->open_options, *this)))
147
 
  {
148
 
    if (error == 7)                             // Table def changed
149
 
    {
150
 
      share->resetVersion();                        // Mark share as old
151
 
      if (discover_retry_count++)               // Retry once
152
 
      {
153
 
        table::instance::release(share);
154
 
        return 1;
155
 
      }
156
 
 
157
 
      /*
158
 
        TODO->
159
 
        Here we should wait until all threads has released the table.
160
 
        For now we do one retry. This may cause a deadlock if there
161
 
        is other threads waiting for other tables used by this thread.
162
 
 
163
 
        Proper fix would be to if the second retry failed:
164
 
        - Mark that table def changed
165
 
        - Return from open table
166
 
        - Close all tables used by this thread
167
 
        - Start waiting that the share is released
168
 
        - Retry by opening all tables again
169
 
      */
170
 
 
171
 
      /*
172
 
        TO BE FIXED
173
 
        To avoid deadlock, only wait for release if no one else is
174
 
        using the share.
175
 
      */
176
 
      if (share->getTableCount() != 1)
177
 
      {
178
 
        table::instance::release(share);
179
 
        return 1;
180
 
      }
181
 
 
182
 
      /* Free share and wait until it's released by all threads */
183
 
      table::instance::release(share);
184
 
 
185
 
      if (not session->getKilled())
186
 
      {
187
 
        drizzle_reset_errors(session, 1);         // Clear warnings
188
 
        session->clear_error();                 // Clear error message
189
 
        goto retry;
190
 
      }
191
 
 
192
 
      return 1;
193
 
    }
194
 
 
195
 
    table::instance::release(share);
196
 
 
197
 
    return 1;
198
 
  }
199
 
 
200
 
  return 0;
201
 
}
202
 
 
203
 
void table::Concurrent::release(void)
204
 
{
205
 
  // During an ALTER TABLE we could see the proto go away when the
206
 
  // definition is pushed out of this table object. In this case we would
207
 
  // not release from the cache because we were not in the cache. We just
208
 
  // delete if this happens.
209
 
  if (getShare()->getType() == message::Table::STANDARD)
210
 
  {
211
 
    table::instance::release(getMutableShare());
212
 
  }
213
 
  else
214
 
  {
215
 
    delete _share;
216
 
  }
217
 
  _share= NULL;
218
 
}
219
 
 
220
39
} /* namespace table */
221
40
} /* namespace drizzled */