LCOV - code coverage report
Current view: top level - libdbproxy - cell.cpp (source / functions) Hit Total Coverage
Test: coverage.info Lines: 1 82 1.2 %
Date: 2019-12-15 17:13:15 Functions: 2 21 9.5 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :  * Text:
       3             :  *      libsnapwebsites/src/libdbproxy/cell.cpp
       4             :  *
       5             :  * Description:
       6             :  *      Handling of cell. There is no class representing a row in Cassandra.
       7             :  *      A row is just a key. We have this object to allow for our C++ array
       8             :  *      syntax to access the Cassandra data.
       9             :  *
      10             :  * Documentation:
      11             :  *      See each function below.
      12             :  *
      13             :  * License:
      14             :  *      Copyright (c) 2011-2019  Made to Order Software Corp.  All Rights Reserved
      15             :  * 
      16             :  *      https://snapwebsites.org/
      17             :  *      contact@m2osw.com
      18             :  * 
      19             :  *      Permission is hereby granted, free of charge, to any person obtaining a
      20             :  *      copy of this software and associated documentation files (the
      21             :  *      "Software"), to deal in the Software without restriction, including
      22             :  *      without limitation the rights to use, copy, modify, merge, publish,
      23             :  *      distribute, sublicense, and/or sell copies of the Software, and to
      24             :  *      permit persons to whom the Software is furnished to do so, subject to
      25             :  *      the following conditions:
      26             :  *
      27             :  *      The above copyright notice and this permission notice shall be included
      28             :  *      in all copies or substantial portions of the Software.
      29             :  *
      30             :  *      THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
      31             :  *      OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
      32             :  *      MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
      33             :  *      IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
      34             :  *      CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
      35             :  *      TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
      36             :  *      SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
      37             :  */
      38             : 
      39             : #include "libdbproxy/cell.h"
      40             : #include "libdbproxy/exception.h"
      41             : #include "libdbproxy/row.h"
      42             : 
      43             : #include <stdexcept>
      44             : #include <iostream>
      45             : 
      46             : namespace libdbproxy
      47             : {
      48             : 
      49             : 
      50             : /** \class cell
      51             :  * \brief A cell holds a name and value pair.
      52             :  *
      53             :  * A cell represents the value of a column in a row. The name of a cell
      54             :  * is the name of the corresponding column. The value is the data saved
      55             :  * in the Cassandra database.
      56             :  *
      57             :  * The name of the cell is kept as a binary key (it can be binary.) It
      58             :  * is limited it length to a little under 64Kb.
      59             :  *
      60             :  * Cells are loaded from the Cassandra database whenever the user
      61             :  * reads its value. Actually, the value is marked as cached once read
      62             :  * the first time. Each further access is done using the memory value
      63             :  * thus avoiding accessing the Cassandra server each time. Note that
      64             :  * may have some side effects if your process runs for a long time.
      65             :  * Use the cell, row, table, or context clearCache() functions to
      66             :  * palliate to this problem.
      67             :  *
      68             :  * Cells are saved to the Cassandra database whenever the user overwrite
      69             :  * its current value. In this case the cache is updated but the data is
      70             :  * non the less written to Cassandra except if the value was not modified
      71             :  * and the cache was marked as active.
      72             :  */
      73             : 
      74             : 
      75             : /** \var cell::f_row
      76             :  * \brief A pointer back to the row onwer.
      77             :  *
      78             :  * This bare pointer back to the row owner is used whenever the value is
      79             :  * read (and not yet cached) or written. This way we can send the data
      80             :  * back to the Cassandra database.
      81             :  */
      82             : 
      83             : 
      84             : /** \var cell::f_key
      85             :  * \brief The column name of this cell.
      86             :  *
      87             :  * This cell has a name paired with its value. This is the name part.
      88             :  * The key is saved in binary form only.
      89             :  */
      90             : 
      91             : 
      92             : /** \var cell::f_cached
      93             :  * \brief Whether a cell is a cache.
      94             :  *
      95             :  * This flag mark the cell as being a cache for the value defined in it.
      96             :  * By default a cell is marked as not caching anything. It becomes a cached
      97             :  * value once the value was saved in the Cassandra database or read from
      98             :  * the Cassandra system.
      99             :  *
     100             :  * Note however that the cell is no aware of whether the table is a memory
     101             :  * or Cassandra table. As such, the cache flag may be lying.
     102             :  */
     103             : 
     104             : 
     105             : /** \var cell::f_value
     106             :  * \brief A cell value.
     107             :  *
     108             :  * This member represents the value of this cell.
     109             :  *
     110             :  * Note that by default when you copy a cell value the value buffer itself
     111             :  * is not copied, instead it is shared. This is quite useful to avoid many
     112             :  * memory copies.
     113             :  */
     114             : 
     115             : 
     116             : /** \brief Initialize a row object.
     117             :  *
     118             :  * This function initializes a cell object. You must specify the
     119             :  * key of the column.
     120             :  *
     121             :  * In this case, the key of the cell is a binary buffer of data. Remember
     122             :  * however that the column names that are not ASCII may cause problems
     123             :  * (i.e. with CQL and the Cassandra CLI.)
     124             :  *
     125             :  * A cell is set to the NULL value by default.
     126             :  *
     127             :  * \exception exception
     128             :  * The key of the column cannot be empty or more than 64Kb. If that happens,
     129             :  * this exception is raised.
     130             :  *
     131             :  * \param[in] row  The parent row of this cell.
     132             :  * \param[in] column_key  The binary key of this cell.
     133             :  */
     134           0 : cell::cell(row::pointer_t row, const QByteArray& column_key)
     135             :     : f_row(row)
     136           0 :     , f_key(column_key)
     137             :     //, f_value() -- auto-init to "NULL" (nullValue() == true)
     138             : {
     139           0 :     if(f_key.size() == 0) {
     140           0 :         throw exception("the cell binary column key cannot be empty");
     141             :     }
     142           0 :     if(f_key.size() > 65535) {
     143           0 :         throw exception("the cell binary column key is more than 64Kb");
     144             :     }
     145           0 : }
     146             : 
     147             : 
     148             : /** \brief Clean up the cell object.
     149             :  *
     150             :  * This function ensures that all resources allocated by the
     151             :  * cell are released.
     152             :  */
     153           0 : cell::~cell()
     154             : {
     155           0 : }
     156             : 
     157             : 
     158             : /** \brief Retrieve the name of the column.
     159             :  *
     160             :  * This function returns the name of the column as specified in the
     161             :  * constructor.
     162             :  *
     163             :  * The name cannot be changed.
     164             :  *
     165             :  * Note that if you created the cell with a binary key (i.e. a
     166             :  * QByteArray parameter) then you CANNOT retrieve the column name.
     167             :  * Instead, use the columnKey() function.
     168             :  *
     169             :  * \exception exception
     170             :  * This function raises an exception if the cell was created with
     171             :  * a binary key.
     172             :  *
     173             :  * \return A string with the column name.
     174             :  *
     175             :  * \sa rowKey()
     176             :  */
     177           0 : QString cell::columnName() const
     178             : {
     179           0 :     return QString::fromUtf8(f_key.data());
     180             : }
     181             : 
     182             : 
     183             : /** \brief Retrieve the column key.
     184             :  *
     185             :  * This function returns the column key of this cell. The key is a binary
     186             :  * buffer of data. This function works whether the cell was created with a
     187             :  * name or a key.
     188             :  *
     189             :  * Note that when creating a cell with a binary key, you cannot retrieve
     190             :  * it using the columnName() function.
     191             :  *
     192             :  * \return A buffer of data representing the column key.
     193             :  *
     194             :  * \sa columnName()
     195             :  */
     196           0 : const QByteArray& cell::columnKey() const
     197             : {
     198           0 :     return f_key;
     199             : }
     200             : 
     201             : 
     202             : /** \brief Retrieve the cell value.
     203             :  *
     204             :  * This function is used to retrieve the cell value.
     205             :  *
     206             :  * Note that the value gets cached. That means if you call the function
     207             :  * again, then the same value will be returned (although the setValue()
     208             :  * can be used to change the cached value.)
     209             :  *
     210             :  * To reset the cache, use the clearCache() function.
     211             :  *
     212             :  * \return The current value defined in the cell
     213             :  *
     214             :  * \sa clearCache()
     215             :  * \sa setValue()
     216             :  */
     217           0 : const value& cell::getValue() const
     218             : {
     219           0 :     if(!f_cached)
     220             :     {
     221           0 :         parentRow()->getValue( f_key, const_cast<value&>(f_value) );
     222           0 :         f_cached = true;
     223             :     }
     224           0 :     return f_value;
     225             : }
     226             : 
     227             : 
     228             : /** \brief Change the value.
     229             :  *
     230             :  * This function changes the value of this cell. If the cell is currently
     231             :  * attached to a table in the Cassandra server, then it is written to the
     232             :  * server except if the value does not change.
     233             :  *
     234             :  * In other words, we avoid sending the same value to the Cassandra server
     235             :  * over and over again. To force a write to the Cassandra server, call
     236             :  * the clearCache() function before the setValue() function.
     237             :  *
     238             :  * \todo
     239             :  * If setting a counter, "value" is save in the cache as is. This means
     240             :  * the value may be an integer of any size instead of being a 64 bit
     241             :  * integer.
     242             :  *
     243             :  * \note
     244             :  * When the values are compared, the timestamp is ignored.
     245             :  *
     246             :  * \param[in] value  The new value for this cell.
     247             :  */
     248           0 : void cell::setValue(const value& val)
     249             : {
     250           0 :     if(!f_cached || f_value != val)
     251             :     {
     252             :         // TODO: if the cell represents a counter, it should be resized
     253             :         //       to a 64 bit value to work in all places
     254           0 :         f_value = val;
     255           0 :         parentRow()->insertValue(f_key, f_value);
     256           0 :         f_cached = true;
     257             :     }
     258           0 : }
     259             : 
     260             : 
     261             : /** \brief Change the value as if read from Cassandra.
     262             :  *
     263             :  * This function assigns the specified value as if it had been read from
     264             :  * Cassandra. This way the Row can set a value it just read and avoid
     265             :  * another read() (or worse, a write!)
     266             :  *
     267             :  * The value is marked as cached meaning that it was read or written to
     268             :  * the Cassandra database.
     269             :  *
     270             :  * This generally happens when you call value(). There is a simplified
     271             :  * view of what happens (without the row, table,
     272             :  * libdbproxy, and Thrift shown):
     273             :  *
     274             :  * \msc
     275             :  * width=900;
     276             :  * cell,context,QCassandraPrivate,Cassandra;
     277             :  * cell:>context [label="getValue()"];
     278             :  * context=>QCassandraPrivate [label="getValue()"];
     279             :  * QCassandraPrivate->Cassandra [label="get()"];
     280             :  * ...;
     281             :  * Cassandra->QCassandraPrivate [label="return"];
     282             :  * |||;
     283             :  * cell abox QCassandraPrivate [label="if value returned from last get()"];
     284             :  * QCassandraPrivate=>cell [label="getValue()", linecolor="red"];
     285             :  * cell>>QCassandraPrivate [label="return"];
     286             :  * cell abox QCassandraPrivate [label="end if"];
     287             :  * |||;
     288             :  * QCassandraPrivate>>context [label="return"];
     289             :  * context:>cell [label="return"];
     290             :  * \endmsc
     291             :  *
     292             :  * Note that similar calls happen whenever you call row::readCells()
     293             :  * and table::readRows().
     294             :  *
     295             :  * \param[in] value  The new value to assign to this cell.
     296             :  */
     297           0 : void cell::assignValue(const value& val)
     298             : {
     299           0 :     f_value = val;
     300           0 :     f_cached = true;
     301           0 : }
     302             : 
     303             : 
     304             : /** \brief Set the cell value.
     305             :  *
     306             :  * This function is called whenever you write a value to the Cassandra
     307             :  * database using the array syntax such as:
     308             :  *
     309             :  * \code
     310             :  * cluster["context"]["table"]["row"]["column"] = value;
     311             :  * \endcode
     312             :  *
     313             :  * Note that the value gets cached. That means if you call a getValue()
     314             :  * function, you get a copy of the value you saved here.
     315             :  *
     316             :  * To reset the cache, use the clearCache() function.
     317             :  *
     318             :  * \param[in] value  The new cell value.
     319             :  *
     320             :  * \return A reference to this cell.
     321             :  *
     322             :  * \sa clearCache()
     323             :  * \sa setValue()
     324             :  */
     325           0 : cell& cell::operator = (const value& val)
     326             : {
     327           0 :     setValue(val);
     328           0 :     return *this;
     329             : }
     330             : 
     331             : 
     332             : /** \brief Retrieve the cell value.
     333             :  *
     334             :  * This function is called whenever you read a value from the Cassandra
     335             :  * database using the array syntax such as:
     336             :  *
     337             :  * \code
     338             :  * value value = cluster["context"]["table"]["row"]["column"];
     339             :  * \endcode
     340             :  *
     341             :  * Note that the value gets cached. That means if you call the function
     342             :  * again, then the same value will be returned (although the setValue()
     343             :  * can be used to change the cached value.)
     344             :  *
     345             :  * To reset the cache, use the clearCache() function.
     346             :  *
     347             :  * \return The current value defined in the cell
     348             :  *
     349             :  * \sa clearCache()
     350             :  * \sa setValue()
     351             :  */
     352           0 : cell::operator value () const
     353             : {
     354           0 :     return value();
     355             : }
     356             : 
     357             : 
     358             : /** \brief Add a value to a counter.
     359             :  *
     360             :  * This function is used to add a value to a counter.
     361             :  *
     362             :  * The current cell value is expected to be 8 bytes, although we support
     363             :  * 1, 2, 4, and 8 byte integers. The result is saved back in this cell as
     364             :  * a 64 bits value (8 bytes).
     365             :  *
     366             :  * \param[in] value  The value to add to the counter. It may be negative.
     367             :  *
     368             :  * \return The expected value defined in the cell.
     369             :  */
     370           0 : void cell::add(int64_t val)
     371             : {
     372             :     // if cached, we update the value in memory as it is expected to be
     373           0 :     if(!f_value.nullValue())
     374             :     {
     375             :         // if the value is not defined, we'd have to read it before we can
     376             :         // increment it in memory; for this reason we don't do it at this point
     377           0 :         int64_t r(0);
     378           0 :         switch(f_value.size())
     379             :         {
     380           0 :         case 8:
     381           0 :             r = f_value.int64Value() + val;
     382           0 :             break;
     383             : 
     384           0 :         case 4:
     385           0 :             r = f_value.int32Value() + val;
     386           0 :             break;
     387             : 
     388           0 :         case 2:
     389           0 :             r = f_value.int16Value() + val;
     390           0 :             break;
     391             : 
     392           0 :         case 1:
     393           0 :             r = f_value.signedCharValue() + val;
     394           0 :             break;
     395             : 
     396           0 :         default:
     397           0 :             throw exception("a counter cell is expected to be an 8, 16, 32, or 64 bit value");
     398             : 
     399             :         }
     400           0 :         f_value.setInt64Value(r);
     401           0 :         f_cached = true;
     402             :     }
     403             : 
     404           0 :     parentRow()->insertValue( f_key, f_value );
     405           0 : }
     406             : 
     407             : 
     408             : /** \brief Add to a counter.
     409             :  *
     410             :  * This operator adds a value to a counter.
     411             :  *
     412             :  * \code
     413             :  * cluster["context"]["table"]["row"]["column"] += 5;
     414             :  * \endcode
     415             :  *
     416             :  * Note that the resulting value gets cached. That means if reading the value
     417             :  * after this call, the cached value is returned. To reset the cache, use
     418             :  * the clearCache() function.
     419             :  *
     420             :  * \warning
     421             :  * The value in the cell after this call is an approximation of the counter
     422             :  * value. The operator does not read the most current value.
     423             :  *
     424             :  * \param[in] value  The value to add to the existing value of this cell.
     425             :  *
     426             :  * \return A reference to this Cassandra cell.
     427             :  *
     428             :  * \sa clearCache()
     429             :  * \sa add()
     430             :  */
     431           0 : cell& cell::operator += (int64_t val)
     432             : {
     433           0 :     add(val);
     434           0 :     return *this;
     435             : }
     436             : 
     437             : 
     438             : /** \brief Increment a counter.
     439             :  *
     440             :  * This operator is used to add one to a counter.
     441             :  *
     442             :  * \code
     443             :  * ++cluster["context"]["table"]["row"]["column"];
     444             :  * \endcode
     445             :  *
     446             :  * \return A reference to this Cassandra cell.
     447             :  *
     448             :  * \sa add()
     449             :  * \sa operator + ()
     450             :  */
     451           0 : cell& cell::operator ++ ()
     452             : {
     453           0 :     add(1);
     454           0 :     return *this;
     455             : }
     456             : 
     457             : 
     458             : /** \brief Increment a counter.
     459             :  *
     460             :  * This operator is used to add one to a counter.
     461             :  *
     462             :  * \code
     463             :  * cluster["context"]["table"]["row"]["column"]++;
     464             :  * \endcode
     465             :  *
     466             :  * \warning
     467             :  * Note that this operator returns this cell and not
     468             :  * a copy because we cannot create a copy of the cell.
     469             :  *
     470             :  * \return A reference to this Cassandra cell.
     471             :  *
     472             :  * \sa add()
     473             :  * \sa operator + ()
     474             :  */
     475             : //cell& cell::operator ++ (int)
     476             : //{
     477             : //    add(1);
     478             : //    return *this;
     479             : //}
     480             : 
     481             : 
     482             : /** \brief Subtract from a counter.
     483             :  *
     484             :  * This operator subtract a value from a counter.
     485             :  *
     486             :  * \code
     487             :  * cluster["context"]["table"]["row"]["column"] -= 9;
     488             :  * \endcode
     489             :  *
     490             :  * Note that the resulting value gets cached. That means if reading the value
     491             :  * after this call, the cached value is returned. To reset the cache, use
     492             :  * the clearCache() function.
     493             :  *
     494             :  * \warning
     495             :  * The value in the cell after this call is an approximation of the counter
     496             :  * value. The operator does not read the most current value.
     497             :  *
     498             :  * \param[in] value  The value to subtract from the current content of the cell.
     499             :  *
     500             :  * \return A reference to this Cassandra cell.
     501             :  *
     502             :  * \sa clearCache()
     503             :  * \sa add()
     504             :  */
     505           0 : cell& cell::operator -= (int64_t val)
     506             : {
     507           0 :     add(-val);
     508           0 :     return *this;
     509             : }
     510             : 
     511             : 
     512             : /** \brief Decrement a counter.
     513             :  *
     514             :  * This operator is used to subtract one from a counter.
     515             :  *
     516             :  * \code
     517             :  * --cluster["context"]["table"]["row"]["column"];
     518             :  * \endcode
     519             :  *
     520             :  * \return A reference to this Cassandra cell.
     521             :  *
     522             :  * \sa add()
     523             :  * \sa operator - ()
     524             :  */
     525           0 : cell& cell::operator -- ()
     526             : {
     527           0 :     add(-1);
     528           0 :     return *this;
     529             : }
     530             : 
     531             : 
     532             : /** \brief Decrement a counter.
     533             :  *
     534             :  * This operator is used to subtract one from a counter.
     535             :  *
     536             :  * \code
     537             :  * cluster["context"]["table"]["row"]["column"]--;
     538             :  * \endcode
     539             :  *
     540             :  * \warning
     541             :  * Note that this operator returns this cell and not
     542             :  * a copy because we cannot create a copy of the cell.
     543             :  *
     544             :  * \return A reference to this Cassandra cell.
     545             :  *
     546             :  * \sa add()
     547             :  * \sa operator - ()
     548             :  */
     549             : //cell& cell::operator -- (int)
     550             : //{
     551             : //    add(-1);
     552             : //    return *this;
     553             : //}
     554             : 
     555             : 
     556             : /** \brief Retrieve the current consistency level of this value.
     557             :  *
     558             :  * This function returns the consistency level of this value. By default
     559             :  * it is set to one (CONSISTENCY_LEVEL_ONE.)
     560             :  *
     561             :  * The consistency level can be set using the setConsistencyLevel() function.
     562             :  *
     563             :  * \return The consistency level of this value.
     564             :  *
     565             :  * \sa setConsistencyLevel()
     566             :  * \sa value::consistencyLevel()
     567             :  */
     568           0 : consistency_level_t cell::consistencyLevel() const
     569             : {
     570           0 :     return f_value.consistencyLevel();
     571             : }
     572             : 
     573             : 
     574             : /** \brief Define the consistency level of this cell.
     575             :  *
     576             :  * This function sets the consistency of the f_value field of this cell.
     577             :  * This can be used to ensure the proper consistency on a read. In case
     578             :  * of a write, the consistency is always taken from the input value
     579             :  * parameter. For a read this is the only way to specify the consistency.
     580             :  *
     581             :  * By default, the consistency level is set to CONSISTENCY_LEVEL_DEFAULT
     582             :  * which means: use the consistency level defined in the libdbproxy object
     583             :  * linked with this cell. It is possible to set the consistency level
     584             :  * back to CONSISTENCY_LEVEL_DEFAULT.
     585             :  *
     586             :  * \param[in] level  The new consistency level for this cell next read.
     587             :  *
     588             :  * \sa consistencyLevel()
     589             :  * \sa value::setConsistencyLevel()
     590             :  */
     591           0 : void cell::setConsistencyLevel(consistency_level_t level)
     592             : {
     593           0 :     f_value.setConsistencyLevel(level);
     594           0 : }
     595             : 
     596             : 
     597             : /** \brief The value of a cell is automatically cached in memory.
     598             :  *
     599             :  * This function can be used to mark that the currently cached
     600             :  * value need to be reset on the next call to the value
     601             :  * casting operator.
     602             :  *
     603             :  * However, note that the data of the cell is NOT released by this
     604             :  * call. To release the data, look into clearing the row cache
     605             :  * instead.
     606             :  *
     607             :  * \note
     608             :  * Setting a cell to the null value (i.e. value.setNullValue()) will
     609             :  * clear the data in the Cassandra database too. So don't use that
     610             :  * function to clear the data from memory!
     611             :  *
     612             :  * \sa row::clearCache()
     613             :  */
     614           0 : void cell::clearCache()
     615             : {
     616           0 :     f_cached = false;
     617           0 :     f_value.setNullValue();
     618           0 : }
     619             : 
     620             : 
     621             : #if 0
     622             : /** \brief Retrieve the current timestamp of this cell value.
     623             :  *
     624             :  * This function returns the timestamp of the value variable member defined
     625             :  * in the cell. This value may be incorrect if the value wasn't read from
     626             :  * the Cassandra database or was never set with setTimestamp().
     627             :  *
     628             :  * \return The timestamp 64bit value.
     629             :  *
     630             :  * \sa setTimestamp()
     631             :  * \sa value::timestamp()
     632             :  */
     633             : int64_t cell::timestamp() const
     634             : {
     635             :     return f_value.timestamp();
     636             : }
     637             : 
     638             : /** \brief Define your own timestamp for this cell value.
     639             :  *
     640             :  * Set the timestamp of the value variable member of this cell.
     641             :  *
     642             :  * \param[in] timestamp  The time used to mark this value.
     643             :  *
     644             :  * \sa timestamp()
     645             :  * \sa value::setTimestamp()
     646             :  */
     647             : void cell::setTimestamp(int64_t val)
     648             : {
     649             :     f_value.setTimestamp(val);
     650             : }
     651             : #endif
     652             : 
     653             : 
     654             : /** \brief Get the pointer to the parent object.
     655             :  *
     656             :  * \return Shared pointer to the cassandra object.
     657             :  */
     658           0 : row::pointer_t cell::parentRow() const
     659             : {
     660           0 :     row::pointer_t row(f_row.lock());
     661           0 :     if(row == nullptr)
     662             :     {
     663           0 :         throw exception("this cell was dropped and is not attached to a row anymore");
     664             :     }
     665             : 
     666           0 :     return row;
     667             : }
     668             : 
     669             : 
     670           6 : } // namespace libdbproxy
     671             : // vim: ts=4 sw=4 et

Generated by: LCOV version 1.13