Drizzled Public API Documentation

locks.cc
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 
79  try {
80  create_cond.timed_wait(scope, timeout);
81  }
82  catch(boost::thread_interrupted const& error)
83  {
84  // Currently nothing is done here.
85  throw error;
86  }
87 }
88 
89 bool Locks::lock(drizzled::session_id_t id_arg, const user_locks::Keys &arg)
90 {
91  boost::unique_lock<boost::mutex> scope(mutex);
92  user_locks::Keys created;
93  bool error= false;
94 
95  for (user_locks::Keys::const_iterator iter= arg.begin(); iter != arg.end(); iter++)
96  {
97  LockMap::iterator record= lock_map.find(*iter);
98 
99  if (record != lock_map.end()) // Found, so check ownership of the lock
100  {
101  if (id_arg != (*record).second->id)
102  {
103  // So it turns out the locks exist, and we can't grab them all
104  error= true;
105  break;
106  }
107  }
108  else
109  {
110  lock_map.insert(std::make_pair(*iter, new Lock(id_arg)));
111  created.insert(*iter);
112  }
113  }
114 
115  if (error)
116  {
117  for (user_locks::Keys::const_iterator iter= created.begin(); iter != created.end(); iter++)
118  {
119  lock_map.erase(*iter);
120  }
121 
122  return false;
123  }
124 
125  create_cond.notify_all();
126 
127  return true;
128 }
129 
130 bool Locks::isUsed(const user_locks::Key &arg, drizzled::session_id_t &id_arg)
131 {
132  boost::unique_lock<boost::mutex> scope(mutex);
133 
134  LockMap::iterator iter= lock_map.find(arg);
135 
136  if ( iter == lock_map.end())
137  return false;
138 
139  id_arg= iter->second->id;
140 
141  return true;
142 }
143 
144 bool Locks::isFree(const user_locks::Key &arg)
145 {
146  boost::unique_lock<boost::mutex> scope(mutex);
147 
148  LockMap::iterator iter= lock_map.find(arg);
149 
150  return iter != lock_map.end();
151 }
152 
153 void Locks::Copy(LockMap &lock_map_arg)
154 {
155  boost::unique_lock<boost::mutex> scope(mutex);
156  lock_map_arg= lock_map;
157 }
158 
159 locks::return_t Locks::release(const user_locks::Key &arg, drizzled::session_id_t &id_arg, bool and_wait)
160 {
161  size_t elements= 0;
162  boost::unique_lock<boost::mutex> scope(mutex);
163  LockMap::iterator iter= lock_map.find(arg);
164 
165  // Nothing is found
166  if ( iter == lock_map.end())
167  return locks::NOT_FOUND;
168 
169  if (iter->second->id == id_arg)
170  {
171  elements= lock_map.erase(arg);
172  assert(elements); // If we can't find what we just found, then we are broken
173 
174  if (elements)
175  {
176  release_cond.notify_one();
177 
178  if (and_wait)
179  {
180  bool found= false;
181  while (not found)
182  {
183  assert(boost::this_thread::interruption_enabled());
184  try {
185  create_cond.wait(scope);
186  }
187  catch(boost::thread_interrupted const& error)
188  {
189  // Currently nothing is done here.
190  throw error;
191  }
192  iter= lock_map.find(arg);
193 
194  if (iter != lock_map.end())
195  found= true;
196  }
197  }
198 
199  return locks::SUCCESS;
200  }
201  }
202 
203  return locks::NOT_OWNED_BY;
204 }
205 
206 } /* namespace user_locks */