00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029 #ifdef DRIZZLED
00030 #include <config.h>
00031
00032 #include <drizzled/common.h>
00033 #include <drizzled/current_session.h>
00034 #include <drizzled/session.h>
00035 #endif
00036
00037
00038 #include "cslib/CSConfig.h"
00039 #include "cslib/CSGlobal.h"
00040 #include "cslib/CSStrUtil.h"
00041 #include "cslib/CSThread.h"
00042
00043 #ifndef DRIZZLED
00044 #define PBMS_API pbms_internal
00045 #include "pbms.h"
00046 #endif
00047
00048 #include "engine_ms.h"
00049 #include "connection_handler_ms.h"
00050 #include "open_table_ms.h"
00051 #include "network_ms.h"
00052 #include "transaction_ms.h"
00053 #include "mysql_ms.h"
00054
00055
00056 #ifdef new
00057 #undef new
00058 #endif
00059
00060
00061 extern CSThread *pbms_getMySelf(THD *thd);
00062 extern void pbms_setMySelf(THD *thd, CSThread *self);
00063
00064 #ifndef DRIZZLED
00065
00066
00067
00068
00069
00070
00071 static PBMS_API *StreamingEngines;
00072
00073
00074 static bool have_handler_support = false;
00075
00076
00077
00078
00079
00080
00081 static void ms_register_engine(PBMSEnginePtr engine)
00082 {
00083 if (engine->ms_internal)
00084 have_handler_support = true;
00085 }
00086
00087 static void ms_deregister_engine(PBMSEnginePtr engine)
00088 {
00089 UNUSED(engine);
00090 }
00091
00092 static int ms_create_blob(bool internal, const char *db_name, const char *tab_name, char *blob, size_t blob_len, PBMSBlobURLPtr blob_url, PBMSResultPtr result)
00093 {
00094 if (have_handler_support && !internal) {
00095 MSEngine::errorResult(CS_CONTEXT, MS_ERR_INVALID_OPERATION, "Invalid ms_create_blob() call", result);
00096 return MS_ERR_ENGINE;
00097 }
00098
00099 return MSEngine::createBlob(db_name, tab_name, blob, blob_len, blob_url, result);
00100 }
00101
00102
00103
00104
00105
00106
00107
00108
00109 static int ms_retain_blob(bool internal, const char *db_name, const char *tab_name, PBMSBlobURLPtr ret_blob_url, char *blob_url, unsigned short col_index, PBMSResultPtr result)
00110 {
00111 if (have_handler_support && !internal) {
00112 cs_strcpy(PBMS_BLOB_URL_SIZE, ret_blob_url->bu_data, blob_url);
00113 return MS_OK;
00114 }
00115
00116 return MSEngine::referenceBlob(db_name, tab_name, ret_blob_url, blob_url, col_index, result);
00117 }
00118
00119 static int ms_release_blob(bool internal, const char *db_name, const char *tab_name, char *blob_url, PBMSResultPtr result)
00120 {
00121
00122 if (have_handler_support && !internal)
00123 return MS_OK;
00124
00125 return MSEngine::dereferenceBlob(db_name, tab_name, blob_url, result);
00126 }
00127
00128 static int ms_drop_table(bool internal, const char *db_name, const char *tab_name, PBMSResultPtr result)
00129 {
00130 if (have_handler_support && !internal)
00131 return MS_OK;
00132
00133 return MSEngine::dropTable(db_name, tab_name, result);
00134 }
00135
00136 static int ms_rename_table(bool internal, const char * db_name, const char *from_table, const char *to_db, const char *to_table, PBMSResultPtr result)
00137 {
00138 if (have_handler_support && !internal)
00139 return MS_OK;
00140
00141 return MSEngine::renameTable(db_name, from_table, to_db, to_table, result);
00142 }
00143
00144 static void ms_completed(bool internal, bool ok)
00145 {
00146 if (have_handler_support && !internal)
00147 return;
00148
00149 MSEngine::callCompleted(ok);
00150 }
00151
00152 PBMSCallbacksRec engine_callbacks = {
00153 MS_CALLBACK_VERSION,
00154 ms_register_engine,
00155 ms_deregister_engine,
00156 ms_create_blob,
00157 ms_retain_blob,
00158 ms_release_blob,
00159 ms_drop_table,
00160 ms_rename_table,
00161 ms_completed
00162 };
00163
00164
00165 int MSEngine::startUp(PBMSResultPtr result)
00166 {
00167 int err = 0;
00168
00169 StreamingEngines = new PBMS_API();
00170 err = StreamingEngines->PBMSStartup(&engine_callbacks, result);
00171 if (err)
00172 delete StreamingEngines;
00173 else {
00174 PBMSSharedMemoryPtr sh_mem = StreamingEngines->sharedMemory;
00175 PBMSEnginePtr engine;
00176
00177 for (int i=0; i<sh_mem->sm_list_len; i++) {
00178 if ((engine = sh_mem->sm_engine_list[i]))
00179 ms_register_engine(engine);
00180 }
00181 }
00182 return err;
00183 }
00184
00185 void MSEngine::shutDown()
00186 {
00187 StreamingEngines->PBMSShutdown();
00188
00189 delete StreamingEngines;
00190 }
00191
00192 const PBMSEnginePtr MSEngine::getEngineInfoAt(int indx)
00193 {
00194 PBMSSharedMemoryPtr sh_mem = StreamingEngines->sharedMemory;
00195 PBMSEnginePtr engine = NULL;
00196
00197 if (sh_mem) {
00198 for (int i=0; i<sh_mem->sm_list_len; i++) {
00199 if ((engine = sh_mem->sm_engine_list[i])) {
00200 if (!indx)
00201 return engine;
00202 indx--;
00203 }
00204 }
00205 }
00206
00207 return (const PBMSEnginePtr)NULL;
00208 }
00209 #endif
00210
00211
00212 bool MSEngine::try_createBlob(CSThread *self, const char *db_name, const char *tab_name, char *blob, size_t blob_len, PBMSBlobURLPtr blob_url)
00213 {
00214 volatile bool rtc = true;
00215
00216 try_(a) {
00217 MSOpenTable *otab;
00218 CSInputStream *i_stream = NULL;
00219
00220 otab = openTable(db_name, tab_name, true);
00221 frompool_(otab);
00222
00223 if (!otab->getDB()->isRecovering()) {
00224 i_stream = CSMemoryInputStream::newStream((unsigned char *)blob, blob_len);
00225 otab->createBlob(blob_url, blob_len, NULL, 0, i_stream);
00226 } else
00227 CSException::throwException(CS_CONTEXT, MS_ERR_RECOVERY_IN_PROGRESS, "Cannot create BLOBs during repository recovery.");
00228
00229 backtopool_(otab);
00230 rtc = false;
00231 }
00232 catch_(a);
00233 cont_(a);
00234 return rtc;
00235 }
00236
00237
00238 int32_t MSEngine::createBlob(const char *db_name, const char *tab_name, char *blob, size_t blob_len, PBMSBlobURLPtr blob_url, PBMSResultPtr result)
00239 {
00240
00241 CSThread *self;
00242 int32_t err = MS_OK;
00243
00244 if ((err = enterConnectionNoThd(&self, result)))
00245 return err;
00246
00247 inner_();
00248 if (try_createBlob(self, db_name, tab_name, blob, blob_len, blob_url))
00249 err = exceptionToResult(&self->myException, result);
00250
00251 return_(err);
00252 }
00253
00254
00255 bool MSEngine::try_referenceBlob(CSThread *self, const char *db_name, const char *tab_name, PBMSBlobURLPtr ret_blob_url, char *blob_url, uint16_t col_index)
00256 {
00257 volatile bool rtc = true;
00258 try_(a) {
00259 MSBlobURLRec blob;
00260 MSOpenTable *otab;
00261
00262 if (! PBMSBlobURLTools::couldBeURL(blob_url, &blob)){
00263 char buffer[CS_EXC_MESSAGE_SIZE];
00264
00265 cs_strcpy(CS_EXC_MESSAGE_SIZE, buffer, "Incorrect URL: ");
00266 cs_strcat(CS_EXC_MESSAGE_SIZE, buffer, blob_url);
00267 CSException::throwException(CS_CONTEXT, MS_ERR_INCORRECT_URL, buffer);
00268 }
00269
00270 otab = openTable(db_name, tab_name, true);
00271 frompool_(otab);
00272
00273 otab->useBlob(blob.bu_type, blob.bu_db_id, blob.bu_tab_id, blob.bu_blob_id, blob.bu_auth_code, col_index, blob.bu_blob_size, blob.bu_blob_ref_id, ret_blob_url);
00274
00275 backtopool_(otab);
00276 rtc = false;
00277 }
00278 catch_(a);
00279 cont_(a);
00280 return rtc;
00281 }
00282
00283
00284 int32_t MSEngine::referenceBlob(const char *db_name, const char *tab_name, PBMSBlobURLPtr ret_blob_url, char *blob_url, uint16_t col_index, PBMSResultPtr result)
00285 {
00286
00287 CSThread *self;
00288 int32_t err = MS_OK;
00289
00290 if ((err = enterConnectionNoThd(&self, result)))
00291 return err;
00292
00293 inner_();
00294 if (try_referenceBlob(self, db_name, tab_name, ret_blob_url, blob_url, col_index))
00295 err = exceptionToResult(&self->myException, result);
00296
00297 return_(err);
00298
00299 }
00300
00301
00302 bool MSEngine::try_dereferenceBlob(CSThread *self, const char *db_name, const char *tab_name, char *blob_url)
00303 {
00304 volatile bool rtc = true;
00305 try_(a) {
00306 MSBlobURLRec blob;
00307 MSOpenTable *otab;
00308
00309 if (! PBMSBlobURLTools::couldBeURL(blob_url, &blob)){
00310 char buffer[CS_EXC_MESSAGE_SIZE];
00311
00312 cs_strcpy(CS_EXC_MESSAGE_SIZE, buffer, "Incorrect URL: ");
00313 cs_strcat(CS_EXC_MESSAGE_SIZE, buffer, blob_url);
00314 CSException::throwException(CS_CONTEXT, MS_ERR_INCORRECT_URL, buffer);
00315 }
00316
00317 otab = openTable(db_name, tab_name, true);
00318 frompool_(otab);
00319 if (!otab->getDB()->isRecovering()) {
00320 if (otab->getTableID() == blob.bu_tab_id)
00321 otab->releaseReference(blob.bu_blob_id, blob.bu_blob_ref_id);
00322 else {
00323 char buffer[CS_EXC_MESSAGE_SIZE];
00324
00325 cs_strcpy(CS_EXC_MESSAGE_SIZE, buffer, "Incorrect table ID: ");
00326 cs_strcat(CS_EXC_MESSAGE_SIZE, buffer, blob_url);
00327 CSException::throwException(CS_CONTEXT, MS_ERR_INCORRECT_URL, buffer);
00328 }
00329 }
00330 else {
00331 char buffer[CS_EXC_MESSAGE_SIZE];
00332
00333 cs_strcpy(CS_EXC_MESSAGE_SIZE, buffer, "Incorrect URL: ");
00334 cs_strcat(CS_EXC_MESSAGE_SIZE, buffer, blob_url);
00335 CSException::throwException(CS_CONTEXT, MS_ERR_INCORRECT_URL, buffer);
00336 }
00337
00338 backtopool_(otab);
00339 rtc = false;
00340 }
00341 catch_(a);
00342 cont_(a);
00343 return rtc;
00344 }
00345
00346 int32_t MSEngine::dereferenceBlob(const char *db_name, const char *tab_name, char *blob_url, PBMSResultPtr result)
00347 {
00348 CSThread *self;
00349 int32_t err = MS_OK;
00350
00351 if ((err = enterConnectionNoThd(&self, result)))
00352 return err;
00353
00354 inner_();
00355 if (try_dereferenceBlob(self, db_name, tab_name, blob_url))
00356 err = exceptionToResult(&self->myException, result);
00357
00358 return_(err);
00359 }
00360
00361 bool MSEngine::try_dropDatabase(CSThread *self, const char *db_name)
00362 {
00363 volatile bool rtc = true;
00364 try_(a) {
00365 MSDatabase::dropDatabase(db_name);
00366 rtc = false;
00367 }
00368 catch_(a);
00369 cont_(a);
00370
00371 return rtc;
00372 }
00373
00374 int32_t MSEngine::dropDatabase(const char *db_name, PBMSResultPtr result)
00375 {
00376 CSThread *self;
00377 int err = MS_OK;
00378
00379 if ((err = enterConnectionNoThd(&self, result)))
00380 return err;
00381
00382 inner_();
00383
00384 if (try_dropDatabase(self, db_name))
00385 err = exceptionToResult(&self->myException, result);
00386
00387 return_(err);
00388 }
00389
00390
00391 typedef struct UnDoInfo {
00392 bool udo_WasRename;
00393 CSString *udo_toDatabaseName;
00394 CSString *udo_fromDatabaseName;
00395 CSString *udo_OldName;
00396 CSString *udo_NewName;
00397 } UnDoInfoRec, *UnDoInfoPtr;
00398
00399
00400 bool MSEngine::try_dropTable(CSThread *self, const char *db_name, const char *tab_name)
00401 {
00402 volatile bool rtc = true;
00403 try_(a) {
00404
00405 CSPath *new_path;
00406 CSPath *old_path;
00407 MSOpenTable *otab;
00408 MSOpenTablePool *tab_pool;
00409 MSTable *tab;
00410 UnDoInfoPtr undo_info = NULL;
00411
00412 undo_info = (UnDoInfoPtr) cs_malloc(sizeof(UnDoInfoRec));
00413
00414 undo_info->udo_WasRename = false;
00415 self->myInfo = undo_info;
00416
00417 otab = openTable(db_name, tab_name, false);
00418 if (!otab) {
00419 goto end_try;
00420 }
00421
00422
00423
00424
00425
00426 if (otab->getDB()->isRecovering()) {
00427 otab->returnToPool();
00428 goto end_try;
00429 }
00430
00431 frompool_(otab);
00432
00433
00434
00435
00436
00437 old_path = otab->getDBTable()->getTableFile();
00438 push_(old_path);
00439
00440 new_path = otab->getDBTable()->getTableFile(tab_name, true);
00441
00442
00443 pop_(old_path);
00444 pop_(otab);
00445
00446 push_(new_path);
00447 push_(old_path);
00448 frompool_(otab);
00449
00450 tab = otab->getDBTable();
00451 pop_(otab);
00452 push_(tab);
00453
00454 tab_pool = MSTableList::lockTablePoolForDeletion(otab);
00455 frompool_(tab_pool);
00456
00457 if (old_path->exists())
00458 old_path->move(RETAIN(new_path));
00459 tab->myDatabase->dropTable(RETAIN(tab));
00460
00461
00462 tab->prepareToDelete();
00463
00464 backtopool_(tab_pool);
00465 pop_(tab);
00466 release_(old_path);
00467 release_(new_path);
00468
00469
00470
00471 end_try:
00472 rtc = false;
00473 }
00474 catch_(a);
00475 cont_(a);
00476 return rtc;
00477 }
00478
00479
00480 int32_t MSEngine::dropTable(const char *db_name, const char *tab_name, PBMSResultPtr result)
00481 {
00482 CSThread *self;
00483 int err = MS_OK;
00484
00485 if ((err = enterConnectionNoThd(&self, result)))
00486 return err;
00487
00488 inner_();
00489 if (try_dropTable(self, db_name, tab_name))
00490 err = exceptionToResult(&self->myException, result);
00491
00492 outer_();
00493 exitConnection();
00494 return err;
00495 }
00496
00497
00498 static void completeDeleteTable(UnDoInfoPtr info, bool ok)
00499 {
00500
00501 cs_free(info);
00502 if (!ok)
00503 CSException::throwException(CS_CONTEXT, MS_ERR_NOT_IMPLEMENTED, "Cannot undo delete table.");
00504 }
00505
00506
00507 bool MSEngine::renameTable(const char *from_db_name, const char *from_table, const char *to_db_name, const char *to_table)
00508 {
00509 MSOpenTable *otab;
00510 CSPath *from_path;
00511 CSPath *to_path;
00512 MSOpenTablePool *tab_pool;
00513 MSTable *tab;
00514
00515 enter_();
00516
00517 if (strcmp(to_db_name, from_db_name) != 0) {
00518 CSException::throwException(CS_CONTEXT, MS_ERR_NOT_IMPLEMENTED, "Cannot rename tables containing BLOBs across databases (yet). Sorry!");
00519 }
00520
00521 otab = openTable(from_db_name, from_table, false);
00522 if (!otab)
00523 return_(false);
00524
00525 frompool_(otab);
00526
00527 if (otab->getDB()->isRecovering())
00528 CSException::throwException(CS_CONTEXT, MS_ERR_RECOVERY_IN_PROGRESS, "Cannot rename tables during repository recovery.");
00529
00530 from_path = otab->getDBTable()->getTableFile();
00531 push_(from_path);
00532
00533 to_path = otab->getDBTable()->getTableFile(to_table, false);
00534
00535
00536 pop_(from_path);
00537 pop_(otab);
00538
00539 push_(to_path);
00540 push_(from_path);
00541 frompool_(otab);
00542
00543 otab->openForReading();
00544 tab = otab->getDBTable();
00545 tab->retain();
00546 pop_(otab);
00547 push_(tab);
00548
00549 tab_pool = MSTableList::lockTablePoolForDeletion(otab);
00550 frompool_(tab_pool);
00551
00552 from_path->move(RETAIN(to_path));
00553 tab->myDatabase->renameTable(tab, to_table);
00554
00555 backtopool_(tab_pool);
00556 pop_(tab);
00557 release_(from_path);
00558 release_(to_path);
00559
00560 return_(true);
00561 }
00562
00563
00564 bool MSEngine::try_renameTable(CSThread *self, const char *from_db_name, const char *from_table, const char *to_db_name, const char *to_table)
00565 {
00566 volatile bool rtc = true;
00567 try_(a) {
00568 UnDoInfoPtr undo_info = (UnDoInfoPtr) cs_malloc(sizeof(UnDoInfoRec));
00569 push_ptr_(undo_info);
00570
00571 undo_info->udo_WasRename = true;
00572 if (renameTable(from_db_name, from_table, to_db_name, to_table)) {
00573 undo_info->udo_fromDatabaseName = CSString::newString(from_db_name);
00574 push_(undo_info->udo_fromDatabaseName);
00575
00576 undo_info->udo_toDatabaseName = CSString::newString(to_db_name);
00577 push_(undo_info->udo_toDatabaseName);
00578
00579 undo_info->udo_OldName = CSString::newString(from_table);
00580 push_(undo_info->udo_OldName);
00581
00582 undo_info->udo_NewName = CSString::newString(to_table);
00583
00584 pop_(undo_info->udo_OldName);
00585 pop_(undo_info->udo_toDatabaseName);
00586 pop_(undo_info->udo_fromDatabaseName);
00587 } else {
00588 undo_info->udo_fromDatabaseName = undo_info->udo_toDatabaseName = undo_info->udo_OldName = undo_info->udo_NewName = NULL;
00589 }
00590 self->myInfo = undo_info;
00591 pop_(undo_info);
00592 rtc = false;
00593 }
00594 catch_(a);
00595 cont_(a);
00596 return rtc;
00597 }
00598
00599
00600 int32_t MSEngine::renameTable(const char *from_db_name, const char *from_table, const char *to_db_name, const char *to_table, PBMSResultPtr result)
00601 {
00602 CSThread *self;
00603 int err = MS_OK;
00604
00605 if ((err = enterConnectionNoThd(&self, result)))
00606 return err;
00607
00608 inner_();
00609 if (try_renameTable(self, from_db_name, from_table, to_db_name, to_table))
00610 err = exceptionToResult(&self->myException, result);
00611
00612 outer_();
00613 exitConnection();
00614 return err;
00615 }
00616
00617
00618 void MSEngine::completeRenameTable(UnDoInfoPtr info, bool ok)
00619 {
00620
00621 CSString *from_db_name= info->udo_toDatabaseName;
00622 CSString *to_db_name= info->udo_fromDatabaseName;
00623 CSString *from_table= info->udo_NewName;
00624 CSString *to_table= info->udo_OldName;
00625
00626 enter_();
00627
00628 cs_free(info);
00629 if (from_db_name) {
00630 push_(from_db_name);
00631 push_(from_table);
00632 push_(to_db_name);
00633 push_(to_table);
00634 if (!ok)
00635 renameTable(from_db_name->getCString(), from_table->getCString(), to_db_name->getCString(), to_table->getCString());
00636
00637 release_(to_table);
00638 release_(to_db_name);
00639 release_(from_table);
00640 release_(from_db_name);
00641 }
00642 exit_();
00643 }
00644
00645
00646 static bool try_CompleteTransaction(CSThread *self, bool ok)
00647 {
00648 volatile bool rtc = true;
00649 try_(a) {
00650 if (ok)
00651 MSTransactionManager::commit();
00652 else if (self->myIsAutoCommit)
00653 MSTransactionManager::rollback();
00654 else
00655 MSTransactionManager::rollbackToPosition(self->myStartStmt);
00656 rtc = false;
00657 }
00658 catch_(a)
00659 cont_(a);
00660
00661 return rtc;
00662 }
00663
00664
00665 void MSEngine::callCompleted(bool ok)
00666 {
00667 CSThread *self;
00668 PBMSResultRec result;
00669
00670 if (enterConnectionNoThd(&self, &result))
00671 return ;
00672
00673 if (self->myInfo) {
00674 UnDoInfoPtr info = (UnDoInfoPtr) self->myInfo;
00675 if (info->udo_WasRename)
00676 completeRenameTable(info, ok);
00677 else
00678 completeDeleteTable(info, ok);
00679
00680
00681 self->myInfo = NULL;
00682 } else if (self->myTID && (self->myIsAutoCommit || !ok)) {
00683 inner_();
00684 if (try_CompleteTransaction(self, ok)) {
00685 self->logException();
00686 }
00687 outer_();
00688 }
00689
00690 self->myStartStmt = self->myStmtCount;
00691 }
00692
00693
00694 MSOpenTable *MSEngine::openTable(const char *db_name, const char *tab_name, bool create)
00695 {
00696 MSOpenTable *otab = NULL;
00697 uint32_t db_id, tab_id;
00698 enter_();
00699
00700 if ( MSDatabase::convertTableAndDatabaseToIDs(db_name, tab_name, &db_id, &tab_id, create))
00701 otab = MSTableList::getOpenTableByID(db_id, tab_id);
00702
00703 return_(otab);
00704 }
00705
00706
00707 bool MSEngine::couldBeURL(const char *blob_url, size_t length)
00708 {
00709 MSBlobURLRec blob;
00710 return PBMSBlobURLTools::couldBeURL(blob_url, length, &blob);
00711 }
00712
00713
00714 int MSEngine::exceptionToResult(CSException *e, PBMSResultPtr result)
00715 {
00716 const char *context, *trace;
00717
00718 result->mr_code = e->getErrorCode();
00719 cs_strcpy(MS_RESULT_MESSAGE_SIZE, result->mr_message, e->getMessage());
00720 context = e->getContext();
00721 trace = e->getStackTrace();
00722 if (context && *context) {
00723 cs_strcpy(MS_RESULT_STACK_SIZE, result->mr_stack, context);
00724 if (trace && *trace)
00725 cs_strcat(MS_RESULT_STACK_SIZE, result->mr_stack, "\n");
00726 }
00727 else
00728 *result->mr_stack = 0;
00729 if (trace && *trace)
00730 cs_strcat(MS_RESULT_STACK_SIZE, result->mr_stack, trace);
00731 return MS_ERR_ENGINE;
00732 }
00733
00734
00735 int MSEngine::errorResult(const char *func, const char *file, int line, int err, const char *message, PBMSResultPtr result)
00736 {
00737 CSException e;
00738
00739 e.initException(func, file, line, err, message);
00740 return exceptionToResult(&e, result);
00741 }
00742
00743
00744 int MSEngine::osErrorResult(const char *func, const char *file, int line, int err, PBMSResultPtr result)
00745 {
00746 CSException e;
00747
00748 e.initOSError(func, file, line, err);
00749 return MSEngine::exceptionToResult(&e, result);
00750 }
00751
00752
00753 int MSEngine::enterConnection(THD *thd, CSThread **r_self, PBMSResultPtr result, bool doCreate)
00754 {
00755 CSThread *self = NULL;
00756
00757 #ifndef DRIZZLED
00758
00759
00760 self = CSThread::getSelf();
00761 #endif
00762 if (!self) {
00763 if (thd) {
00764 if (!(self = pbms_getMySelf(thd))) {
00765 if (!doCreate)
00766 return MS_ERR_NOT_FOUND;
00767
00768 if (!(self = CSThread::newCSThread()))
00769 return osErrorResult(CS_CONTEXT, ENOMEM, result);
00770 if (!CSThread::attach(self))
00771 return MSEngine::exceptionToResult(&self->myException, result);
00772 pbms_setMySelf(thd, self);
00773 } else {
00774 if (!CSThread::setSelf(self))
00775 return MSEngine::exceptionToResult(&self->myException, result);
00776 }
00777 } else {
00778 if (!doCreate)
00779 return MS_ERR_NOT_FOUND;
00780
00781 if (!(self = CSThread::newCSThread()))
00782 return osErrorResult(CS_CONTEXT, ENOMEM, result);
00783 if (!CSThread::attach(self))
00784 return MSEngine::exceptionToResult(&self->myException, result);
00785 }
00786 }
00787
00788 *r_self = self;
00789 return MS_OK;
00790 }
00791
00792
00793 int MSEngine::enterConnectionNoThd(CSThread **r_self, PBMSResultPtr result)
00794 {
00795 return enterConnection(current_thd, r_self, result, true);
00796 }
00797
00798
00799 void MSEngine::exitConnection()
00800 {
00801 THD *thd = (THD *) current_thd;
00802 CSThread *self;
00803
00804 self = CSThread::getSelf();
00805 if (self && self->pbms_api_owner)
00806 return;
00807
00808
00809 if (thd)
00810 CSThread::setSelf(NULL);
00811 else {
00812 self = CSThread::getSelf();
00813 CSThread::detach(self);
00814 }
00815 }
00816
00817
00818 void MSEngine::closeConnection(THD* thd)
00819 {
00820 CSThread *self;
00821
00822 self = CSThread::getSelf();
00823 if (self && self->pbms_api_owner)
00824 return;
00825
00826 if (thd) {
00827 if ((self = pbms_getMySelf(thd))) {
00828 pbms_setMySelf(thd, NULL);
00829 CSThread::setSelf(self);
00830 CSThread::detach(self);
00831 }
00832 }
00833 else {
00834 self = CSThread::getSelf();
00835 CSThread::detach(self);
00836 }
00837 }
00838
00839
00840
00841