aboutsummaryrefslogtreecommitdiff
path: root/src/zennet/beacon.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/zennet/beacon.cpp')
-rw-r--r--src/zennet/beacon.cpp170
1 files changed, 170 insertions, 0 deletions
diff --git a/src/zennet/beacon.cpp b/src/zennet/beacon.cpp
new file mode 100644
index 000000000..394a4afbb
--- /dev/null
+++ b/src/zennet/beacon.cpp
@@ -0,0 +1,170 @@
+// Copyright Epic Games, Inc. All Rights Reserved.
+
+#include <zennet/beacon.h>
+
+#include <zencore/basicfile.h>
+#include <zencore/compactbinary.h>
+#include <zencore/compactbinaryfile.h>
+#include <zencore/filesystem.h>
+#include <zencore/fmtutils.h>
+#include <zencore/session.h>
+#include <zencore/uid.h>
+
+#include <fmt/format.h>
+#include <asio.hpp>
+#include <map>
+
+namespace zen {
+
+//////////////////////////////////////////////////////////////////////////
+
+struct FsBeacon::Impl
+{
+ Impl(std::filesystem::path ShareRoot);
+ ~Impl();
+
+ void EnsureValid();
+
+ void AddGroup(std::string_view GroupId, CbObject Metadata);
+ void ScanGroup(std::string_view GroupId, std::vector<Oid>& OutSessions);
+ void ReadMetadata(std::string_view GroupId, const std::vector<Oid>& InSessions, std::vector<CbObject>& OutMetadata);
+
+private:
+ std::filesystem::path m_ShareRoot;
+ zen::Oid m_SessionId;
+
+ struct GroupData
+ {
+ CbObject Metadata;
+ BasicFile LockFile;
+ };
+
+ std::map<std::string, GroupData> m_Registration;
+
+ std::filesystem::path GetSessionMarkerPath(std::string_view GroupId, const Oid& SessionId)
+ {
+ Oid::String_t SessionIdString;
+ SessionId.ToString(SessionIdString);
+
+ return m_ShareRoot / GroupId / SessionIdString;
+ }
+};
+
+FsBeacon::Impl::Impl(std::filesystem::path ShareRoot) : m_ShareRoot(ShareRoot), m_SessionId(GetSessionId())
+{
+}
+
+FsBeacon::Impl::~Impl()
+{
+}
+
+void
+FsBeacon::Impl::EnsureValid()
+{
+}
+
+void
+FsBeacon::Impl::AddGroup(std::string_view GroupId, CbObject Metadata)
+{
+ zen::CreateDirectories(m_ShareRoot / GroupId);
+ std::filesystem::path MarkerFile = GetSessionMarkerPath(GroupId, m_SessionId);
+
+ GroupData& Group = m_Registration[std::string(GroupId)];
+
+ Group.Metadata = Metadata;
+
+ std::error_code Ec;
+ Group.LockFile.Open(MarkerFile,
+ BasicFile::Mode::kTruncate | BasicFile::Mode::kPreventDelete |
+ BasicFile::Mode::kPreventWrite /* | BasicFile::Mode::kDeleteOnClose */,
+ Ec);
+
+ if (Ec)
+ {
+ throw std::system_error(Ec, fmt::format("failed to open beacon marker file '{}' for write", MarkerFile));
+ }
+
+ Group.LockFile.WriteAll(Metadata.GetBuffer().AsIoBuffer(), Ec);
+
+ if (Ec)
+ {
+ throw std::system_error(Ec, fmt::format("failed to write to beacon marker file '{}'", MarkerFile));
+ }
+
+ Group.LockFile.Flush();
+}
+
+void
+FsBeacon::Impl::ScanGroup(std::string_view GroupId, std::vector<Oid>& OutSessions)
+{
+ DirectoryContent Dc;
+ zen::GetDirectoryContent(m_ShareRoot / GroupId, zen::DirectoryContentFlags::IncludeFiles, /* out */ Dc);
+
+ for (const std::filesystem::path& FilePath : Dc.Files)
+ {
+ std::filesystem::path File = FilePath.filename();
+
+ std::error_code Ec;
+ if (std::filesystem::remove(FilePath, Ec) == false)
+ {
+ auto FileString = File.generic_string();
+
+ if (FileString.length() != Oid::StringLength)
+ continue;
+
+ if (const Oid SessionId = Oid::FromHexString(FileString))
+ {
+ if (std::filesystem::file_size(File, Ec) > 0)
+ {
+ OutSessions.push_back(SessionId);
+ }
+ }
+ }
+ }
+}
+
+void
+FsBeacon::Impl::ReadMetadata(std::string_view GroupId, const std::vector<Oid>& InSessions, std::vector<CbObject>& OutMetadata)
+{
+ for (const Oid& SessionId : InSessions)
+ {
+ const std::filesystem::path MarkerFile = GetSessionMarkerPath(GroupId, SessionId);
+
+ if (CbObject Metadata = LoadCompactBinaryObject(MarkerFile).Object)
+ {
+ OutMetadata.push_back(std::move(Metadata));
+ }
+ }
+}
+
+//////////////////////////////////////////////////////////////////////////
+
+FsBeacon::FsBeacon(std::filesystem::path ShareRoot) : m_Impl(std::make_unique<Impl>(ShareRoot))
+{
+}
+
+FsBeacon::~FsBeacon()
+{
+}
+
+void
+FsBeacon::AddGroup(std::string_view GroupId, CbObject Metadata)
+{
+ m_Impl->AddGroup(GroupId, Metadata);
+}
+
+void
+FsBeacon::ScanGroup(std::string_view GroupId, std::vector<Oid>& OutSessions)
+{
+ m_Impl->ScanGroup(GroupId, OutSessions);
+}
+
+void
+FsBeacon::ReadMetadata(std::string_view GroupId, const std::vector<Oid>& InSessions, std::vector<CbObject>& OutMetadata)
+{
+ m_Impl->ReadMetadata(GroupId, InSessions, OutMetadata);
+}
+
+//////////////////////////////////////////////////////////////////////////
+
+} // namespace zen