Skip to content

Commit 55e7e1a

Browse files
author
Leonid Kramer
authored
Merge pull request #265 from vibe-d/batch_getfileinfo
Add a batch overload of getFileInfo
2 parents 0706b67 + 5911980 commit 55e7e1a

File tree

1 file changed

+73
-0
lines changed

1 file changed

+73
-0
lines changed

source/vibe/core/file.d

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ import std.file;
2828
import std.path;
2929
import std.string;
3030
import std.typecons : Flag, No;
31+
import taggedalgebraic.taggedunion;
3132

3233

3334
version(Posix){
@@ -331,6 +332,78 @@ FileInfo getFileInfo(string path)
331332
return ret[0];
332333
}
333334

335+
/** Returns file information about multiple files at once.
336+
337+
This version of `getFileInfo` is more efficient than many individual calls
338+
to the singular version.
339+
*/
340+
FileInfoResult[] getFileInfo(const(NativePath)[] paths)
341+
nothrow {
342+
import vibe.core.channel : Channel, ChannelConfig, ChannelPriority, createChannel;
343+
import vibe.core.core : runTask, runWorkerTask;
344+
345+
if (!paths.length) return null;
346+
347+
ChannelConfig cc;
348+
cc.priority = ChannelPriority.overhead;
349+
350+
Channel!NativePath inch;
351+
Channel!FileInfoResult outch;
352+
353+
try {
354+
inch = createChannel!NativePath(cc);
355+
outch = createChannel!FileInfoResult(cc);
356+
} catch (Exception e) assert(false, e.msg);
357+
358+
static void getInfos(Channel!NativePath inch, Channel!FileInfoResult outch) nothrow {
359+
NativePath p;
360+
while (inch.tryConsumeOne(p)) {
361+
FileInfoResult fi;
362+
if (!existsFile(p)) fi = FileInfoResult.missing;
363+
else {
364+
try {
365+
auto ent = DirEntry(p.toString);
366+
fi = FileInfoResult.info(makeFileInfo(ent));
367+
} catch (Exception e) {
368+
fi = FileInfoResult.error(e.msg.length ? e.msg : "Failed to get file information");
369+
}
370+
}
371+
try outch.put(fi);
372+
catch (Exception e) assert(false, e.msg);
373+
}
374+
outch.close();
375+
}
376+
377+
try runWorkerTask(&getInfos, inch, outch);
378+
catch (Exception e) assert(false, e.msg);
379+
380+
runTask(() nothrow {
381+
foreach (p; paths) {
382+
try inch.put(p);
383+
catch (Exception e) assert(false, e.msg);
384+
}
385+
inch.close();
386+
});
387+
388+
auto ret = new FileInfoResult[](paths.length);
389+
size_t i = 0;
390+
foreach (ref fi; ret) {
391+
if (!outch.tryConsumeOne(fi))
392+
assert(false);
393+
}
394+
assert(outch.empty);
395+
396+
return ret;
397+
}
398+
399+
struct FileInfoResultFields {
400+
Void missing;
401+
string error;
402+
FileInfo info;
403+
}
404+
alias FileInfoResult = TaggedUnion!FileInfoResultFields;
405+
406+
334407
/**
335408
Creates a new directory.
336409
*/

0 commit comments

Comments
 (0)