~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
55
  This function assumes that its caller already acquired LOCK_open mutex.
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
{
64
  safe_mutex_assert_owner(LOCK_open.native_handle());
65
66
  if (session->killed)
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
113
  One must have a lock on LOCK_open when calling this function
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;
125
  TableSharePtr share;
126
  uint32_t discover_retry_count= 0;
127
128
  safe_mutex_assert_owner(LOCK_open.native_handle());
129
retry:
130
  if (not (share= TableShare::getShareCreate(session,
131
                                             identifier,
132
                                             &error)))
133
    return 1;
134
135
  while ((error= share->open_table_from_share(session,
136
                                              identifier,
137
                                              alias,
138
                                              (uint32_t) (HA_OPEN_KEYFILE |
139
                                                          HA_OPEN_RNDFILE |
140
                                                          HA_GET_INDEX |
141
                                                          HA_TRY_READ_ONLY),
142
                                              session->open_options, *this)))
143
  {
144
    if (error == 7)                             // Table def changed
145
    {
146
      share->resetVersion();                        // Mark share as old
147
      if (discover_retry_count++)               // Retry once
148
      {
149
        TableShare::release(share);
150
        return 1;
151
      }
152
153
      /*
154
        TODO->
155
        Here we should wait until all threads has released the table.
156
        For now we do one retry. This may cause a deadlock if there
157
        is other threads waiting for other tables used by this thread.
158
159
        Proper fix would be to if the second retry failed:
160
        - Mark that table def changed
161
        - Return from open table
162
        - Close all tables used by this thread
163
        - Start waiting that the share is released
164
        - Retry by opening all tables again
165
      */
166
167
      /*
168
        TO BE FIXED
169
        To avoid deadlock, only wait for release if no one else is
170
        using the share.
171
      */
172
      if (share->getTableCount() != 1)
173
      {
174
        TableShare::release(share);
175
        return 1;
176
      }
177
      /* Free share and wait until it's released by all threads */
178
      TableShare::release(share);
179
180
      if (!session->killed)
181
      {
182
        drizzle_reset_errors(session, 1);         // Clear warnings
183
        session->clear_error();                 // Clear error message
184
        goto retry;
185
      }
186
      return 1;
187
    }
188
189
    TableShare::release(share);
190
191
    return 1;
192
  }
193
194
  return 0;
195
}
196
1843.8.5 by Brian Aker
Added concurrent type.
197
} /* namespace table */
198
} /* namespace drizzled */