|
| 1 | +#pragma once |
| 2 | + |
| 3 | +#include <vector> |
| 4 | +#include <memory> |
| 5 | +#include <shared_mutex> |
| 6 | +#include <unordered_map> |
| 7 | +#include <optional> |
| 8 | + |
| 9 | +#include "../../utility.hpp" |
| 10 | +#include "../../hashing.hpp" |
| 11 | + |
| 12 | +using namespace TinyCDN::Utility::Exceptions; |
| 13 | +using namespace TinyCDN::Utility::Hashing; |
| 14 | + |
| 15 | +namespace TinyCDN::Middleware::Volume { |
| 16 | + |
| 17 | +using TinyCDN::Utility::Size; |
| 18 | + |
| 19 | +using FileBucketId = Id<64>; |
| 20 | +using VolumeId = Id<32>; |
| 21 | + |
| 22 | +/*! |
| 23 | + * \brief Abstract Static size blob |
| 24 | +*/ |
| 25 | +class Volume { |
| 26 | +public: |
| 27 | + // TODO remove this? StorageVolumeManager needs this, not Volume itself |
| 28 | + const VolumeId id; |
| 29 | + //! The maximum allowed size |
| 30 | + Size size; |
| 31 | + |
| 32 | + // virtual void resize(t size) = 0; |
| 33 | + virtual void destroy() = 0; |
| 34 | + |
| 35 | + // bool hasBucketId(FileBucketId id); |
| 36 | + |
| 37 | + inline Volume(VolumeId id, Size size) : id(id), size(size) {}; |
| 38 | +}; |
| 39 | + |
| 40 | +/*! Volume capable of storing files. |
| 41 | + * FileBuckets are assigned volumes based on location, config, etc. |
| 42 | + A StorageVolume will be assigned many different buckets from a VirtualVolume, but if a bucket does not populate, it can "spill over" into another StorageVolume if necessary. |
| 43 | + At some point, every now and then the volume can reallocate space by reclaiming lost volume space. (?) |
| 44 | + A StorageVolume is not be tied to the storage requirements of its buckets. |
| 45 | + StorageVolumes are replicated at a lower level than buckets. Buckets with default replication settings will be replicated as part of a volume manager's replication strategy. |
| 46 | +*/ |
| 47 | +template <typename storageType> |
| 48 | +class StorageVolume : Volume { |
| 49 | +public: |
| 50 | + inline void resize() { |
| 51 | + throw new NotImplementedException(); |
| 52 | + } |
| 53 | + |
| 54 | + inline void destroy() { |
| 55 | + throw new NotImplementedException(); |
| 56 | + } |
| 57 | + |
| 58 | + //! A file storage driver that provides methods to retrieve, modify, and delete files |
| 59 | + std::unique_ptr<storageType> storage; |
| 60 | + |
| 61 | + inline StorageVolume(Size size, fs::path location, bool preallocated) |
| 62 | + : Volume(id, size) { |
| 63 | + storage = std::make_unique<storageType>(size, location, preallocated); |
| 64 | + |
| 65 | + } |
| 66 | + // TODO delete default, volume constructors |
| 67 | +}; |
| 68 | + |
| 69 | +//! All StorageVolume types |
| 70 | +using AnyStorageVolume = std::variant<StorageVolume<FileStorage::FilesystemStorage>>; |
| 71 | +// Could be any StorageVolume instance, or a non-existent value |
| 72 | +// Could use std::optional, but wrapping variant would make std::visit less usable |
| 73 | +using MaybeAnyStorageVolume = std::variant<std::monostate, StorageVolume<FileStorage::FilesystemStorage>>; |
| 74 | + |
| 75 | +//class BackupVolume : Volume; |
| 76 | + |
| 77 | +/*! |
| 78 | + * \brief Responsible for allocating, replicating, and removing volumes as necessary |
| 79 | + */ |
| 80 | +class StorageVolumeManager { |
| 81 | +public: |
| 82 | + uintmax_t getSize(); |
| 83 | + //! Checks if size is going DOWN, if so, will replicate elsewhere? |
| 84 | + void setSize(uintmax_t size); |
| 85 | + |
| 86 | + std::unique_ptr<AnyStorageVolume> getStorageVolume(VolumeId id); |
| 87 | + template <typename T> |
| 88 | + std::unique_ptr<StorageVolume<T>> createStorageVolume(fs::path location); |
| 89 | + // replicateVolume |
| 90 | + void removeVolume(VolumeId id); |
| 91 | + |
| 92 | + inline StorageVolumeManager(uintmax_t size) : size(size) {} |
| 93 | + |
| 94 | +private: |
| 95 | + uintmax_t size; |
| 96 | + |
| 97 | + std::unordered_map<VolumeId, std::unique_ptr<MaybeAnyStorageVolume>, IdHasher> volumes; |
| 98 | + std::unordered_map<VolumeId, std::shared_mutex, IdHasher> volumeMutexes; |
| 99 | +}; |
| 100 | + |
| 101 | +/*! |
| 102 | + * \brief Volume that can be of a very large indeterminate size and manages many volumes within it. |
| 103 | + * The simple difference between a VirtualVolume and a StorageVolume is that a virtual volume is an alias to a single Volume that manages many volumes internally to efficently store large amounts of files. |
| 104 | + A FileBucket references a single virtual volume instead of the set of StorageVolumes that store its files. |
| 105 | +*/ |
| 106 | +class VirtualVolume : Volume { |
| 107 | +public: |
| 108 | + fs::path location; |
| 109 | + std::optional<std::vector<VolumeId>> getVolumeIds(); |
| 110 | + //! Also modifies storage volume manager's size |
| 111 | + void setSize(uintmax_t size); |
| 112 | + StorageVolumeManager storageVolumeManager; |
| 113 | + |
| 114 | +private: |
| 115 | + uintmax_t size; |
| 116 | + std::unordered_map<FileBucketId, std::vector<VolumeId>, IdHasher> fbVolDb; |
| 117 | + |
| 118 | +}; |
| 119 | +} |
0 commit comments