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 <array> 24 25 #include "common/goal.h" 26 #include "common/serialization.h" 27 #include "common/serialization_macros.h" 28 29 namespace detail { 30 31 template <class T> 32 class SerializableGoalIdArray : public std::array<T, GoalId::kMax + 1> { 33 typedef std::array<T, GoalId::kMax + 1> base; 34 35 public: serializedSize()36 uint32_t serializedSize() const { 37 return ::serializedSize(goalsAsMap()); 38 } 39 serialize(uint8_t ** destination)40 void serialize(uint8_t **destination) const { 41 ::serialize(destination, goalsAsMap()); 42 } 43 deserialize(const uint8_t ** source,uint32_t & bytes_left_in_buffer)44 void deserialize(const uint8_t **source, uint32_t &bytes_left_in_buffer) { 45 // verify if the map is empty 46 for (uint8_t goal = 0; goal <= GoalId::kMax; ++goal) { 47 assert(operator[](goal) == T()); 48 } 49 50 // deserialize the map 51 std::map<uint8_t, T> map; 52 ::deserialize(source, bytes_left_in_buffer, map); 53 for (const auto &goal_and_value : map) { 54 operator[](goal_and_value.first) = goal_and_value.second; 55 } 56 } 57 58 using base::operator[]; 59 60 private: goalsAsMap()61 std::map<uint8_t, T> goalsAsMap() const { 62 std::map<uint8_t, T> result; 63 T default_value = T(); 64 65 for (uint8_t goal = 0; goal <= GoalId::kMax; ++goal) { 66 if (operator[](goal) != default_value) { // Packet size optimization! 67 result[goal] = operator[](goal); 68 } 69 } 70 71 return result; 72 } 73 }; 74 75 } // detail 76 77 class ChunksAvailabilityState { 78 public: 79 enum State { kSafe = 0, kEndangered, kLost, kStateCount }; 80 ChunksAvailabilityState()81 ChunksAvailabilityState() : data_() { 82 } 83 safeChunks(uint8_t goal)84 uint64_t safeChunks(uint8_t goal) const { 85 return data_[kSafe][goal]; 86 } endangeredChunks(uint8_t goal)87 uint64_t endangeredChunks(uint8_t goal) const { 88 return data_[kEndangered][goal]; 89 } lostChunks(uint8_t goal)90 uint64_t lostChunks(uint8_t goal) const { 91 return data_[kLost][goal]; 92 } addChunk(uint8_t goal,State state)93 void addChunk(uint8_t goal, State state) { 94 getMapForState(state)[goal]++; 95 } removeChunk(uint8_t goal,State state)96 void removeChunk(uint8_t goal, State state) { 97 getMapForState(state)[goal]--; 98 } 99 100 LIZARDFS_DEFINE_SERIALIZE_METHODS(data_); 101 102 private: getMapForState(State state)103 detail::SerializableGoalIdArray<uint64_t> &getMapForState(State state) { 104 assert(state >= kSafe && state <= kLost); 105 return data_[state]; 106 } 107 108 // count of safe/endangered/lost chunks for each goal 109 std::array<detail::SerializableGoalIdArray<uint64_t>, 3> data_; 110 }; 111 112 /*! \brief Class for keeping statistics for chunk parts. 113 * 114 * Basically this is 2x two dimensional matrix for keeping integer values 115 * describing number of chunk part copies. 116 * 117 * Names of the class methods start to make sens after looking 118 * at the cgi table "All chunks state matrix". 119 */ 120 class ChunksReplicationState { 121 public: 122 constexpr static uint32_t kMaxPartsCount = 11; /*!< Maximum number of parts that we keep 123 in statistics. */ 124 ChunksReplicationState()125 ChunksReplicationState() : chunksToReplicate_(), chunksToDelete_() { 126 } 127 chunksToReplicate(uint8_t goal,uint32_t missingParts)128 uint64_t chunksToReplicate(uint8_t goal, uint32_t missingParts) const { 129 assert(missingParts < kMaxPartsCount); 130 return chunksToReplicate_[goal][missingParts]; 131 } chunksToDelete(uint8_t goal,uint32_t redundantParts)132 uint64_t chunksToDelete(uint8_t goal, uint32_t redundantParts) const { 133 assert(redundantParts < kMaxPartsCount); 134 return chunksToDelete_[goal][redundantParts]; 135 } addChunk(uint8_t goal,uint32_t missingParts,uint32_t redundantParts)136 void addChunk(uint8_t goal, uint32_t missingParts, uint32_t redundantParts) { 137 missingParts = std::min(missingParts, kMaxPartsCount - 1); 138 redundantParts = std::min(redundantParts, kMaxPartsCount - 1); 139 chunksToReplicate_[goal][missingParts]++; 140 chunksToDelete_[goal][redundantParts]++; 141 } removeChunk(uint8_t goal,uint32_t missingParts,uint32_t redundantParts)142 void removeChunk(uint8_t goal, uint32_t missingParts, uint32_t redundantParts) { 143 missingParts = std::min(missingParts, kMaxPartsCount - 1); 144 redundantParts = std::min(redundantParts, kMaxPartsCount - 1); 145 chunksToReplicate_[goal][missingParts]--; 146 chunksToDelete_[goal][redundantParts]--; 147 } 148 149 LIZARDFS_DEFINE_SERIALIZE_METHODS(chunksToReplicate_, chunksToDelete_); 150 151 private: 152 // count of chunks that need replication/deletion for each goal and number of missing parts 153 detail::SerializableGoalIdArray<std::array<uint64_t, kMaxPartsCount>> chunksToReplicate_; 154 detail::SerializableGoalIdArray<std::array<uint64_t, kMaxPartsCount>> chunksToDelete_; 155 }; 156