1 | #pragma once |
2 | |
3 | #include <Disks/IDisk.h> |
4 | #include <IO/WriteHelpers.h> |
5 | #include <Common/CurrentMetrics.h> |
6 | #include <Common/Exception.h> |
7 | #include <Common/formatReadable.h> |
8 | #include <common/logger_useful.h> |
9 | |
10 | #include <memory> |
11 | #include <mutex> |
12 | #include <unistd.h> |
13 | #include <boost/noncopyable.hpp> |
14 | #include <Poco/Util/AbstractConfiguration.h> |
15 | |
16 | |
17 | namespace DB |
18 | { |
19 | namespace ErrorCodes |
20 | { |
21 | extern const int LOGICAL_ERROR; |
22 | extern const int NOT_ENOUGH_SPACE; |
23 | extern const int NOT_IMPLEMENTED; |
24 | extern const int SYSTEM_ERROR; |
25 | extern const int UNKNOWN_ELEMENT_IN_CONFIG; |
26 | extern const int EXCESSIVE_ELEMENT_IN_CONFIG; |
27 | extern const int UNKNOWN_POLICY; |
28 | extern const int UNKNOWN_DISK; |
29 | } |
30 | |
31 | /// Parse .xml configuration and store information about disks |
32 | /// Mostly used for introspection. |
33 | class DiskSelector |
34 | { |
35 | public: |
36 | DiskSelector(const Poco::Util::AbstractConfiguration & config, const String & config_prefix, const Context & context); |
37 | |
38 | /// Get disk by name |
39 | const DiskPtr & operator[](const String & name) const; |
40 | |
41 | /// Get all disks with names |
42 | const auto & getDisksMap() const { return disks; } |
43 | |
44 | private: |
45 | std::map<String, DiskPtr> disks; |
46 | }; |
47 | |
48 | /** |
49 | * Disks group by some (user) criteria. For example, |
50 | * - Volume("slow_disks", [d1, d2], 100) |
51 | * - Volume("fast_disks", [d3, d4], 200) |
52 | * Cannot store parts larger than max_data_part_size. |
53 | */ |
54 | class Volume : public Space |
55 | { |
56 | friend class StoragePolicy; |
57 | |
58 | public: |
59 | Volume(String name_, std::vector<DiskPtr> disks_, UInt64 max_data_part_size_) |
60 | : max_data_part_size(max_data_part_size_), disks(std::move(disks_)), name(std::move(name_)) |
61 | { |
62 | } |
63 | |
64 | Volume( |
65 | String name_, |
66 | const Poco::Util::AbstractConfiguration & config, |
67 | const String & config_prefix, |
68 | const DiskSelector & disk_selector); |
69 | |
70 | /// Uses Round-robin to choose disk for reservation. |
71 | /// Returns valid reservation or nullptr if there is no space left on any disk. |
72 | ReservationPtr reserve(UInt64 bytes) override; |
73 | |
74 | /// Return biggest unreserved space across all disks |
75 | UInt64 getMaxUnreservedFreeSpace() const; |
76 | |
77 | /// Volume name from config |
78 | const String & getName() const override { return name; } |
79 | |
80 | /// Max size of reservation |
81 | UInt64 max_data_part_size = 0; |
82 | |
83 | /// Disks in volume |
84 | Disks disks; |
85 | |
86 | private: |
87 | mutable std::atomic<size_t> last_used = 0; |
88 | const String name; |
89 | }; |
90 | |
91 | using VolumePtr = std::shared_ptr<Volume>; |
92 | using Volumes = std::vector<VolumePtr>; |
93 | |
94 | |
95 | /** |
96 | * Contains all information about volumes configuration for Storage. |
97 | * Can determine appropriate Volume and Disk for each reservation. |
98 | */ |
99 | class StoragePolicy |
100 | { |
101 | public: |
102 | StoragePolicy(String name_, const Poco::Util::AbstractConfiguration & config, const String & config_prefix, const DiskSelector & disks); |
103 | |
104 | StoragePolicy(String name_, Volumes volumes_, double move_factor_); |
105 | |
106 | bool isDefaultPolicy() const; |
107 | |
108 | /// Returns disks ordered by volumes priority |
109 | Disks getDisks() const; |
110 | |
111 | /// Returns any disk |
112 | /// Used when it's not important, for example for |
113 | /// mutations files |
114 | DiskPtr getAnyDisk() const; |
115 | |
116 | DiskPtr getDiskByName(const String & disk_name) const; |
117 | |
118 | /// Get free space from most free disk |
119 | UInt64 getMaxUnreservedFreeSpace() const; |
120 | |
121 | const String & getName() const { return name; } |
122 | |
123 | /// Returns valid reservation or null |
124 | ReservationPtr reserve(UInt64 bytes) const; |
125 | |
126 | /// Reserve space on any volume with index > min_volume_index |
127 | ReservationPtr reserve(UInt64 bytes, size_t min_volume_index) const; |
128 | |
129 | /// Find volume index, which contains disk |
130 | size_t getVolumeIndexByDisk(const DiskPtr & disk_ptr) const; |
131 | |
132 | /// Reserves 0 bytes on disk with max available space |
133 | /// Do not use this function when it is possible to predict size. |
134 | ReservationPtr makeEmptyReservationOnLargestDisk() const; |
135 | |
136 | const Volumes & getVolumes() const { return volumes; } |
137 | |
138 | /// Returns number [0., 1.] -- fraction of free space on disk |
139 | /// which should be kept with help of background moves |
140 | double getMoveFactor() const { return move_factor; } |
141 | |
142 | /// Get volume by index from storage_policy |
143 | VolumePtr getVolume(size_t i) const { return (i < volumes_names.size() ? volumes[i] : VolumePtr()); } |
144 | |
145 | VolumePtr getVolumeByName(const String & volume_name) const |
146 | { |
147 | auto it = volumes_names.find(volume_name); |
148 | if (it == volumes_names.end()) |
149 | return {}; |
150 | return getVolume(it->second); |
151 | } |
152 | |
153 | private: |
154 | Volumes volumes; |
155 | const String name; |
156 | std::map<String, size_t> volumes_names; |
157 | |
158 | /// move_factor from interval [0., 1.] |
159 | /// We move something if disk from this policy |
160 | /// filled more than total_size * move_factor |
161 | double move_factor = 0.1; /// by default move factor is 10% |
162 | }; |
163 | |
164 | |
165 | using StoragePolicyPtr = std::shared_ptr<const StoragePolicy>; |
166 | |
167 | /// Parse .xml configuration and store information about policies |
168 | /// Mostly used for introspection. |
169 | class StoragePolicySelector |
170 | { |
171 | public: |
172 | StoragePolicySelector(const Poco::Util::AbstractConfiguration & config, const String & config_prefix, const DiskSelector & disks); |
173 | |
174 | /// Policy by name |
175 | const StoragePolicyPtr & operator[](const String & name) const; |
176 | |
177 | /// All policies |
178 | const std::map<String, StoragePolicyPtr> & getPoliciesMap() const { return policies; } |
179 | |
180 | private: |
181 | std::map<String, StoragePolicyPtr> policies; |
182 | }; |
183 | |
184 | } |
185 | |