Skip to content

Commit 78002ef

Browse files
committed
Rearchitecture initial commit. Most of StorageCluster & Volume spec now in header files
1 parent 0a1f6e0 commit 78002ef

14 files changed

+310
-16
lines changed

.gitignore

+3
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
# emacs
2+
*~
3+
14
# Prerequisites
25
*.d
36

CMakeLists.txt

+13-5
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ set(PROJECT_VERSION 0.0.1)
44

55
set(CMAKE_INCLUDE_CURRENT_DIR ON)
66
set(CMAKE_INCLUDE_CURRENT_DIR_IN_INTERFACE ON)
7-
set(CMAKE_CXX_COMPILER "/usr/lib64/llvm/8/bin/clang++")
7+
set(CMAKE_CXX_COMPILER "clang++")
88
set(CMAKE_CXX_STANDARD 17)
99
set(CMAKE_CXX_STANDARD_REQUIRED on)
1010
set(CMAKE_VERBOSE_MAKEFILE ON)
@@ -38,10 +38,17 @@ set(SOURCES
3838
src/middlewares/FileStorage/storage.hpp
3939
src/middlewares/FileStorage/storage.hpp
4040
src/middlewares/FileStorage/storage.cpp
41-
src/middlewares/FileStorage/haystack.hpp
42-
src/middlewares/FileStorage/haystack.cpp
41+
# src/middlewares/FileStorage/haystack.hpp
42+
# src/middlewares/FileStorage/haystack.cpp
4343
src/middlewares/FileStorage/filesystem.hpp
4444
src/middlewares/FileStorage/filesystem.cpp
45+
src/middlewares/Volume/marshaller.hpp
46+
src/middlewares/Volume/volume.hpp
47+
src/middlewares/Volume/services.hpp
48+
src/middlewares/StorageCluster/request.hpp
49+
src/middlewares/StorageCluster/response.hpp
50+
src/middlewares/StorageCluster/services.hpp
51+
src/middlewares/StorageCluster/storagecluster.hpp
4552
src/master.hpp
4653
src/master.cpp
4754
src/services.hpp
@@ -60,9 +67,11 @@ set(TEST_SOURCES
6067
include_directories("${PROJECT_SOURCE_DIR}")
6168

6269
#add_subdirectory(src)
70+
include_directories(/usr/local/include/asio)
6371
add_library(TinyCDN_Base SHARED ${SOURCES})
6472
add_library(stdc++fs UNKNOWN IMPORTED)
65-
set_property(TARGET stdc++fs PROPERTY IMPORTED_LOCATION "/usr/lib64/gcc/x86_64-pc-linux-gnu/7.3.0/libstdc++fs.a")
73+
set_property(TARGET stdc++fs PROPERTY IMPORTED_LOCATION "/usr/lib/gcc/x86_64-linux-gnu/8/libstdc++fs.a")
74+
6675
#target_link_libraries(TinyCDN_Base PUBLIC)
6776
add_executable(Run src/main.cpp)
6877
target_link_libraries(TinyCDN_Base stdc++fs)
@@ -79,7 +88,6 @@ add_executable(Test ${TEST_SOURCES})
7988
target_link_libraries(Test TinyCDN_Base Catch stdc++fs)
8089
add_test(NAME TestBase COMMAND Test)
8190

82-
8391
option(BUILD_CFFI "Generate the shared library" ON)
8492
if(BUILD_CFFI)
8593
add_library(tinyCDN SHARED src/middlewares/file_interop.h src/interop.c src/interop.cpp)

goals.org

+6
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,12 @@
33
* TODO remove META file necessity (buckets should have uuid)
44
* TODO volume node/master node distinction
55
* TODO spawnCDN should load from configuration for storage nodes
6+
* TODO make FileBucketRegistry and VolumeRegistry use same base class
7+
** converter changes
8+
*** convertInput -> deserialize
9+
*** convertField -> deserializeField
10+
*** convertToValue -> serialize
11+
* TODO make Volume an abstract class like FileStorage?
612
* TODO Dockerfiles for master node and storage node
713
* TODO replication strategy class (geolocation, backup, & )
814
* TODO owned filebuckets

src/hashing.hpp

+17-5
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
#include <cstring>
55
#include <sstream>
66

7-
namespace TinyCDN {
7+
namespace TinyCDN::Utility::Hashing {
88

99
class PseudoRandomHexFactory {
1010
public:
@@ -31,7 +31,6 @@ class PseudoRandomHexFactory {
3131
static constexpr char hex[17]{"0123456789ABCDEF"};
3232
};
3333

34-
3534
//! Wrapper type for fixed-size bitset with hex conversion to/from a string
3635
template <int fixedSize>
3736
class Id {
@@ -59,6 +58,10 @@ class Id {
5958
return *this;
6059
}
6160

61+
bool operator==(const Id<fixedSize> &other) const {
62+
return this->_value == other->value();
63+
}
64+
6265
friend std::ostream& operator<< (std::ostream &out, const Id<fixedSize> &id) {
6366
out << std::hex << id.value().to_ulong();
6467
return out;
@@ -69,17 +72,17 @@ class Id {
6972
return out;
7073
}
7174

72-
std::string str() {
75+
std::string str() const {
7376
std::stringstream hex;
7477
hex << std::hex << _value.to_ulong();
7578
return hex.str();
7679
}
7780

78-
const char* c_str() {
81+
const char* c_str() const {
7982
return this->str().c_str();
8083
}
8184

82-
inline std::bitset<fixedSize> value() noexcept {
85+
inline std::bitset<fixedSize> value() const noexcept {
8386
return _value;
8487
}
8588

@@ -95,6 +98,15 @@ class Id {
9598
std::bitset<fixedSize> _value;
9699
};
97100

101+
class IdHasher {
102+
public:
103+
template <int fixedSize>
104+
std::size_t operator()(const Id<fixedSize> &id) const {
105+
const std::bitset<fixedSize> id2 = id.value();
106+
return std::hash<std::bitset<fixedSize>>()(id2);
107+
}
108+
};
109+
98110
using UUID = Id<128>;
99111

100112
class UUID4Factory {

src/middlewares/StorageCluster/interop.h

Whitespace-only changes.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
#pragma once
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
#pragma once
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
#pragma once
2+
3+
#include "storagecluster.hpp"
4+
5+
namespace TinyCDN::Middleware::StorageCluster {
6+
7+
struct StorageFileUploadingSession {
8+
};
9+
10+
struct StorageFileHostingSession {
11+
};
12+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
#pragma once
2+
3+
#include <memory>
4+
#include <mutex>
5+
6+
#include "../Volume/volume.hpp"
7+
#include "request.hpp"
8+
#include "response.hpp"
9+
10+
struct StorageFileHostingService;
11+
struct StorageFileUploadingService;
12+
13+
namespace TinyCDN::Middleware::StorageCluster {
14+
using namespace TinyCDN::Middleware::Volume;
15+
16+
struct MasterRequest;
17+
struct MasterResponse;
18+
class StorageClusterRequest;
19+
class StorageClusterResponse;
20+
21+
/*!
22+
* \brief A single "core" allocated with available storage.
23+
* Hosts a virtual volume and receives commands from Master node to store/retrieve files to/from filebuckets, or replicate filebuckets, etc.
24+
Gets a authentication key from the Master node that gives permission to store/retrieve a file.
25+
*/
26+
class StorageClusterNode {
27+
public:
28+
std::unique_ptr<VirtualVolume> virtualVolume;
29+
30+
std::unique_ptr<StorageFileHostingService> getHostingService();
31+
std::unique_ptr<StorageFileUploadingService> getUploadingService();
32+
33+
// std::map<SessionId, StorageFileHostingSession>
34+
p
35+
// HTTP frontend: implement the following
36+
// parseStorageClusterMasterRequest(std::string message); -> StorageClusterRequest
37+
// parseStorageClusterClientRequest(std::string message); -> StorageClusterRequest
38+
39+
// TODO: Use Command pattern
40+
StorageClusterResponse receiveMasterCommand(StorageClusterRequest request);
41+
void sendMasterCommand(MasterRequest request);
42+
// NOTE: The client does not need TCP wrappers, client communication going from HTTP -> CFFI
43+
// StorageClusterResponse receiveClientCommand(StorageClusterRequest request);
44+
// StorageClusterResponse sendClientCommand(StorageClusterRequest request);
45+
46+
private:
47+
// TODO: object pool of services
48+
/*
49+
This is where we can create the most threads.
50+
Each service will exist in its own thread.
51+
The service shares access to the virtual volume's volumemanager and access to the lookup of storagevolumes
52+
*/
53+
std::unique_ptr<StorageFileUploadingService> uploadingService;
54+
std::unique_ptr<StorageFileHostingService> hostingService;
55+
56+
// TODO pool of services... see above
57+
std::mutex uploadServiceMutex;
58+
std::mutex hostingServiceMutex;
59+
std::mutex virtualVolumeMutex;
60+
61+
// TODO: networking
62+
// masterSocket
63+
};
64+
}

src/middlewares/Volume/marshaller.hpp

+49
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
#pragma once
2+
3+
#include <memory>
4+
#include <string>
5+
6+
#include "volume.hpp"
7+
8+
namespace TinyCDN::Middleware::Volume {
9+
10+
//! A Volume CSV gets converted into this POD and subsequently this data is assigned to a Volume instance
11+
struct VolumeParams {
12+
VolumeId id;
13+
uintmax_t size;
14+
15+
VolumeParams() : size(0) {};
16+
VolumeParams(VolumeId id, uintmax_t size) : id(id), size(size) {};
17+
};
18+
19+
//! Converts volumes from a CSV into a POD into an object instance
20+
struct VolumeCSVMarshaller {
21+
std::unique_ptr<VolumeParams> params;
22+
23+
//! Takes a Volume field and assigns it to its deduced conversion value
24+
auto deserializeField(std::string field, std::string value);
25+
26+
//! Creates a Volume instance by taking params and creating a Volume instance from it
27+
template <typename T>
28+
std::unique_ptr<T> deserialize();
29+
30+
//! Convenience helper method for generating fieldName=
31+
inline std::string assignmentToken(std::string fieldName) {
32+
return fieldName + "=";
33+
}
34+
35+
//! Resets the converter by emptying the current VolumeParams
36+
inline void reset() {
37+
params = std::make_unique<VolumeParams>();
38+
}
39+
40+
inline VolumeCSVMarshaller() {
41+
params = std::make_unique<VolumeParams>();
42+
}
43+
};
44+
45+
// JSON because this may be read by other programs and will not grow very large
46+
struct VirtualVolumeJsonMarshaller {
47+
// TODO decide what JSON library to use
48+
};
49+
}

src/middlewares/Volume/services.hpp

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
// class VolumeStorageService;
2+
namespace TinyCDN::Middleware::Volume {
3+
}

src/middlewares/Volume/volume.hpp

+119
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
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

Comments
 (0)