Skip to content

Commit bcb3e17

Browse files
committed
core: Prepare AbstractLockManager for Opaque support
Add "Opaque" methods to AbstractLockManager, which in turn call their byte[]-counterpart. Add a temporary, non-public AbstractLockManager2, which reverses this logic. Also add some simple logging for deprecated calls into AbstractLockManager2 (which will be removed very soon). Mark all byte[]-variants deprecated for removal. Related: #149 Signed-off-by: Christian Kohlschütter <[email protected]>
1 parent e0176ff commit bcb3e17

File tree

2 files changed

+297
-2
lines changed

2 files changed

+297
-2
lines changed

core/src/main/java/org/dcache/nfs/v4/nlm/AbstractLockManager.java

Lines changed: 70 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
import java.util.concurrent.locks.Lock;
2727
import java.util.stream.Collectors;
2828

29+
import org.dcache.nfs.util.Opaque;
2930
import org.dcache.nfs.v4.xdr.nfs4_prot;
3031

3132
/**
@@ -42,49 +43,116 @@ public abstract class AbstractLockManager implements LockManager {
4243
* @param objId object id.
4344
* @return exclusive lock.
4445
*/
46+
@Deprecated(forRemoval = true)
4547
abstract protected Lock getObjectLock(byte[] objId);
4648

49+
/**
50+
* Get exclusive lock on objects locks.
51+
*
52+
* @param objId object id.
53+
* @return exclusive lock.
54+
*/
55+
protected Lock getObjectLock(Opaque objId) {
56+
return getObjectLock(objId.asBytes());
57+
}
58+
4759
/**
4860
* Get collection of currently used active locks on the object.
4961
*
5062
* @param objId object id.
5163
* @return collection of active locks.
5264
*/
65+
@Deprecated(forRemoval = true)
5366
abstract protected Collection<NlmLock> getActiveLocks(byte[] objId);
5467

68+
/**
69+
* Get collection of currently used active locks on the object.
70+
*
71+
* @param objId object id.
72+
* @return collection of active locks.
73+
*/
74+
protected Collection<NlmLock> getActiveLocks(Opaque objId) {
75+
return getActiveLocks(objId.asBytes());
76+
}
77+
5578
/**
5679
* Add {@code lock} to an object.
5780
*
5881
* @param objId object id.
5982
* @param lock lock to add.
6083
*/
84+
@Deprecated(forRemoval = true)
6185
abstract protected void add(byte[] objId, NlmLock lock);
6286

87+
/**
88+
* Add {@code lock} to an object.
89+
*
90+
* @param objId object id.
91+
* @param lock lock to add.
92+
*/
93+
protected void add(Opaque objId, NlmLock lock) {
94+
add(objId.asBytes(), lock);
95+
}
96+
6397
/**
6498
* Remove a lock for the given object.
6599
*
66100
* @param objId object id.
67101
* @param lock lock to remove.
68102
* @return true, if specified lock was removed.
69103
*/
104+
@Deprecated(forRemoval = true)
70105
abstract protected boolean remove(byte[] objId, NlmLock lock);
71106

107+
/**
108+
* Remove a lock for the given object.
109+
*
110+
* @param objId object id.
111+
* @param lock lock to remove.
112+
* @return true, if specified lock was removed.
113+
*/
114+
protected boolean remove(Opaque objId, NlmLock lock) {
115+
return remove(objId.asBytes(), lock);
116+
}
117+
72118
/**
73119
* Add all locks from a given collection of locks
74120
*
75-
* @param objId
76-
* @param locks
121+
* @param objId object id.
122+
* @param locks locks to add.
77123
*/
124+
@Deprecated(forRemoval = true)
78125
abstract protected void addAll(byte[] objId, Collection<NlmLock> locks);
79126

127+
/**
128+
* Add all locks from a given collection of locks
129+
*
130+
* @param objId object id.
131+
* @param locks locks to add.
132+
*/
133+
protected void addAll(Opaque objId, Collection<NlmLock> locks) {
134+
addAll(objId.asBytes(), locks);
135+
}
136+
80137
/**
81138
* Remove all locks specified by {@code locks} associated with the given object.
82139
*
83140
* @param objId object id.
84141
* @param locks collections of locks to remove.
85142
*/
143+
@Deprecated(forRemoval = true)
86144
abstract protected void removeAll(byte[] objId, Collection<NlmLock> locks);
87145

146+
/**
147+
* Remove all locks specified by {@code locks} associated with the given object.
148+
*
149+
* @param objId object id.
150+
* @param locks collections of locks to remove.
151+
*/
152+
protected void removeAll(Opaque objId, Collection<NlmLock> locks) {
153+
removeAll(objId.asBytes(), locks);
154+
}
155+
88156
@Override
89157
public void lock(byte[] objId, NlmLock lock) throws LockException {
90158
Lock dlmLock = getObjectLock(objId);
Lines changed: 227 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,227 @@
1+
/*
2+
* Copyright (c) 2017 Deutsches Elektronen-Synchroton,
3+
* Member of the Helmholtz Association, (DESY), HAMBURG, GERMANY
4+
*
5+
* This library is free software; you can redistribute it and/or modify
6+
* it under the terms of the GNU Library General Public License as
7+
* published by the Free Software Foundation; either version 2 of the
8+
* License, or (at your option) any later version.
9+
*
10+
* This library is distributed in the hope that it will be useful,
11+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13+
* GNU Library General Public License for more details.
14+
*
15+
* You should have received a copy of the GNU Library General Public
16+
* License along with this program (see the file COPYING.LIB for more
17+
* details); if not, write to the Free Software Foundation, Inc.,
18+
* 675 Mass Ave, Cambridge, MA 02139, USA.
19+
*/
20+
package org.dcache.nfs.v4.nlm;
21+
22+
import java.util.ArrayList;
23+
import java.util.Collection;
24+
import java.util.List;
25+
import java.util.Optional;
26+
import java.util.concurrent.locks.Lock;
27+
import java.util.stream.Collectors;
28+
29+
import org.dcache.nfs.util.Opaque;
30+
import org.dcache.nfs.v4.xdr.nfs4_prot;
31+
32+
abstract class AbstractLockManager2 extends AbstractLockManager {
33+
private static final boolean DEBUG_DEPRECATED_CALLS = false;
34+
35+
@Override
36+
@Deprecated(forRemoval = true)
37+
protected final Lock getObjectLock(byte[] objId) {
38+
throw new IllegalStateException();
39+
}
40+
41+
@Override
42+
protected abstract Lock getObjectLock(Opaque objId);
43+
44+
@Override
45+
@Deprecated(forRemoval = true)
46+
protected final Collection<NlmLock> getActiveLocks(byte[] objId) {
47+
throw new IllegalStateException();
48+
}
49+
50+
@Override
51+
protected abstract Collection<NlmLock> getActiveLocks(Opaque objId);
52+
53+
@Override
54+
@Deprecated(forRemoval = true)
55+
protected final void add(byte[] objId, NlmLock lock) {
56+
throw new IllegalStateException();
57+
}
58+
59+
@Override
60+
protected abstract void add(Opaque objId, NlmLock lock);
61+
62+
@Override
63+
@Deprecated(forRemoval = true)
64+
protected final boolean remove(byte[] objId, NlmLock lock) {
65+
throw new IllegalStateException();
66+
}
67+
68+
@Override
69+
protected abstract boolean remove(Opaque objId, NlmLock lock);
70+
71+
@Override
72+
@Deprecated(forRemoval = true)
73+
protected final void addAll(byte[] objId, Collection<NlmLock> locks) {
74+
throw new IllegalStateException();
75+
}
76+
77+
@Override
78+
protected abstract void addAll(Opaque objId, Collection<NlmLock> locks);
79+
80+
@Override
81+
@Deprecated(forRemoval = true)
82+
protected final void removeAll(byte[] objId, Collection<NlmLock> locks) {
83+
throw new IllegalStateException();
84+
}
85+
86+
@Override
87+
protected abstract void removeAll(Opaque objId, Collection<NlmLock> locks);
88+
89+
@Override
90+
@Deprecated(forRemoval = true)
91+
public void lock(byte[] objId, NlmLock lock) throws LockException {
92+
if (DEBUG_DEPRECATED_CALLS) {
93+
new IllegalStateException("Called deprecated method").printStackTrace();
94+
}
95+
lock(Opaque.forBytes(objId), lock);
96+
}
97+
98+
@Override
99+
public void lock(Opaque objId, NlmLock lock) throws LockException {
100+
Lock dlmLock = getObjectLock(objId);
101+
dlmLock.lock();
102+
try {
103+
Collection<NlmLock> currentLocks = getActiveLocks(objId);
104+
Optional<NlmLock> conflictingLock = currentLocks.stream().filter((NlmLock l) -> l.isConflicting(lock))
105+
.findAny();
106+
if (conflictingLock.isPresent()) {
107+
throw new LockDeniedException("object locked", conflictingLock.get());
108+
}
109+
// no conflicting locks. try to merge existing locks
110+
List<NlmLock> toMerge = currentLocks.stream().filter((NlmLock l) -> l.isOverlappingRange(lock)).filter((
111+
NlmLock l) -> l.isSameOwner(lock)).filter((NlmLock l) -> l.getLockType() == lock.getLockType())
112+
.collect(Collectors.toList());
113+
if (toMerge.isEmpty()) {
114+
add(objId, lock);
115+
} else {
116+
// merge overlaping/continues locks
117+
long lockBegin = lock.getOffset();
118+
long lockEnd = lock.getLength() == nfs4_prot.NFS4_UINT64_MAX ? nfs4_prot.NFS4_UINT64_MAX : (lockBegin
119+
+ lock.getLength());
120+
for (NlmLock l : toMerge) {
121+
lockBegin = Math.min(lockBegin, l.getOffset());
122+
lockEnd = lockEnd == nfs4_prot.NFS4_UINT64_MAX || l.getLength() == nfs4_prot.NFS4_UINT64_MAX
123+
? nfs4_prot.NFS4_UINT64_MAX : Math.max(lockEnd, l.getOffset() + l.getLength() - 1);
124+
}
125+
NlmLock mergedLock = new NlmLock(lock.getOwner(), lock.getLockType(), lockBegin,
126+
lockEnd == nfs4_prot.NFS4_UINT64_MAX ? lockEnd : lockEnd - lockBegin);
127+
removeAll(objId, toMerge);
128+
add(objId, mergedLock);
129+
}
130+
} finally {
131+
dlmLock.unlock();
132+
}
133+
}
134+
135+
@Override
136+
@Deprecated(forRemoval = true)
137+
public void unlock(byte[] objId, NlmLock lock) throws LockException {
138+
if (DEBUG_DEPRECATED_CALLS) {
139+
new IllegalStateException("Called deprecated method").printStackTrace();
140+
}
141+
unlock(Opaque.forBytes(objId), lock);
142+
}
143+
144+
@Override
145+
public void unlock(Opaque objId, NlmLock lock) throws LockException {
146+
Lock dlmLock = getObjectLock(objId);
147+
dlmLock.lock();
148+
try {
149+
Collection<NlmLock> currentLocks = getActiveLocks(objId);
150+
// check for exact match first
151+
if (remove(objId, lock)) {
152+
return;
153+
}
154+
List<NlmLock> toRemove = new ArrayList<>();
155+
List<NlmLock> toAdd = new ArrayList<>();
156+
currentLocks.stream().filter((NlmLock l) -> l.isSameOwner(lock)).filter((NlmLock l) -> l.isOverlappingRange(
157+
lock)).forEach((NlmLock l) -> {
158+
toRemove.add(l);
159+
long l1 = lock.getOffset() - l.getOffset();
160+
if (l1 > 0) {
161+
NlmLock first = new NlmLock(l.getOwner(), l.getLockType(), l.getOffset(), l1);
162+
toAdd.add(first);
163+
}
164+
if (lock.getLength() != nfs4_prot.NFS4_UINT64_MAX) {
165+
long l2 = l.getLength() - l1 - 1;
166+
if (l2 > 0) {
167+
NlmLock second = new NlmLock(l.getOwner(), l.getLockType(), lock.getOffset() + lock
168+
.getLength(), l2);
169+
toAdd.add(second);
170+
}
171+
}
172+
});
173+
if (toRemove.isEmpty()) {
174+
throw new LockRangeUnavailabeException("no matching lock");
175+
}
176+
removeAll(objId, toRemove);
177+
addAll(objId, toAdd);
178+
} finally {
179+
dlmLock.unlock();
180+
}
181+
}
182+
183+
@Override
184+
@Deprecated(forRemoval = true)
185+
public void test(byte[] objId, NlmLock lock) throws LockException {
186+
if (DEBUG_DEPRECATED_CALLS) {
187+
new IllegalStateException("Called deprecated method").printStackTrace();
188+
}
189+
test(Opaque.forBytes(objId), lock);
190+
}
191+
192+
@Override
193+
public void test(Opaque objId, NlmLock lock) throws LockException {
194+
Lock dlmLock = getObjectLock(objId);
195+
dlmLock.lock();
196+
try {
197+
Collection<NlmLock> currentLocks = getActiveLocks(objId);
198+
Optional<NlmLock> conflictingLock = currentLocks.stream().filter((NlmLock l) -> l.isOverlappingRange(lock)
199+
&& !l.isSameOwner(lock)).findAny();
200+
if (conflictingLock.isPresent()) {
201+
throw new LockDeniedException("object locked", conflictingLock.get());
202+
}
203+
} finally {
204+
dlmLock.unlock();
205+
}
206+
}
207+
208+
@Override
209+
@Deprecated(forRemoval = true)
210+
public void unlockIfExists(byte[] objId, NlmLock lock) {
211+
if (DEBUG_DEPRECATED_CALLS) {
212+
new IllegalStateException("Called deprecated method").printStackTrace();
213+
}
214+
unlockIfExists(Opaque.forBytes(objId), lock);
215+
}
216+
217+
@Override
218+
public void unlockIfExists(Opaque objId, NlmLock lock) {
219+
Lock dlmLock = getObjectLock(objId);
220+
dlmLock.lock();
221+
try {
222+
remove(objId, lock);
223+
} finally {
224+
dlmLock.unlock();
225+
}
226+
}
227+
}

0 commit comments

Comments
 (0)