~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to plugin/user_locks/locks.cc

* Completes the blueprint for splitting the XA Resource Manager
  API from the storage engine API:

We add a new plugin::XaResourceManager abstract interface class
which exposes the X/Open XA distributed transaction protocol for
resource managers.

We add a new plugin::MonitoredInTransaction base class from
which all plugins that need monitored by Drizzle's transaction
manager (drizzled::TransactionServices component) derive.

All plugin::StorageEngine's now derive from plugin::MonitoredInTransaction
since all storage engines a monitored by the transaction manager
and the Session keeps a "slot" available for keeping the engine's
per-session data state.  In a future patch, the transaction log's
XaApplier plugin will also derive from MonitoredInTransaction, as
the transaction log, in XA mode, is also monitored by Drizzle's
transaction manager and automatically enlisted in XA transactions.

* Updates all documentation in /drizzled/transaction_services.cc
  to accurately reflect Drizzle's new transaction management
  process and explicit transaction and statement boundaries.

* Kills off dead code:

  binlog_format_names
  ha_init()
  total_ha, total_ha_2pc (no longer necessary, as the above-mentioned
  abstract base classes provide all of this functionality)
  StorageEngine::slot (now plugin::MonitoredInTransaction::getId())
  TransactionalStorageEngine::two_phase_commit (same as above)

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 */