M module-services/service-fileindexer/ServiceFileIndexer.cpp => module-services/service-fileindexer/ServiceFileIndexer.cpp +2 -5
@@ 30,7 30,6 @@ namespace service
auto inotify = dynamic_cast<purefs::fs::message::inotify *>(msg);
if (inotify) {
int err;
- LOG_ERROR("Inotify event %s %08x", inotify->name.c_str(), int(inotify->flags));
if (inotify->flags && (purefs::fs::inotify_flags::close_write | purefs::fs::inotify_flags::move_dst)) {
err = onUpdateOrCreate(inotify->name);
if (err) {
@@ 62,10 61,6 @@ namespace service
// Initialize data notification handler
sys::ReturnCodes ServiceFileIndexer::InitHandler()
{
- /*
- mStartupIndexer.start(shared_from_this(), service::name::file_indexer);
- */
-
mfsNotifier = purefs::fs::inotify_create(shared_from_this());
if (!mfsNotifier) {
LOG_ERROR("Unable to create inotify object");
@@ 80,6 75,8 @@ namespace service
LOG_ERROR("Unable to create inotify watch errno: %i", err);
return sys::ReturnCodes::Failure;
}
+ // Start the initial indexer
+ mStartupIndexer.start(shared_from_this(), service::name::file_indexer);
return sys::ReturnCodes::Success;
}
M module-services/service-fileindexer/StartupIndexer.cpp => module-services/service-fileindexer/StartupIndexer.cpp +78 -40
@@ 3,9 3,11 @@
#include "StartupIndexer.hpp"
#include <Timers/TimerFactory.hpp>
-#include <filesystem>
#include <purefs/filesystem_paths.hpp>
+#include <purefs/fs/inotify_message.hpp>
#include "Constants.hpp"
+#include <filesystem>
+#include <fstream>
namespace service::detail
{
@@ 15,60 17,96 @@ namespace service::detail
{
using namespace std::string_literals;
// File extensions indexing allow list
- const std::vector<std::pair<std::string_view, mimeType>> allowed_exts{
- {".txt", mimeType::text}, {".wav", mimeType::audio}, {".mp3", mimeType::audio}, {".flac", mimeType::audio}};
+ static constexpr const char *allowed_exts[]{".wav", ".mp3", ".flac"};
// List of initial dirs for scan
- const std::vector<std::string> start_dirs{purefs::dir::getUserDiskPath(), purefs::dir::getCurrentOSPath()};
+ const std::vector<std::string> start_dirs{purefs::dir::getUserDiskPath() / "music"};
+ // Lock file name
+ const auto lock_file_name = purefs::dir::getUserDiskPath() / ".directory_is_indexed";
+ // Time for indexing first unit
+ constexpr auto timer_indexing_delay = 400;
+ // Time for initial delay after start
+ constexpr auto timer_run_delay = 10000;
} // namespace
- auto StartupIndexer::getFileType(std::string_view path) -> mimeType
+ // Process single entry
+ auto StartupIndexer::processEntry(std::shared_ptr<sys::Service> svc,
+ const std::filesystem::recursive_directory_iterator::value_type &entry) -> void
{
- for (const auto &ext : allowed_exts) {
- if (fs::path(path).extension() == ext.first) {
- return ext.second;
+ using namespace std::string_view_literals;
+ if (fs::is_regular_file(entry)) {
+ for (const auto &ext : allowed_exts) {
+ if (fs::path(entry).extension() == ext) {
+ const auto abspath = fs::absolute(entry).string();
+ const auto inotifyMsg = std::make_shared<purefs::fs::message::inotify>(
+ purefs::fs::inotify_flags::close_write, abspath, ""sv);
+ svc->bus.sendUnicast(inotifyMsg, std::string(service::name::file_indexer));
+ }
}
}
- return mimeType::_none_;
}
-
- // Collect startup files when service starts
- auto StartupIndexer::collectStartupFiles() -> void
+ // On timer timeout
+ auto StartupIndexer::onTimerTimeout(std::shared_ptr<sys::Service> svc) -> void
{
- /*
- using namespace std::string_literals;
- auto searcher_cb = [](void *ctx, const char *path, bool isDir) {
- auto _this = reinterpret_cast<StartupIndexer *>(ctx);
- if (!isDir) {
- for (const auto &ext : allowed_exts) {
- if (fs::path(path).extension() == ext.first) {
- _this->mMsgs.emplace_back(std::make_shared<msg::FileChangeMessage>(
- path, msg::FileChangeMessage::evt_t::modified, ""s));
- LOG_DEBUG("Initial indexing file added");
- }
- }
+ if (!mStarted) {
+ mIdxTimer.restart(std::chrono::milliseconds{timer_indexing_delay});
+ mStarted = true;
+ }
+ if (mSubDirIterator == std::filesystem::recursive_directory_iterator()) {
+ if (mTopDirIterator == std::cend(start_dirs)) {
+ createLockFile();
+ LOG_INFO("Initial startup indexer - Finished ...");
+ mIdxTimer.stop();
+ }
+ else {
+ mSubDirIterator = fs::recursive_directory_iterator(*mTopDirIterator);
+ mTopDirIterator++;
}
- };
- for (const auto &path : start_dirs) {
- ff_stdio_listdir_recursive(path.c_str(), searcher_cb, this);
}
- */
+ else {
+ processEntry(svc, *mSubDirIterator);
+ mSubDirIterator++;
+ }
}
+
// Setup timers for notification
auto StartupIndexer::setupTimers(std::shared_ptr<sys::Service> svc, std::string_view svc_name) -> void
{
- if (!mIdxTimer.isValid()) {
- mIdxTimer = sys::TimerFactory::createPeriodicTimer(
- svc.get(), "file_indexing", std::chrono::milliseconds{timer_indexing_time}, [this, svc](sys::Timer &) {
- if (!mMsgs.empty()) {
- // svc->bus.sendUnicast(mMsgs.front(), std::string(service::name::file_indexer));
- mMsgs.pop_front();
- }
- else {
- mIdxTimer.stop();
- }
- });
- mIdxTimer.start();
+ mIdxTimer = sys::TimerFactory::createPeriodicTimer(svc.get(),
+ "file_indexing",
+ std::chrono::milliseconds{timer_run_delay},
+ [this, svc](sys::Timer &) { onTimerTimeout(svc); });
+ mIdxTimer.start();
+ }
+
+ // Start the initial file indexing
+ auto StartupIndexer::start(std::shared_ptr<sys::Service> svc, std::string_view svc_name) -> void
+ {
+ if (!hasLockFile()) {
+ LOG_INFO("Initial startup indexer - Started...");
+ mTopDirIterator = std::begin(start_dirs);
+ setupTimers(svc, svc_name);
}
+ else {
+ LOG_INFO("Initial startup indexer - Not needed...");
+ }
+ }
+
+ // Create lock file
+ auto StartupIndexer::createLockFile() -> bool
+ {
+ std::ofstream ofs(lock_file_name);
+ ofs << time(nullptr);
+ return ofs.good();
+ }
+ // Check if lock file exists
+ auto StartupIndexer::hasLockFile() -> bool
+ {
+#if 0
+ std::error_code ec;
+ return fs::is_regular_file(lock_file_name, ec);
+#else
+ return false;
+#endif
}
} // namespace service::detail
M module-services/service-fileindexer/StartupIndexer.hpp => module-services/service-fileindexer/StartupIndexer.hpp +14 -28
@@ 5,51 5,37 @@
#include <Service/Service.hpp>
#include <module-sys/Timers/TimerHandle.hpp>
+#include <filesystem>
-#include <list>
-
-namespace service::msg
-{
- class FileChangeMessage;
-}
namespace service::detail
{
- // RFC6838 IANA MIME types
- enum class mimeType
- {
- _none_,
- application,
- audio,
- example,
- font,
- image,
- text,
- video
- };
class StartupIndexer
{
- static constexpr auto timer_indexing_time = 100U;
public:
StartupIndexer() = default;
~StartupIndexer() = default;
StartupIndexer(const StartupIndexer &) = delete;
StartupIndexer &operator=(StartupIndexer) = delete;
- auto start(std::shared_ptr<sys::Service> svc, std::string_view svc_name) -> void
- {
- collectStartupFiles();
- setupTimers(svc, svc_name);
- }
- static auto getFileType(std::string_view path) -> mimeType;
+ auto start(std::shared_ptr<sys::Service> svc, std::string_view svc_name) -> void;
private:
- // Collect startup files when service starts
- auto collectStartupFiles() -> void;
+ // Process single entry
+ static auto processEntry(std::shared_ptr<sys::Service> svc,
+ const std::filesystem::recursive_directory_iterator::value_type &entry) -> void;
// Setup timers for notification
auto setupTimers(std::shared_ptr<sys::Service> svc, std::string_view svc_name) -> void;
+ // On timer timeout
+ auto onTimerTimeout(std::shared_ptr<sys::Service> svc) -> void;
+ // Create lock file
+ static auto createLockFile() -> bool;
+ // Check if lock file exists
+ static auto hasLockFile() -> bool;
private:
- std::list<std::shared_ptr<msg::FileChangeMessage>> mMsgs;
+ std::vector<std::string>::const_iterator mTopDirIterator;
+ std::filesystem::recursive_directory_iterator mSubDirIterator;
sys::TimerHandle mIdxTimer;
+ bool mStarted{};
};
} // namespace service::detail