Drizzled Public API Documentation

ha_pbms.cc

00001 /* Copyright (C) 2008 PrimeBase Technologies GmbH, Germany
00002  *
00003  * PrimeBase Media Stream for MySQL
00004  *
00005  * This program is free software; you can redistribute it and/or modify
00006  * it under the terms of the GNU General Public License as published by
00007  * the Free Software Foundation; either version 2 of the License, or
00008  * (at your option) any later version.
00009  *
00010  * This program is distributed in the hope that it will be useful,
00011  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00012  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013  * GNU General Public License for more details.
00014  *
00015  * You should have received a copy of the GNU General Public License
00016  * along with this program; if not, write to the Free Software
00017  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
00018  *
00019  * Original author: Paul McCullagh
00020  * Continued development: Barry Leslie
00021  *
00022  * 2007-05-20
00023  *
00024  * H&G2JCtL
00025  *
00026  * Table handler.
00027  *
00028  */
00029 
00030 #ifdef USE_PRAGMA_IMPLEMENTATION
00031 #pragma implementation        // gcc: Class implementation
00032 #endif
00033 
00034 #ifdef DRIZZLED
00035 #include <config.h>
00036 
00037 #include <drizzled/current_session.h>
00038 #include <drizzled/common.h>
00039 #include <drizzled/plugin.h>
00040 #include <drizzled/field.h>
00041 #include <drizzled/session.h>
00042 #include <drizzled/data_home.h>
00043 #include <drizzled/error.h>
00044 #include <drizzled/table.h>
00045 #include <drizzled/plugin/transactional_storage_engine.h>
00046 
00047 #define my_strdup(a,b) strdup(a)
00048 using namespace drizzled;
00049 using namespace drizzled::plugin;
00050 
00051 
00052 
00053 #include "cslib/CSConfig.h"
00054 #else
00055 #include "cslib/CSConfig.h"
00056 #include "mysql_priv.h"
00057 #include <mysql/plugin.h>
00058 #include <my_dir.h>
00059 #endif 
00060 
00061 #include <stdlib.h>
00062 #include <time.h>
00063 #include <inttypes.h>
00064 
00065 
00066 #include "defs_ms.h"
00067 
00068 #include "cslib/CSDefs.h"
00069 #include "cslib/CSObject.h"
00070 #include "cslib/CSGlobal.h"
00071 #include "cslib/CSThread.h"
00072 #include "cslib/CSStrUtil.h"
00073 #include "cslib/CSLog.h"
00074 
00075 #include "engine_ms.h"  
00076 #include "ha_pbms.h"
00077 #include "network_ms.h"
00078 #include "connection_handler_ms.h"
00079 #include "open_table_ms.h"
00080 #include "database_ms.h"
00081 #include "temp_log_ms.h"
00082 #include "system_table_ms.h"
00083 #include "mysql_ms.h"
00084 #include "discover_ms.h"
00085 #include "metadata_ms.h"
00086 #include "transaction_ms.h"
00087 #include "systab_httpheader_ms.h"
00088 #include "system_table_ms.h"
00089 #include "parameters_ms.h"
00090 #include "pbmsdaemon_ms.h"
00091 #include "version_ms.h"
00092 
00093 /* Note: 'new' used here is NOT CSObject::new which is a DEBUG define*/
00094 #ifdef new
00095 #undef new
00096 #endif
00097 
00098 
00099 #ifdef DRIZZLED
00100 
00101 static int pbms_done_func(void *);
00102 
00103 class PBMSStorageEngine : public drizzled::plugin::TransactionalStorageEngine {
00104 public:
00105   PBMSStorageEngine()
00106   : TransactionalStorageEngine(std::string("PBMS"), HTON_NO_FLAGS | HTON_HIDDEN) {}
00107 
00108   ~PBMSStorageEngine()
00109   {
00110     pbms_done_func(NULL);
00111   }
00112   
00113   int close_connection(Session *);
00114   
00115   int doStartTransaction(Session *session, start_transaction_option_t options);
00116   int doCommit(Session *, bool);
00117   int doRollback(Session *, bool);
00118   Cursor *create(Table& table);
00119   bool doDropSchema(const drizzled::identifier::Schema&);
00120   
00121   /*
00122   * Indicates to a storage engine the start of a
00123   * new SQL statement.
00124   */
00125   void doStartStatement(Session *session)
00126   {
00127     (void) session;
00128   }
00129 
00130   /*
00131   * Indicates to a storage engine the end of
00132   * the current SQL statement in the supplied
00133   * Session.
00134   */
00135   void doEndStatement(Session *session)
00136   {
00137     (void) session;
00138   }
00139   
00140   int doCreateTable(Session&, Table&, const identifier::Table& ident, const drizzled::message::Table& );  
00141   int doDropTable(Session &, const identifier::Table& );
00142   
00143   int doRenameTable(Session&, const identifier::Table &from, const identifier::Table &to);
00144   
00145         void doGetTableIdentifiers(drizzled::CachedDirectory &dir,
00146                                    const drizzled::identifier::Schema &schema,
00147                                    drizzled::identifier::Table::vector &set_of_identifiers) 
00148   {
00149     std::set<std::string> set_of_names;
00150     
00151     doGetTableNames(dir, schema, set_of_names);
00152     for (std::set<std::string>::iterator set_iter = set_of_names.begin(); set_iter != set_of_names.end(); ++set_iter)
00153     {
00154       set_of_identifiers.push_back(identifier::Table(schema, *set_iter));
00155     }
00156   }
00157   
00158   void doGetTableNames(CachedDirectory&, 
00159           const identifier::Schema &schema, 
00160           std::set<std::string> &set_of_names) 
00161   {
00162     bool isPBMS = schema.compare("PBMS");
00163     
00164     if (isPBMS || PBMSParameters::isBLOBDatabase(schema.getSchemaName().c_str()))
00165       PBMSSystemTables::getSystemTableNames(isPBMS, set_of_names);
00166   }
00167 
00168   int doSetSavepoint(Session *thd, NamedSavepoint &savepoint);
00169   int doRollbackToSavepoint(Session *session, NamedSavepoint &savepoint);
00170   int doReleaseSavepoint(Session *session, NamedSavepoint &savepoint);
00171   const char **bas_ext() const;
00172 
00173   int doGetTableDefinition(Session&, const identifier::Table &identifier,
00174                                           drizzled::message::Table &table_proto)
00175   {
00176     int err;
00177     const char *tab_name = identifier.getTableName().c_str();
00178 
00179     // Set some required table proto info:
00180     table_proto.set_schema(identifier.getSchemaName().c_str());
00181     table_proto.set_creation_timestamp(0);
00182     table_proto.set_update_timestamp(0);
00183     
00184     err = PBMSSystemTables::getSystemTableInfo(tab_name, table_proto);
00185     if (err)
00186       return err;
00187       
00188     return EEXIST;
00189   }
00190 
00191   bool doDoesTableExist(Session&, const identifier::Table &identifier)
00192   {
00193     const char *tab_name = identifier.getTableName().c_str();
00194     const char *db_name = identifier.getSchemaName().c_str();
00195     bool isPBMS = identifier.getSchemaName().compare("PBMS");
00196     
00197     if (isPBMS || PBMSParameters::isBLOBDatabase(db_name)) {
00198       return PBMSSystemTables::isSystemTable(isPBMS, tab_name);                  
00199     }
00200     
00201     return false;   
00202   }
00203 
00204 
00205 };
00206 
00207 PBMSStorageEngine *pbms_hton;
00208 #else
00209 handlerton    *pbms_hton;
00210 #endif
00211 
00212 static const char *ha_pbms_exts[] = {
00213   NullS
00214 };
00215 
00216 /*
00217  * ---------------------------------------------------------------
00218  * UTILITIES
00219  */
00220 
00221 #ifndef DRIZZLED
00222 void pbms_take_part_in_transaction(void *thread)
00223 {
00224   THD     *thd;
00225   if ((thd = (THD *) thread)) {
00226     trans_register_ha(thd, true, pbms_hton); 
00227   }
00228 }
00229 #endif
00230 
00231 #ifdef DRIZZLED
00232 const char **PBMSStorageEngine::bas_ext() const
00233 #else
00234 const char **ha_pbms::bas_ext() const
00235 #endif
00236 {
00237   return ha_pbms_exts;
00238 }
00239 
00240 #ifdef DRIZZLED
00241 int PBMSStorageEngine::close_connection(Session *thd)
00242 {
00243 #else
00244 static int pbms_close_connection(handlerton *hton, THD* thd)
00245 {
00246   (void)hton;
00247 #endif
00248   MSEngine::closeConnection(thd);
00249   return 0;
00250 }
00251 
00252 
00253 
00254 /*
00255  * ---------------------------------------------------------------
00256  * HANDLER INTERFACE
00257  */
00258 
00259 
00260 #ifdef DRIZZLED
00261 Cursor *PBMSStorageEngine::create(Table& table)
00262 {
00263   PBMSStorageEngine * const hton = this;
00264   return new ha_pbms(hton, table);
00265 }
00266 #else
00267 static handler *pbms_create_handler(handlerton *hton, TABLE_SHARE *table, MEM_ROOT *mem_root)
00268 {
00269   return new (mem_root) ha_pbms(hton, table);
00270 }
00271 #endif
00272 
00273 #ifdef DRIZZLED
00274 int PBMSStorageEngine::doStartTransaction(Session *thd, start_transaction_option_t options)
00275 {
00276   (void)thd;
00277   (void)options;
00278   return 0;
00279 }
00280 
00281 int PBMSStorageEngine::doCommit(Session *thd, bool all)
00282 {
00283 #else
00284 static int pbms_commit(handlerton *, THD *thd, bool all)
00285 {
00286 #endif
00287   int     err = 0;
00288   CSThread  *self;
00289   PBMSResultRec result;
00290 
00291   // I am not interesed in single statement transactions.
00292   if (all == false)
00293     return 0;
00294 
00295   if (MSEngine::enterConnection(thd, &self, &result, false))
00296     return 0;
00297   inner_();
00298   try_(a) {
00299     MSTransactionManager::commit();
00300   }
00301   catch_(a) {
00302     err = MSEngine::exceptionToResult(&self->myException, &result);
00303   }
00304   cont_(a);
00305   self->myIsAutoCommit = true;
00306   return_(err);
00307 }
00308 
00309 #ifdef DRIZZLED
00310 int PBMSStorageEngine::doRollback(THD *thd, bool all)
00311 {
00312 #else
00313 static int pbms_rollback(handlerton *, THD *thd, bool all)
00314 {
00315 #endif
00316   int     err = 0;
00317   CSThread  *self;
00318   PBMSResultRec result;
00319   
00320   UNUSED(all);
00321   
00322   if (MSEngine::enterConnection(thd, &self, &result, false))
00323     return 0;
00324   inner_();
00325   try_(a) {
00326     MSTransactionManager::rollback();
00327   }
00328   catch_(a) {
00329     err = MSEngine::exceptionToResult(&self->myException, &result);
00330   }
00331   cont_(a);
00332   self->myIsAutoCommit = true;
00333   return_(err);
00334 }
00335 
00336 #ifdef DRIZZLED
00337 int PBMSStorageEngine::doSetSavepoint(Session *thd, NamedSavepoint &savepoint)
00338 {
00339   int     err = 0;
00340   CSThread  *self;
00341   PBMSResultRec result;
00342 
00343   if (MSEngine::enterConnection(thd, &self, &result, false))
00344     return 0;
00345   
00346   inner_();
00347   try_(a) {
00348     MSTransactionManager::setSavepoint(savepoint.getName().c_str());
00349   }
00350   catch_(a) {
00351     err = MSEngine::exceptionToResult(&self->myException, &result);
00352   }
00353   cont_(a);
00354   return_(err);
00355   
00356 }
00357 
00358 int PBMSStorageEngine::doRollbackToSavepoint(Session *session, NamedSavepoint &savepoint)
00359 {
00360   int     err = 0;
00361   CSThread  *self;
00362   PBMSResultRec result;
00363 
00364   if (MSEngine::enterConnection(session, &self, &result, false))
00365     return 0;
00366   inner_();
00367   try_(a) {
00368     MSTransactionManager::rollbackTo(savepoint.getName().c_str());
00369   }
00370   catch_(a) {
00371     err = MSEngine::exceptionToResult(&self->myException, &result);
00372   }
00373   cont_(a);
00374   return_(err);
00375 }
00376 
00377 
00378 int PBMSStorageEngine::doReleaseSavepoint(Session *session, NamedSavepoint &savepoint)
00379 {
00380   int     err = 0;
00381   CSThread  *self;
00382   PBMSResultRec result;
00383 
00384   if (MSEngine::enterConnection(session, &self, &result, false))
00385     return 0;
00386     
00387   inner_();
00388   try_(a) {
00389     MSTransactionManager::releaseSavepoint(savepoint.getName().c_str());
00390   }
00391   catch_(a) {
00392     err = MSEngine::exceptionToResult(&self->myException, &result);
00393   }
00394   cont_(a);
00395   return_(err);
00396 }
00397 
00398 #else
00399 static int pbms_savepoint_set(handlerton *hton, THD *thd, void *sv)
00400 {
00401   int     err = 0;
00402   CSThread  *self;
00403   PBMSResultRec result;
00404 
00405   if (MSEngine::enterConnection(thd, &self, &result, false))
00406     return 0;
00407     
00408   *((uint32_t*)sv) = self->myStmtCount;
00409   return 0; 
00410 }
00411 
00412 static int pbms_savepoint_rollback(handlerton *hton, THD *thd, void *sv)
00413 {
00414   int     err = 0;
00415   CSThread  *self;
00416   PBMSResultRec result;
00417 
00418   if (MSEngine::enterConnection(thd, &self, &result, false))
00419     return 0;
00420   inner_();
00421   try_(a) {
00422     MSTransactionManager::rollbackToPosition(*((uint32_t*)sv));
00423   }
00424   catch_(a) {
00425     err = MSEngine::exceptionToResult(&self->myException, &result);
00426   }
00427   cont_(a);
00428   return_(err);
00429 }
00430 
00431 static int pbms_savepoint_release(handlerton *hton, THD *thd, void *sv)
00432 {
00433   return 0;
00434 }
00435 
00436 #endif
00437 
00438 #ifdef DRIZZLED
00439 bool  PBMSStorageEngine::doDropSchema(const drizzled::identifier::Schema &schema)
00440 {
00441   CSThread *self;
00442   PBMSResultRec result;
00443   
00444   if (MSEngine::enterConnectionNoThd(&self, &result))
00445     return false;
00446   inner_();
00447   
00448   try_(a) {
00449     MSDatabase::dropDatabase(schema.getSchemaName().c_str());
00450   }
00451   catch_(a);
00452   self->logException();
00453   cont_(a);
00454   return_(false);
00455 }
00456 #else
00457 static void pbms_drop_database(handlerton *, char *path)
00458 {
00459   CSThread *self;
00460   char db_name[PATH_MAX];
00461   PBMSResultRec result;
00462   
00463   if (MSEngine::enterConnectionNoThd(&self, &result))
00464     return;
00465   inner_();
00466   
00467   cs_strcpy(PATH_MAX, db_name, cs_last_directory_of_path(path));
00468   cs_remove_dir_char(db_name);
00469   try_(a) {
00470     MSDatabase::dropDatabase(db_name);
00471   }
00472   catch_(a);
00473   self->logException();
00474   cont_(a);
00475   exit_();
00476 }
00477 #endif
00478 
00479 static bool pbms_started = false;
00480 
00481 
00482 #ifdef DRIZZLED
00483 int pbms_init_func(module::Context &registry);
00484 int pbms_init_func(module::Context &registry)
00485 #else
00486 int pbms_init_func(void *p);
00487 int pbms_discover_system_tables(handlerton *hton, THD* thd, const char *db, const char *name, uchar **frmblob, size_t *frmlen);
00488 int pbms_init_func(void *p)
00489 #endif
00490 {
00491   PBMSResultRec   result;
00492   int         err;
00493   int         my_res = 0;
00494   CSThread      *thread;
00495 
00496   ASSERT(!pbms_started);
00497   pbms_started = false;
00498   PBMSDaemon::setDaemonState(PBMSDaemon::DaemonStartUp);
00499   
00500   {
00501     char info[120];
00502     snprintf(info, 120, "PrimeBase Media Stream (PBMS) Daemon %s loaded...", PBMSVersion::getCString());
00503     CSL.logLine(NULL, CSLog::Protocol, info);
00504   }
00505   CSL.logLine(NULL, CSLog::Protocol, "Barry Leslie, PrimeBase Technologies GmbH, http://www.primebase.org");
00506   
00507   if ((err = MSEngine::startUp(&result))) {
00508     CSL.logLine(NULL, CSLog::Error, result.mr_message);
00509     PBMSDaemon::setDaemonState(PBMSDaemon::DaemonError);
00510     return(1);
00511   }
00512 
00513 #ifdef DRIZZLED
00514     pbms_hton= new PBMSStorageEngine();
00515     registry.add(pbms_hton);
00516 #else
00517   pbms_hton = (handlerton *) p;
00518   pbms_hton->state = SHOW_OPTION_YES;
00519   pbms_hton->close_connection = pbms_close_connection; /* close_connection, cleanup thread related data. */
00520   pbms_hton->create = pbms_create_handler;
00521   pbms_hton->flags = HTON_CAN_RECREATE | HTON_HIDDEN;
00522   pbms_hton->drop_database = pbms_drop_database; /* Drop a database */
00523   pbms_hton->discover = pbms_discover_system_tables;
00524 
00525   pbms_hton->commit = pbms_commit; /* commit */
00526   pbms_hton->rollback = pbms_rollback; /* rollback */
00527 
00528   pbms_hton->savepoint_offset = 4;
00529   pbms_hton->savepoint_set = pbms_savepoint_set;
00530   pbms_hton->savepoint_rollback = pbms_savepoint_rollback; 
00531   pbms_hton->savepoint_release = pbms_savepoint_release; 
00532 #endif
00533   
00534   /* Startup the Media Stream network: */
00535   cs_init_memory();
00536   CSThread::startUp();
00537   if (!(thread = CSThread::newCSThread())) {
00538     CSException::logOSError(CS_CONTEXT, ENOMEM);
00539     PBMSDaemon::setDaemonState(PBMSDaemon::DaemonError);
00540     return(1);
00541   }
00542   if (!CSThread::attach(thread)) {
00543     PBMSDaemon::setDaemonState(PBMSDaemon::DaemonError);
00544     thread->myException.log(NULL);
00545     CSThread::shutDown();
00546     cs_exit_memory();
00547     MSEngine::shutDown();
00548     return(1);
00549   }
00550   enter_();
00551   try_(a) {
00552     thread->threadName = CSString::newString("startup");
00553     MSDatabase::startUp(PBMSParameters::getDefaultMetaDataHeaders());
00554     MSTableList::startUp();
00555     MSSystemTableShare::startUp();
00556     MSNetwork::startUp(PBMSParameters::getPortNumber());
00557     MSTransactionManager::startUp();
00558     MSNetwork::startNetwork();
00559   }
00560   catch_(a) {
00561     self->logException();
00562     my_res = 1;
00563   }
00564   cont_(a);
00565   if (my_res) {
00566     try_(b) {
00567       MSNetwork::shutDown();
00568       MSTransactionManager::shutDown();
00569       MSSystemTableShare::shutDown();
00570       MSDatabase::stopThreads();
00571       MSTableList::shutDown();
00572       MSDatabase::shutDown();
00573       CSThread::shutDown();
00574     }
00575     catch_(b) {
00576       self->logException();
00577     }
00578     cont_(b);
00579   }
00580   outer_();
00581   CSThread::detach(thread);
00582 
00583   if (my_res) {
00584     cs_exit_memory();
00585     MSEngine::shutDown();
00586   }
00587   else {
00588     srandom(time(NULL));
00589     pbms_started = true;
00590     
00591   }
00592 
00593   if (pbms_started)
00594     PBMSDaemon::setDaemonState(PBMSDaemon::DaemonRunning);
00595   else
00596     PBMSDaemon::setDaemonState(PBMSDaemon::DaemonError);
00597 
00598   return(my_res);
00599 }
00600 
00601 #ifdef DRIZZLED
00602 static int pbms_done_func(void *)
00603 #else
00604 int pbms_done_func(void *)
00605 #endif
00606 {
00607   CSThread  *thread;
00608 
00609   if (!pbms_started)
00610     return 0;
00611 
00612   PBMSDaemon::setDaemonState(PBMSDaemon::DaemonShuttingDown);
00613   CSL.logLine(NULL, CSLog::Protocol, "PrimeBase Media Stream (PBMS) Daemon shutdown...");
00614   
00615   /* Shutdown the Media Stream network. */
00616   if (!(thread = CSThread::newCSThread()))
00617     CSException::logOSError(CS_CONTEXT, ENOMEM);
00618   else if (!CSThread::attach(thread))
00619     thread->myException.log(NULL);
00620   else {
00621     enter_();
00622     try_(a) {
00623       thread->threadName = CSString::newString("shutdown");
00624       MSNetwork::shutDown();
00625       MSSystemTableShare::shutDown();
00626       /* Ensure that the database threads are stopped before
00627        * freeing the tables.
00628        */
00629       MSDatabase::stopThreads();
00630       MSTableList::shutDown();
00631       /* Databases must be shutdown after table because tables
00632        * have references to repositories.
00633        */
00634       MSDatabase::shutDown();
00635       
00636       /* Shutdown the transaction manager after the databases
00637        * incase they want to commit or rollback a transaction.
00638        */
00639       MSTransactionManager::shutDown();
00640     }
00641     catch_(a) {
00642       self->logException();
00643     }
00644     cont_(a);
00645     outer_();
00646     CSThread::shutDown();
00647     CSThread::detach(thread);
00648   }
00649 
00650   MSEngine::shutDown();
00651   cs_exit_memory();
00652 
00653   CSL.logLine(NULL, CSLog::Protocol, "PrimeBase Media Stream (PBMS) Daemon shutdown completed");
00654   pbms_started = false;
00655   return(0);
00656 }
00657 
00658 #ifdef DRIZZLED
00659 ha_pbms::ha_pbms(handlerton *hton, Table& table_arg) : handler(*hton, table_arg),
00660 #else
00661 ha_pbms::ha_pbms(handlerton *hton, TABLE_SHARE *table_arg) : handler(hton, table_arg),
00662 #endif
00663 ha_open_tab(NULL),
00664 ha_error(0)
00665 {
00666   memset(&ha_result, 0, sizeof(PBMSResultRec));
00667 }
00668 
00669 #ifndef DRIZZLED
00670 MX_TABLE_TYPES_T ha_pbms::table_flags() const
00671 {
00672   return (
00673     /* We need this flag because records are not packed
00674      * into a table which means #ROWID != offset
00675      */
00676     HA_REC_NOT_IN_SEQ |
00677     HA_CAN_SQL_HANDLER |
00678 #if MYSQL_VERSION_ID > 50119
00679     /* We can do row logging, but not statement, because
00680      * MVCC is not serializable!
00681      */
00682     HA_BINLOG_ROW_CAPABLE |
00683 #endif
00684     /*
00685      * Auto-increment is allowed on a partial key.
00686      */
00687     0);
00688 }
00689 #endif
00690 
00691 int ha_pbms::open(const char *table_path, int , uint )
00692 {
00693   CSThread *self;
00694 
00695   if ((ha_error = MSEngine::enterConnection(current_thd, &self, &ha_result, true)))
00696     return 1;
00697 
00698   inner_();
00699   try_(a) {
00700 #ifdef DRIZZLED
00701     ha_open_tab = MSSystemTableShare::openSystemTable(table_path, getTable());
00702     ha_lock.init(&ha_open_tab->myShare->myThrLock);
00703 #else
00704     ha_open_tab = MSSystemTableShare::openSystemTable(table_path, table);
00705     thr_lock_data_init(&ha_open_tab->myShare->myThrLock, &ha_lock, NULL);
00706 #endif
00707     ref_length = ha_open_tab->getRefLen();
00708   }
00709   catch_(a) {
00710     ha_error = MSEngine::exceptionToResult(&self->myException, &ha_result);
00711   }
00712   cont_(a);
00713   return_(ha_error != MS_OK);
00714 }
00715 
00716 int ha_pbms::close(void)
00717 {
00718   CSThread *self;
00719 
00720   if ((ha_error = MSEngine::enterConnection(current_thd, &self, &ha_result, true)))
00721     return 1;
00722 
00723   inner_();
00724   if (ha_open_tab) {
00725     ha_open_tab->release();
00726     ha_open_tab = NULL;
00727   }
00728   outer_();
00729   MSEngine::exitConnection();
00730   return 0;
00731 }
00732 
00733 #ifdef PBMS_HAS_KEYS
00734 /* Index access functions: */
00735 int ha_pbms::index_init(uint idx, bool sorted)
00736 {
00737   int err = 0;
00738   UNUSED(sorted);
00739   
00740   enter_();
00741   try_(a) {
00742     ha_open_tab->index_init(idx);
00743   }
00744   catch_(a) {
00745     ha_error = MSEngine::exceptionToResult(&self->myException, &ha_result);
00746     err = 1;
00747   }
00748   cont_(a);
00749   return_(err);
00750 }
00751 
00752 //-------
00753 int ha_pbms::index_end()
00754 {
00755   int err = 0;
00756   enter_();
00757   try_(a) {
00758     ha_open_tab->index_end();
00759   }
00760   catch_(a) {
00761     ha_error = MSEngine::exceptionToResult(&self->myException, &ha_result);
00762     err = 1;
00763   }
00764   cont_(a);
00765   return_(err);
00766 }
00767 
00768 //-------
00769 int ha_pbms::index_read(byte * buf, const byte * key,
00770                uint key_len, enum ha_rkey_function find_flag)
00771 {
00772   int err = 0;
00773   enter_();
00774   try_(a) {
00775     if (!ha_open_tab->index_read(buf, key, key_len, find_flag))
00776       err = HA_ERR_KEY_NOT_FOUND;
00777 
00778   }
00779   catch_(a) {
00780     ha_error = MSEngine::exceptionToResult(&self->myException, &ha_result);
00781     err = 1;
00782   }
00783   cont_(a);
00784   return_(err);
00785 }
00786 
00787 //-------
00788 int ha_pbms::index_read_idx(byte * buf, uint idx, const byte * key,
00789                    uint key_len, enum ha_rkey_function find_flag)
00790 {
00791   int err = 0;
00792   enter_();
00793   try_(a) {
00794     if (!ha_open_tab->index_read_idx(buf, idx, key, key_len, find_flag))
00795       err = HA_ERR_KEY_NOT_FOUND;
00796   }
00797   catch_(a) {
00798     ha_error = MSEngine::exceptionToResult(&self->myException, &ha_result);
00799     err = 1;
00800   }
00801   cont_(a);
00802   return_(err);
00803 }
00804 
00805 //-------
00806 int ha_pbms::index_next(byte * buf)
00807 {
00808   int err = 0;
00809   enter_();
00810   try_(a) {
00811     if (!ha_open_tab->index_next(buf))
00812       err = HA_ERR_END_OF_FILE;
00813   }
00814   catch_(a) {
00815     ha_error = MSEngine::exceptionToResult(&self->myException, &ha_result);
00816     err = 1;
00817   }
00818   cont_(a);
00819   return_(err);
00820 }
00821 
00822 //-------
00823 int ha_pbms::index_prev(byte * buf)
00824 {
00825   int err = 0;
00826   enter_();
00827   try_(a) {
00828     if (!ha_open_tab->index_prev(buf))
00829       err = HA_ERR_END_OF_FILE;
00830   }
00831   catch_(a) {
00832     ha_error = MSEngine::exceptionToResult(&self->myException, &ha_result);
00833     err = 1;
00834   }
00835   cont_(a);
00836   return_(err);
00837 }
00838 
00839 //-------
00840 int ha_pbms::index_first(byte * buf)
00841 {
00842   int err = 0;
00843   enter_();
00844   try_(a) {
00845     if (!ha_open_tab->index_first(buf))
00846       err = HA_ERR_END_OF_FILE;
00847   }
00848   catch_(a) {
00849     ha_error = MSEngine::exceptionToResult(&self->myException, &ha_result);
00850     err = 1;
00851   }
00852   cont_(a);
00853   return_(err);
00854 }
00855 
00856 //-------
00857 int ha_pbms::index_last(byte * buf)
00858 {
00859   int err = 0;
00860   enter_();
00861   try_(a) {
00862     if (!ha_open_tab->index_last(buf))
00863       err = HA_ERR_END_OF_FILE;
00864   }
00865   catch_(a) {
00866     ha_error = MSEngine::exceptionToResult(&self->myException, &ha_result);
00867     err = 1;
00868   }
00869   cont_(a);
00870   return_(err);
00871 }
00872 
00873 //-------
00874 int ha_pbms::index_read_last(byte * buf, const byte * key, uint key_len)
00875 {
00876   int err = 0;
00877   enter_();
00878   try_(a) {
00879     if (!ha_open_tab->index_read_last(buf, key, key_len))
00880       err = HA_ERR_KEY_NOT_FOUND;
00881   }
00882   catch_(a) {
00883     ha_error = MSEngine::exceptionToResult(&self->myException, &ha_result);
00884     err = 1;
00885   }
00886   cont_(a);
00887   return_(err);
00888 }
00889 
00890 //-------
00891 
00892 #endif // PBMS_HAS_KEYS
00893 
00894 /* Sequential scan functions: */
00895 #ifdef DRIZZLED
00896 int ha_pbms::doStartTableScan(bool )
00897 #else
00898 int ha_pbms::rnd_init(bool )
00899 #endif
00900 {
00901   int err = 0;
00902   enter_();
00903   try_(a) {
00904     ha_open_tab->seqScanInit();
00905   }
00906   catch_(a) {
00907     ha_error = MSEngine::exceptionToResult(&self->myException, &ha_result);
00908     err = 1;
00909   }
00910   cont_(a);
00911   return_(err);
00912 }
00913 
00914 //-------
00915 int ha_pbms::rnd_next(unsigned char *buf)
00916 {
00917   int err = 0;
00918   enter_();
00919   try_(a) {
00920     if (!ha_open_tab->seqScanNext((char *) buf))
00921       err = HA_ERR_END_OF_FILE;
00922   }
00923   catch_(a) {
00924     ha_error = MSEngine::exceptionToResult(&self->myException, &ha_result);
00925     err = 1;
00926   }
00927   cont_(a);
00928   return_(err);
00929 }
00930 
00931 //-------
00932 void ha_pbms::position(const unsigned char *)
00933 {
00934   ha_open_tab->seqScanPos((unsigned char *) ref);
00935 }
00936 
00937 //-------
00938 int ha_pbms::rnd_pos(unsigned char * buf, unsigned char *pos)
00939 {
00940   int err = 0;
00941   enter_();
00942   try_(a) {
00943     ha_open_tab->seqScanRead(pos, (char *) buf);
00944   }
00945   catch_(a) {
00946     ha_error = MSEngine::exceptionToResult(&self->myException, &ha_result);
00947     err = 1;
00948   }
00949   cont_(a);
00950   return_(err);
00951 }
00952 
00954 #ifdef DRIZZLED
00955 int ha_pbms::doInsertRecord(byte * buf)
00956 #else
00957 int ha_pbms::write_row(unsigned char * buf)
00958 #endif
00959 {
00960   int err = 0;
00961   enter_();
00962   try_(a) {
00963     ha_open_tab->insertRow((char *) buf);
00964   }
00965   catch_(a) {
00966     ha_error = MSEngine::exceptionToResult(&self->myException, &ha_result);
00967     err = 1;
00968   }
00969   cont_(a);
00970   return_(err);
00971 }
00972 
00973 #ifdef DRIZZLED
00974 int ha_pbms::doDeleteRecord(const byte * buf)
00975 #else
00976 int ha_pbms::delete_row(const  unsigned char * buf)
00977 #endif
00978 {
00979   int err = 0;
00980   enter_();
00981   try_(a) {
00982     ha_open_tab->deleteRow((char *) buf);
00983   }
00984   catch_(a) {
00985     ha_error = MSEngine::exceptionToResult(&self->myException, &ha_result);
00986     err = 1;
00987   }
00988   cont_(a);
00989   return_(err);
00990 }
00991 
00992 #ifdef DRIZZLED
00993 int ha_pbms::doUpdateRecord(const byte * old_data, byte * new_data)
00994 #else
00995 int ha_pbms::update_row(const unsigned char * old_data, unsigned char * new_data)
00996 #endif
00997 {
00998   int err = 0;
00999   enter_();
01000   try_(a) {
01001     ha_open_tab->updateRow((char *) old_data, (char *) new_data);
01002   }
01003   catch_(a) {
01004     ha_error = MSEngine::exceptionToResult(&self->myException, &ha_result);
01005     err = 1;
01006   }
01007   cont_(a);
01008   return_(err);
01009 }
01010 
01011 int ha_pbms::info(uint )
01012 {
01013   return 0;
01014 }
01015 
01016 int ha_pbms::external_lock(THD *thd, int lock_type)
01017 {
01018   CSThread  *self;
01019   int     err = 0;
01020 
01021   if ((ha_error = MSEngine::enterConnection(thd, &self, &ha_result, true)))
01022     return 1;
01023 
01024   inner_();
01025   try_(a) {
01026     if (lock_type == F_UNLCK)
01027       ha_open_tab->unuse();
01028     else
01029       ha_open_tab->use();
01030   }
01031   catch_(a) {
01032     ha_error = MSEngine::exceptionToResult(&self->myException, &ha_result);
01033     err = 1;
01034   }
01035   cont_(a);
01036   return_(err);
01037 }
01038 
01039 THR_LOCK_DATA **ha_pbms::store_lock(THD *, THR_LOCK_DATA **to, enum thr_lock_type lock_type)
01040 {
01041   if (lock_type != TL_IGNORE && ha_lock.type == TL_UNLOCK)
01042     ha_lock.type = lock_type;
01043   *to++ = &ha_lock;
01044   return to;
01045 }
01046 
01047 
01048 #ifdef DRIZZLED
01049 int PBMSStorageEngine::doCreateTable(Session&, Table&, const identifier::Table& , const drizzled::message::Table& )
01050 {
01051   /* You cannot create PBMS tables. */
01052   return( HA_ERR_WRONG_COMMAND );
01053 }
01054 
01055 int PBMSStorageEngine::doDropTable(Session &, const identifier::Table& )
01056 {
01057   /* You cannot delete PBMS tables. */
01058   return( 0 );
01059 }
01060 
01061 int PBMSStorageEngine::doRenameTable(Session&, const identifier::Table &, const identifier::Table &)
01062 {
01063   /* You cannot rename PBMS tables. */
01064   return( HA_ERR_WRONG_COMMAND );
01065 }
01066 
01067 #else // DRIZZLED
01068 
01069 int ha_pbms::create(const char *table_name, TABLE *table, HA_CREATE_INFO *)
01070 {
01071   bool isPBMS = (strcasecmp(table->s->db.str, "PBMS") == 0);
01072   
01073   if (PBMSSystemTables::isSystemTable(isPBMS, cs_last_name_of_path(table_name)))
01074     return(0);
01075     
01076   /* Create only works for system tables. */
01077   return( HA_ERR_WRONG_COMMAND );
01078 }
01079 #endif // DRIZZLED
01080 
01081 bool ha_pbms::get_error_message(int , String *buf)
01082 {
01083   if (!ha_result.mr_code)
01084     return false;
01085 
01086   buf->copy(ha_result.mr_message, strlen(ha_result.mr_message), system_charset_info);
01087   return true;
01088 }
01089 
01090 
01091 CSThread *pbms_getMySelf(THD *thd);
01092 void pbms_setMySelf(THD *thd, CSThread *self);
01093 #ifdef DRIZZLED
01094 CSThread *pbms_getMySelf(THD *thd) { return ((CSThread *) *thd->getEngineData(pbms_hton));}
01095 void pbms_setMySelf(THD *thd, CSThread *self) { *thd->getEngineData(pbms_hton) = (void *)self;}
01096 #else
01097 CSThread *pbms_getMySelf(THD *thd) { return ((CSThread *) *thd_ha_data(thd, pbms_hton));}
01098 void pbms_setMySelf(THD *thd, CSThread *self) { *thd_ha_data(thd, pbms_hton) = (void *)self;}
01099 #endif
01100 
01101