LCOV - code coverage report
Current view: top level - libdbproxy - order_result.cpp (source / functions) Hit Total Coverage
Test: coverage.info Lines: 1 48 2.1 %
Date: 2019-12-15 17:13:15 Functions: 2 10 20.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :  * Text:
       3             :  *      libsnapwebsites/src/libdbprox/order_result.cpp
       4             :  *
       5             :  * Description:
       6             :  *      Handle receiving results from a CQL order sent to snapdbproxy.
       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             : //#pragma GCC push
      38             : //#pragma GCC diagnostic ignored "-Wundef"
      39             : //#include <sys/time.h>
      40             : //#pragma GCC pop
      41             : 
      42             : #include "libdbproxy/exception.h"
      43             : #include "libdbproxy/proxy.h"
      44             : #include "libdbproxy/value.h"
      45             : 
      46             : #include <QtCore>
      47             : 
      48             : #include <iostream>
      49             : #include <sstream>
      50             : 
      51             : #include <unistd.h>
      52             : 
      53             : 
      54             : namespace libdbproxy
      55             : {
      56             : 
      57             : 
      58             : /** \brief Check whether the result represents a success or not.
      59             :  *
      60             :  * When you send an order to the snapdbproxy, the result may be a
      61             :  * failure. If this flag is false, then the result represents an
      62             :  * error and not the otherwise expected results from the order
      63             :  * sent.
      64             :  *
      65             :  * \return true if the order was successful.
      66             :  */
      67           0 : bool order_result::succeeded() const
      68             : {
      69           0 :     return f_succeeded;
      70             : }
      71             : 
      72             : 
      73             : /** \brief Set whether the result was a success or not.
      74             :  *
      75             :  * This function can beused to set the succeeded flag to true
      76             :  * (i.e. the CQL order succeeded) or false (the CQL order
      77             :  * or something in between failed.)
      78             :  *
      79             :  * \param[in] success  The new value of the succeeded flag.
      80             :  */
      81           0 : void order_result::setSucceeded(bool success)
      82             : {
      83           0 :     f_succeeded = success;
      84           0 : }
      85             : 
      86             : 
      87             : /** \brief Retrieve the number of results present in this object.
      88             :  *
      89             :  * In general you want to use this function to know how far your index
      90             :  * can go while calling the result() function.
      91             :  *
      92             :  * \return The number of results available in this object. It may be zero.
      93             :  *
      94             :  * \sa result()
      95             :  */
      96           0 : size_t order_result::resultCount() const
      97             : {
      98           0 :     return f_result.size();
      99             : }
     100             : 
     101             : 
     102             : /** \brief Retrieve a result blob.
     103             :  *
     104             :  * This function is used to read back a resulting blob.
     105             :  *
     106             :  * \exception overflow_exception
     107             :  * The index must be between 0 and resultCount() - 1 or the
     108             :  * function raises this exception.
     109             :  *
     110             :  * \return A reference to a QByteArray representing this result data.
     111             :  *
     112             :  * \sa resultCount()
     113             :  */
     114           0 : QByteArray const & order_result::result(int index) const
     115             : {
     116           0 :     if(static_cast<size_t>(index) >= f_result.size())
     117             :     {
     118           0 :         throw overflow_exception("order_result::result() called with an index too large.");
     119             :     }
     120           0 :     return f_result[index];
     121             : }
     122             : 
     123             : 
     124             : /** \brief Add one result.
     125             :  *
     126             :  * This function adds one block of data representing a result.
     127             :  *
     128             :  * \param[in] data  A blob representing a result (i.e. maybe a cell).
     129             :  */
     130           0 : void order_result::addResult(QByteArray const & data)
     131             : {
     132           0 :     f_result.push_back(data);
     133           0 : }
     134             : 
     135             : 
     136             : /** \brief Encode a set of results to be sent back to the client.
     137             :  *
     138             :  * This function is used by the snapdbproxy daemon to encode the results
     139             :  * and sent them to the client.
     140             :  *
     141             :  * \return A blob that the snapdbproxy can send to the client.
     142             :  */
     143           0 : QByteArray order_result::encodeResult() const
     144             : {
     145           0 :     if(f_result.size() > 65535)
     146             :     {
     147           0 :         throw exception("result has too make values, limit is 64Kb - 1 value (a maximum of about 20,000 rows in one go)");
     148             :     }
     149             : 
     150             :     // the expected size of the final buffer, to avoid realloc() calls,
     151             :     // possibly many such calls, we use the final size in a reserve()
     152             :     // before adding the data
     153             :     //
     154           0 :     uint32_t expected_size(4 + 4 + 2);
     155           0 :     for(auto r : f_result)
     156             :     {
     157           0 :         expected_size += 4 + r.size();
     158             :     }
     159           0 :     QCassandraEncoder encoder(expected_size);
     160             : 
     161             :     // success or failure is encoded in the 4 letter we first send
     162             :     // when replying to the client
     163             :     //
     164           0 :     if(f_succeeded)
     165             :     {
     166           0 :         encoder.appendSignedCharValue('S');
     167           0 :         encoder.appendSignedCharValue('U');
     168           0 :         encoder.appendSignedCharValue('C');
     169           0 :         encoder.appendSignedCharValue('S');
     170             :     }
     171             :     else
     172             :     {
     173           0 :         encoder.appendSignedCharValue('E');
     174           0 :         encoder.appendSignedCharValue('R');
     175           0 :         encoder.appendSignedCharValue('O');
     176           0 :         encoder.appendSignedCharValue('R');
     177             :     }
     178             : 
     179             :     // we already have the size, contrary to the order, this size does
     180             :     // not vary depending on certain flags, so we can directly save the
     181             :     // correct value at once
     182             :     //
     183           0 :     encoder.appendUInt32Value(expected_size - 8);
     184             : 
     185             :     // save the number of result buffers
     186             :     //
     187             :     // then save each result with its size followed by its data
     188             :     //
     189           0 :     encoder.appendUInt16Value(f_result.size());
     190           0 :     for(auto r : f_result)
     191             :     {
     192           0 :         encoder.appendBinaryValue(r);
     193             :     }
     194             : 
     195             : #ifdef _DEBUG
     196           0 :     if(encoder.size() != expected_size)
     197             :     {
     198           0 :         throw logic_exception( "order_result::encodeResult(): the expected and encoded sizes do not match..." );
     199             :     }
     200             : #endif
     201             : 
     202           0 :     return encoder.result();
     203             : }
     204             : 
     205             : 
     206             : /** \brief Decode a set of result buffers.
     207             :  *
     208             :  * This function is the opposite of the encodeResult() function. It is
     209             :  * used by the client to decode results sent to it by the snapdbproxy
     210             :  * daemon.
     211             :  *
     212             :  * \exception exception
     213             :  * If the buffer is of the wrong size, the reading of the data will
     214             :  * fail raising this exception. We may later add a try/catch within
     215             :  * this function to return false instead. Yet, if the order is wrong
     216             :  * we are going to have a hard time reading the next buffer. Plus,
     217             :  * if things work as expected, synchronizing the input should never
     218             :  * be required.
     219             :  *
     220             :  * \param[in] encoded_result  A pointer to the raw data just read from
     221             :  *                            the socket.
     222             :  * \param[in] size  The number of bytes in encoded_result.
     223             :  *
     224             :  * \return true if the function worked successfully.
     225             :  */
     226           0 : bool order_result::decodeResult(unsigned char const * encoded_result, size_t size)
     227             : {
     228             :     // WARNING: Here I use the horrible fromRawData() function which does
     229             :     //          NOT copy the data to be checked here. However, that gives
     230             :     //          me full access to the value functions against
     231             :     //          QByteArray which is practical.
     232             :     //
     233             :     //          Just make sure to only use that 'decoder' buffer in this
     234             :     //          function. Do not pass it anywhere, or worst, return it!
     235             :     //
     236           0 :     QCassandraDecoder const decoder(QByteArray::fromRawData(reinterpret_cast<char const *>(encoded_result), size));
     237             : 
     238             :     // read the number of parameters that were included
     239             :     // this may be zero
     240             :     //
     241           0 :     size_t const result_count(decoder.uint16Value());
     242           0 :     for(size_t idx(0); idx < result_count; ++idx)
     243             :     {
     244             :         // read this parameter data and immediately push it in the
     245             :         // list of parameters
     246             :         //
     247           0 :         f_result.push_back(decoder.binaryValue());
     248             :     }
     249             : 
     250           0 :     return true;
     251             : }
     252             : 
     253             : 
     254           0 : void order_result::swap(order_result& rhs)
     255             : {
     256           0 :     std::swap(f_succeeded, rhs.f_succeeded);
     257           0 :     f_result.swap(rhs.f_result);
     258           0 : }
     259             : 
     260             : 
     261             : 
     262           6 : } // namespace libdbproxy
     263             : // vim: ts=4 sw=4 et

Generated by: LCOV version 1.13