1 // Copyright (C) 2018-2019 Internet Systems Consortium, Inc. ("ISC") 2 // 3 // This Source Code Form is subject to the terms of the Mozilla Public 4 // License, v. 2.0. If a copy of the MPL was not distributed with this 5 // file, You can obtain one at http://mozilla.org/MPL/2.0/. 6 7 #ifndef STAMPED_VALUE_H 8 #define STAMPED_VALUE_H 9 10 #include <cc/data.h> 11 #include <cc/stamped_element.h> 12 #include <boost/multi_index/hashed_index.hpp> 13 #include <boost/multi_index/mem_fun.hpp> 14 #include <boost/multi_index/ordered_index.hpp> 15 #include <boost/multi_index_container.hpp> 16 #include <boost/shared_ptr.hpp> 17 #include <cstdint> 18 #include <string> 19 20 namespace isc { 21 namespace data { 22 23 class StampedValue; 24 25 /// @brief Pointer to the stamped value. 26 typedef boost::shared_ptr<StampedValue> StampedValuePtr; 27 28 /// @brief This class represents a named configuration parameter, 29 /// e.g. global parameter of the DHCP server. 30 /// 31 /// Global configuration elements having simple types, e.g. DHCP 32 /// timers, need to be associatied with modification timestamps. 33 /// This association is made by deriving from @c StampedElement. 34 /// The values can be strings, integers, booleans or real numbers. 35 /// 36 /// Because the strings are more flexible, configuration elements 37 /// are always held as strings in the configuration backends. This 38 /// class reflects a single value held in the database. The value 39 /// can be return in its orginal type or can be returned as a 40 /// string. Also the null values are allowed. 41 class StampedValue : public StampedElement { 42 public: 43 44 /// @brief Constructor creating a null value. 45 /// 46 /// @param name Name of the value. 47 StampedValue(const std::string& name); 48 49 /// @brief Constructor creating a value from the @c Element. 50 /// 51 /// @param name Name of the value. 52 /// @param value Value encapsulated in the @c Element object. 53 /// 54 /// @throw BadValue if the value is null. 55 /// @throw TypeError if the value is neither a string, integer, 56 /// bool nor real. 57 StampedValue(const std::string& name, const ElementPtr& value); 58 59 /// @brief Constructor creating a string value. 60 /// 61 /// Creates stamped value from a string. 62 /// 63 /// @param name Name of the value. 64 /// @param value Value to be set. 65 StampedValue(const std::string& name, const std::string& value); 66 67 /// @brief Factory function creating a null value. 68 /// 69 /// @param name Name of the value. 70 static StampedValuePtr create(const std::string& name); 71 72 /// @brief Factory function creating a value from the @c Element. 73 /// 74 /// @param name Name of the value. 75 /// @param value Value encapsulated in the @c Element object. 76 /// 77 /// @throw BadValue if the value is null. 78 /// @throw TypeError if the value is neither a string, integer, 79 /// bool nor real. 80 static StampedValuePtr create(const std::string& name, 81 const ElementPtr& value); 82 83 /// @brief Factory function creating a string value. 84 /// 85 /// Creates stamped value from a string. 86 /// 87 /// @param name Name of the value. 88 /// @param value Value to be set. 89 static StampedValuePtr create(const std::string& name, 90 const std::string& value); 91 92 /// @brief Factory function which attempts to convert provided 93 /// string value to a given type. 94 /// 95 /// This factory function is useful in cases when the value is 96 /// read as a string from a database. The string value has to 97 /// be converted to the appropriate data type. The type is also 98 /// known from the database. 99 /// 100 /// @param name Name of the value. 101 /// @param value Value given as string to be converted. 102 /// @param type Type of the value to convert to. 103 static StampedValuePtr create(const std::string& name, 104 const std::string& value, 105 Element::types type); 106 107 /// @brief Returns a type of the value. 108 /// 109 /// @return Type of the value as integer. It can be compared 110 /// with the @c Element::getType() output. 111 /// @throw InvalidOperation if the value is null. 112 int getType() const; 113 114 /// @brief Returns value name. 115 /// 116 /// @return Value name. getName()117 std::string getName() const { 118 return (name_); 119 } 120 121 /// @brief Returns value as string. 122 /// 123 /// It is allowed to call this function for all supported data 124 /// types. They are converted to a string. For example, a real 125 /// number of 1.4 will be returned as "1.4". The boolean true 126 /// value will be returned as "1" etc. 127 /// 128 /// @return Stored value as string. 129 /// @throw InvalidOperation if the value is null. 130 std::string getValue() const; 131 132 /// @brief Checks if the value is null. 133 /// 134 /// @return true if the value is null, false otherwise. amNull()135 bool amNull() const { 136 return (!value_); 137 } 138 139 /// @brief Returns value as signed integer. 140 /// 141 /// @return Stored value as a signed integer. 142 /// @throw TypeError if the value is not of @c Element::integer 143 /// type. 144 int64_t getIntegerValue() const; 145 146 /// @brief Returns value as a boolean. 147 /// 148 /// @return Stored value as a boolean. 149 /// @throw TypeError if the value is not of @c Element::boolean 150 /// type. 151 bool getBoolValue() const; 152 153 /// @brief Returns value as a real number. 154 /// 155 /// @return Stored value as a real number. 156 /// @throw TypeError if the value is not of @c Element::real 157 /// type. 158 double getDoubleValue() const; 159 160 /// @brief Returns the value as @c Element. getElementValue()161 ConstElementPtr getElementValue() const { 162 return (value_); 163 } 164 165 private: 166 167 /// @brief Checks if the values passed to the constructors 168 /// were correct. 169 /// 170 /// This is called from the constructors. 171 /// 172 /// @throw BadValue if the value is null. 173 /// @throw TypeError if the value type is neither a string, 174 /// integer, boolean nor real. 175 void validateConstruct() const; 176 177 /// @brief Checks if the value is accessed correctly. 178 /// 179 /// This is called from the accessors of this class. 180 /// 181 /// @param type Type of the value expected by the accessor 182 /// function. 183 /// 184 /// @throw InvalidOperation if the accessed value is null. 185 /// @throw TypeError if the expected type is not a string 186 /// and it doesn't match the value type. 187 void validateAccess(Element::types type) const; 188 189 /// @brief Name of the value. 190 std::string name_; 191 192 /// @brief Stored value. 193 ElementPtr value_; 194 }; 195 196 /// @name Definition of the multi index container for @c StampedValue. 197 /// 198 //@{ 199 200 /// @brief Tag for the index for access by value name. 201 struct StampedValueNameIndexTag { }; 202 203 /// @brief Tag for the index for access by modification time. 204 struct StampedValueModificationTimeIndexTag { }; 205 206 /// @brief Multi index container for @c StampedValue. 207 typedef boost::multi_index_container< 208 StampedValuePtr, 209 boost::multi_index::indexed_by< 210 // Index used to access value by name. 211 boost::multi_index::hashed_non_unique< 212 boost::multi_index::tag<StampedValueNameIndexTag>, 213 boost::multi_index::const_mem_fun< 214 StampedValue, 215 std::string, 216 &StampedValue::getName 217 > 218 >, 219 220 // Index used to access value by modification time. 221 boost::multi_index::ordered_non_unique< 222 boost::multi_index::tag<StampedValueModificationTimeIndexTag>, 223 boost::multi_index::const_mem_fun< 224 BaseStampedElement, 225 boost::posix_time::ptime, 226 &BaseStampedElement::getModificationTime 227 > 228 > 229 > 230 > StampedValueCollection; 231 232 //@} 233 234 } // end of namespace isc::data 235 } // end of namespace isc 236 237 #endif 238