コード例 #1
0
        /// <summary>
        /// Queries datanodes for the blocks specified in <code>datanodeBlocks</code>,
        /// making one RPC to each datanode.
        /// </summary>
        /// <remarks>
        /// Queries datanodes for the blocks specified in <code>datanodeBlocks</code>,
        /// making one RPC to each datanode. These RPCs are made in parallel using a
        /// threadpool.
        /// </remarks>
        /// <param name="datanodeBlocks">Map of datanodes to the blocks present on the DN</param>
        /// <returns>metadatas Map of datanodes to block metadata of the DN</returns>
        /// <exception cref="Org.Apache.Hadoop.Hdfs.Security.Token.Block.InvalidBlockTokenException
        ///     ">if client does not have read access on a requested block</exception>
        internal static IDictionary <DatanodeInfo, HdfsBlocksMetadata> QueryDatanodesForHdfsBlocksMetadata
            (Configuration conf, IDictionary <DatanodeInfo, IList <LocatedBlock> > datanodeBlocks
            , int poolsize, int timeoutMs, bool connectToDnViaHostname)
        {
            IList <BlockStorageLocationUtil.VolumeBlockLocationCallable> callables = CreateVolumeBlockLocationCallables
                                                                                         (conf, datanodeBlocks, timeoutMs, connectToDnViaHostname, Trace.CurrentSpan());
            // Use a thread pool to execute the Callables in parallel
            IList <Future <HdfsBlocksMetadata> > futures = new AList <Future <HdfsBlocksMetadata> >
                                                               ();
            ExecutorService executor = new ScheduledThreadPoolExecutor(poolsize);

            try
            {
                futures = executor.InvokeAll(callables, timeoutMs, TimeUnit.Milliseconds);
            }
            catch (Exception)
            {
            }
            // Swallow the exception here, because we can return partial results
            executor.Shutdown();
            IDictionary <DatanodeInfo, HdfsBlocksMetadata> metadatas = Maps.NewHashMapWithExpectedSize
                                                                           (datanodeBlocks.Count);

            // Fill in metadatas with results from DN RPCs, where possible
            for (int i = 0; i < futures.Count; i++)
            {
                BlockStorageLocationUtil.VolumeBlockLocationCallable callable = callables[i];
                DatanodeInfo datanode = callable.GetDatanodeInfo();
                Future <HdfsBlocksMetadata> future = futures[i];
                try
                {
                    HdfsBlocksMetadata metadata = future.Get();
                    metadatas[callable.GetDatanodeInfo()] = metadata;
                }
                catch (CancellationException e)
                {
                    Log.Info("Cancelled while waiting for datanode " + datanode.GetIpcAddr(false) + ": "
                             + e.ToString());
                }
                catch (ExecutionException e)
                {
                    Exception t = e.InnerException;
                    if (t is InvalidBlockTokenException)
                    {
                        Log.Warn("Invalid access token when trying to retrieve " + "information from datanode "
                                 + datanode.GetIpcAddr(false));
                        throw (InvalidBlockTokenException)t;
                    }
                    else
                    {
                        if (t is NotSupportedException)
                        {
                            Log.Info("Datanode " + datanode.GetIpcAddr(false) + " does not support" + " required #getHdfsBlocksMetadata() API"
                                     );
                            throw (NotSupportedException)t;
                        }
                        else
                        {
                            Log.Info("Failed to query block locations on datanode " + datanode.GetIpcAddr(false
                                                                                                          ) + ": " + t);
                        }
                    }
                    if (Log.IsDebugEnabled())
                    {
                        Log.Debug("Could not fetch information from datanode", t);
                    }
                }
                catch (Exception)
                {
                    // Shouldn't happen, because invokeAll waits for all Futures to be ready
                    Log.Info("Interrupted while fetching HdfsBlocksMetadata");
                }
            }
            return(metadatas);
        }
コード例 #2
0
        /// <summary>
        /// Group the per-replica
        /// <see cref="Org.Apache.Hadoop.FS.VolumeId"/>
        /// info returned from
        /// <see cref="DFSClient#queryDatanodesForHdfsBlocksMetadata(Map)"/>
        /// to be
        /// associated
        /// with the corresponding
        /// <see cref="Org.Apache.Hadoop.Hdfs.Protocol.LocatedBlock"/>
        /// .
        /// </summary>
        /// <param name="blocks">Original LocatedBlock array</param>
        /// <param name="metadatas">VolumeId information for the replicas on each datanode</param>
        /// <returns>
        /// blockVolumeIds per-replica VolumeId information associated with the
        /// parent LocatedBlock
        /// </returns>
        internal static IDictionary <LocatedBlock, IList <VolumeId> > AssociateVolumeIdsWithBlocks
            (IList <LocatedBlock> blocks, IDictionary <DatanodeInfo, HdfsBlocksMetadata> metadatas
            )
        {
            // Initialize mapping of ExtendedBlock to LocatedBlock.
            // Used to associate results from DN RPCs to the parent LocatedBlock
            IDictionary <long, LocatedBlock> blockIdToLocBlock = new Dictionary <long, LocatedBlock
                                                                                 >();

            foreach (LocatedBlock b in blocks)
            {
                blockIdToLocBlock[b.GetBlock().GetBlockId()] = b;
            }
            // Initialize the mapping of blocks -> list of VolumeIds, one per replica
            // This is filled out with real values from the DN RPCs
            IDictionary <LocatedBlock, IList <VolumeId> > blockVolumeIds = new Dictionary <LocatedBlock
                                                                                           , IList <VolumeId> >();

            foreach (LocatedBlock b_1 in blocks)
            {
                AList <VolumeId> l = new AList <VolumeId>(b_1.GetLocations().Length);
                for (int i = 0; i < b_1.GetLocations().Length; i++)
                {
                    l.AddItem(null);
                }
                blockVolumeIds[b_1] = l;
            }
            // Iterate through the list of metadatas (one per datanode).
            // For each metadata, if it's valid, insert its volume location information
            // into the Map returned to the caller
            foreach (KeyValuePair <DatanodeInfo, HdfsBlocksMetadata> entry in metadatas)
            {
                DatanodeInfo       datanode = entry.Key;
                HdfsBlocksMetadata metadata = entry.Value;
                // Check if metadata is valid
                if (metadata == null)
                {
                    continue;
                }
                long[]         metaBlockIds      = metadata.GetBlockIds();
                IList <byte[]> metaVolumeIds     = metadata.GetVolumeIds();
                IList <int>    metaVolumeIndexes = metadata.GetVolumeIndexes();
                // Add VolumeId for each replica in the HdfsBlocksMetadata
                for (int j = 0; j < metaBlockIds.Length; j++)
                {
                    int  volumeIndex = metaVolumeIndexes[j];
                    long blockId     = metaBlockIds[j];
                    // Skip if block wasn't found, or not a valid index into metaVolumeIds
                    // Also skip if the DN responded with a block we didn't ask for
                    if (volumeIndex == int.MaxValue || volumeIndex >= metaVolumeIds.Count || !blockIdToLocBlock
                        .Contains(blockId))
                    {
                        if (Log.IsDebugEnabled())
                        {
                            Log.Debug("No data for block " + blockId);
                        }
                        continue;
                    }
                    // Get the VolumeId by indexing into the list of VolumeIds
                    // provided by the datanode
                    byte[]       volumeId = metaVolumeIds[volumeIndex];
                    HdfsVolumeId id       = new HdfsVolumeId(volumeId);
                    // Find out which index we are in the LocatedBlock's replicas
                    LocatedBlock   locBlock = blockIdToLocBlock[blockId];
                    DatanodeInfo[] dnInfos  = locBlock.GetLocations();
                    int            index    = -1;
                    for (int k = 0; k < dnInfos.Length; k++)
                    {
                        if (dnInfos[k].Equals(datanode))
                        {
                            index = k;
                            break;
                        }
                    }
                    if (index < 0)
                    {
                        if (Log.IsDebugEnabled())
                        {
                            Log.Debug("Datanode responded with a block volume id we did" + " not request, omitting."
                                      );
                        }
                        continue;
                    }
                    // Place VolumeId at the same index as the DN's index in the list of
                    // replicas
                    IList <VolumeId> volumeIds = blockVolumeIds[locBlock];
                    volumeIds.Set(index, id);
                }
            }
            return(blockVolumeIds);
        }