[ https://issues.apache.org/jira/browse/HDFS-9543?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=15246011#comment-15246011 ]
Anu Engineer commented on HDFS-9543: ------------------------------------ [~eddyxu] Thank you for the code review comments. Please see some of my thoughts on your suggestions. bq.Could you put getNextBlock() logic into a separate Iterator, and make it Closable, which will include getBlockToCopy(), openPoolIters(), getNextBlock(), closePoolIters(). There are a few draw backs of separating them into different functions. I thought that this is an excellent idea, and I explored this path of code organization. But I got stuck in an intractable problem which makes me want to abandon this path. Please do let me know if you have suggestions on how you think I can solve this. In supporting an Iterator interface, we have to support hasNext. In our case it is a scan of the block list and finding a block that is small than the required move size. There are 2 ways to do this, look for the block and report true if found, but there is no gurantee that it will indeed be returned in the next() call since these blocks can go away underneath us. So a common pattern of iterator code becomes complex to write -- while(hasNext()) next() -- pattern now needs to worry next() failing even when hasNext has been successful. We can keep a pointer to the found block in memory, and return that in the next call, but that means that we have to do some unnecessary block state management in the iterator. I ended up writing all this and found that code is getting more complex instead of simpler and has kind of decided to abandon this approach. bq. 1) The states (i.e. poolIndex,) are stored outside these functions, the caller needs maintain these states. These are part of BlockMover class, and copyblocks in the only call made by other classes. So it is not visible to caller at all. bq. 2) poolIndex is never initialized and is not able be reset. PoolIndex is a index to a circular array, if you like I can initialize this to 0, but in most cases we just move to next block pool and get the next block. Before each block fetch we init the count variable so that we know if we have visited all the block pools. In other words, users should not be able to see this, nor need to reset this variable. bq. Please always log the IOEs. And I think it is better to throw IOE here as well as many other places. I will log a debug trace here. The reason why we are not throwing is because it is possible that we might encounter a damaged block when we try to move large number of blocks from one volume to another. Instead of failing or aborting the action we keep a count of errors we have encountered. We will just ignore that block and continue copy, until we hit max_error_counts. For each move -- that is a source disk, destination disk, bytes to move -- you can specify the max error count. Hence we are not throwing but keeping track of the error count. bq. Can it be a private static List<BlockIterator> openPoolIters() ? Since we are not doing the iterator interface, I am skipping this too. bq. In a few such places, should we actually break the while loop? Wouldn't continue here just generate a lot of LOGS and spend CPU cycles? You are right and I did think of writing a break here. The reason that I chose continue over break was this. It is easier to reason about a loop if it has only one exit point. With break, you have to reason about all exit points. This loop is a pretty complicated one since it can exit in many ways. Here are some : # when we meet the maximum error count. # if we have reach close enough to move bytes -- say close to 10% of the target # if we get an interrupt call from the client. # if we get a shutdown call. # if we are not able to find any blocks to move. # if we are out of destination space. so instead of making people reason about each of these, we set exit flag and loop back up. Since the while will turn to false, it will have one single exit, and will exit without any extra logging. bq. Why do you need to change float to double. In this case, wouldn't float good enough ? This is a stylistic change, Java docs recommend double as the default choice over float. Hence this fix. > DiskBalancer : Add Data mover > ------------------------------ > > Key: HDFS-9543 > URL: https://issues.apache.org/jira/browse/HDFS-9543 > Project: Hadoop HDFS > Issue Type: Sub-task > Components: datanode > Reporter: Anu Engineer > Assignee: Anu Engineer > Attachments: HDFS-9543-HDFS-1312.001.patch > > > This patch adds the actual mover logic to the datanode. -- This message was sent by Atlassian JIRA (v6.3.4#6332)