Recursive scan of the directory starting from the given parentID. Match files and directories that match the prefix and delimiter criteria. Stop when the number of matches reaches a threshold or all files and directories are scanned.
(fileInfos []*FSFileInfo, prefixMap PrefixMap, parentId, maxKeys, readLimit, rc uint64, dirs []string, prefix, marker, delimiter string, onlyObject, firstEnter bool, )
| 2266 | // that match the prefix and delimiter criteria. Stop when the number of matches reaches a threshold |
| 2267 | // or all files and directories are scanned. |
| 2268 | func (v *Volume) recursiveScan(fileInfos []*FSFileInfo, prefixMap PrefixMap, parentId, maxKeys, readLimit, rc uint64, dirs []string, |
| 2269 | prefix, marker, delimiter string, onlyObject, firstEnter bool, |
| 2270 | ) ([]*FSFileInfo, PrefixMap, string, uint64, error) { |
| 2271 | var err error |
| 2272 | var nextMarker string |
| 2273 | var lastKey string |
| 2274 | |
| 2275 | currentPath := strings.Join(dirs, pathSep) + pathSep |
| 2276 | currentPath = strings.TrimPrefix(currentPath, pathSep) |
| 2277 | log.LogDebugf("recursiveScan enter: currentPath(/%v) fileInfos(%v) parentId(%v) prefix(%v) marker(%v) rc(%v)", |
| 2278 | currentPath, fileInfos, parentId, prefix, marker, rc) |
| 2279 | defer func() { |
| 2280 | log.LogDebugf("recursiveScan exit: currentPath(/%v) fileInfos(%v) parentId(%v) prefix(%v) nextMarker(%v) rc(%v)", |
| 2281 | currentPath, fileInfos, parentId, prefix, nextMarker, rc) |
| 2282 | }() |
| 2283 | |
| 2284 | // The "prefix" needs to be extracted as marker when it is larger than "marker". |
| 2285 | // So extract prefixMarker in this layer. |
| 2286 | prefixMarker := "" |
| 2287 | if prefix != "" { |
| 2288 | if len(dirs) == 0 { |
| 2289 | prefixMarker = prefix |
| 2290 | } else if strings.HasPrefix(prefix, currentPath) { |
| 2291 | prefixMarker = strings.TrimPrefix(prefix, currentPath) |
| 2292 | } |
| 2293 | } |
| 2294 | |
| 2295 | // To be sent in the readdirlimit request as a search start point. |
| 2296 | fromName := "" |
| 2297 | // Marker in this layer, shall be compared with prefixMarker to |
| 2298 | // determine which one should be used as the search start point. |
| 2299 | currentMarker := "" |
| 2300 | if marker != "" { |
| 2301 | markerNames := strings.Split(marker, pathSep) |
| 2302 | if len(markerNames) > len(dirs) { |
| 2303 | currentMarker = markerNames[len(dirs)] |
| 2304 | } |
| 2305 | if prefixMarker > currentMarker { |
| 2306 | fromName = prefixMarker |
| 2307 | } else { |
| 2308 | fromName = currentMarker |
| 2309 | } |
| 2310 | } else if prefixMarker != "" { |
| 2311 | fromName = prefixMarker |
| 2312 | } |
| 2313 | |
| 2314 | // During the process of scanning the child nodes of the current directory, there may be other |
| 2315 | // parallel operations that may delete the current directory. |
| 2316 | // If got the syscall.ENOENT error when invoke readdir, it means that the above situation has occurred. |
| 2317 | // At this time, stops process and returns success. |
| 2318 | var children []proto.Dentry |
| 2319 | |
| 2320 | readDir: |
| 2321 | children, err = v.mw.ReadDirLimit_ll(parentId, fromName, readLimit+1) // one more for nextMarker |
| 2322 | if err != nil && err != syscall.ENOENT { |
| 2323 | return fileInfos, prefixMap, "", 0, err |
| 2324 | } |
| 2325 | if err == syscall.ENOENT { |