/// <summary>Get the file info for a specific file.</summary>
 /// <param name="fsd">FSDirectory</param>
 /// <param name="src">The string representation of the path to the file</param>
 /// <param name="isRawPath">true if a /.reserved/raw pathname was passed by the user</param>
 /// <param name="includeStoragePolicy">whether to include storage policy</param>
 /// <returns>
 /// object containing information regarding the file
 /// or null if file not found
 /// </returns>
 /// <exception cref="System.IO.IOException"/>
 internal static HdfsFileStatus GetFileInfo(FSDirectory fsd, string path, INodesInPath
                                            src, bool isRawPath, bool includeStoragePolicy)
 {
     fsd.ReadLock();
     try
     {
         INode i        = src.GetLastINode();
         byte  policyId = includeStoragePolicy && i != null && !i.IsSymlink() ? i.GetStoragePolicyID
                              () : BlockStoragePolicySuite.IdUnspecified;
         return(i == null ? null : CreateFileStatus(fsd, path, HdfsFileStatus.EmptyName, i
                                                    , policyId, src.GetPathSnapshotId(), isRawPath, src));
     }
     finally
     {
         fsd.ReadUnlock();
     }
 }
        /// <summary>
        /// Get a partial listing of the indicated directory
        /// We will stop when any of the following conditions is met:
        /// 1) this.lsLimit files have been added
        /// 2) needLocation is true AND enough files have been added such
        /// that at least this.lsLimit block locations are in the response
        /// </summary>
        /// <param name="fsd">FSDirectory</param>
        /// <param name="iip">
        /// the INodesInPath instance containing all the INodes along the
        /// path
        /// </param>
        /// <param name="src">the directory name</param>
        /// <param name="startAfter">the name to start listing after</param>
        /// <param name="needLocation">if block locations are returned</param>
        /// <returns>a partial listing starting after startAfter</returns>
        /// <exception cref="System.IO.IOException"/>
        private static DirectoryListing GetListing(FSDirectory fsd, INodesInPath iip, string
                                                   src, byte[] startAfter, bool needLocation, bool isSuperUser)
        {
            string srcs      = FSDirectory.NormalizePath(src);
            bool   isRawPath = FSDirectory.IsReservedRawName(src);

            fsd.ReadLock();
            try
            {
                if (srcs.EndsWith(HdfsConstants.SeparatorDotSnapshotDir))
                {
                    return(GetSnapshotsListing(fsd, srcs, startAfter));
                }
                int   snapshot   = iip.GetPathSnapshotId();
                INode targetNode = iip.GetLastINode();
                if (targetNode == null)
                {
                    return(null);
                }
                byte parentStoragePolicy = isSuperUser ? targetNode.GetStoragePolicyID() : BlockStoragePolicySuite
                                           .IdUnspecified;
                if (!targetNode.IsDirectory())
                {
                    return(new DirectoryListing(new HdfsFileStatus[] { CreateFileStatus(fsd, src, HdfsFileStatus
                                                                                        .EmptyName, targetNode, needLocation, parentStoragePolicy, snapshot, isRawPath,
                                                                                        iip) }, 0));
                }
                INodeDirectory       dirInode = targetNode.AsDirectory();
                ReadOnlyList <INode> contents = dirInode.GetChildrenList(snapshot);
                int startChild           = INodeDirectory.NextChild(contents, startAfter);
                int totalNumChildren     = contents.Size();
                int numOfListing         = Math.Min(totalNumChildren - startChild, fsd.GetLsLimit());
                int locationBudget       = fsd.GetLsLimit();
                int listingCnt           = 0;
                HdfsFileStatus[] listing = new HdfsFileStatus[numOfListing];
                for (int i = 0; i < numOfListing && locationBudget > 0; i++)
                {
                    INode cur       = contents.Get(startChild + i);
                    byte  curPolicy = isSuperUser && !cur.IsSymlink() ? cur.GetLocalStoragePolicyID() :
                                      BlockStoragePolicySuite.IdUnspecified;
                    listing[i] = CreateFileStatus(fsd, src, cur.GetLocalNameBytes(), cur, needLocation
                                                  , GetStoragePolicyID(curPolicy, parentStoragePolicy), snapshot, isRawPath, iip);
                    listingCnt++;
                    if (needLocation)
                    {
                        // Once we  hit lsLimit locations, stop.
                        // This helps to prevent excessively large response payloads.
                        // Approximate #locations with locatedBlockCount() * repl_factor
                        LocatedBlocks blks = ((HdfsLocatedFileStatus)listing[i]).GetBlockLocations();
                        locationBudget -= (blks == null) ? 0 : blks.LocatedBlockCount() * listing[i].GetReplication
                                              ();
                    }
                }
                // truncate return array if necessary
                if (listingCnt < numOfListing)
                {
                    listing = Arrays.CopyOf(listing, listingCnt);
                }
                return(new DirectoryListing(listing, totalNumChildren - startChild - listingCnt));
            }
            finally
            {
                fsd.ReadUnlock();
            }
        }