Line data Source code
1 : /*
2 : * Text:
3 : * libsnapwebsites/src/libdbproxy/value.cpp
4 : *
5 : * Description:
6 : * Handling of a cell value.
7 : *
8 : * Documentation:
9 : * See each function below.
10 : *
11 : * License:
12 : * Copyright (c) 2011-2019 Made to Order Software Corp. All Rights Reserved
13 : *
14 : * https://snapwebsites.org/
15 : * contact@m2osw.com
16 : *
17 : * Permission is hereby granted, free of charge, to any person obtaining a
18 : * copy of this software and associated documentation files (the
19 : * "Software"), to deal in the Software without restriction, including
20 : * without limitation the rights to use, copy, modify, merge, publish,
21 : * distribute, sublicense, and/or sell copies of the Software, and to
22 : * permit persons to whom the Software is furnished to do so, subject to
23 : * the following conditions:
24 : *
25 : * The above copyright notice and this permission notice shall be included
26 : * in all copies or substantial portions of the Software.
27 : *
28 : * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
29 : * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
30 : * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
31 : * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
32 : * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
33 : * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
34 : * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
35 : */
36 :
37 : #include "libdbproxy/value.h"
38 : #include "libdbproxy/exception.h"
39 : #include <stdexcept>
40 :
41 : namespace libdbproxy
42 : {
43 :
44 : /** \class value
45 : * \brief Holds a cell value.
46 : *
47 : * This class defines a value that is saved in a cell in the Cassandra
48 : * database. The class is optimized to with a QByteArray as the main
49 : * data holder.
50 : *
51 : * You can set the value as an integer, a floating point, a string, or
52 : * directly as a binary buffer. Strings are converted to UTF-8. Integers
53 : * and floating points are saved in big endian format (i.e. can then
54 : * be compared with a simple memcmp() call and sorted without magic
55 : * when saved as a Cassandra BytesType.)
56 : *
57 : * At this point, the copy operator is not overloaded meaning that
58 : * everything is copied as is. This also means the QByteArray copy
59 : * on write feature is used (i.e. the data buffer itself doesn't
60 : * get copied until the source of the destination is written to.)
61 : *
62 : * On the other hand, this means we need to copy the QByteArray
63 : * buffer to the std::string of the Column structure defined in
64 : * the Cassandra thrift code before sending it to Cassandra. In other
65 : * words, you may end up with one copy that you could otherwise have
66 : * avoided. On the other hand, many times just the value
67 : * objects will be copied between each others.
68 : */
69 :
70 : /** \var value::f_ttl
71 : * \brief The TTL of this value.
72 : *
73 : * The TTL represents the number of seconds this value will be kept in the
74 : * Cassandra database. For example, a log could be made to disappear
75 : * automatically after 3 months.
76 : *
77 : * The default value is TTL_PERMANENT which means that the value
78 : * is permanent.
79 : */
80 :
81 : /** \var value::timestamp_mode_t
82 : * \brief A timestamp mode.
83 : *
84 : * The timestamp can be defined in multiple ways. This mode specifies which
85 : * way you want to use for this value. The same mode is used by the different
86 : * remove() functions.
87 : *
88 : * The available modes are:
89 : *
90 : * \li TIMESTAMP_MODE_CASSANDRA -- the Cassandra server defines the timestamp
91 : * \li TIMESTAMP_MODE_AUTO -- the libQtCassandra library defines the timestamp
92 : * \li TIMESTAMP_MODE_DEFINED -- the user defined the timestamp
93 : *
94 : * \sa value::f_timestamp_mode
95 : */
96 :
97 : /** \var value::f_timestamp_mode
98 : * \brief The timestamp mode.
99 : *
100 : * This variable member defines how the timestamp value is used. It can
101 : * be set to any one of the timestamp_mode_t values.
102 : */
103 :
104 : /** \var value::f_timestamp
105 : * \brief The timestamp for this value.
106 : *
107 : * This variable member holds the timestamp of this value, however it is
108 : * used only if the value::f_timestamp_mode is set to
109 : * CASSANDRA_VALUE_TIMESTAMP. In all other cases it is ignored.
110 : */
111 :
112 : /** \brief Initialize a value object.
113 : *
114 : * This function initializes a row object to NULL. This is
115 : * an equivalent to a BINARY with a size of 0.
116 : */
117 3 : value::value( ) : cassvalue::Value() {}
118 0 : value::value(bool val) : cassvalue::Value(val) {}
119 0 : value::value(char val) : cassvalue::Value(val) {}
120 0 : value::value(signed char val) : cassvalue::Value(val) {}
121 0 : value::value(unsigned char val) : cassvalue::Value(val) {}
122 0 : value::value(int16_t val) : cassvalue::Value(val) {}
123 0 : value::value(uint16_t val) : cassvalue::Value(val) {}
124 0 : value::value(int32_t val) : cassvalue::Value(val) {}
125 0 : value::value(uint32_t val) : cassvalue::Value(val) {}
126 0 : value::value(int64_t val) : cassvalue::Value(val) {}
127 0 : value::value(uint64_t val) : cassvalue::Value(val) {}
128 0 : value::value(float val) : cassvalue::Value(val) {}
129 0 : value::value(double val) : cassvalue::Value(val) {}
130 0 : value::value(const QString& val) : cassvalue::Value(val) {}
131 0 : value::value(const QByteArray& val) : cassvalue::Value(val) {}
132 0 : value::value(const char *data, int size) : cassvalue::Value(data, size) {}
133 :
134 :
135 : /** \brief Compare this and rhs values for equality.
136 : *
137 : * This function returns true if this value and the rhs value are considered
138 : * equal.
139 : *
140 : * The equality takes the value buffer content, the TTL and the consistency
141 : * level in account. All three must be equal for the function to return true.
142 : *
143 : * \param[in] rhs The value to compare against this value.
144 : *
145 : * \return true if both values are considered equal, false otherwise.
146 : */
147 0 : bool value::operator == (const value& rhs)
148 : {
149 0 : if(f_ttl != rhs.f_ttl) {
150 0 : return false;
151 : }
152 0 : return static_cast<Value>(*this) == static_cast<Value>(rhs);
153 : }
154 :
155 : /** \brief Compare this and rhs values for inequality.
156 : *
157 : * This function returns true if this value and the rhs value are considered
158 : * inequal.
159 : *
160 : * The inequality takes the value buffer content, the TTL and the consistency
161 : * level in account. Any of the three must be inequal for the function to
162 : * return true.
163 : *
164 : * \param[in] rhs The value to compare against this value.
165 : *
166 : * \return true if both values are considered inequal, false otherwise.
167 : */
168 0 : bool value::operator != (const value& rhs)
169 : {
170 0 : if(f_ttl != rhs.f_ttl) {
171 0 : return true;
172 : }
173 0 : return static_cast<Value>(*this) != static_cast<Value>(rhs);
174 : }
175 :
176 : /** \brief Retrieve the current time to live value.
177 : *
178 : * This function returns the number of seconds defined as the lifetime of this
179 : * cell. The time to live is useful to create some temporary data. For example,
180 : * if you create an index of recent posts, you may want the older posts to
181 : * automatically be dropped after a given amount of time (i.e. 2 weeks.)
182 : *
183 : * This value can be set using the setTtl() function.
184 : *
185 : * \warning
186 : * The value is NOT read from an existing cell in the database. This is
187 : * because it slows down the SELECT quite a bit to read this value each
188 : * time even though 99.9% of the time it is not defined. If you really
189 : * need to have access, you can directly access the QCassandraQuery
190 : * system and send your own "SELECT TTL(value) FROM ...". Chances are,
191 : * you do not need to know how much longer a cell has to live. However,
192 : * if you read a cell to modify it and then save it back and that cell
193 : * may have a TTL, then it would be crusial to get that value. So far,
194 : * though, we only had to update with the standard TTL (i.e. if we update
195 : * a cell with a TTL, the TTL is reset back to the original, so something
196 : * that gets modified will last another full cycle instead of whatever
197 : * is left on it.)
198 : *
199 : * \return The number of seconds the cell will live.
200 : */
201 0 : int32_t value::ttl() const
202 : {
203 0 : return f_ttl;
204 : }
205 :
206 : /** \brief Set the time to live of this cell.
207 : *
208 : * Each cell can be defined as permanent (i.e. TTL not defined, or
209 : * set to TTL_PERMANENT) or can be defined as temporary.
210 : *
211 : * This value represents the number of seconds you want this value
212 : * to remain in the database.
213 : *
214 : * Note that if you want to keep values while running and then
215 : * lose them, you may want to consider creating a context in
216 : * memory only (i.e. a context on which you never call the
217 : * create() function.) Then the TTL is completely ignored, but
218 : * when you quit your application, the data is gone.
219 : *
220 : * \param[in] ttl The new time to live of this value.
221 : */
222 0 : void value::setTtl(int32_t ttl_val)
223 : {
224 0 : if(ttl_val < 0) {
225 0 : throw exception("the TTL value cannot be negative");
226 : }
227 :
228 0 : f_ttl = ttl_val;
229 0 : }
230 :
231 : /** \brief Retrieve the current consistency level of this value.
232 : *
233 : * This function returns the consistency level of this value. By default
234 : * it is set to one (CONSISTENCY_LEVEL_ONE.)
235 : *
236 : * The consistency level can be set using the setConsistencyLevel() function.
237 : *
238 : * \return The consistency level of this value.
239 : *
240 : * \sa setConsistencyLevel()
241 : * \sa cell::consistencyLevel()
242 : */
243 0 : consistency_level_t value::consistencyLevel() const
244 : {
245 0 : return f_consistency_level;
246 : }
247 :
248 : /** \brief Define the consistency level of this value.
249 : *
250 : * This function defines the consistency level of this value. The level is
251 : * defined as a static value in the value.
252 : *
253 : * Note that this value is mandatory so defining the right value is probably
254 : * often a good idea. The default is set to one which means the data is only
255 : * saved on that one cluster you are connected to. One of the best value is
256 : * QUORUM. The default can be changed in your libdbproxy object, set it with
257 : * your libdbproxy::setDefaultConsistencyLevel() function.
258 : *
259 : * The available values are:
260 : *
261 : * \li CONSISTENCY_LEVEL_ONE
262 : * \li CONSISTENCY_LEVEL_QUORUM
263 : * \li CONSISTENCY_LEVEL_LOCAL_QUORUM
264 : * \li CONSISTENCY_LEVEL_EACH_QUORUM
265 : * \li CONSISTENCY_LEVEL_ALL
266 : * \li CONSISTENCY_LEVEL_ANY
267 : * \li CONSISTENCY_LEVEL_TWO
268 : * \li CONSISTENCY_LEVEL_THREE
269 : *
270 : * The consistency level is probably better explained in the Cassandra
271 : * documentations that here.
272 : *
273 : * \param[in] level The new consistency level for this cell.
274 : *
275 : * \sa consistencyLevel()
276 : * \sa libdbproxy::setDefaultConsistencyLevel()
277 : * \sa cell::setConsistencyLevel()
278 : */
279 0 : void value::setConsistencyLevel(consistency_level_t level)
280 : {
281 : // we cannot use a switch because these are not really
282 : // constants (i.e. these are pointers to values); although
283 : // we could cast to the Cassandra definition and switch on
284 : // those...
285 0 : if(level != CONSISTENCY_LEVEL_DEFAULT
286 0 : && level != CONSISTENCY_LEVEL_ONE
287 0 : && level != CONSISTENCY_LEVEL_QUORUM
288 0 : && level != CONSISTENCY_LEVEL_LOCAL_QUORUM
289 0 : && level != CONSISTENCY_LEVEL_EACH_QUORUM
290 0 : && level != CONSISTENCY_LEVEL_ALL
291 0 : && level != CONSISTENCY_LEVEL_ANY
292 0 : && level != CONSISTENCY_LEVEL_TWO
293 0 : && level != CONSISTENCY_LEVEL_THREE) {
294 0 : throw exception("invalid consistency level");
295 : }
296 :
297 0 : f_consistency_level = level;
298 0 : }
299 :
300 :
301 6 : } // namespace libdbproxy
302 : // vim: ts=4 sw=4 et
|