diff --git a/libi2pd/Storage.cpp b/libi2pd/Storage.cpp new file mode 100644 index 00000000..61f52128 --- /dev/null +++ b/libi2pd/Storage.cpp @@ -0,0 +1,81 @@ +#include +#include + +#include + +#include "Storage.h" + +namespace i2p { +namespace data { + +FsIdentStorage::~FsIdentStorage() {} +IdentStorage::~IdentStorage() {} + +bool IdentStorage::Init() { return true; } +bool FsIdentStorage::Init() +{ + m_Storage.SetPlace(i2p::fs::GetDataDir()); + if (m_IsB32) + m_Storage.Init(i2p::data::GetBase32SubstitutionTable(), 32); + else + m_Storage.Init(i2p::data::GetBase64SubstitutionTable(), 64); + return true; +} + +bool FsIdentStorage::Store(const i2p::data::IdentHash &ident, const StorageRecord &record) +{ + std::string strid = m_IsB32 ? ident.ToBase32() : ident.ToBase64(); + std::string path = m_Storage.Path(strid); + std::ofstream ofs(path, std::ios::binary); + ofs.write(record.data.get(), record.len); + ofs.flush(); + return true; +} + +StorageRecord FsIdentStorage::Fetch(const i2p::data::IdentHash &ident) +{ + std::string strid = m_IsB32 ? ident.ToBase32() : ident.ToBase64(); + std::string path = m_Storage.Path(strid); + if (boost::filesystem::exists(path)) { + std::ifstream ifs(path, std::ios::binary); + ifs.seekg(0, std::ios::end); + + int size = ifs.tellg(); + ifs.seekg(0, std::ios::beg); + + StorageRecord result(size); + + ifs.read(result.data.get(), size); + return result; + } + + return StorageRecord(); +} + +bool FsIdentStorage::Remove(const IdentHash & ident) +{ + std::string strid = m_IsB32 ? ident.ToBase32() : ident.ToBase64(); + std::string path = m_Storage.Path(strid); + return i2p::fs::Remove(path); +} + +void FsIdentStorage::Iterate(const DVisitor &f) +{ + auto fv = [&f, this](const std::string &path) + { + boost::filesystem::path p(path); + std::string id = p.stem().string().substr(m_Fprefix.length()); + i2p::data::IdentHash ident; + if (m_IsB32) + ident.FromBase32(id); + else + ident.FromBase64(id); + StorageRecord data = Fetch(ident); + if (data.IsValid()) f(ident,data); + }; + + m_Storage.Iterate(fv); +} + +} //ns data +} //ns i2p diff --git a/libi2pd/Storage.h b/libi2pd/Storage.h new file mode 100644 index 00000000..0fc69cc1 --- /dev/null +++ b/libi2pd/Storage.h @@ -0,0 +1,74 @@ +#ifndef STORAGE_H +#define STORAGE_H +#include +#include +#include +#include + +#include "FS.h" +#include "Identity.h" +#include "Log.h" + +namespace i2p +{ +namespace data +{ + +class StorageRecord +{ +public: + std::shared_ptr data; + size_t len; + StorageRecord(size_t len): data(new char[len]), len(len) {} + StorageRecord(const char *buf, size_t len): StorageRecord(len) + { + memcpy(data.get(), buf, len); + } + + StorageRecord(): data(nullptr), len(0) {} + bool IsValid() { return len > 0; } +}; + +typedef std::function DVisitor; + +class IdentStorage +{ +public: + IdentStorage() {} + virtual bool Init(); + virtual void DeInit() {} + virtual bool BeginUpdate() { return true; } + virtual bool EndUpdate() { return true; } + virtual bool Store(const IdentHash &, const StorageRecord&) { return true; } + virtual bool Remove(const IdentHash &) { return true; } + virtual StorageRecord Fetch(const IdentHash&) { return StorageRecord(); } + virtual void Iterate(const DVisitor&) {} + virtual ~IdentStorage(); +}; + +class FsIdentStorage : public IdentStorage +{ +public: + FsIdentStorage(const char *name, const char* dprefix, const char *fprefix, const char *suffix, bool isB32=false) : + m_Storage(name, dprefix, fprefix, suffix), m_Fprefix(fprefix), m_IsB32(isB32) {} + + virtual bool Init(); + virtual void DeInit() {} + virtual bool BeginUpdate() { return true; } + virtual bool EndUpdate() { return true; } + virtual bool Store(const IdentHash &, const StorageRecord&); + virtual bool Remove(const IdentHash &); + StorageRecord Fetch(const IdentHash&); + virtual void Iterate(const DVisitor&); + virtual ~FsIdentStorage(); + +private: + i2p::fs::HashedStorage m_Storage; + std::string m_Fprefix; + bool m_IsB32; +}; + +} //ns data +} //ns i2p + +#endif // STORAGE_H