MySQL 5.6.14 Source Code Document
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
LockQueue.cpp
1 /*
2  Copyright (C) 2007, 2008 MySQL AB
3  All rights reserved. Use is subject to license terms.
4 
5  This program is free software; you can redistribute it and/or modify
6  it under the terms of the GNU General Public License as published by
7  the Free Software Foundation; version 2 of the License.
8 
9  This program is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  GNU General Public License for more details.
13 
14  You should have received a copy of the GNU General Public License
15  along with this program; if not, write to the Free Software
16  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
17 */
18 
19 
20 #include "LockQueue.hpp"
21 #include "SimulatedBlock.hpp"
22 
23 Uint32
24 LockQueue::lock(SimulatedBlock* block,
25  Pool & thePool,
26  const UtilLockReq* req, const UtilLockReq** lockOwner)
27 {
28  const bool exclusive = ! (req->requestInfo & UtilLockReq::SharedLock);
29  const bool trylock = req->requestInfo & UtilLockReq::TryLock;
30  const bool notify = req->requestInfo & UtilLockReq::Notify;
31 
32  LocalDLFifoList<LockQueueElement> queue(thePool, m_queue);
33 
34  bool grant = true;
35  Ptr<LockQueueElement> lockEPtr;
36  if (queue.last(lockEPtr))
37  {
38  jamBlock(block);
39  if (! (lockEPtr.p->m_req.requestInfo & UtilLockReq::SharedLock))
40  {
41  jamBlock(block);
42  grant = false;
43  }
44  else if (exclusive)
45  {
46  jamBlock(block);
47  grant = false;
48  }
49  else if (lockEPtr.p->m_req.requestInfo & UtilLockReq::Granted)
50  {
51  jamBlock(block);
52  grant = true;
53  }
54  else
55  {
56  jamBlock(block);
57  grant = false;
58  }
59  }
60 
61  if(trylock && grant == false)
62  {
63  jamBlock(block);
64  if (notify && lockOwner)
65  {
66  jamBlock(block);
67  queue.first(lockEPtr);
68  * lockOwner = &lockEPtr.p->m_req;
69  }
70  return UtilLockRef::LockAlreadyHeld;
71  }
72 
73  if(!thePool.seize(lockEPtr))
74  {
75  jamBlock(block);
76  return UtilLockRef::OutOfLockRecords;
77  }
78 
79  lockEPtr.p->m_req = *req;
80  queue.addLast(lockEPtr);
81 
82  if(grant)
83  {
84  jamBlock(block);
85  lockEPtr.p->m_req.requestInfo |= UtilLockReq::Granted;
86  return UtilLockRef::OK;
87  }
88  else
89  {
90  jamBlock(block);
91  return UtilLockRef::InLockQueue;
92  }
93 }
94 
95 Uint32
96 LockQueue::unlock(SimulatedBlock* block,
97  Pool & thePool,
98  const UtilUnlockReq* req)
99 {
100  const Uint32 senderRef = req->senderRef;
101  const Uint32 senderData = req->senderData;
102 
103  Ptr<LockQueueElement> lockEPtr;
104  LocalDLFifoList<LockQueueElement> queue(thePool, m_queue);
105 
106  for (queue.first(lockEPtr); !lockEPtr.isNull(); queue.next(lockEPtr))
107  {
108  jamBlock(block);
109  if (lockEPtr.p->m_req.senderData == senderData &&
110  lockEPtr.p->m_req.senderRef == senderRef)
111  {
112  jamBlock(block);
113 
114  Uint32 res;
115  if (lockEPtr.p->m_req.requestInfo & UtilLockReq::Granted)
116  {
117  jamBlock(block);
118  res = UtilUnlockRef::OK;
119  }
120  else
121  {
122  jamBlock(block);
123  res = UtilUnlockRef::NotLockOwner;
124  }
125  queue.release(lockEPtr);
126  return res;
127  }
128  }
129 
130  return UtilUnlockRef::NotInLockQueue;
131 }
132 
133 bool
134 LockQueue::first(SimulatedBlock* block,
135  Pool& thePool, Iterator & iter)
136 {
137  LocalDLFifoList<LockQueueElement> queue(thePool, m_queue);
138  if (queue.first(iter.m_curr))
139  {
140  iter.m_block = block;
141  iter.m_prev.setNull();
142  iter.thePool = &thePool;
143  return true;
144  }
145  return false;
146 }
147 
148 bool
149 LockQueue::next(Iterator& iter)
150 {
151  iter.m_prev = iter.m_curr;
152  LocalDLFifoList<LockQueueElement> queue(*iter.thePool, m_queue);
153  return queue.next(iter.m_curr);
154 }
155 
156 int
158 {
159  SimulatedBlock* block = iter.m_block;
160  LocalDLFifoList<LockQueueElement> queue(*iter.thePool, m_queue);
161  if (iter.m_prev.isNull())
162  {
163  if (iter.m_curr.p->m_req.requestInfo & UtilLockReq::Granted)
164  {
165  jamBlock(block);
166  return 1;
167  }
168  else
169  {
170  jamBlock(block);
171  * req = iter.m_curr.p->m_req;
172  iter.m_curr.p->m_req.requestInfo |= UtilLockReq::Granted;
173  return 2;
174  }
175  }
176  else
177  {
178  jamBlock(block);
182  assert(iter.m_prev.p->m_req.requestInfo & UtilLockReq::Granted);
183  if (iter.m_prev.p->m_req.requestInfo & UtilLockReq::SharedLock)
184  {
185  jamBlock(block);
186  if (iter.m_curr.p->m_req.requestInfo & UtilLockReq::SharedLock)
187  {
188  jamBlock(block);
189  if (iter.m_curr.p->m_req.requestInfo & UtilLockReq::Granted)
190  {
191  jamBlock(block);
192  return 1;
193  }
194  else
195  {
196  jamBlock(block);
197  * req = iter.m_curr.p->m_req;
198  iter.m_curr.p->m_req.requestInfo |= UtilLockReq::Granted;
199  return 2;
200  }
201  }
202  }
203  return 0;
204  }
205 }
206 
207 void
209 {
210  LocalDLFifoList<LockQueueElement> queue(thePool, m_queue);
211  queue.release();
212 }
213 
214 #include "SimulatedBlock.hpp"
215 
216 void
218 {
220  LocalDLFifoList<LockQueueElement> queue(thePool, m_queue);
221 
222  for (queue.first(ptr); !ptr.isNull(); queue.next(ptr))
223  {
224  jamBlock(block);
225  block->infoEvent("- sender: 0x%x data: %u %s %s extra: %u",
226  ptr.p->m_req.senderRef,
227  ptr.p->m_req.senderData,
228  (ptr.p->m_req.requestInfo & UtilLockReq::SharedLock) ?
229  "S":"X",
230  (ptr.p->m_req.requestInfo & UtilLockReq::Granted) ?
231  "granted" : "",
232  ptr.p->m_req.extra);
233  }
234 }
235