Skip to content

Commit b688ac8

Browse files
ZanderXuzengqiang.xu
authored andcommitted
HDFS-17398. [FGL] Implement the FGL lock for FSNLockManager (#6599)
1 parent 9b9ac73 commit b688ac8

File tree

2 files changed

+575
-0
lines changed

2 files changed

+575
-0
lines changed
Lines changed: 300 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,300 @@
1+
/**
2+
* Licensed to the Apache Software Foundation (ASF) under one
3+
* or more contributor license agreements. See the NOTICE file
4+
* distributed with this work for additional information
5+
* regarding copyright ownership. The ASF licenses this file
6+
* to you under the Apache License, Version 2.0 (the
7+
* "License"); you may not use this file except in compliance
8+
* with the License. You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing, software
13+
* distributed under the License is distributed on an "AS IS" BASIS,
14+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
* See the License for the specific language governing permissions and
16+
* limitations under the License.
17+
*/
18+
package org.apache.hadoop.hdfs.server.namenode.fgl;
19+
20+
import org.apache.hadoop.conf.Configuration;
21+
import org.apache.hadoop.hdfs.server.namenode.FSNamesystemLock;
22+
import org.apache.hadoop.metrics2.lib.MutableRatesWithAggregation;
23+
24+
import java.util.concurrent.locks.ReentrantReadWriteLock;
25+
import java.util.function.Supplier;
26+
27+
/**
28+
* Splitting the global FSN lock into FSLock and BMLock.
29+
* FSLock is used to protect directory tree-related operations.
30+
* BMLock is used to protect block-related and dn-related operations.
31+
* The lock order should be: FSLock,BMLock.
32+
*/
33+
public class FineGrainedFSNamesystemLock implements FSNLockManager {
34+
private final FSNamesystemLock fsLock;
35+
private final FSNamesystemLock bmLock;
36+
37+
public FineGrainedFSNamesystemLock(Configuration conf, MutableRatesWithAggregation aggregation) {
38+
this.fsLock = new FSNamesystemLock(conf, aggregation);
39+
this.bmLock = new FSNamesystemLock(conf, aggregation);
40+
}
41+
42+
@Override
43+
public void readLock(FSNamesystemLockMode lockMode) {
44+
if (lockMode.equals(FSNamesystemLockMode.GLOBAL)) {
45+
this.fsLock.readLock();
46+
this.bmLock.readLock();
47+
} else if (lockMode.equals(FSNamesystemLockMode.FS)) {
48+
this.fsLock.readLock();
49+
} else if (lockMode.equals(FSNamesystemLockMode.BM)) {
50+
this.bmLock.readLock();
51+
}
52+
}
53+
54+
public void readLockInterruptibly(FSNamesystemLockMode lockMode) throws InterruptedException {
55+
if (lockMode.equals(FSNamesystemLockMode.GLOBAL)) {
56+
this.fsLock.readLockInterruptibly();
57+
try {
58+
this.bmLock.readLockInterruptibly();
59+
} catch (InterruptedException e) {
60+
// The held FSLock should be released if the current thread is interrupted
61+
// while acquiring the BMLock.
62+
this.fsLock.readUnlock("BMReadLockInterruptiblyFailed");
63+
throw e;
64+
}
65+
} else if (lockMode.equals(FSNamesystemLockMode.FS)) {
66+
this.fsLock.readLockInterruptibly();
67+
} else if (lockMode.equals(FSNamesystemLockMode.BM)) {
68+
this.bmLock.readLockInterruptibly();
69+
}
70+
}
71+
72+
@Override
73+
public void readUnlock(FSNamesystemLockMode lockMode, String opName) {
74+
if (lockMode.equals(FSNamesystemLockMode.GLOBAL)) {
75+
this.bmLock.readUnlock(opName);
76+
this.fsLock.readUnlock(opName);
77+
} else if (lockMode.equals(FSNamesystemLockMode.FS)) {
78+
this.fsLock.readUnlock(opName);
79+
} else if (lockMode.equals(FSNamesystemLockMode.BM)) {
80+
this.bmLock.readUnlock(opName);
81+
}
82+
}
83+
84+
public void readUnlock(FSNamesystemLockMode lockMode, String opName,
85+
Supplier<String> lockReportInfoSupplier) {
86+
if (lockMode.equals(FSNamesystemLockMode.GLOBAL)) {
87+
this.bmLock.readUnlock(opName, lockReportInfoSupplier);
88+
this.fsLock.readUnlock(opName, lockReportInfoSupplier);
89+
} else if (lockMode.equals(FSNamesystemLockMode.FS)) {
90+
this.fsLock.readUnlock(opName, lockReportInfoSupplier);
91+
} else if (lockMode.equals(FSNamesystemLockMode.BM)) {
92+
this.bmLock.readUnlock(opName, lockReportInfoSupplier);
93+
}
94+
}
95+
96+
@Override
97+
public void writeLock(FSNamesystemLockMode lockMode) {
98+
if (lockMode.equals(FSNamesystemLockMode.GLOBAL)) {
99+
this.fsLock.writeLock();
100+
this.bmLock.writeLock();
101+
} else if (lockMode.equals(FSNamesystemLockMode.FS)) {
102+
this.fsLock.writeLock();
103+
} else if (lockMode.equals(FSNamesystemLockMode.BM)) {
104+
this.bmLock.writeLock();
105+
}
106+
}
107+
108+
@Override
109+
public void writeUnlock(FSNamesystemLockMode lockMode, String opName) {
110+
if (lockMode.equals(FSNamesystemLockMode.GLOBAL)) {
111+
this.bmLock.writeUnlock(opName);
112+
this.fsLock.writeUnlock(opName);
113+
} else if (lockMode.equals(FSNamesystemLockMode.FS)) {
114+
this.fsLock.writeUnlock(opName);
115+
} else if (lockMode.equals(FSNamesystemLockMode.BM)) {
116+
this.bmLock.writeUnlock(opName);
117+
}
118+
}
119+
120+
@Override
121+
public void writeUnlock(FSNamesystemLockMode lockMode, String opName,
122+
boolean suppressWriteLockReport) {
123+
if (lockMode.equals(FSNamesystemLockMode.GLOBAL)) {
124+
this.bmLock.writeUnlock(opName, suppressWriteLockReport);
125+
this.fsLock.writeUnlock(opName, suppressWriteLockReport);
126+
} else if (lockMode.equals(FSNamesystemLockMode.FS)) {
127+
this.fsLock.writeUnlock(opName, suppressWriteLockReport);
128+
} else if (lockMode.equals(FSNamesystemLockMode.BM)) {
129+
this.bmLock.writeUnlock(opName, suppressWriteLockReport);
130+
}
131+
}
132+
133+
public void writeUnlock(FSNamesystemLockMode lockMode, String opName,
134+
Supplier<String> lockReportInfoSupplier) {
135+
if (lockMode.equals(FSNamesystemLockMode.GLOBAL)) {
136+
this.bmLock.writeUnlock(opName, lockReportInfoSupplier);
137+
this.fsLock.writeUnlock(opName, lockReportInfoSupplier);
138+
} else if (lockMode.equals(FSNamesystemLockMode.FS)) {
139+
this.fsLock.writeUnlock(opName, lockReportInfoSupplier);
140+
} else if (lockMode.equals(FSNamesystemLockMode.BM)) {
141+
this.bmLock.writeUnlock(opName, lockReportInfoSupplier);
142+
}
143+
}
144+
145+
@Override
146+
public void writeLockInterruptibly(FSNamesystemLockMode lockMode)
147+
throws InterruptedException {
148+
if (lockMode.equals(FSNamesystemLockMode.GLOBAL)) {
149+
this.fsLock.writeLockInterruptibly();
150+
try {
151+
this.bmLock.writeLockInterruptibly();
152+
} catch (InterruptedException e) {
153+
// The held FSLock should be released if the current thread is interrupted
154+
// while acquiring the BMLock.
155+
this.fsLock.writeUnlock("BMWriteLockInterruptiblyFailed");
156+
throw e;
157+
}
158+
} else if (lockMode.equals(FSNamesystemLockMode.FS)) {
159+
this.fsLock.writeLockInterruptibly();
160+
} else if (lockMode.equals(FSNamesystemLockMode.BM)) {
161+
this.bmLock.writeLockInterruptibly();
162+
}
163+
}
164+
165+
@Override
166+
public boolean hasWriteLock(FSNamesystemLockMode lockMode) {
167+
if (lockMode.equals(FSNamesystemLockMode.GLOBAL)) {
168+
if (this.fsLock.isWriteLockedByCurrentThread()) {
169+
// The bm writeLock should be held by the current thread.
170+
assert this.bmLock.isWriteLockedByCurrentThread();
171+
return true;
172+
} else {
173+
// The bm writeLock should not be held by the current thread.
174+
assert !this.bmLock.isWriteLockedByCurrentThread();
175+
return false;
176+
}
177+
} else if (lockMode.equals(FSNamesystemLockMode.FS)) {
178+
return this.fsLock.isWriteLockedByCurrentThread();
179+
} else if (lockMode.equals(FSNamesystemLockMode.BM)) {
180+
return this.bmLock.isWriteLockedByCurrentThread();
181+
}
182+
return false;
183+
}
184+
185+
@Override
186+
public boolean hasReadLock(FSNamesystemLockMode lockMode) {
187+
if (lockMode.equals(FSNamesystemLockMode.GLOBAL)) {
188+
if (hasWriteLock(FSNamesystemLockMode.GLOBAL)) {
189+
return true;
190+
} else if (this.fsLock.getReadHoldCount() > 0) {
191+
// The bm readLock should be held by the current thread.
192+
assert this.bmLock.getReadHoldCount() > 0;
193+
return true;
194+
} else {
195+
// The bm readLock should not be held by the current thread.
196+
assert this.bmLock.getReadHoldCount() <= 0;
197+
return false;
198+
}
199+
} else if (lockMode.equals(FSNamesystemLockMode.FS)) {
200+
return this.fsLock.getReadHoldCount() > 0 || this.fsLock.isWriteLockedByCurrentThread();
201+
} else if (lockMode.equals(FSNamesystemLockMode.BM)) {
202+
return this.bmLock.getReadHoldCount() > 0 || this.bmLock.isWriteLockedByCurrentThread();
203+
}
204+
return false;
205+
}
206+
207+
@Override
208+
/**
209+
* This method is only used for ComputeDirectoryContentSummary.
210+
* For the GLOBAL mode, just return the FSLock's ReadHoldCount.
211+
*/
212+
public int getReadHoldCount(FSNamesystemLockMode lockMode) {
213+
if (lockMode.equals(FSNamesystemLockMode.GLOBAL)) {
214+
return this.fsLock.getReadHoldCount();
215+
} else if (lockMode.equals(FSNamesystemLockMode.FS)) {
216+
return this.fsLock.getReadHoldCount();
217+
} else if (lockMode.equals(FSNamesystemLockMode.BM)) {
218+
return this.bmLock.getReadHoldCount();
219+
}
220+
return -1;
221+
}
222+
223+
@Override
224+
public int getQueueLength(FSNamesystemLockMode lockMode) {
225+
if (lockMode.equals(FSNamesystemLockMode.GLOBAL)) {
226+
return -1;
227+
} else if (lockMode.equals(FSNamesystemLockMode.FS)) {
228+
return this.fsLock.getQueueLength();
229+
} else if (lockMode.equals(FSNamesystemLockMode.BM)) {
230+
return this.bmLock.getQueueLength();
231+
}
232+
return -1;
233+
}
234+
235+
@Override
236+
public long getNumOfReadLockLongHold(FSNamesystemLockMode lockMode) {
237+
if (lockMode.equals(FSNamesystemLockMode.GLOBAL)) {
238+
return -1;
239+
} else if (lockMode.equals(FSNamesystemLockMode.FS)) {
240+
return this.fsLock.getNumOfReadLockLongHold();
241+
} else if (lockMode.equals(FSNamesystemLockMode.BM)) {
242+
return this.bmLock.getNumOfReadLockLongHold();
243+
}
244+
return -1;
245+
}
246+
247+
@Override
248+
public long getNumOfWriteLockLongHold(FSNamesystemLockMode lockMode) {
249+
if (lockMode.equals(FSNamesystemLockMode.GLOBAL)) {
250+
return -1;
251+
} else if (lockMode.equals(FSNamesystemLockMode.FS)) {
252+
return this.fsLock.getNumOfWriteLockLongHold();
253+
} else if (lockMode.equals(FSNamesystemLockMode.BM)) {
254+
return this.bmLock.getNumOfWriteLockLongHold();
255+
}
256+
return -1;
257+
}
258+
259+
@Override
260+
public boolean isMetricsEnabled() {
261+
return this.fsLock.isMetricsEnabled();
262+
}
263+
264+
public void setMetricsEnabled(boolean metricsEnabled) {
265+
this.fsLock.setMetricsEnabled(metricsEnabled);
266+
this.bmLock.setMetricsEnabled(metricsEnabled);
267+
}
268+
269+
@Override
270+
public void setReadLockReportingThresholdMs(long readLockReportingThresholdMs) {
271+
this.fsLock.setReadLockReportingThresholdMs(readLockReportingThresholdMs);
272+
this.bmLock.setReadLockReportingThresholdMs(readLockReportingThresholdMs);
273+
}
274+
275+
@Override
276+
public long getReadLockReportingThresholdMs() {
277+
return this.fsLock.getReadLockReportingThresholdMs();
278+
}
279+
280+
@Override
281+
public void setWriteLockReportingThresholdMs(long writeLockReportingThresholdMs) {
282+
this.fsLock.setWriteLockReportingThresholdMs(writeLockReportingThresholdMs);
283+
this.bmLock.setWriteLockReportingThresholdMs(writeLockReportingThresholdMs);
284+
}
285+
286+
@Override
287+
public long getWriteLockReportingThresholdMs() {
288+
return this.fsLock.getWriteLockReportingThresholdMs();
289+
}
290+
291+
@Override
292+
public void setLockForTests(ReentrantReadWriteLock lock) {
293+
throw new UnsupportedOperationException("SetLockTests is unsupported");
294+
}
295+
296+
@Override
297+
public ReentrantReadWriteLock getLockForTests() {
298+
throw new UnsupportedOperationException("SetLockTests is unsupported");
299+
}
300+
}

0 commit comments

Comments
 (0)