22
22
import java .io .IOException ;
23
23
import java .net .InetSocketAddress ;
24
24
import java .util .HashMap ;
25
+ import java .util .Iterator ;
25
26
import java .util .List ;
26
27
import java .util .Map ;
27
28
import java .util .Random ;
38
39
import org .apache .hadoop .hdfs .protocol .HdfsConstants .DatanodeReportType ;
39
40
import org .apache .hadoop .hdfs .protocol .LocatedBlock ;
40
41
import org .apache .hadoop .hdfs .protocol .LocatedBlocks ;
42
+ import org .apache .hadoop .hdfs .server .blockmanagement .BlockInfo ;
43
+ import org .apache .hadoop .hdfs .server .blockmanagement .BlockManagerTestUtil ;
41
44
import org .apache .hadoop .hdfs .server .blockmanagement .DatanodeDescriptor ;
45
+ import org .apache .hadoop .hdfs .server .blockmanagement .DatanodeStorageInfo ;
42
46
import org .apache .hadoop .hdfs .server .datanode .DataNode ;
43
47
import org .apache .hadoop .hdfs .server .datanode .DataNodeTestUtils ;
48
+ import org .apache .hadoop .hdfs .server .namenode .FSNamesystem ;
44
49
import org .apache .hadoop .hdfs .server .protocol .BlocksWithLocations .BlockWithLocations ;
45
50
import org .apache .hadoop .hdfs .server .protocol .NamenodeProtocol ;
46
51
import org .apache .hadoop .ipc .RemoteException ;
@@ -182,25 +187,27 @@ public void testGetBlocks() throws Exception {
182
187
CONF .setLong (DFSConfigKeys .DFS_BALANCER_GETBLOCKS_MIN_BLOCK_SIZE_KEY ,
183
188
DEFAULT_BLOCK_SIZE );
184
189
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 ();
187
194
try {
188
195
cluster .waitActive ();
189
196
// 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 ;
191
198
DFSTestUtil .createFile (cluster .getFileSystem (), new Path ("/tmp.txt" ),
192
199
fileLen , REPLICATION_FACTOR , 0L );
193
200
194
201
// get blocks & data nodes
195
202
List <LocatedBlock > locatedBlocks ;
196
203
DatanodeInfo [] dataNodes = null ;
197
204
boolean notWritten ;
205
+ final DFSClient dfsclient = new DFSClient (
206
+ DFSUtilClient .getNNAddress (CONF ), CONF );
198
207
do {
199
- final DFSClient dfsclient = new DFSClient (
200
- DFSUtilClient .getNNAddress (CONF ), CONF );
201
208
locatedBlocks = dfsclient .getNamenode ()
202
209
.getBlockLocations ("/tmp.txt" , 0 , fileLen ).getLocatedBlocks ();
203
- assertEquals (3 , locatedBlocks .size ());
210
+ assertEquals (13 , locatedBlocks .size ());
204
211
notWritten = false ;
205
212
for (int i = 0 ; i < 2 ; i ++) {
206
213
dataNodes = locatedBlocks .get (i ).getLocations ();
@@ -214,6 +221,7 @@ public void testGetBlocks() throws Exception {
214
221
}
215
222
}
216
223
} while (notWritten );
224
+ dfsclient .close ();
217
225
218
226
// get RPC client to namenode
219
227
InetSocketAddress addr = new InetSocketAddress ("localhost" ,
@@ -224,7 +232,7 @@ public void testGetBlocks() throws Exception {
224
232
// get blocks of size fileLen from dataNodes[0]
225
233
BlockWithLocations [] locs ;
226
234
locs = namenode .getBlocks (dataNodes [0 ], fileLen ).getBlocks ();
227
- assertEquals (locs .length , 2 );
235
+ assertEquals (locs .length , 12 );
228
236
assertEquals (locs [0 ].getStorageIDs ().length , 2 );
229
237
assertEquals (locs [1 ].getStorageIDs ().length , 2 );
230
238
@@ -247,6 +255,8 @@ public void testGetBlocks() throws Exception {
247
255
// get blocks of size BlockSize from a non-existent datanode
248
256
DatanodeInfo info = DFSTestUtil .getDatanodeInfo ("1.2.3.4" );
249
257
getBlocksWithException (namenode , info , 2 );
258
+
259
+ testBlockIterator (cluster );
250
260
} finally {
251
261
cluster .shutdown ();
252
262
}
@@ -264,6 +274,59 @@ private void getBlocksWithException(NamenodeProtocol namenode,
264
274
assertTrue (getException );
265
275
}
266
276
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
+
267
330
@ Test
268
331
public void testBlockKey () {
269
332
Map <Block , Long > map = new HashMap <Block , Long >();
0 commit comments