~drizzle-trunk/drizzle/development

1823.6.1 by Brian Aker
First pass through adding back user_locks.
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
1823.6.3 by Brian Aker
Time out code now inserted for user locks.
24
#include <boost/thread/locks.hpp>
25
1823.6.1 by Brian Aker
First pass through adding back user_locks.
26
#include <string>
27
28
namespace user_locks {
29
1823.6.7 by Brian Aker
Cleans up namespace for locks (now per user).
30
bool Locks::lock(drizzled::session_id_t id_arg, const user_locks::Key &arg, int64_t wait_for)
1823.6.1 by Brian Aker
First pass through adding back user_locks.
31
{
1955.1.2 by Brian Aker
Update such that we can now do a lock test with a wait.
32
  boost::unique_lock<boost::mutex> scope(mutex);
1823.6.3 by Brian Aker
Time out code now inserted for user locks.
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
    }
1933.2.5 by Brian Aker
Merge in the ability to kill off locks as well as barriers.
43
    try {
1955.1.2 by Brian Aker
Update such that we can now do a lock test with a wait.
44
      if (wait_for)
45
      {
46
        bool success= release_cond.timed_wait(scope, timeout);
1823.6.3 by Brian Aker
Time out code now inserted for user locks.
47
1955.1.2 by Brian Aker
Update such that we can now do a lock test with a wait.
48
        if (not success)
49
          return false;
50
      }
51
      else
52
      {
53
        release_cond.wait(scope);
54
      }
1933.2.5 by Brian Aker
Merge in the ability to kill off locks as well as barriers.
55
    }
56
    catch(boost::thread_interrupted const& error)
57
    {
58
      // Currently nothing is done here.
59
      throw error;
60
    }
1823.6.3 by Brian Aker
Time out code now inserted for user locks.
61
  }
62
63
  if (iter == lock_map.end())
64
  {
1955.1.1 by Brian Aker
Finally added pieces so that you can do a drop lock and wait.
65
    create_cond.notify_all();
1933.2.7 by Brian Aker
Break out observer to its own class, same with lock.
66
    return lock_map.insert(std::make_pair(arg, new Lock(id_arg))).second;
1823.6.3 by Brian Aker
Time out code now inserted for user locks.
67
  }
68
69
  return false;
70
}
71
1955.1.1 by Brian Aker
Finally added pieces so that you can do a drop lock and wait.
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
{
1955.1.2 by Brian Aker
Update such that we can now do a lock test with a wait.
76
  boost::unique_lock<boost::mutex> scope(mutex);
1955.1.1 by Brian Aker
Finally added pieces so that you can do a drop lock and wait.
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
1823.6.7 by Brian Aker
Cleans up namespace for locks (now per user).
90
bool Locks::lock(drizzled::session_id_t id_arg, const user_locks::Keys &arg)
1823.6.5 by Brian Aker
Added get_locks() and release_locks();
91
{
92
  boost::unique_lock<boost::mutex> scope(mutex);
1955.1.2 by Brian Aker
Update such that we can now do a lock test with a wait.
93
  user_locks::Keys created;
94
  bool error= false;
1823.6.5 by Brian Aker
Added get_locks() and release_locks();
95
1823.6.7 by Brian Aker
Cleans up namespace for locks (now per user).
96
  for (user_locks::Keys::const_iterator iter= arg.begin(); iter != arg.end(); iter++)
1823.6.5 by Brian Aker
Added get_locks() and release_locks();
97
  {
98
    LockMap::iterator record= lock_map.find(*iter);
99
1955.1.2 by Brian Aker
Update such that we can now do a lock test with a wait.
100
    if (record != lock_map.end()) // Found, so check ownership of the lock
1823.6.5 by Brian Aker
Added get_locks() and release_locks();
101
    {
102
      if (id_arg != (*record).second->id)
1955.1.2 by Brian Aker
Update such that we can now do a lock test with a wait.
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);
1823.6.5 by Brian Aker
Added get_locks() and release_locks();
113
    }
114
  }
115
1955.1.2 by Brian Aker
Update such that we can now do a lock test with a wait.
116
  if (error)
1823.6.5 by Brian Aker
Added get_locks() and release_locks();
117
  {
1955.1.2 by Brian Aker
Update such that we can now do a lock test with a wait.
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;
1823.6.5 by Brian Aker
Added get_locks() and release_locks();
124
  }
125
1955.1.2 by Brian Aker
Update such that we can now do a lock test with a wait.
126
  create_cond.notify_all();
127
1823.6.5 by Brian Aker
Added get_locks() and release_locks();
128
  return true;
129
}
130
1823.6.7 by Brian Aker
Cleans up namespace for locks (now per user).
131
bool Locks::isUsed(const user_locks::Key &arg, drizzled::session_id_t &id_arg)
1823.6.1 by Brian Aker
First pass through adding back user_locks.
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
1823.6.7 by Brian Aker
Cleans up namespace for locks (now per user).
145
bool Locks::isFree(const user_locks::Key &arg)
1823.6.1 by Brian Aker
First pass through adding back user_locks.
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
1823.6.6 by Brian Aker
Added a table function to see locks, updated some tests to see the
154
void Locks::Copy(LockMap &lock_map_arg)
155
{
1933.2.8 by Brian Aker
Updating test to have a bit more deterministic behavior.
156
  boost::unique_lock<boost::mutex> scope(mutex);
1823.6.6 by Brian Aker
Added a table function to see locks, updated some tests to see the
157
  lock_map_arg= lock_map;
158
}
159
1955.1.2 by Brian Aker
Update such that we can now do a lock test with a wait.
160
locks::return_t Locks::release(const user_locks::Key &arg, drizzled::session_id_t &id_arg, bool and_wait)
1823.6.1 by Brian Aker
First pass through adding back user_locks.
161
{
1823.6.2 by Brian Aker
Solves the "dangling lock" problem.
162
  size_t elements= 0;
1823.6.1 by Brian Aker
First pass through adding back user_locks.
163
  boost::unique_lock<boost::mutex> scope(mutex);
1823.6.2 by Brian Aker
Solves the "dangling lock" problem.
164
  LockMap::iterator iter= lock_map.find(arg);
165
1823.6.3 by Brian Aker
Time out code now inserted for user locks.
166
  // Nothing is found
1823.6.2 by Brian Aker
Solves the "dangling lock" problem.
167
  if ( iter == lock_map.end())
1955.1.2 by Brian Aker
Update such that we can now do a lock test with a wait.
168
    return locks::NOT_FOUND;
1823.6.2 by Brian Aker
Solves the "dangling lock" problem.
169
170
  if ((*iter).second->id == id_arg)
1955.1.2 by Brian Aker
Update such that we can now do a lock test with a wait.
171
  {
1823.6.2 by Brian Aker
Solves the "dangling lock" problem.
172
    elements= lock_map.erase(arg);
1955.1.2 by Brian Aker
Update such that we can now do a lock test with a wait.
173
    assert(elements); // If we can't find what we just found, then we are broken
174
175
    if (elements)
1955.1.1 by Brian Aker
Finally added pieces so that you can do a drop lock and wait.
176
    {
1955.1.2 by Brian Aker
Update such that we can now do a lock test with a wait.
177
      release_cond.notify_one();
178
179
      if (and_wait)
1955.1.1 by Brian Aker
Finally added pieces so that you can do a drop lock and wait.
180
      {
1955.1.2 by Brian Aker
Update such that we can now do a lock test with a wait.
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
        }
1955.1.1 by Brian Aker
Finally added pieces so that you can do a drop lock and wait.
198
      }
1955.1.2 by Brian Aker
Update such that we can now do a lock test with a wait.
199
200
      return locks::SUCCESS;
1955.1.1 by Brian Aker
Finally added pieces so that you can do a drop lock and wait.
201
    }
1823.6.3 by Brian Aker
Time out code now inserted for user locks.
202
  }
203
1955.1.2 by Brian Aker
Update such that we can now do a lock test with a wait.
204
  return locks::NOT_OWNED_BY;
1823.6.1 by Brian Aker
First pass through adding back user_locks.
205
}
206
207
} /* namespace user_locks */