~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to plugin/user_locks/locks.cc

  • Committer: Prafulla Tekawade
  • Date: 2010-07-13 16:07:35 UTC
  • mto: (1662.1.4 rollup)
  • mto: This revision was merged to the branch mainline in revision 1664.
  • Revision ID: prafulla_t@users.sourceforge.net-20100713160735-2fsdtrm3azayuyu1
This bug is simillar to mysql bug 36133
http://bugs.mysql.com/bug.php?id=36133

Taking changes from that fix.

  - The problem was that the range optimizer evaluated constant expressions, 
    and among them it would try to evaluate IN-subquery predicates slated for
    handling with materialization strategy. However, these predicates require
    that parent_join->setup_subquery_materialization() is invoked before one
    attempts to evaluate them.
  
  - Fixed by making the range optimizer not to evaluate expressions that have
    item->is_expensive() == TRUE (these are materialization subqueries and 
    stored function calls). This should also resolve the problem that EXPLAIN 
    may be too long. 
    This change cuts off some opportunities for range optimizer, but this is 
    the price we're willing to pay for separation of query optimization and
    execution. 

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
 
#include <plugin/user_locks/module.h>
23
 
 
24
 
#include <boost/thread/locks.hpp>
25
 
 
26
 
#include <string>
27
 
 
28
 
namespace user_locks {
29
 
 
30
 
bool Locks::lock(drizzled::session_id_t id_arg, const user_locks::Key &arg, int64_t wait_for)
31
 
{
32
 
  boost::unique_lock<boost::mutex> scope(mutex);
33
 
  boost::system_time timeout= boost::get_system_time() + boost::posix_time::seconds(wait_for);
34
 
  
35
 
  LockMap::iterator iter;
36
 
  while ((iter= lock_map.find(arg)) != lock_map.end())
37
 
  {
38
 
    if (id_arg == (*iter).second->id)
39
 
    {
40
 
      // We own the lock, so we just exit.
41
 
      return true;
42
 
    }
43
 
    try {
44
 
      if (wait_for)
45
 
      {
46
 
        bool success= release_cond.timed_wait(scope, timeout);
47
 
 
48
 
        if (not success)
49
 
          return false;
50
 
      }
51
 
      else
52
 
      {
53
 
        release_cond.wait(scope);
54
 
      }
55
 
    }
56
 
    catch(boost::thread_interrupted const& error)
57
 
    {
58
 
      // Currently nothing is done here.
59
 
      throw error;
60
 
    }
61
 
  }
62
 
 
63
 
  if (iter == lock_map.end())
64
 
  {
65
 
    create_cond.notify_all();
66
 
    return lock_map.insert(std::make_pair(arg, new Lock(id_arg))).second;
67
 
  }
68
 
 
69
 
  return false;
70
 
}
71
 
 
72
 
// Currently we just let timeouts occur, and the caller will need to know
73
 
// what it is looking for/whether to go back into this.
74
 
void Locks::waitCreate(int64_t wait_for)
75
 
{
76
 
  boost::unique_lock<boost::mutex> scope(mutex);
77
 
  boost::system_time timeout= boost::get_system_time() + boost::posix_time::seconds(wait_for);
78
 
  bool timed_out;
79
 
 
80
 
  try {
81
 
    timed_out= create_cond.timed_wait(scope, timeout);
82
 
  }
83
 
  catch(boost::thread_interrupted const& error)
84
 
  {
85
 
    // Currently nothing is done here.
86
 
    throw error;
87
 
  }
88
 
}
89
 
 
90
 
bool Locks::lock(drizzled::session_id_t id_arg, const user_locks::Keys &arg)
91
 
{
92
 
  boost::unique_lock<boost::mutex> scope(mutex);
93
 
  user_locks::Keys created;
94
 
  bool error= false;
95
 
 
96
 
  for (user_locks::Keys::const_iterator iter= arg.begin(); iter != arg.end(); iter++)
97
 
  {
98
 
    LockMap::iterator record= lock_map.find(*iter);
99
 
 
100
 
    if (record != lock_map.end()) // Found, so check ownership of the lock
101
 
    {
102
 
      if (id_arg != (*record).second->id)
103
 
      {
104
 
        // So it turns out the locks exist, and we can't grab them all
105
 
        error= true;
106
 
        break;
107
 
      }
108
 
    }
109
 
    else
110
 
    {
111
 
      lock_map.insert(std::make_pair(*iter, new Lock(id_arg)));
112
 
      created.insert(*iter);
113
 
    }
114
 
  }
115
 
 
116
 
  if (error)
117
 
  {
118
 
    for (user_locks::Keys::const_iterator iter= created.begin(); iter != created.end(); iter++)
119
 
    {
120
 
      lock_map.erase(*iter);
121
 
    }
122
 
 
123
 
    return false;
124
 
  }
125
 
 
126
 
  create_cond.notify_all();
127
 
 
128
 
  return true;
129
 
}
130
 
 
131
 
bool Locks::isUsed(const user_locks::Key &arg, drizzled::session_id_t &id_arg)
132
 
{
133
 
  boost::unique_lock<boost::mutex> scope(mutex);
134
 
  
135
 
  LockMap::iterator iter= lock_map.find(arg);
136
 
  
137
 
  if ( iter == lock_map.end())
138
 
    return false;
139
 
 
140
 
  id_arg= (*iter).second->id;
141
 
 
142
 
  return true;
143
 
}
144
 
 
145
 
bool Locks::isFree(const user_locks::Key &arg)
146
 
{
147
 
  boost::unique_lock<boost::mutex> scope(mutex);
148
 
 
149
 
  LockMap::iterator iter= lock_map.find(arg);
150
 
  
151
 
  return iter != lock_map.end();
152
 
}
153
 
 
154
 
void Locks::Copy(LockMap &lock_map_arg)
155
 
{
156
 
  boost::unique_lock<boost::mutex> scope(mutex);
157
 
  lock_map_arg= lock_map;
158
 
}
159
 
 
160
 
locks::return_t Locks::release(const user_locks::Key &arg, drizzled::session_id_t &id_arg, bool and_wait)
161
 
{
162
 
  size_t elements= 0;
163
 
  boost::unique_lock<boost::mutex> scope(mutex);
164
 
  LockMap::iterator iter= lock_map.find(arg);
165
 
 
166
 
  // Nothing is found
167
 
  if ( iter == lock_map.end())
168
 
    return locks::NOT_FOUND;
169
 
 
170
 
  if ((*iter).second->id == id_arg)
171
 
  {
172
 
    elements= lock_map.erase(arg);
173
 
    assert(elements); // If we can't find what we just found, then we are broken
174
 
 
175
 
    if (elements)
176
 
    {
177
 
      release_cond.notify_one();
178
 
 
179
 
      if (and_wait)
180
 
      {
181
 
        bool found= false;
182
 
        while (not found)
183
 
        {
184
 
          assert(boost::this_thread::interruption_enabled());
185
 
          try {
186
 
            create_cond.wait(scope);
187
 
          }
188
 
          catch(boost::thread_interrupted const& error)
189
 
          {
190
 
            // Currently nothing is done here.
191
 
            throw error;
192
 
          }
193
 
          iter= lock_map.find(arg);
194
 
 
195
 
          if (iter != lock_map.end())
196
 
            found= true;
197
 
        }
198
 
      }
199
 
 
200
 
      return locks::SUCCESS;
201
 
    }
202
 
  }
203
 
 
204
 
  return locks::NOT_OWNED_BY;
205
 
}
206
 
 
207
 
} /* namespace user_locks */