libQtCassandra 0.3.2
|
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
This document is part of the libQtCassandra Project.
Copyright by Made to Order Software Corp.