2020import static org .apache .hadoop .hdds .HddsConfigKeys .HDDS_COMMAND_STATUS_REPORT_INTERVAL ;
2121import static org .apache .hadoop .hdds .HddsConfigKeys .HDDS_CONTAINER_REPORT_INTERVAL ;
2222import static org .junit .Assert .fail ;
23+ import static org .mockito .Matchers .any ;
24+ import static org .mockito .Matchers .argThat ;
25+ import static org .mockito .Matchers .eq ;
26+ import static org .mockito .Mockito .doNothing ;
27+ import static org .mockito .Mockito .mock ;
28+ import static org .mockito .Mockito .verify ;
29+ import static org .mockito .Mockito .when ;
2330
24- import com .google .common .collect .Lists ;
25- import com .google .common .collect .Maps ;
2631import java .io .IOException ;
32+ import java .lang .reflect .Field ;
33+ import java .lang .reflect .Modifier ;
2734import java .nio .file .Path ;
2835import java .nio .file .Paths ;
2936import java .util .Collections ;
3340import java .util .Set ;
3441import java .util .UUID ;
3542import java .util .concurrent .TimeUnit ;
43+
3644import org .apache .commons .lang3 .RandomUtils ;
3745import org .apache .hadoop .hdds .HddsConfigKeys ;
3846import org .apache .hadoop .hdds .conf .OzoneConfiguration ;
4654import org .apache .hadoop .hdds .scm .XceiverClientManager ;
4755import org .apache .hadoop .hdds .scm .block .DeletedBlockLog ;
4856import org .apache .hadoop .hdds .scm .block .SCMBlockDeletingService ;
57+ import org .apache .hadoop .hdds .scm .container .ContainerInfo ;
4958import org .apache .hadoop .hdds .scm .container .ContainerNotFoundException ;
59+ import org .apache .hadoop .hdds .scm .container .ReplicationManager ;
5060import org .apache .hadoop .hdds .scm .container .common .helpers .ContainerWithPipeline ;
61+ import org .apache .hadoop .hdds .scm .events .SCMEvents ;
5162import org .apache .hadoop .hdds .scm .exceptions .SCMException ;
5263import org .apache .hadoop .hdds .scm .node .NodeManager ;
5364import org .apache .hadoop .hdds .scm .server .SCMClientProtocolServer ;
5465import org .apache .hadoop .hdds .scm .server .SCMStorageConfig ;
5566import org .apache .hadoop .hdds .scm .server .StorageContainerManager ;
5667import org .apache .hadoop .hdds .scm .server .StorageContainerManager .StartupOption ;
68+ import org .apache .hadoop .hdds .server .events .EventPublisher ;
69+ import org .apache .hadoop .hdds .server .events .TypedEvent ;
5770import org .apache .hadoop .ozone .container .ContainerTestHelper ;
5871import org .apache .hadoop .ozone .om .helpers .OmKeyInfo ;
5972import org .apache .hadoop .ozone .om .helpers .OmKeyLocationInfo ;
73+ import org .apache .hadoop .ozone .protocol .commands .CloseContainerCommand ;
74+ import org .apache .hadoop .ozone .protocol .commands .CommandForDatanode ;
6075import org .apache .hadoop .ozone .protocol .commands .DeleteBlocksCommand ;
6176import org .apache .hadoop .ozone .protocol .commands .SCMCommand ;
6277import org .apache .hadoop .security .authentication .client .AuthenticationException ;
6378import org .apache .hadoop .test .GenericTestUtils ;
6479import org .apache .hadoop .util .ExitUtil ;
6580import org .apache .hadoop .utils .HddsVersionInfo ;
66-
6781import org .junit .Assert ;
6882import org .junit .Rule ;
6983import org .junit .Test ;
7084import org .junit .rules .ExpectedException ;
85+ import org .junit .rules .TemporaryFolder ;
7186import org .junit .rules .Timeout ;
87+ import org .mockito .ArgumentMatcher ;
7288import org .mockito .Mockito ;
7389import org .slf4j .Logger ;
7490import org .slf4j .LoggerFactory ;
7591
92+ import com .google .common .collect .Lists ;
93+ import com .google .common .collect .Maps ;
94+
7695/**
7796 * Test class that exercises the StorageContainerManager.
7897 */
7998public class TestStorageContainerManager {
8099 private static XceiverClientManager xceiverClientManager =
81100 new XceiverClientManager (
82101 new OzoneConfiguration ());
83- private static final Logger LOG = LoggerFactory
84- .getLogger (TestStorageContainerManager .class );
102+ private static final Logger LOG = LoggerFactory .getLogger (
103+ TestStorageContainerManager .class );
104+
85105 /**
86106 * Set the timeout for every test.
87107 */
@@ -94,6 +114,9 @@ public class TestStorageContainerManager {
94114 @ Rule
95115 public ExpectedException exception = ExpectedException .none ();
96116
117+ @ Rule
118+ public TemporaryFolder folder = new TemporaryFolder ();
119+
97120 @ Test
98121 public void testRpcPermission () throws Exception {
99122 // Test with default configuration
@@ -119,7 +142,7 @@ private void testRpcPermissionWithConf(
119142
120143 SCMClientProtocolServer mockClientServer = Mockito .spy (
121144 cluster .getStorageContainerManager ().getClientProtocolServer ());
122- Mockito . when (mockClientServer .getRpcRemoteUsername ())
145+ when (mockClientServer .getRpcRemoteUsername ())
123146 .thenReturn (fakeRemoteUsername );
124147
125148 try {
@@ -405,7 +428,6 @@ public void testSCMInitialization() throws Exception {
405428 StorageContainerManager .scmInit (conf );
406429 Assert .assertEquals (NodeType .SCM , scmStore .getNodeType ());
407430 Assert .assertEquals ("testClusterId" , scmStore .getClusterID ());
408-
409431 }
410432
411433 @ Test
@@ -482,4 +504,95 @@ public void testScmInfo() throws Exception {
482504 Assert .assertEquals (expectedVersion , actualVersion );
483505 }
484506
507+ @ Test
508+ @ SuppressWarnings ("unchecked" )
509+ public void testCloseContainerCommandOnRestart () throws Exception {
510+ int numKeys = 15 ;
511+ OzoneConfiguration conf = new OzoneConfiguration ();
512+ conf .setTimeDuration (HDDS_CONTAINER_REPORT_INTERVAL , 1 , TimeUnit .SECONDS );
513+ conf .setInt (ScmConfigKeys .OZONE_SCM_BLOCK_DELETION_MAX_RETRY , 5 );
514+ conf .setTimeDuration (OzoneConfigKeys .OZONE_BLOCK_DELETING_SERVICE_INTERVAL ,
515+ 100 , TimeUnit .MILLISECONDS );
516+ conf .setInt (ScmConfigKeys .OZONE_SCM_PIPELINE_OWNER_CONTAINER_COUNT ,
517+ numKeys );
518+
519+ MiniOzoneCluster cluster = MiniOzoneCluster .newBuilder (conf )
520+ .setHbInterval (1000 )
521+ .setHbProcessorInterval (3000 )
522+ .setTrace (false )
523+ .setNumDatanodes (1 )
524+ .build ();
525+ cluster .waitForClusterToBeReady ();
526+
527+ TestStorageContainerManagerHelper helper =
528+ new TestStorageContainerManagerHelper (cluster , conf );
529+
530+ helper .createKeys (10 , 4096 );
531+ Thread .sleep (5000 );
532+
533+ StorageContainerManager scm = cluster .getStorageContainerManager ();
534+ List <ContainerInfo > containers = cluster .getStorageContainerManager ()
535+ .getContainerManager ().getContainers ();
536+ Assert .assertNotNull (containers );
537+ ContainerInfo selectedContainer = containers .iterator ().next ();
538+
539+ // Stop processing HB
540+ scm .getDatanodeProtocolServer ().stop ();
541+ EventPublisher publisher = mock (EventPublisher .class );
542+ ReplicationManager replicationManager = scm .getReplicationManager ();
543+ Field f = replicationManager .getClass ().getDeclaredField ("eventPublisher" );
544+ f .setAccessible (true );
545+ Field modifiersField = Field .class .getDeclaredField ("modifiers" );
546+ modifiersField .setAccessible (true );
547+ modifiersField .setInt (f , f .getModifiers () & ~Modifier .FINAL );
548+ f .set (replicationManager , publisher );
549+
550+ doNothing ().when (publisher ).fireEvent (any (TypedEvent .class ),
551+ any (CommandForDatanode .class ));
552+
553+ scm .getContainerManager ().updateContainerState (selectedContainer
554+ .containerID (), HddsProtos .LifeCycleEvent .FINALIZE );
555+ cluster .restartStorageContainerManager (true );
556+ scm .getReplicationManager ().start ();
557+ Thread .sleep (2000 );
558+
559+ UUID dnUuid = cluster .getHddsDatanodes ().iterator ().next ()
560+ .getDatanodeDetails ().getUuid ();
561+
562+ CloseContainerCommand closeContainerCommand =
563+ new CloseContainerCommand (selectedContainer .getContainerID (),
564+ selectedContainer .getPipelineID (), false );
565+
566+ CommandForDatanode commandForDatanode = new CommandForDatanode (
567+ dnUuid , closeContainerCommand );
568+
569+ verify (publisher ).fireEvent (eq (SCMEvents .DATANODE_COMMAND ), argThat (new
570+ CloseContainerCommandMatcher (dnUuid , commandForDatanode )));
571+ }
572+
573+ @ SuppressWarnings ("visibilitymodifier" )
574+ static class CloseContainerCommandMatcher
575+ extends ArgumentMatcher <CommandForDatanode > {
576+
577+ private final CommandForDatanode cmd ;
578+ private final UUID uuid ;
579+
580+ CloseContainerCommandMatcher (UUID uuid , CommandForDatanode cmd ) {
581+ this .uuid = uuid ;
582+ this .cmd = cmd ;
583+ }
584+
585+ @ Override
586+ public boolean matches (Object argument ) {
587+ CommandForDatanode cmdRight = (CommandForDatanode ) argument ;
588+ CloseContainerCommand left = (CloseContainerCommand ) cmd .getCommand ();
589+ CloseContainerCommand right =
590+ (CloseContainerCommand ) cmdRight .getCommand ();
591+ return cmdRight .getDatanodeId ().equals (uuid )
592+ && left .getContainerID () == right .getContainerID ()
593+ && left .getPipelineID () == right .getPipelineID ()
594+ && left .getType () == right .getType ()
595+ && left .getProto ().equals (right .getProto ());
596+ }
597+ }
485598}
0 commit comments