Skip to content

Commit a922b9c

Browse files
committed
HDFS-13346. RBF: Fix synchronization of router quota and nameservice quota.
1 parent 9db9cd9 commit a922b9c

File tree

3 files changed

+79
-2
lines changed

3 files changed

+79
-2
lines changed

hadoop-hdfs-project/hadoop-hdfs-rbf/src/main/java/org/apache/hadoop/hdfs/server/federation/router/RouterAdminServer.java

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626

2727
import org.apache.hadoop.conf.Configuration;
2828
import org.apache.hadoop.hdfs.DFSConfigKeys;
29+
import org.apache.hadoop.hdfs.protocol.HdfsConstants;
2930
import org.apache.hadoop.hdfs.protocol.proto.RouterProtocolProtos.RouterAdminProtocolService;
3031
import org.apache.hadoop.hdfs.protocolPB.RouterAdminProtocolPB;
3132
import org.apache.hadoop.hdfs.protocolPB.RouterAdminProtocolServerSideTranslatorPB;
@@ -54,6 +55,7 @@
5455
import org.apache.hadoop.hdfs.server.federation.store.protocol.RemoveMountTableEntryResponse;
5556
import org.apache.hadoop.hdfs.server.federation.store.protocol.UpdateMountTableEntryRequest;
5657
import org.apache.hadoop.hdfs.server.federation.store.protocol.UpdateMountTableEntryResponse;
58+
import org.apache.hadoop.hdfs.server.federation.store.records.MountTable;
5759
import org.apache.hadoop.hdfs.server.namenode.NameNode;
5860
import org.apache.hadoop.ipc.ProtobufRpcEngine;
5961
import org.apache.hadoop.ipc.RPC;
@@ -228,7 +230,31 @@ public AddMountTableEntryResponse addMountTableEntry(
228230
@Override
229231
public UpdateMountTableEntryResponse updateMountTableEntry(
230232
UpdateMountTableEntryRequest request) throws IOException {
231-
return getMountTableStore().updateMountTableEntry(request);
233+
UpdateMountTableEntryResponse response =
234+
getMountTableStore().updateMountTableEntry(request);
235+
236+
MountTable mountTable = request.getEntry();
237+
if (mountTable != null) {
238+
synchronizeQuota(mountTable);
239+
}
240+
return response;
241+
}
242+
243+
/**
244+
* Synchronize the quota value across mount table and subclusters.
245+
* @param mountTable Quota set in given mount table.
246+
* @throws IOException
247+
*/
248+
private void synchronizeQuota(MountTable mountTable) throws IOException {
249+
String path = mountTable.getSourcePath();
250+
long nsQuota = mountTable.getQuota().getQuota();
251+
long ssQuota = mountTable.getQuota().getSpaceQuota();
252+
253+
if (nsQuota != HdfsConstants.QUOTA_DONT_SET
254+
|| ssQuota != HdfsConstants.QUOTA_DONT_SET) {
255+
this.router.getRpcServer().getQuotaModule().setQuota(path, nsQuota,
256+
ssQuota, null);
257+
}
232258
}
233259

234260
@Override

hadoop-hdfs-project/hadoop-hdfs-rbf/src/test/java/org/apache/hadoop/hdfs/server/federation/router/TestRouterAdminCLI.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,8 @@
5151
import org.junit.AfterClass;
5252
import org.junit.BeforeClass;
5353
import org.junit.Test;
54+
import org.mockito.Mockito;
55+
import org.mockito.internal.util.reflection.Whitebox;
5456

5557
import com.google.common.base.Supplier;
5658

@@ -104,6 +106,14 @@ public static void globalSetUp() throws Exception {
104106
membership.registerNamenode(
105107
createNamenodeReport("ns1", "nn1", HAServiceState.ACTIVE));
106108
stateStore.refreshCaches(true);
109+
110+
// Mock the quota module since no real namenode is started up.
111+
Quota quota = Mockito
112+
.spy(routerContext.getRouter().createRpcServer().getQuotaModule());
113+
Mockito.doNothing().when(quota).setQuota(Mockito.anyString(),
114+
Mockito.anyLong(), Mockito.anyLong(), Mockito.any());
115+
Whitebox.setInternalState(
116+
routerContext.getRouter().getRpcServer(), "quotaCall", quota);
107117
}
108118

109119
@AfterClass

hadoop-hdfs-project/hadoop-hdfs-rbf/src/test/java/org/apache/hadoop/hdfs/server/federation/router/TestRouterQuota.java

Lines changed: 42 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
package org.apache.hadoop.hdfs.server.federation.router;
1919

2020
import static org.junit.Assert.assertEquals;
21+
import static org.junit.Assert.assertNotEquals;
2122
import static org.junit.Assert.assertNull;
2223

2324
import java.io.IOException;
@@ -37,9 +38,9 @@
3738
import org.apache.hadoop.hdfs.protocol.ClientProtocol;
3839
import org.apache.hadoop.hdfs.protocol.DSQuotaExceededException;
3940
import org.apache.hadoop.hdfs.protocol.NSQuotaExceededException;
40-
import org.apache.hadoop.hdfs.server.federation.RouterConfigBuilder;
4141
import org.apache.hadoop.hdfs.server.federation.MiniRouterDFSCluster.NamenodeContext;
4242
import org.apache.hadoop.hdfs.server.federation.MiniRouterDFSCluster.RouterContext;
43+
import org.apache.hadoop.hdfs.server.federation.RouterConfigBuilder;
4344
import org.apache.hadoop.hdfs.server.federation.StateStoreDFSCluster;
4445
import org.apache.hadoop.hdfs.server.federation.resolver.MountTableManager;
4546
import org.apache.hadoop.hdfs.server.federation.resolver.MountTableResolver;
@@ -49,8 +50,10 @@
4950
import org.apache.hadoop.hdfs.server.federation.store.protocol.GetMountTableEntriesResponse;
5051
import org.apache.hadoop.hdfs.server.federation.store.protocol.RemoveMountTableEntryRequest;
5152
import org.apache.hadoop.hdfs.server.federation.store.protocol.RemoveMountTableEntryResponse;
53+
import org.apache.hadoop.hdfs.server.federation.store.protocol.UpdateMountTableEntryRequest;
5254
import org.apache.hadoop.hdfs.server.federation.store.records.MountTable;
5355
import org.apache.hadoop.test.GenericTestUtils;
56+
import org.apache.hadoop.util.Time;
5457
import org.junit.After;
5558
import org.junit.Before;
5659
import org.junit.Test;
@@ -452,4 +455,42 @@ private List<MountTable> getMountTable(String path) throws IOException {
452455

453456
return removeResponse.getEntries();
454457
}
458+
459+
@Test
460+
public void testQuotaSynchronization() throws IOException {
461+
long updateNsQuota = 3;
462+
long updateSsQuota = 4;
463+
MountTable mountTable = MountTable.newInstance("/quotaSync",
464+
Collections.singletonMap("ns0", "/"), Time.now(), Time.now());
465+
mountTable.setQuota(new RouterQuotaUsage.Builder().quota(1)
466+
.spaceQuota(2).build());
467+
// Add new mount table
468+
addMountTable(mountTable);
469+
470+
// ensure the quota is not set as updated value
471+
QuotaUsage realQuota = nnContext1.getFileSystem()
472+
.getQuotaUsage(new Path("/"));
473+
assertNotEquals(updateNsQuota, realQuota.getQuota());
474+
assertNotEquals(updateSsQuota, realQuota.getSpaceQuota());
475+
476+
// Call periodicInvoke to ensure quota updated in quota manager
477+
// and state store.
478+
RouterQuotaUpdateService updateService = routerContext.getRouter()
479+
.getQuotaCacheUpdateService();
480+
updateService.periodicInvoke();
481+
482+
mountTable.setQuota(new RouterQuotaUsage.Builder().quota(updateNsQuota)
483+
.spaceQuota(updateSsQuota).build());
484+
UpdateMountTableEntryRequest updateRequest = UpdateMountTableEntryRequest
485+
.newInstance(mountTable);
486+
RouterClient client = routerContext.getAdminClient();
487+
MountTableManager mountTableManager = client.getMountTableManager();
488+
mountTableManager.updateMountTableEntry(updateRequest);
489+
490+
// verify if the quota is updated in real path
491+
realQuota = nnContext1.getFileSystem().getQuotaUsage(
492+
new Path("/"));
493+
assertEquals(updateNsQuota, realQuota.getQuota());
494+
assertEquals(updateSsQuota, realQuota.getSpaceQuota());
495+
}
455496
}

0 commit comments

Comments
 (0)