2222import java .io .IOException ;
2323import java .net .InetSocketAddress ;
2424import java .util .HashMap ;
25+ import java .util .Iterator ;
2526import java .util .List ;
2627import java .util .Map ;
2728import java .util .Random ;
3839import org .apache .hadoop .hdfs .protocol .HdfsConstants .DatanodeReportType ;
3940import org .apache .hadoop .hdfs .protocol .LocatedBlock ;
4041import org .apache .hadoop .hdfs .protocol .LocatedBlocks ;
42+ import org .apache .hadoop .hdfs .server .blockmanagement .BlockInfo ;
43+ import org .apache .hadoop .hdfs .server .blockmanagement .BlockManagerTestUtil ;
4144import org .apache .hadoop .hdfs .server .blockmanagement .DatanodeDescriptor ;
45+ import org .apache .hadoop .hdfs .server .blockmanagement .DatanodeStorageInfo ;
4246import org .apache .hadoop .hdfs .server .datanode .DataNode ;
4347import org .apache .hadoop .hdfs .server .datanode .DataNodeTestUtils ;
48+ import org .apache .hadoop .hdfs .server .namenode .FSNamesystem ;
4449import org .apache .hadoop .hdfs .server .protocol .BlocksWithLocations .BlockWithLocations ;
4550import org .apache .hadoop .hdfs .server .protocol .NamenodeProtocol ;
4651import org .apache .hadoop .ipc .RemoteException ;
@@ -182,25 +187,27 @@ public void testGetBlocks() throws Exception {
182187 CONF .setLong (DFSConfigKeys .DFS_BALANCER_GETBLOCKS_MIN_BLOCK_SIZE_KEY ,
183188 DEFAULT_BLOCK_SIZE );
184189
185- MiniDFSCluster cluster = new MiniDFSCluster .Builder (CONF ).numDataNodes (
186- REPLICATION_FACTOR ).build ();
190+ MiniDFSCluster cluster = new MiniDFSCluster .Builder (CONF )
191+ .numDataNodes (REPLICATION_FACTOR )
192+ .storagesPerDatanode (4 )
193+ .build ();
187194 try {
188195 cluster .waitActive ();
189196 // the third block will not be visible to getBlocks
190- long fileLen = 2 * DEFAULT_BLOCK_SIZE + 1 ;
197+ long fileLen = 12 * DEFAULT_BLOCK_SIZE + 1 ;
191198 DFSTestUtil .createFile (cluster .getFileSystem (), new Path ("/tmp.txt" ),
192199 fileLen , REPLICATION_FACTOR , 0L );
193200
194201 // get blocks & data nodes
195202 List <LocatedBlock > locatedBlocks ;
196203 DatanodeInfo [] dataNodes = null ;
197204 boolean notWritten ;
205+ final DFSClient dfsclient = new DFSClient (
206+ DFSUtilClient .getNNAddress (CONF ), CONF );
198207 do {
199- final DFSClient dfsclient = new DFSClient (
200- DFSUtilClient .getNNAddress (CONF ), CONF );
201208 locatedBlocks = dfsclient .getNamenode ()
202209 .getBlockLocations ("/tmp.txt" , 0 , fileLen ).getLocatedBlocks ();
203- assertEquals (3 , locatedBlocks .size ());
210+ assertEquals (13 , locatedBlocks .size ());
204211 notWritten = false ;
205212 for (int i = 0 ; i < 2 ; i ++) {
206213 dataNodes = locatedBlocks .get (i ).getLocations ();
@@ -214,6 +221,7 @@ public void testGetBlocks() throws Exception {
214221 }
215222 }
216223 } while (notWritten );
224+ dfsclient .close ();
217225
218226 // get RPC client to namenode
219227 InetSocketAddress addr = new InetSocketAddress ("localhost" ,
@@ -224,7 +232,7 @@ public void testGetBlocks() throws Exception {
224232 // get blocks of size fileLen from dataNodes[0]
225233 BlockWithLocations [] locs ;
226234 locs = namenode .getBlocks (dataNodes [0 ], fileLen ).getBlocks ();
227- assertEquals (locs .length , 2 );
235+ assertEquals (locs .length , 12 );
228236 assertEquals (locs [0 ].getStorageIDs ().length , 2 );
229237 assertEquals (locs [1 ].getStorageIDs ().length , 2 );
230238
@@ -247,6 +255,8 @@ public void testGetBlocks() throws Exception {
247255 // get blocks of size BlockSize from a non-existent datanode
248256 DatanodeInfo info = DFSTestUtil .getDatanodeInfo ("1.2.3.4" );
249257 getBlocksWithException (namenode , info , 2 );
258+
259+ testBlockIterator (cluster );
250260 } finally {
251261 cluster .shutdown ();
252262 }
@@ -264,6 +274,59 @@ private void getBlocksWithException(NamenodeProtocol namenode,
264274 assertTrue (getException );
265275 }
266276
277+ /**
278+ * BlockIterator iterates over all blocks belonging to DatanodeDescriptor
279+ * through multiple storages.
280+ * The test verifies that BlockIterator can be set to start iterating from
281+ * a particular starting block index.
282+ */
283+ void testBlockIterator (MiniDFSCluster cluster ) {
284+ FSNamesystem ns = cluster .getNamesystem ();
285+ String dId = cluster .getDataNodes ().get (0 ).getDatanodeUuid ();
286+ DatanodeDescriptor dnd = BlockManagerTestUtil .getDatanode (ns , dId );
287+ DatanodeStorageInfo [] storages = dnd .getStorageInfos ();
288+ assertEquals ("DataNode should have 4 storages" , 4 , storages .length );
289+
290+ Iterator <BlockInfo > dnBlockIt = null ;
291+ // check illegal start block number
292+ try {
293+ dnBlockIt = BlockManagerTestUtil .getBlockIterator (
294+ cluster .getNamesystem (), dId , -1 );
295+ assertTrue ("Should throw IllegalArgumentException" , false );
296+ } catch (IllegalArgumentException ei ) {
297+ // as expected
298+ }
299+ assertNull ("Iterator should be null" , dnBlockIt );
300+
301+ // form an array of all DataNode blocks
302+ int numBlocks = dnd .numBlocks ();
303+ BlockInfo [] allBlocks = new BlockInfo [numBlocks ];
304+ int idx = 0 ;
305+ for (DatanodeStorageInfo s : storages ) {
306+ Iterator <BlockInfo > storageBlockIt =
307+ BlockManagerTestUtil .getBlockIterator (s );
308+ while (storageBlockIt .hasNext ()) {
309+ allBlocks [idx ++] = storageBlockIt .next ();
310+ }
311+ }
312+
313+ // check iterator for every block as a starting point
314+ for (int i = 0 ; i < allBlocks .length ; i ++) {
315+ // create iterator starting from i
316+ dnBlockIt = BlockManagerTestUtil .getBlockIterator (ns , dId , i );
317+ assertTrue ("Block iterator should have next block" , dnBlockIt .hasNext ());
318+ // check iterator lists blocks in the desired order
319+ for (int j = i ; j < allBlocks .length ; j ++) {
320+ assertEquals ("Wrong block order" , allBlocks [j ], dnBlockIt .next ());
321+ }
322+ }
323+
324+ // check start block number larger than numBlocks in the DataNode
325+ dnBlockIt = BlockManagerTestUtil .getBlockIterator (
326+ ns , dId , allBlocks .length + 1 );
327+ assertFalse ("Iterator should not have next block" , dnBlockIt .hasNext ());
328+ }
329+
267330 @ Test
268331 public void testBlockKey () {
269332 Map <Block , Long > map = new HashMap <Block , Long >();
0 commit comments