~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/table/concurrent.cc

  • Committer: Stewart Smith
  • Date: 2010-03-18 12:01:34 UTC
  • mto: (1666.2.3 build)
  • mto: This revision was merged to the branch mainline in revision 1596.
  • Revision ID: stewart@flamingspork.com-20100318120134-45fdnsw8g3j6c7oy
move RAND() into a plugin

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.h"
32
 
 
33
 
namespace drizzled
34
 
{
35
 
 
36
 
namespace table
37
 
{
38
 
 
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 table::Cache::singleton().mutex() 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(table::Cache::singleton().mutex().native_handle());
65
 
 
66
 
  if (session->getKilled())
67
 
    return true;
68
 
 
69
 
  TableIdentifier identifier(table_list->getSchemaName(), table_list->getTableName());
70
 
  if (open_unireg_entry(session, table_list->getTableName(), identifier))
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 table::Cache::singleton().mutex() 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
 
  TableShare::shared_ptr share;
126
 
  uint32_t discover_retry_count= 0;
127
 
 
128
 
  safe_mutex_assert_owner(table::Cache::singleton().mutex().native_handle());
129
 
retry:
130
 
  if (not (share= TableShare::getShareCreate(session,
131
 
                                             identifier,
132
 
                                             error)))
133
 
  {
134
 
    return 1;
135
 
  }
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
 
 
182
 
      if (not session->getKilled())
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
 
 
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
 
 
216
 
} /* namespace table */
217
 
} /* namespace drizzled */