~drizzle-trunk/drizzle/development

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