libQtCassandra 0.3.2

QCassandraContext.cpp

Go to the documentation of this file.
00001 /*
00002  * Text:
00003  *      QCassandraContext.cpp
00004  *
00005  * Description:
00006  *      Handling of the cassandra::KsDef.
00007  *
00008  * Documentation:
00009  *      See each function below.
00010  *
00011  * License:
00012  *      Copyright (c) 2011 Made to Order Software Corp.
00013  * 
00014  *      http://snapwebsites.org/
00015  *      contact@m2osw.com
00016  * 
00017  *      Permission is hereby granted, free of charge, to any person obtaining a
00018  *      copy of this software and associated documentation files (the
00019  *      "Software"), to deal in the Software without restriction, including
00020  *      without limitation the rights to use, copy, modify, merge, publish,
00021  *      distribute, sublicense, and/or sell copies of the Software, and to
00022  *      permit persons to whom the Software is furnished to do so, subject to
00023  *      the following conditions:
00024  *
00025  *      The above copyright notice and this permission notice shall be included
00026  *      in all copies or substantial portions of the Software.
00027  *
00028  *      THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
00029  *      OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
00030  *      MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
00031  *      IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
00032  *      CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
00033  *      TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
00034  *      SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
00035  */
00036 
00037 //#include "QtCassandra/QCassandraContext.h"
00038 #include "QCassandraPrivate.h"
00039 #include <stdexcept>
00040 
00041 #include <QtCore/QDebug>
00042 #include <QtCore/QRegExp>
00043 
00044 
00045 namespace QtCassandra
00046 {
00047 
00121 class QCassandraContextPrivate : public org::apache::cassandra::KsDef {};
00122 
00123 
00124 
00125 
00126 
00127 
00128 
00149 QCassandraContext::QCassandraContext(QCassandra *cassandra, const QString& context_name)
00150     : f_private(new QCassandraContextPrivate),
00151       f_cassandra(cassandra)
00152       //f_options() -- auto-init
00153       //f_tables() -- auto-init
00154 {
00155     // verify the name here (faster than waiting for the server and good documentation)
00156     QRegExp re("[A-Za-z][A-Za-z0-9_]*");
00157     if(!re.exactMatch(context_name)) {
00158         throw std::runtime_error("invalid context name (does not match [A-Za-z][A-Za-z0-9_]*)");
00159     }
00160 
00161     // we save the name and at this point we prevent it from being changed.
00162     f_private->__set_name(context_name.toUtf8().data());
00163 }
00164 
00170 QCassandraContext::~QCassandraContext()
00171 {
00172 }
00173 
00183 QString QCassandraContext::contextName() const
00184 {
00185     return f_private->name.c_str();
00186 }
00187 
00196 void QCassandraContext::setStrategyClass(const QString& strategy_class)
00197 {
00198     f_private->__set_strategy_class(strategy_class.toUtf8().data());
00199 }
00200 
00209 QString QCassandraContext::strategyClass() const
00210 {
00211     return f_private->strategy_class.c_str();
00212 }
00213 
00224 void QCassandraContext::setDescriptionOptions(const QCassandraContextOptions& options)
00225 {
00226     f_options = options;
00227 }
00228 
00242 const QCassandraContext::QCassandraContextOptions& QCassandraContext::descriptionOptions() const
00243 {
00244     return f_options;
00245 }
00246 
00254 void QCassandraContext::setDescriptionOption(const QString& option, const QString& value)
00255 {
00256     f_options[option] = value;
00257 }
00258 
00268 QString QCassandraContext::descriptionOption(const QString& option) const
00269 {
00270     return f_options[option];
00271 }
00272 
00285 QSharedPointer<QCassandraTable> QCassandraContext::table(const QString& table_name)
00286 {
00287     // table already exists?
00288     QCassandraTables::iterator ti(f_tables.find(table_name));
00289     if(ti != f_tables.end()) {
00290         return ti.value();
00291     }
00292 
00293     // this is a new table, allocate it
00294     QSharedPointer<QCassandraTable> t(new QCassandraTable(this, table_name));
00295     f_tables.insert(table_name, t);
00296     return t;
00297 }
00298 
00308 const QCassandraTables& QCassandraContext::tables() const
00309 {
00310     return f_tables;
00311 }
00312 
00323 QSharedPointer<QCassandraTable> QCassandraContext::findTable(const QString& table_name) const
00324 {
00325     QCassandraTables::const_iterator it(f_tables.find(table_name));
00326     if(it == f_tables.end()) {
00327         QSharedPointer<QCassandraTable> null;
00328         return null;
00329     }
00330     return *it;
00331 }
00332 
00351 QCassandraTable& QCassandraContext::operator [] (const QString& table_name)
00352 {
00353     QCassandraTable *table = findTable(table_name).data();
00354     if(table == NULL) {
00355         throw std::runtime_error("named table was not found, cannot return a reference");
00356     }
00357 
00358     return *table;
00359 }
00360 
00379 const QCassandraTable& QCassandraContext::operator [] (const QString& table_name) const
00380 {
00381     const QCassandraTable *table = findTable(table_name).data();
00382     if(table == NULL) {
00383         throw std::runtime_error("named table was not found, cannot return a reference");
00384     }
00385 
00386     return *table;
00387 }
00388 
00395 void QCassandraContext::setReplicationFactor(int32_t factor)
00396 {
00397     f_private->__set_replication_factor(factor);
00398 }
00399 
00407 void QCassandraContext::unsetReplicationFactor()
00408 {
00409     f_private->__isset.replication_factor = false;
00410 }
00411 
00419 int32_t QCassandraContext::replicationFactor() const
00420 {
00421     return f_private->replication_factor;
00422 }
00423 
00432 void QCassandraContext::setDurableWrites(bool durable_writes)
00433 {
00434     f_private->__set_durable_writes(durable_writes);
00435 }
00436 
00443 void QCassandraContext::unsetDurableWrites()
00444 {
00445     f_private->__isset.durable_writes = false;
00446 }
00447 
00455 bool QCassandraContext::durableWrites() const
00456 {
00457     return f_private->durable_writes;
00458 }
00459 
00466 void QCassandraContext::parseContextDefinition(const void *data)
00467 {
00468     const org::apache::cassandra::KsDef *ks = reinterpret_cast<const org::apache::cassandra::KsDef *>(data);
00469 
00470     // name
00471     if(ks->name != f_private->name) {
00472         // what do we do here?
00473         throw std::logic_error("KsDef and QCassandraContextPrivate names don't match");
00474     }
00475 
00476     // strategy class
00477     f_private->__set_strategy_class(ks->strategy_class);
00478 
00479     // replication factor
00480     if(ks->__isset.replication_factor) {
00481         f_private->__set_replication_factor(ks->replication_factor);
00482     }
00483     else {
00484         f_private->__isset.replication_factor = false;
00485     }
00486 
00487     // durable writes
00488     if(ks->__isset.durable_writes) {
00489         f_private->__set_durable_writes(ks->durable_writes);
00490     }
00491     else {
00492         f_private->__isset.durable_writes = false;
00493     }
00494 
00495     // the options is an array that we keep on our end
00496     f_options.clear();
00497     if(ks->__isset.strategy_options) {
00498         for(std::map<std::string, std::string>::const_iterator
00499                     o = ks->strategy_options.begin();
00500                     o != ks->strategy_options.end();
00501                     ++o) {
00502             // TBD: can option strings include binary data?
00503             f_options.insert(o->first.c_str(), o->second.c_str());
00504         }
00505     }
00506 
00507     // table definitions (CfDef, column family definitions)
00508     f_tables.clear();
00509     for(std::vector<org::apache::cassandra::CfDef>::const_iterator
00510                 cf = ks->cf_defs.begin(); cf != ks->cf_defs.end(); ++cf) {
00511         QSharedPointer<QCassandraTable> t(table(cf->name.c_str()));
00512         const org::apache::cassandra::CfDef& cf_def = *cf;
00513         t->parseTableDefinition(&cf_def);
00514     }
00515 }
00516 
00525 void QCassandraContext::prepareContextDefinition(void *data) const
00526 {
00527     org::apache::cassandra::KsDef *ks = reinterpret_cast<org::apache::cassandra::KsDef *>(data);
00528     *ks = *f_private;
00529 
00530     if(ks->strategy_class == "") {
00531         ks->strategy_class = "org.apache.cassandra.locator.LocalStrategy";
00532     }
00533     ks->__set_replication_factor(1);
00534 
00535     // copy the options
00536     ks->strategy_options.clear();
00537     for(QCassandraContextOptions::const_iterator
00538                 o = f_options.begin(); o != f_options.end(); ++o)
00539     {
00540         ks->strategy_options.insert(
00541                 std::pair<std::string, std::string>(o.key().toUtf8().data(),
00542                                                     o.value().toUtf8().data()));
00543     }
00544     ks->__isset.strategy_options = !ks->strategy_options.empty();
00545 
00546     // copy the tables -- apparently we cannot do that here!
00547     // instead we have to loop through the table in the previous
00548     // level and update each column family separately
00549     ks->cf_defs.clear();
00550     for(QtCassandra::QCassandraTables::const_iterator
00551             t = f_tables.begin();
00552             t != f_tables.end();
00553             ++t)
00554     {
00555         org::apache::cassandra::CfDef cf;
00556         (*t)->prepareTableDefinition(&cf);
00557         ks->cf_defs.push_back(cf);
00558     }
00559     //if(ks->cf_defs.empty()) ... problem? it's not optional...
00560 }
00561 
00572 void QCassandraContext::makeCurrent()
00573 {
00574     if(f_cassandra == NULL) {
00575         throw std::runtime_error("this context was dropped and is not attached to a cassandra cluster anymore");
00576     }
00577 
00578     // we need a shared pointer to the context and the only way to
00579     // get that is to retrieve it using our name... (somewhat slow
00580     // but I don't see a cleaner way to do it without generating a
00581     // pointer reference loop.)
00582     QSharedPointer<QCassandraContext> me(f_cassandra->context(f_private->name.c_str()));
00583     f_cassandra->setCurrentContext(me);
00584 }
00585 
00610 void QCassandraContext::create()
00611 {
00612     if(f_cassandra == NULL) {
00613         throw std::runtime_error("this context was dropped and is not attached to a cassandra cluster anymore");
00614     }
00615 
00616     f_cassandra->getPrivate()->createContext(*this);
00617 
00618     // If the user defined tables, we must mark them as loaded from Cassandra
00619     // which in this case would not otherwise happen!
00620     for(QtCassandra::QCassandraTables::const_iterator
00621             t = f_tables.begin();
00622             t != f_tables.end();
00623             ++t)
00624     {
00625         (*t)->setFromCassandra();
00626     }
00627 
00628     // TBD: Should we then call describe_keyspace() to make sure we've
00629     //      got the right data (defaults) in this object, tables, and
00630     //      column definitions?
00631 }
00632 
00639 void QCassandraContext::update()
00640 {
00641     if(f_cassandra == NULL) {
00642         throw std::runtime_error("this context was dropped and is not attached to a cassandra cluster anymore");
00643     }
00644 
00645     f_cassandra->getPrivate()->updateContext(*this);
00646 }
00647 
00664 void QCassandraContext::drop()
00665 {
00666     if(f_cassandra == NULL) {
00667         throw std::runtime_error("this context was dropped and is not attached to a cassandra cluster anymore");
00668     }
00669 
00670     f_cassandra->getPrivate()->dropContext(*this);
00671 }
00672 
00689 void QCassandraContext::dropTable(const QString& table_name)
00690 {
00691     if(f_tables.find(table_name) != f_tables.end()) {
00692         // keep a shared pointer on the table
00693         QSharedPointer<QCassandraTable> t(table(table_name));
00694 
00695         // remove from the Cassandra database
00696         makeCurrent();
00697         f_cassandra->getPrivate()->dropTable(table_name);
00698 
00699         // disconnect all the cached data from this table
00700         t->unparent();
00701         f_tables.remove(table_name);
00702     }
00703 }
00704 
00712 void QCassandraContext::createTable(const QCassandraTable *table)
00713 {
00714     makeCurrent();
00715     f_cassandra->getPrivate()->createTable(table);
00716 }
00717 
00729 void QCassandraContext::updateTable(const QCassandraTable *table)
00730 {
00731     makeCurrent();
00732     f_cassandra->getPrivate()->updateTable(table);
00733 }
00734 
00742 void QCassandraContext::truncateTable(const QCassandraTable *table)
00743 {
00744     makeCurrent();
00745     f_cassandra->getPrivate()->truncateTable(table);
00746 }
00747 
00758 void QCassandraContext::insertValue(const QString& table_name, const QByteArray& row_key, const QByteArray& column_key, const QCassandraValue& value)
00759 {
00760     makeCurrent();
00761     f_cassandra->getPrivate()->insertValue(table_name, row_key, column_key, value);
00762 }
00763 
00774 void QCassandraContext::getValue(const QString& table_name, const QByteArray& row_key, const QByteArray& column_key, QCassandraValue& value)
00775 {
00776     makeCurrent();
00777     f_cassandra->getPrivate()->getValue(table_name, row_key, column_key, value);
00778 }
00779 
00790 int32_t QCassandraContext::getCellCount(const QString& table_name, const QByteArray& row_key, const QCassandraColumnPredicate& column_predicate)
00791 {
00792     makeCurrent();
00793     return f_cassandra->getPrivate()->getCellCount(table_name, row_key, column_predicate);
00794 }
00795 
00804 void QCassandraContext::getColumnSlice(QCassandraTable& table, const QByteArray& row_key, const QCassandraColumnPredicate& column_predicate)
00805 {
00806     makeCurrent();
00807     f_cassandra->getPrivate()->getColumnSlice(table, row_key, column_predicate);
00808 }
00809 
00821 void QCassandraContext::remove(const QString& table_name, const QByteArray& row_key, const QByteArray& column_key, int64_t timestamp, consistency_level_t consistency_level)
00822 {
00823     makeCurrent();
00824     f_cassandra->getPrivate()->remove(table_name, row_key, column_key, timestamp, consistency_level);
00825 }
00826 
00838 uint32_t QCassandraContext::getRowSlices(QCassandraTable& table, const QCassandraRowPredicate& row_predicate)
00839 {
00840     makeCurrent();
00841     return f_cassandra->getPrivate()->getRowSlices(table, row_predicate);
00842 }
00843 
00851 void QCassandraContext::clearCache()
00852 {
00853     // lose all the tables
00854     for(QCassandraTables::iterator ti(f_tables.begin()); ti != f_tables.end(); ++ti) {
00855         (*ti)->unparent();
00856     }
00857     f_tables.clear();
00858 }
00859 
00868 void QCassandraContext::unparent()
00869 {
00870     f_cassandra = NULL;
00871     clearCache();
00872 }
00873 
00874 } // namespace QtCassandra
00875 // vim: ts=4 sw=4 et
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines

This document is part of the libQtCassandra Project.

Copyright by Made to Order Software Corp.