2323import static org .junit .jupiter .api .Assertions .assertEquals ;
2424import static org .junit .jupiter .api .Assertions .assertThrows ;
2525import static org .mockito .ArgumentMatchers .any ;
26+ import static org .mockito .Mockito .anyLong ;
27+ import static org .mockito .Mockito .atLeastOnce ;
28+ import static org .mockito .Mockito .doNothing ;
2629import static org .mockito .Mockito .doReturn ;
2730import static org .mockito .Mockito .mock ;
2831import static org .mockito .Mockito .spy ;
32+ import static org .mockito .Mockito .verify ;
2933import static org .mockito .Mockito .when ;
3034
3135import java .io .File ;
3539import java .nio .charset .StandardCharsets ;
3640import java .nio .file .Files ;
3741import java .util .HashSet ;
42+ import java .util .Optional ;
3843import java .util .concurrent .CompletableFuture ;
3944import java .util .concurrent .Semaphore ;
4045import org .apache .commons .compress .archivers .ArchiveOutputStream ;
5156import org .apache .hadoop .ozone .container .common .impl .ContainerLayoutVersion ;
5257import org .apache .hadoop .ozone .container .common .impl .ContainerSet ;
5358import org .apache .hadoop .ozone .container .common .interfaces .VolumeChoosingPolicy ;
59+ import org .apache .hadoop .ozone .container .common .volume .HddsVolume ;
5460import org .apache .hadoop .ozone .container .common .volume .MutableVolumeSet ;
5561import org .apache .hadoop .ozone .container .common .volume .StorageVolume ;
5662import org .apache .hadoop .ozone .container .common .volume .VolumeChoosingPolicyFactory ;
5763import org .apache .hadoop .ozone .container .keyvalue .KeyValueContainer ;
5864import org .apache .hadoop .ozone .container .keyvalue .KeyValueContainerData ;
5965import org .apache .hadoop .ozone .container .keyvalue .TarContainerPacker ;
6066import org .apache .hadoop .ozone .container .ozoneimpl .ContainerController ;
67+ import org .apache .hadoop .util .Time ;
6168import org .apache .ozone .test .GenericTestUtils ;
6269import org .junit .jupiter .api .Assertions ;
6370import org .junit .jupiter .api .BeforeEach ;
@@ -74,29 +81,41 @@ class TestContainerImporter {
7481
7582 private OzoneConfiguration conf ;
7683 private VolumeChoosingPolicy volumeChoosingPolicy ;
84+ private KeyValueContainerData containerData ;
85+ private KeyValueContainer container ;
86+ private ContainerController controllerMock ;
87+ private long containerId = 1 ;
88+ private ContainerSet containerSet ;
89+ private MutableVolumeSet volumeSet ;
90+ private ContainerImporter containerImporter ;
7791
7892 @ BeforeEach
79- void setup () {
93+ void setup () throws IOException {
8094 conf = new OzoneConfiguration ();
8195 conf .set (ScmConfigKeys .HDDS_DATANODE_DIR_KEY , tempDir .getAbsolutePath ());
8296 volumeChoosingPolicy = VolumeChoosingPolicyFactory .getPolicy (conf );
97+ // create container
98+ containerData = new KeyValueContainerData (containerId ,
99+ ContainerLayoutVersion .FILE_PER_BLOCK , 100 , "test" , "test" );
100+ container = new KeyValueContainer (containerData , conf );
101+ controllerMock = mock (ContainerController .class );
102+ when (controllerMock .importContainer (any (ContainerData .class ), any (), any ())).thenAnswer (
103+ i -> {
104+ containerData = i .getArgument (0 );
105+ container = new KeyValueContainer (containerData , conf );
106+ return container ;
107+ });
108+ containerSet = spy (newContainerSet (0 ));
109+ volumeSet = new MutableVolumeSet ("test" , conf , null ,
110+ StorageVolume .VolumeType .DATA_VOLUME , null );
111+ // create containerImporter object
112+ containerImporter = new ContainerImporter (conf ,
113+ containerSet , controllerMock , volumeSet , volumeChoosingPolicy );
83114 }
84115
85116 @ Test
86117 void importSameContainerWhenAlreadyImport () throws Exception {
87- long containerId = 1 ;
88- // create container
89- KeyValueContainerData containerData = new KeyValueContainerData (containerId ,
90- ContainerLayoutVersion .FILE_PER_BLOCK , 100 , "test" , "test" );
91- KeyValueContainer container = new KeyValueContainer (containerData , conf );
92- ContainerController controllerMock = mock (ContainerController .class );
93- // create containerImporter object
94- ContainerSet containerSet = newContainerSet (0 );
95118 containerSet .addContainer (container );
96- MutableVolumeSet volumeSet = new MutableVolumeSet ("test" , conf , null ,
97- StorageVolume .VolumeType .DATA_VOLUME , null );
98- ContainerImporter containerImporter = new ContainerImporter (conf ,
99- containerSet , controllerMock , volumeSet , volumeChoosingPolicy );
100119 File tarFile = new File ("dummy.tar" );
101120 // second import should fail immediately
102121 StorageContainerException ex = assertThrows (StorageContainerException .class ,
@@ -108,25 +127,13 @@ void importSameContainerWhenAlreadyImport() throws Exception {
108127
109128 @ Test
110129 void importSameContainerWhenFirstInProgress () throws Exception {
111- long containerId = 1 ;
112- // create container
113- KeyValueContainerData containerData = new KeyValueContainerData (containerId ,
114- ContainerLayoutVersion .FILE_PER_BLOCK , 100 , "test" , "test" );
115- KeyValueContainer container = new KeyValueContainer (containerData , conf );
116130 // mock controller for return container data with delay
117- ContainerController controllerMock = mock (ContainerController .class );
118131 Semaphore semaphore = new Semaphore (0 );
119132 when (controllerMock .importContainer (any (), any (), any ()))
120133 .thenAnswer ((invocation ) -> {
121134 semaphore .acquire ();
122135 return container ;
123136 });
124- // create containerImporter object
125- ContainerSet containerSet = newContainerSet (0 );
126- MutableVolumeSet volumeSet = new MutableVolumeSet ("test" , conf , null ,
127- StorageVolume .VolumeType .DATA_VOLUME , null );
128- ContainerImporter containerImporter = new ContainerImporter (conf ,
129- containerSet , controllerMock , volumeSet , volumeChoosingPolicy );
130137 // run import async first time having delay
131138 File tarFile = containerTarFile (containerId , containerData );
132139 CompletableFuture .runAsync (() -> {
@@ -152,45 +159,69 @@ void importSameContainerWhenFirstInProgress() throws Exception {
152159
153160 @ Test
154161 public void testInconsistentChecksumContainerShouldThrowError () throws Exception {
155- // create container
156- long containerId = 1 ;
157- KeyValueContainerData containerData = spy (new KeyValueContainerData (containerId ,
162+ // create container with mock to return different checksums
163+ KeyValueContainerData data = spy (new KeyValueContainerData (containerId ,
158164 ContainerLayoutVersion .FILE_PER_BLOCK , 100 , "test" , "test" ));
159165 // mock to return different checksum
160- when (containerData .getContainerFileChecksum ()).thenReturn ("checksum1" , "checksum2" );
161- // create containerImporter object
162- ContainerController controllerMock = mock (ContainerController .class );
163- ContainerSet containerSet = newContainerSet (0 );
164- MutableVolumeSet volumeSet = new MutableVolumeSet ("test" , conf , null ,
165- StorageVolume .VolumeType .DATA_VOLUME , null );
166- ContainerImporter containerImporter = spy (new ContainerImporter (conf ,
166+ when (data .getContainerFileChecksum ()).thenReturn ("checksum1" , "checksum2" );
167+ // create containerImporter object with mock
168+ ContainerImporter importer = spy (new ContainerImporter (conf ,
167169 containerSet , controllerMock , volumeSet , volumeChoosingPolicy ));
168170
169171 TarContainerPacker packer = mock (TarContainerPacker .class );
170172 when (packer .unpackContainerDescriptor (any ())).thenReturn ("test" .getBytes (
171173 StandardCharsets .UTF_8 ));
172- when (containerImporter .getPacker (any ())).thenReturn (packer );
174+ when (importer .getPacker (any ())).thenReturn (packer );
173175
174- doReturn (containerData ).when (containerImporter ).getKeyValueContainerData (any (byte [].class ));
175- when (containerImporter .getImportContainerProgress ()).thenReturn (new HashSet <>());
176+ doReturn (data ).when (importer ).getKeyValueContainerData (any (byte [].class ));
177+ when (importer .getImportContainerProgress ()).thenReturn (new HashSet <>());
176178
177179 File tarFile = File .createTempFile ("temp_" + System
178180 .currentTimeMillis (), ".tar" );
179181
180182 StorageContainerException scException =
181183 assertThrows (StorageContainerException .class ,
182- () -> containerImporter .importContainer (containerId ,
184+ () -> importer .importContainer (containerId ,
183185 tarFile .toPath (), null , NO_COMPRESSION ));
184186 Assertions .assertTrue (scException .getMessage ().
185187 contains ("Container checksum error" ));
186188 }
187189
188- private File containerTarFile (
189- long containerId , ContainerData containerData ) throws IOException {
190+ @ Test
191+ public void testImportContainerTriggersOnDemandScanner () throws Exception {
192+ // create containerImporter object
193+ HddsVolume targetVolume = mock (HddsVolume .class );
194+ doNothing ().when (targetVolume ).incrementUsedSpace (anyLong ());
195+
196+ // import the container
197+ File tarFile = containerTarFile (containerId , containerData );
198+ containerImporter .importContainer (containerId , tarFile .toPath (),
199+ targetVolume , NO_COMPRESSION );
200+
201+ verify (containerSet , atLeastOnce ()).scanContainer (containerId );
202+ }
203+
204+ @ Test
205+ public void testImportContainerResetsLastScanTime () throws Exception {
206+ containerData .setDataScanTimestamp (Time .monotonicNow ());
207+
208+ // create containerImporter object
209+ HddsVolume targetVolume = mock (HddsVolume .class );
210+ doNothing ().when (targetVolume ).incrementUsedSpace (anyLong ());
211+
212+ // import the container
213+ File tarFile = containerTarFile (containerId , containerData );
214+ containerImporter .importContainer (containerId , tarFile .toPath (),
215+ targetVolume , NO_COMPRESSION );
216+
217+ assertEquals (Optional .empty (), containerData .lastDataScanTime ());
218+ }
219+
220+ private File containerTarFile (long id , ContainerData data ) throws IOException {
190221 File yamlFile = new File (tempDir , "container.yaml" );
191- ContainerDataYaml .createContainerFile (containerData , yamlFile );
222+ ContainerDataYaml .createContainerFile (data , yamlFile );
192223 File tarFile = new File (tempDir ,
193- ContainerUtils .getContainerTarName (containerId ));
224+ ContainerUtils .getContainerTarName (id ));
194225 try (OutputStream output = Files .newOutputStream (tarFile .toPath ())) {
195226 ArchiveOutputStream <TarArchiveEntry > archive = new TarArchiveOutputStream (output );
196227 TarArchiveEntry entry = archive .createArchiveEntry (yamlFile ,
0 commit comments