Skip to content
Snippets Groups Projects
Commit 55c2f3a7 authored by Florian Fischer's avatar Florian Fischer
Browse files

add callback based fsearch implementation

parent 3d43918d
No related branches found
No related tags found
No related merge requests found
Pipeline #57658 canceled
// SPDX-License-Identifier: LGPL-3.0-or-later
// Copyright © 2021 Florian Fischer
#include <fcntl.h>
#include <array>
#include <cassert>
#include <cerrno>
#include <cstdint>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <filesystem>
#include <iostream>
#include <string>
#include <utility>
#include "Common.hpp"
#include "CountingPrivateSemaphore.hpp"
#include "Fiber.hpp"
#include "Runtime.hpp"
#include "emper.hpp"
#include "io.hpp"
#include "io/Future.hpp"
namespace fs = std::filesystem;
using emper::io::OpenatFuture;
using emper::io::ReadFuture;
const size_t EMPER_RIPGREP_BUFSIZE = 4096;
const char* needle;
size_t needle_len;
class FileSearcher {
std::string path;
int fd = -1;
std::array<char, EMPER_RIPGREP_BUFSIZE> buf;
CPS& finished;
public:
FileSearcher(std::string path, CPS& finished) : path(std::move(path)), finished(finished) {}
~FileSearcher() {
if (fd > 0) {
emper::io::closeAndForget(fd);
fd = -1;
}
finished.signalAndExit();
}
void kickoffSearch() {
OpenatFuture f(AT_FDCWD, path.c_str(), O_RDONLY);
f.setCallback([this](int32_t fd) {
if (fd < 0) {
errno = -fd;
DIE_MSG_ERRNO("open failed");
}
this->fd = fd;
submitRead();
});
f.submit();
}
void onRead(int32_t bytes_read) {
if (bytes_read <= 0) {
// file was fully searched
if (bytes_read == 0) {
delete this;
return;
}
errno = -bytes_read;
DIE_MSG_ERRNO("read failed");
}
if (memmem(&buf[0], bytes_read, needle, needle_len)) {
printf("%s\n", path.c_str());
delete this;
return;
}
submitRead();
}
void submitRead() {
assert(fd > 0);
ReadFuture f(fd, buf.data(), EMPER_RIPGREP_BUFSIZE, -1);
f.setCallback([this](int32_t bytes_read) { this->onRead(bytes_read); });
f.submit();
}
};
void walk_dir() {
CPS cps;
for (const auto& p : fs::recursive_directory_iterator(".")) {
if (!p.is_regular_file()) {
continue;
}
cps.incrementCounterByOne();
auto* searcher = new FileSearcher(p.path(), cps);
async([searcher] { searcher->kickoffSearch(); });
}
cps.wait();
exit(EXIT_SUCCESS);
}
auto main(int argc, char* argv[]) -> int {
if (argc < 2) {
std::cerr << "Usage: " << argv[0] << " <needle>" << std::endl;
return EXIT_FAILURE;
}
needle = argv[1];
needle_len = strlen(needle);
Runtime runtime;
auto* dirWalker = Fiber::from(walk_dir);
runtime.scheduleFromAnywhere(*dirWalker);
runtime.waitUntilFinished();
}
......@@ -3,3 +3,9 @@ fsearch_exe = executable(
'fsearch.cpp',
dependencies: emper_dep,
)
fsearch_callback_exe = executable(
'fsearch_callback',
'fsearch_callback.cpp',
dependencies: emper_dep,
)
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment