1 /* 2 Copyright 2013-2014 EditShare, 2013-2015 Skytechnology sp. z o.o. 3 4 This file is part of LizardFS. 5 6 LizardFS is free software: you can redistribute it and/or modify 7 it under the terms of the GNU General Public License as published by 8 the Free Software Foundation, version 3. 9 10 LizardFS is distributed in the hope that it will be useful, 11 but WITHOUT ANY WARRANTY; without even the implied warranty of 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 GNU General Public License for more details. 14 15 You should have received a copy of the GNU General Public License 16 along with LizardFS. If not, see <http://www.gnu.org/licenses/>. 17 */ 18 19 #pragma once 20 21 #include "common/platform.h" 22 23 #include <functional> 24 25 #include "common/io_limiting.h" 26 #include "mount/mastercomm.h" 27 28 namespace ioLimiting { 29 30 // An object used locally in mount that communicates with a global limiter 31 // running in master 32 struct MasterLimiter : public Limiter { 33 MasterLimiter(); 34 ~MasterLimiter(); 35 // Passes a request to master 36 uint64_t request(const IoLimitGroupId& groupId, uint64_t size) override; 37 private: 38 class IolimitsConfigHandler : public PacketHandler { 39 public: IolimitsConfigHandlerMasterLimiter40 IolimitsConfigHandler(MasterLimiter& parent) : parent_(parent) {} 41 42 bool handle(MessageBuffer buffer); 43 private: 44 MasterLimiter& parent_; 45 }; 46 47 IolimitsConfigHandler iolimitsConfigHandler_; 48 uint32_t configVersion_; 49 }; 50 51 // The local limiter running in this mount instance (used in local I/O limiting) 52 struct MountLimiter : public Limiter { 53 uint64_t request(const IoLimitGroupId& groupId, uint64_t size) override; 54 void loadConfiguration(const IoLimitsConfigLoader& config); 55 private: 56 IoLimitsDatabase database_; 57 }; 58 59 // This class is a proxy that locally handles calls to a possibly remote Limiter. 60 // It classifies clients into groups and performs required delays. 61 class LimiterProxy { 62 public: LimiterProxy(Limiter & limiter,Clock & clock)63 LimiterProxy(Limiter& limiter, Clock& clock) : 64 shared_(limiter, std::chrono::milliseconds(100)), 65 enabled_(true), 66 clock_(clock) 67 { 68 using namespace std::placeholders; 69 limiter.registerReconfigure(std::bind( 70 &LimiterProxy::reconfigure, 71 this, 72 std::placeholders::_1, 73 std::placeholders::_2, 74 std::placeholders::_3)); 75 } 76 77 // Try to acquire an assignment of 'size' bytes. This method pauses a callee until a request 78 // is satisfied or a deadline is exceeded. Return when returns MFS status 79 uint8_t waitForRead(const pid_t pid, const uint64_t size, SteadyTimePoint deadline); 80 // Works the same as waitForRead 81 uint8_t waitForWrite(const pid_t pid, const uint64_t size, SteadyTimePoint deadline); 82 83 private: 84 typedef std::map<IoLimitGroupId, std::shared_ptr<Group>> Groups; 85 86 std::shared_ptr<Group> getGroup(const IoLimitGroupId& groupId) const; 87 // Remove groups that were deleted, cancel queued operations assigned to them. Add new groups. 88 // Update the delta_us parameter. 89 // If subsystem was changed, cancel all queued operations and removed groups that were used. 90 void reconfigure(uint32_t delta_us, const std::string& subsystem, 91 const std::vector<IoLimitGroupId>& groupIds); 92 93 std::mutex mutex_; 94 SharedState shared_; 95 std::string subsystem_; 96 Groups groups_; 97 bool enabled_; 98 Clock& clock_; 99 }; 100 101 } // namespace ioLimiting 102