29
29
import org .apache .hadoop .hdfs .protocol .HdfsConstants ;
30
30
import org .apache .hadoop .hdfs .server .blockmanagement .BlockStoragePolicySuite ;
31
31
import org .apache .hadoop .hdfs .server .namenode .snapshot .Snapshot ;
32
+ import org .apache .hadoop .ipc .RemoteException ;
32
33
import org .apache .hadoop .test .GenericTestUtils ;
33
34
import org .apache .hadoop .test .PathUtils ;
34
35
import org .junit .jupiter .api .BeforeAll ;
35
36
import org .junit .jupiter .api .Test ;
37
+ import org .mockito .Mockito ;
36
38
37
39
import java .io .IOException ;
38
40
39
41
import static org .apache .hadoop .hdfs .protocol .HdfsConstants .HOT_STORAGE_POLICY_NAME ;
40
42
import static org .apache .hadoop .hdfs .protocol .HdfsConstants .ONESSD_STORAGE_POLICY_NAME ;
41
43
import static org .junit .jupiter .api .Assertions .assertEquals ;
44
+ import static org .junit .jupiter .api .Assertions .assertFalse ;
45
+ import static org .junit .jupiter .api .Assertions .assertThrows ;
42
46
import static org .junit .jupiter .api .Assertions .assertTrue ;
47
+ import static org .mockito .ArgumentMatchers .anyBoolean ;
48
+ import static org .mockito .ArgumentMatchers .anyInt ;
49
+ import static org .mockito .Mockito .doReturn ;
43
50
44
51
public class TestCorrectnessOfQuotaAfterRenameOp {
45
52
private static MiniDFSCluster cluster ;
@@ -193,7 +200,7 @@ public void testRenameWithoutValidFeature() throws Exception {
193
200
QuotaUsage rootQuotaUsage1 = dfs .getQuotaUsage (new Path ("/" ));
194
201
ContentSummary contentSummary1 = dfs .getContentSummary (testParentDir1 );
195
202
// srcDir=/testRename/testDir1/src-dir
196
- // dstDir=/testRename/testDir2/dst-dir dstDir1 not exist
203
+ // dstDir=/testRename/testDir2/dst-dir dstDir not exist
197
204
final Path dstDir2 = new Path (testParentDir2 , "dst-dir" );
198
205
assertTrue (dfs .rename (srcDir , dstDir2 ));
199
206
ContentSummary contentSummary2 = dfs .getContentSummary (testParentDir2 );
@@ -208,19 +215,106 @@ public void testRenameWithoutValidFeature() throws Exception {
208
215
// 2. Test rename2
209
216
final Path dstDir3 = new Path (testParentDir3 , "dst-dir" );
210
217
assertTrue (dfs .mkdirs (dstDir3 ));
211
- long originDstDir2Usage = dfs .getQuotaUsage (dstDir3 ).getFileAndDirectoryCount ();
212
- // Exclude dstDir2 usage
213
- long rootINodeCount1 =
214
- dfs .getQuotaUsage (new Path ("/" )).getFileAndDirectoryCount () - originDstDir2Usage ;
218
+ long originDstDirUsage = dfs .getQuotaUsage (dstDir3 ).getFileAndDirectoryCount ();
219
+ // Overwrite the rename destination, the usage of dstDir3 should be excluded
220
+ long expectedCount =
221
+ dfs .getQuotaUsage (new Path ("/" )).getFileAndDirectoryCount () - originDstDirUsage ;
215
222
ContentSummary contentSummary3 = dfs .getContentSummary (testParentDir2 );
216
223
217
- // Src and dst must be same (all file or all dir)
218
- // dstDir2=/testRename/testDir3 /dst-dir
224
+ // Src and dst must be same
225
+ // dstDir2=/testRename/testDir2 /dst-dir
219
226
// dstDir3=/testRename/testDir3/dst-dir
220
227
dfs .rename (dstDir2 , dstDir3 , Options .Rename .OVERWRITE );
221
- long rootINodeCount2 = dfs .getQuotaUsage (new Path ("/" )).getFileAndDirectoryCount ();
222
- assertEquals (rootINodeCount1 , rootINodeCount2 );
228
+ long actualCount = dfs .getQuotaUsage (new Path ("/" )).getFileAndDirectoryCount ();
229
+ assertEquals (expectedCount , actualCount );
223
230
ContentSummary contentSummary4 = dfs .getContentSummary (testParentDir3 );
224
231
assertEquals (contentSummary3 , contentSummary4 );
225
232
}
233
+
234
+ @ Test
235
+ public void testRenameUndoWithoutValidFeature () throws Exception {
236
+ final int fileLen = 1024 ;
237
+ final short replication = 3 ;
238
+ final Path root = new Path ("/testRenameUndo" );
239
+ assertTrue (dfs .mkdirs (root ));
240
+
241
+ Path testParentDir1 = new Path (root , "testDir1" );
242
+ assertTrue (dfs .mkdirs (testParentDir1 ));
243
+ Path testParentDir2 = new Path (root , "testDir2" );
244
+ assertTrue (dfs .mkdirs (testParentDir2 ));
245
+ Path testParentDir3 = new Path (root , "testDir3" );
246
+ assertTrue (dfs .mkdirs (testParentDir3 ));
247
+ Path testParentDir4 = new Path (root , "testDir4" );
248
+ assertTrue (dfs .mkdirs (testParentDir4 ));
249
+
250
+ final Path srcDir1 = new Path (testParentDir1 , "src-dir" );
251
+ for (int i = 0 ; i < 2 ; i ++) {
252
+ Path file1 = new Path (srcDir1 , "file" + i );
253
+ DFSTestUtil .createFile (dfs , file1 , fileLen , replication , 0 );
254
+ }
255
+
256
+ final Path srcDir3 = new Path (testParentDir3 , "src-dir" );
257
+ for (int i = 0 ; i < 2 ; i ++) {
258
+ Path file1 = new Path (srcDir3 , "file" + i );
259
+ DFSTestUtil .createFile (dfs , file1 , fileLen , replication , 0 );
260
+ }
261
+
262
+ // Test rename1
263
+ ContentSummary rootContentSummary1 = dfs .getContentSummary (new Path ("/" ));
264
+ QuotaUsage rootQuotaUsage1 = dfs .getQuotaUsage (new Path ("/" ));
265
+ ContentSummary contentSummary1 = dfs .getContentSummary (testParentDir1 );
266
+
267
+ FSNamesystem fsn = cluster .getNamesystem ();
268
+ FSDirectory fsDirectory = fsn .getFSDirectory ();
269
+
270
+ // Replace INode, expected addChild return false
271
+ INodeDirectory dir = fsDirectory .getINode4Write (testParentDir2 .toString ()).asDirectory ();
272
+ INodeDirectory mockDir = Mockito .spy (dir );
273
+ INode srcInode = fsDirectory .getINode (srcDir3 .toString ());
274
+ // Fail the rename but succeed in undo
275
+ Mockito .doReturn (false ).when (mockDir ).addChild (Mockito .eq (srcInode ), anyBoolean (), anyInt ());
276
+ INodeDirectory rootDir = fsDirectory .getINode4Write (root .toString ()).asDirectory ();
277
+ rootDir .replaceChild (dir , mockDir , fsDirectory .getINodeMap ());
278
+ mockDir .setParent (rootDir );
279
+
280
+ // srcDir=/testRenameUndo/testDir1/src-dir
281
+ // dstDir=/testRenameUndo/testDir2/
282
+ assertFalse (dfs .rename (srcDir3 , testParentDir2 ));
283
+
284
+ ContentSummary rootContentSummary2 = dfs .getContentSummary (new Path ("/" ));
285
+ QuotaUsage rootQuotaUsage2 = dfs .getQuotaUsage (new Path ("/" ));
286
+ ContentSummary contentSummary2 = dfs .getContentSummary (testParentDir1 );
287
+ assertEquals (rootContentSummary1 .toString (), rootContentSummary2 .toString ());
288
+ assertEquals (rootQuotaUsage1 .toString (), rootQuotaUsage2 .toString ());
289
+ assertEquals (contentSummary1 .toString (), contentSummary2 .toString ());
290
+ assertEquals (rootContentSummary1 .getFileAndDirectoryCount (),
291
+ rootQuotaUsage2 .getFileAndDirectoryCount ());
292
+
293
+ // Test rename2
294
+ final Path dstDir4 = new Path (testParentDir4 , "src-dir" );
295
+ assertTrue (dfs .mkdirs (dstDir4 ));
296
+ ContentSummary rootContentSummary3 = dfs .getContentSummary (new Path ("/" ));
297
+ QuotaUsage rootQuotaUsage3 = dfs .getQuotaUsage (new Path ("/" ));
298
+ ContentSummary contentSummary3 = dfs .getContentSummary (testParentDir3 );
299
+
300
+ // Replace INode, expected addChild return false
301
+ INodeDirectory dir4 = fsDirectory .getINode4Write (testParentDir4 .toString ()).asDirectory ();
302
+ INodeDirectory mockDir4 = Mockito .spy (dir4 );
303
+ INode srcInode3 = fsDirectory .getINode (srcDir3 .toString ());
304
+ Mockito .doReturn (false ).when (mockDir4 ).addChild (Mockito .eq (srcInode3 ), anyBoolean (), anyInt ());
305
+ rootDir .replaceChild (dir4 , mockDir4 , fsDirectory .getINodeMap ());
306
+ mockDir4 .setParent (rootDir );
307
+ // srcDir=/testRenameUndo/testDir3/src-dir
308
+ // dstDir=/testRenameUndo/testDir4/src-dir dstDir exist
309
+ assertThrows (RemoteException .class ,
310
+ () -> dfs .rename (srcDir3 , dstDir4 , Options .Rename .OVERWRITE ));
311
+ ContentSummary rootContentSummary4 = dfs .getContentSummary (new Path ("/" ));
312
+ QuotaUsage rootQuotaUsage4 = dfs .getQuotaUsage (new Path ("/" ));
313
+ ContentSummary contentSummary4 = dfs .getContentSummary (testParentDir3 );
314
+ assertEquals (rootContentSummary3 .toString (), rootContentSummary4 .toString ());
315
+ assertEquals (rootQuotaUsage3 .toString (), rootQuotaUsage4 .toString ());
316
+ assertEquals (contentSummary3 .toString (), contentSummary4 .toString ());
317
+ assertEquals (rootContentSummary3 .getFileAndDirectoryCount (),
318
+ rootQuotaUsage4 .getFileAndDirectoryCount ());
319
+ }
226
320
}
0 commit comments