Skip to content

Commit ce0e01f

Browse files
committed
HDFS-17398. [FGL] Implement the FGL lock for FSNLockManager
1 parent 1f146ec commit ce0e01f

File tree

2 files changed

+628
-0
lines changed

2 files changed

+628
-0
lines changed
Lines changed: 293 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,293 @@
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+
// release the holding FSLock
61+
this.fsLock.readUnlock("BMReadLockInterruptiblyFailed");
62+
throw e;
63+
}
64+
} else if (lockMode.equals(FSNamesystemLockMode.FS)) {
65+
this.fsLock.readLockInterruptibly();
66+
} else if (lockMode.equals(FSNamesystemLockMode.BM)) {
67+
this.bmLock.readLockInterruptibly();
68+
}
69+
}
70+
71+
@Override
72+
public void readUnlock(FSNamesystemLockMode lockMode, String opName) {
73+
if (lockMode.equals(FSNamesystemLockMode.GLOBAL)) {
74+
this.bmLock.readUnlock(opName);
75+
this.fsLock.readUnlock(opName);
76+
} else if (lockMode.equals(FSNamesystemLockMode.FS)) {
77+
this.fsLock.readUnlock(opName);
78+
} else if (lockMode.equals(FSNamesystemLockMode.BM)) {
79+
this.bmLock.readUnlock(opName);
80+
}
81+
}
82+
83+
public void readUnlock(FSNamesystemLockMode lockMode, String opName,
84+
Supplier<String> lockReportInfoSupplier) {
85+
if (lockMode.equals(FSNamesystemLockMode.GLOBAL)) {
86+
this.bmLock.readUnlock(opName, lockReportInfoSupplier);
87+
this.fsLock.readUnlock(opName, lockReportInfoSupplier);
88+
} else if (lockMode.equals(FSNamesystemLockMode.FS)) {
89+
this.fsLock.readUnlock(opName, lockReportInfoSupplier);
90+
} else if (lockMode.equals(FSNamesystemLockMode.BM)) {
91+
this.bmLock.readUnlock(opName, lockReportInfoSupplier);
92+
}
93+
}
94+
95+
@Override
96+
public void writeLock(FSNamesystemLockMode lockMode) {
97+
if (lockMode.equals(FSNamesystemLockMode.GLOBAL)) {
98+
this.fsLock.writeLock();
99+
this.bmLock.writeLock();
100+
} else if (lockMode.equals(FSNamesystemLockMode.FS)) {
101+
this.fsLock.writeLock();
102+
} else if (lockMode.equals(FSNamesystemLockMode.BM)) {
103+
this.bmLock.writeLock();
104+
}
105+
}
106+
107+
@Override
108+
public void writeUnlock(FSNamesystemLockMode lockMode, String opName) {
109+
if (lockMode.equals(FSNamesystemLockMode.GLOBAL)) {
110+
this.bmLock.writeUnlock(opName);
111+
this.fsLock.writeUnlock(opName);
112+
} else if (lockMode.equals(FSNamesystemLockMode.FS)) {
113+
this.fsLock.writeUnlock(opName);
114+
} else if (lockMode.equals(FSNamesystemLockMode.BM)) {
115+
this.bmLock.writeUnlock(opName);
116+
}
117+
}
118+
119+
@Override
120+
public void writeUnlock(FSNamesystemLockMode lockMode, String opName,
121+
boolean suppressWriteLockReport) {
122+
if (lockMode.equals(FSNamesystemLockMode.GLOBAL)) {
123+
this.bmLock.writeUnlock(opName, suppressWriteLockReport);
124+
this.fsLock.writeUnlock(opName, suppressWriteLockReport);
125+
} else if (lockMode.equals(FSNamesystemLockMode.FS)) {
126+
this.fsLock.writeUnlock(opName, suppressWriteLockReport);
127+
} else if (lockMode.equals(FSNamesystemLockMode.BM)) {
128+
this.bmLock.writeUnlock(opName, suppressWriteLockReport);
129+
}
130+
}
131+
132+
public void writeUnlock(FSNamesystemLockMode lockMode, String opName,
133+
Supplier<String> lockReportInfoSupplier) {
134+
if (lockMode.equals(FSNamesystemLockMode.GLOBAL)) {
135+
this.bmLock.writeUnlock(opName, lockReportInfoSupplier);
136+
this.fsLock.writeUnlock(opName, lockReportInfoSupplier);
137+
} else if (lockMode.equals(FSNamesystemLockMode.FS)) {
138+
this.fsLock.writeUnlock(opName, lockReportInfoSupplier);
139+
} else if (lockMode.equals(FSNamesystemLockMode.BM)) {
140+
this.bmLock.writeUnlock(opName, lockReportInfoSupplier);
141+
}
142+
}
143+
144+
@Override
145+
public void writeLockInterruptibly(FSNamesystemLockMode lockMode)
146+
throws InterruptedException {
147+
if (lockMode.equals(FSNamesystemLockMode.GLOBAL)) {
148+
this.fsLock.writeLockInterruptibly();
149+
try {
150+
this.bmLock.writeLockInterruptibly();
151+
} catch (InterruptedException e) {
152+
this.fsLock.writeUnlock("BMWriteLockInterruptiblyFailed");
153+
throw e;
154+
}
155+
} else if (lockMode.equals(FSNamesystemLockMode.FS)) {
156+
this.fsLock.writeLockInterruptibly();
157+
} else if (lockMode.equals(FSNamesystemLockMode.BM)) {
158+
this.bmLock.writeLockInterruptibly();
159+
}
160+
}
161+
162+
@Override
163+
public boolean hasWriteLock(FSNamesystemLockMode lockMode) {
164+
if (lockMode.equals(FSNamesystemLockMode.GLOBAL)) {
165+
if (this.fsLock.isWriteLockedByCurrentThread()) {
166+
assert this.bmLock.isWriteLockedByCurrentThread();
167+
return true;
168+
} else {
169+
assert !this.bmLock.isWriteLockedByCurrentThread();
170+
return false;
171+
}
172+
} else if (lockMode.equals(FSNamesystemLockMode.FS)) {
173+
return this.fsLock.isWriteLockedByCurrentThread();
174+
} else if (lockMode.equals(FSNamesystemLockMode.BM)) {
175+
return this.bmLock.isWriteLockedByCurrentThread();
176+
}
177+
return false;
178+
}
179+
180+
@Override
181+
public boolean hasReadLock(FSNamesystemLockMode lockMode) {
182+
if (lockMode.equals(FSNamesystemLockMode.GLOBAL)) {
183+
if (hasWriteLock(FSNamesystemLockMode.GLOBAL)) {
184+
return true;
185+
} else if (this.fsLock.getReadHoldCount() > 0) {
186+
assert this.bmLock.getReadHoldCount() > 0;
187+
return true;
188+
} else {
189+
assert this.bmLock.getReadHoldCount() <= 0;
190+
return false;
191+
}
192+
} else if (lockMode.equals(FSNamesystemLockMode.FS)) {
193+
return this.fsLock.getReadHoldCount() > 0 || this.fsLock.isWriteLockedByCurrentThread();
194+
} else if (lockMode.equals(FSNamesystemLockMode.BM)) {
195+
return this.bmLock.getReadHoldCount() > 0 || this.bmLock.isWriteLockedByCurrentThread();
196+
}
197+
return false;
198+
}
199+
200+
@Override
201+
/**
202+
* This method is only used for ComputeDirectoryContentSummary.
203+
* For the GLOBAL mode, just return the FSLock's ReadHoldCount.
204+
*/
205+
public int getReadHoldCount(FSNamesystemLockMode lockMode) {
206+
if (lockMode.equals(FSNamesystemLockMode.GLOBAL)) {
207+
return this.fsLock.getReadHoldCount();
208+
} else if (lockMode.equals(FSNamesystemLockMode.FS)) {
209+
return this.fsLock.getReadHoldCount();
210+
} else if (lockMode.equals(FSNamesystemLockMode.BM)) {
211+
return this.bmLock.getReadHoldCount();
212+
}
213+
return -1;
214+
}
215+
216+
@Override
217+
public int getQueueLength(FSNamesystemLockMode lockMode) {
218+
if (lockMode.equals(FSNamesystemLockMode.GLOBAL)) {
219+
return -1;
220+
} else if (lockMode.equals(FSNamesystemLockMode.FS)) {
221+
return this.fsLock.getQueueLength();
222+
} else if (lockMode.equals(FSNamesystemLockMode.BM)) {
223+
return this.bmLock.getQueueLength();
224+
}
225+
return -1;
226+
}
227+
228+
@Override
229+
public long getNumOfReadLockLongHold(FSNamesystemLockMode lockMode) {
230+
if (lockMode.equals(FSNamesystemLockMode.GLOBAL)) {
231+
return -1;
232+
} else if (lockMode.equals(FSNamesystemLockMode.FS)) {
233+
return this.fsLock.getNumOfReadLockLongHold();
234+
} else if (lockMode.equals(FSNamesystemLockMode.BM)) {
235+
return this.bmLock.getNumOfReadLockLongHold();
236+
}
237+
return -1;
238+
}
239+
240+
@Override
241+
public long getNumOfWriteLockLongHold(FSNamesystemLockMode lockMode) {
242+
if (lockMode.equals(FSNamesystemLockMode.GLOBAL)) {
243+
return -1;
244+
} else if (lockMode.equals(FSNamesystemLockMode.FS)) {
245+
return this.fsLock.getNumOfWriteLockLongHold();
246+
} else if (lockMode.equals(FSNamesystemLockMode.BM)) {
247+
return this.bmLock.getNumOfWriteLockLongHold();
248+
}
249+
return -1;
250+
}
251+
252+
@Override
253+
public boolean isMetricsEnabled() {
254+
return this.fsLock.isMetricsEnabled();
255+
}
256+
257+
public void setMetricsEnabled(boolean metricsEnabled) {
258+
this.fsLock.setMetricsEnabled(metricsEnabled);
259+
this.bmLock.setMetricsEnabled(metricsEnabled);
260+
}
261+
262+
@Override
263+
public void setReadLockReportingThresholdMs(long readLockReportingThresholdMs) {
264+
this.fsLock.setReadLockReportingThresholdMs(readLockReportingThresholdMs);
265+
this.bmLock.setReadLockReportingThresholdMs(readLockReportingThresholdMs);
266+
}
267+
268+
@Override
269+
public long getReadLockReportingThresholdMs() {
270+
return this.fsLock.getReadLockReportingThresholdMs();
271+
}
272+
273+
@Override
274+
public void setWriteLockReportingThresholdMs(long writeLockReportingThresholdMs) {
275+
this.fsLock.setWriteLockReportingThresholdMs(writeLockReportingThresholdMs);
276+
this.bmLock.setWriteLockReportingThresholdMs(writeLockReportingThresholdMs);
277+
}
278+
279+
@Override
280+
public long getWriteLockReportingThresholdMs() {
281+
return this.fsLock.getWriteLockReportingThresholdMs();
282+
}
283+
284+
@Override
285+
public void setLockForTests(ReentrantReadWriteLock lock) {
286+
throw new UnsupportedOperationException("SetLockTests is unsupported");
287+
}
288+
289+
@Override
290+
public ReentrantReadWriteLock getLockForTests() {
291+
throw new UnsupportedOperationException("SetLockTests is unsupported");
292+
}
293+
}

0 commit comments

Comments
 (0)