~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/table/concurrent.cc

  • Committer: Brian Aker
  • Date: 2011-02-22 06:12:02 UTC
  • mfrom: (2190.1.6 drizzle-build)
  • Revision ID: brian@tangent.org-20110222061202-k03czxykqy4x9hjs
List update, header fixes, multiple symbols, and David deletes some code.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* -*- mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; -*-
 
2
 *  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
 
3
 *
 
4
 *  Copyright (C) 2010 Brian Aker
 
5
 *
 
6
 *  This program is free software; you can redistribute it and/or modify
 
7
 *  it under the terms of the GNU General Public License as published by
 
8
 *  the Free Software Foundation; either version 2 of the License, or
 
9
 *  (at your option) any later version.
 
10
 *
 
11
 *  This program is distributed in the hope that it will be useful,
 
12
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 
13
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
14
 *  GNU General Public License for more details.
 
15
 *
 
16
 *  You should have received a copy of the GNU General Public License
 
17
 *  along with this program; if not, write to the Free Software
 
18
 *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 
19
 */
 
20
 
 
21
#include <config.h>
 
22
 
 
23
#include <sys/types.h>
 
24
#include <sys/stat.h>
 
25
#include <fcntl.h>
 
26
 
 
27
#include <drizzled/session.h>
 
28
#include <plugin/myisam/myisam.h>
 
29
#include <drizzled/plugin/transactional_storage_engine.h>
 
30
 
 
31
#include <drizzled/table/instance.h>
 
32
 
 
33
#include <drizzled/table.h>
 
34
 
 
35
namespace drizzled
 
36
{
 
37
 
 
38
namespace table
 
39
{
 
40
 
 
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
} /* namespace table */
 
221
} /* namespace drizzled */