~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to plugin/pbms/src/engine_ms.cc

  • Committer: Daniel Nichter
  • Date: 2011-10-23 16:01:37 UTC
  • mto: This revision was merged to the branch mainline in revision 2448.
  • Revision ID: daniel@percona.com-20111023160137-7ac3blgz8z4tf8za
Add Administration Getting Started and Logging.  Capitalize SQL clause keywords.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* Copyright (C) 2008 PrimeBase Technologies GmbH, Germany
 
2
 *
 
3
 * PrimeBase Media Stream for MySQL
 
4
 *
 
5
 * This program is free software; you can redistribute it and/or modify
 
6
 * it under the terms of the GNU General Public License as published by
 
7
 * the Free Software Foundation; either version 2 of the License, or
 
8
 * (at your option) any later version.
 
9
 *
 
10
 * This program is distributed in the hope that it will be useful,
 
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
13
 * GNU General Public License for more details.
 
14
 *
 
15
 * You should have received a copy of the GNU General Public License
 
16
 * along with this program; if not, write to the Free Software
 
17
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
 
18
 *
 
19
 * Original author: Paul McCullagh
 
20
 * Continued development: Barry Leslie
 
21
 *
 
22
 * 2007-07-20
 
23
 *
 
24
 * H&G2JCtL
 
25
 *
 
26
 * Engine interface.
 
27
 *
 
28
 */
 
29
#ifdef DRIZZLED
 
30
#include <config.h>
 
31
 
 
32
#include <drizzled/common.h>
 
33
#include <drizzled/current_session.h>
 
34
#include <drizzled/session.h>
 
35
#endif
 
36
 
 
37
 
 
38
#include "cslib/CSConfig.h"
 
39
#include "cslib/CSGlobal.h"
 
40
#include "cslib/CSStrUtil.h"
 
41
#include "cslib/CSThread.h"
 
42
 
 
43
#ifndef DRIZZLED
 
44
#define PBMS_API pbms_internal  
 
45
#include "pbms.h"
 
46
#endif
 
47
 
 
48
#include "engine_ms.h"
 
49
#include "connection_handler_ms.h"
 
50
#include "open_table_ms.h"
 
51
#include "network_ms.h"
 
52
#include "transaction_ms.h"
 
53
#include "mysql_ms.h"
 
54
 
 
55
 
 
56
#ifdef new
 
57
#undef new
 
58
#endif
 
59
 
 
60
// From ha-pbms.cc:
 
61
extern CSThread *pbms_getMySelf(THD *thd);
 
62
extern void pbms_setMySelf(THD *thd, CSThread *self);
 
63
 
 
64
#ifndef DRIZZLED
 
65
 
 
66
/*
 
67
 * ---------------------------------------------------------------
 
68
 * ENGINE CALL-IN INTERFACE
 
69
 */
 
70
 
 
71
static PBMS_API *StreamingEngines;
 
72
// If PBMS support is built directly into the mysql/drizzle handler code 
 
73
// then calls from all other handlers are ignored.
 
74
static bool have_handler_support = false; 
 
75
 
 
76
/*
 
77
 * ---------------------------------------------------------------
 
78
 * ENGINE CALLBACK INTERFACE
 
79
 */
 
80
 
 
81
static void ms_register_engine(PBMSEnginePtr engine)
 
82
{
 
83
        if (engine->ms_internal)
 
84
                have_handler_support = true;
 
85
}
 
86
 
 
87
static void ms_deregister_engine(PBMSEnginePtr engine)
 
88
{
 
89
        UNUSED(engine);
 
90
}
 
91
 
 
92
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)
 
93
{
 
94
        if (have_handler_support && !internal) {
 
95
                MSEngine::errorResult(CS_CONTEXT, MS_ERR_INVALID_OPERATION, "Invalid ms_create_blob() call", result);
 
96
                return MS_ERR_ENGINE;
 
97
        }
 
98
 
 
99
        return MSEngine::createBlob(db_name, tab_name, blob, blob_len, blob_url, result);
 
100
}
 
101
 
 
102
/*
 
103
 * ms_use_blob() may or may not alter the blob url depending on the type of URL and if the BLOB is in a
 
104
 * different database or not. It may also add a BLOB reference to the BLOB table log if the BLOB was from
 
105
 * a different table or no table was specified when the BLOB was uploaded.
 
106
 *
 
107
 * There is no need to undo this function because it will be undone automaticly if the BLOB is not retained.
 
108
 */
 
109
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)
 
110
{
 
111
        if (have_handler_support && !internal) {
 
112
                cs_strcpy(PBMS_BLOB_URL_SIZE, ret_blob_url->bu_data, blob_url); // This should have already been converted.
 
113
                return MS_OK;
 
114
        }
 
115
        
 
116
        return MSEngine::referenceBlob(db_name, tab_name, ret_blob_url, blob_url, col_index, result);   
 
117
}
 
118
 
 
119
static int ms_release_blob(bool internal, const char *db_name, const char *tab_name, char *blob_url, PBMSResultPtr result)
 
120
{
 
121
 
 
122
        if (have_handler_support && !internal) 
 
123
                return MS_OK;
 
124
        
 
125
        return MSEngine::dereferenceBlob(db_name, tab_name, blob_url, result);  
 
126
}
 
127
 
 
128
static int ms_drop_table(bool internal, const char *db_name, const char *tab_name, PBMSResultPtr result)
 
129
{
 
130
        if (have_handler_support && !internal) 
 
131
                return MS_OK;
 
132
 
 
133
        return MSEngine::dropTable(db_name, tab_name, result);  
 
134
}
 
135
 
 
136
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)
 
137
{
 
138
        if (have_handler_support && !internal) 
 
139
                return MS_OK;
 
140
 
 
141
        return MSEngine::renameTable(db_name, from_table, to_db, to_table, result);     
 
142
}
 
143
 
 
144
static void ms_completed(bool internal, bool ok)
 
145
{
 
146
        if (have_handler_support && !internal) 
 
147
                return;
 
148
                
 
149
        MSEngine::callCompleted(ok);    
 
150
}
 
151
 
 
152
PBMSCallbacksRec engine_callbacks = {
 
153
        MS_CALLBACK_VERSION,
 
154
        ms_register_engine,
 
155
        ms_deregister_engine,
 
156
        ms_create_blob,
 
157
        ms_retain_blob,
 
158
        ms_release_blob,
 
159
        ms_drop_table,
 
160
        ms_rename_table,
 
161
        ms_completed
 
162
};
 
163
 
 
164
// =============================
 
165
int MSEngine::startUp(PBMSResultPtr result)
 
166
{
 
167
        int err = 0;
 
168
        
 
169
        StreamingEngines = new PBMS_API();
 
170
        err = StreamingEngines->PBMSStartup(&engine_callbacks, result);
 
171
        if (err)
 
172
                delete StreamingEngines;
 
173
        else { // Register the PBMS enabled engines the startup before PBMS
 
174
                PBMSSharedMemoryPtr             sh_mem = StreamingEngines->sharedMemory;
 
175
                PBMSEnginePtr                   engine;
 
176
                
 
177
                for (int i=0; i<sh_mem->sm_list_len; i++) {
 
178
                        if ((engine = sh_mem->sm_engine_list[i])) 
 
179
                                ms_register_engine(engine);
 
180
                }
 
181
        }
 
182
        return err;
 
183
}
 
184
 
 
185
void MSEngine::shutDown()
 
186
{
 
187
        StreamingEngines->PBMSShutdown();
 
188
 
 
189
        delete StreamingEngines;
 
190
}
 
191
 
 
192
const PBMSEnginePtr MSEngine::getEngineInfoAt(int indx)
 
193
{
 
194
        PBMSSharedMemoryPtr             sh_mem = StreamingEngines->sharedMemory;
 
195
        PBMSEnginePtr                   engine = NULL;
 
196
        
 
197
        if (sh_mem) {
 
198
                for (int i=0; i<sh_mem->sm_list_len; i++) {
 
199
                        if ((engine = sh_mem->sm_engine_list[i])) {
 
200
                                if (!indx)
 
201
                                        return engine;
 
202
                                indx--;
 
203
                        }
 
204
                }
 
205
        }
 
206
        
 
207
        return (const PBMSEnginePtr)NULL;
 
208
}
 
209
#endif  
 
210
 
 
211
//---------------
 
212
bool MSEngine::try_createBlob(CSThread *self, const char *db_name, const char *tab_name, char *blob, size_t blob_len, PBMSBlobURLPtr blob_url)
 
213
{
 
214
        volatile bool rtc = true;
 
215
        
 
216
        try_(a) {
 
217
                MSOpenTable             *otab;
 
218
                CSInputStream   *i_stream = NULL;
 
219
                
 
220
                otab = openTable(db_name, tab_name, true);
 
221
                frompool_(otab);
 
222
                
 
223
                if (!otab->getDB()->isRecovering()) {
 
224
                        i_stream = CSMemoryInputStream::newStream((unsigned char *)blob, blob_len);
 
225
                        otab->createBlob(blob_url, blob_len, NULL, 0, i_stream);
 
226
                } else
 
227
                        CSException::throwException(CS_CONTEXT, MS_ERR_RECOVERY_IN_PROGRESS, "Cannot create BLOBs during repository recovery.");
 
228
 
 
229
                backtopool_(otab);
 
230
                rtc = false;                    
 
231
        }
 
232
        catch_(a);
 
233
        cont_(a);
 
234
        return rtc;
 
235
}
 
236
 
 
237
//---------------
 
238
int32_t MSEngine::createBlob(const char *db_name, const char *tab_name, char *blob, size_t blob_len, PBMSBlobURLPtr blob_url, PBMSResultPtr result)
 
239
{
 
240
 
 
241
        CSThread                *self;
 
242
        int32_t                 err = MS_OK;
 
243
        
 
244
        if ((err = enterConnectionNoThd(&self, result)))
 
245
                return err;
 
246
 
 
247
        inner_();
 
248
        if (try_createBlob(self, db_name, tab_name, blob, blob_len, blob_url))
 
249
                err = exceptionToResult(&self->myException, result);
 
250
 
 
251
        return_(err);
 
252
}
 
253
 
 
254
//---------------
 
255
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)
 
256
{
 
257
        volatile bool rtc = true;
 
258
        try_(a) {
 
259
                MSBlobURLRec    blob;
 
260
                MSOpenTable             *otab;
 
261
                
 
262
                if (! PBMSBlobURLTools::couldBeURL(blob_url, &blob)){
 
263
                        char buffer[CS_EXC_MESSAGE_SIZE];
 
264
                        
 
265
                        cs_strcpy(CS_EXC_MESSAGE_SIZE, buffer, "Incorrect URL: ");
 
266
                        cs_strcat(CS_EXC_MESSAGE_SIZE, buffer, blob_url);
 
267
                        CSException::throwException(CS_CONTEXT, MS_ERR_INCORRECT_URL, buffer);
 
268
                }
 
269
                
 
270
                otab = openTable(db_name, tab_name, true);
 
271
                frompool_(otab);
 
272
 
 
273
                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);
 
274
 
 
275
                backtopool_(otab);
 
276
                rtc = false;                    
 
277
        }
 
278
        catch_(a);
 
279
        cont_(a);
 
280
        return rtc;
 
281
}
 
282
 
 
283
//---------------
 
284
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)
 
285
{
 
286
 
 
287
        CSThread                *self;
 
288
        int32_t                 err = MS_OK;
 
289
        
 
290
        if ((err = enterConnectionNoThd(&self, result)))
 
291
                return err;
 
292
 
 
293
        inner_();
 
294
        if (try_referenceBlob(self, db_name, tab_name, ret_blob_url, blob_url, col_index))
 
295
                err = exceptionToResult(&self->myException, result);
 
296
 
 
297
        return_(err);
 
298
 
 
299
}
 
300
 
 
301
//---------------
 
302
bool MSEngine::try_dereferenceBlob(CSThread *self, const char *db_name, const char *tab_name, char *blob_url)
 
303
{
 
304
        volatile bool rtc = true;
 
305
        try_(a) {
 
306
                MSBlobURLRec    blob;
 
307
                MSOpenTable             *otab;
 
308
 
 
309
                if (! PBMSBlobURLTools::couldBeURL(blob_url, &blob)){
 
310
                        char buffer[CS_EXC_MESSAGE_SIZE];
 
311
 
 
312
                        cs_strcpy(CS_EXC_MESSAGE_SIZE, buffer, "Incorrect URL: ");
 
313
                        cs_strcat(CS_EXC_MESSAGE_SIZE, buffer, blob_url);
 
314
                        CSException::throwException(CS_CONTEXT, MS_ERR_INCORRECT_URL, buffer);
 
315
                }
 
316
                
 
317
                otab = openTable(db_name, tab_name, true);
 
318
                frompool_(otab);
 
319
                if (!otab->getDB()->isRecovering()) {
 
320
                        if (otab->getTableID() == blob.bu_tab_id)
 
321
                                otab->releaseReference(blob.bu_blob_id, blob.bu_blob_ref_id);
 
322
                        else {
 
323
                                char buffer[CS_EXC_MESSAGE_SIZE];
 
324
 
 
325
                                cs_strcpy(CS_EXC_MESSAGE_SIZE, buffer, "Incorrect table ID: ");
 
326
                                cs_strcat(CS_EXC_MESSAGE_SIZE, buffer, blob_url);
 
327
                                CSException::throwException(CS_CONTEXT, MS_ERR_INCORRECT_URL, buffer);
 
328
                        }
 
329
                }
 
330
                else {
 
331
                        char buffer[CS_EXC_MESSAGE_SIZE];
 
332
 
 
333
                        cs_strcpy(CS_EXC_MESSAGE_SIZE, buffer, "Incorrect URL: ");
 
334
                        cs_strcat(CS_EXC_MESSAGE_SIZE, buffer, blob_url);
 
335
                        CSException::throwException(CS_CONTEXT, MS_ERR_INCORRECT_URL, buffer);
 
336
                }
 
337
                
 
338
                backtopool_(otab);      
 
339
                rtc = false;                    
 
340
        }
 
341
        catch_(a);
 
342
        cont_(a);
 
343
        return rtc;
 
344
}
 
345
 
 
346
int32_t MSEngine::dereferenceBlob(const char *db_name, const char *tab_name, char *blob_url, PBMSResultPtr result)
 
347
{
 
348
        CSThread                *self;
 
349
        int32_t                 err = MS_OK;
 
350
 
 
351
        if ((err = enterConnectionNoThd(&self, result)))
 
352
                return err;
 
353
 
 
354
        inner_();
 
355
        if (try_dereferenceBlob(self, db_name, tab_name, blob_url))
 
356
                err = exceptionToResult(&self->myException, result);
 
357
 
 
358
        return_(err);
 
359
}
 
360
 
 
361
bool MSEngine::try_dropDatabase(CSThread *self, const char *db_name)
 
362
{
 
363
        volatile bool rtc = true;
 
364
        try_(a) {
 
365
                MSDatabase::dropDatabase(db_name);
 
366
                rtc = false;
 
367
        }
 
368
        catch_(a);
 
369
        cont_(a);
 
370
        
 
371
        return rtc;
 
372
}
 
373
 
 
374
int32_t MSEngine::dropDatabase(const char *db_name, PBMSResultPtr result)
 
375
{
 
376
        CSThread *self;
 
377
        int             err = MS_OK;
 
378
        
 
379
        if ((err = enterConnectionNoThd(&self, result)))
 
380
                return err;
 
381
 
 
382
        inner_();
 
383
        
 
384
        if (try_dropDatabase(self, db_name))
 
385
                err = exceptionToResult(&self->myException, result);
 
386
 
 
387
        return_(err);
 
388
}
 
389
 
 
390
//---------------
 
391
typedef struct UnDoInfo {
 
392
        bool udo_WasRename;
 
393
        CSString *udo_toDatabaseName;
 
394
        CSString *udo_fromDatabaseName;
 
395
        CSString *udo_OldName;
 
396
        CSString *udo_NewName;
 
397
} UnDoInfoRec, *UnDoInfoPtr;
 
398
 
 
399
//---------------
 
400
bool MSEngine::try_dropTable(CSThread *self, const char *db_name, const char *tab_name)
 
401
{
 
402
        volatile bool rtc = true;
 
403
        try_(a) {
 
404
 
 
405
                CSPath                  *new_path;
 
406
                CSPath                  *old_path;
 
407
                MSOpenTable             *otab;
 
408
                MSOpenTablePool *tab_pool;
 
409
                MSTable                 *tab;
 
410
                UnDoInfoPtr             undo_info = NULL;
 
411
 
 
412
                undo_info = (UnDoInfoPtr) cs_malloc(sizeof(UnDoInfoRec));
 
413
                
 
414
                undo_info->udo_WasRename = false;
 
415
                self->myInfo = undo_info;
 
416
 
 
417
                otab = openTable(db_name, tab_name, false);
 
418
                if (!otab) {
 
419
                        goto end_try;
 
420
                }
 
421
                
 
422
                // If we are recovering do not delete the table.
 
423
                // It is normal for MySQL recovery scripts to delete any table they aare about to
 
424
                // recover and then recreate it. If this is done after the repository has been recovered
 
425
                // then this would delete all the recovered BLOBs in the table.
 
426
                if (otab->getDB()->isRecovering()) {
 
427
                        otab->returnToPool();
 
428
                        goto end_try;
 
429
                }
 
430
 
 
431
                frompool_(otab);
 
432
 
 
433
                // Before dropping the table the table ref file is renamed so that
 
434
                // it is out of the way incase a new table is created before the
 
435
                // old one is cleaned up.
 
436
                
 
437
                old_path = otab->getDBTable()->getTableFile();
 
438
                push_(old_path);
 
439
 
 
440
                new_path = otab->getDBTable()->getTableFile(tab_name, true);
 
441
 
 
442
                // Rearrage the object stack to pop the otab object
 
443
                pop_(old_path);
 
444
                pop_(otab);
 
445
 
 
446
                push_(new_path);
 
447
                push_(old_path);
 
448
                frompool_(otab);
 
449
                
 
450
                tab = otab->getDBTable();
 
451
                pop_(otab);
 
452
                push_(tab);
 
453
 
 
454
                tab_pool = MSTableList::lockTablePoolForDeletion(otab);
 
455
                frompool_(tab_pool);
 
456
 
 
457
                if (old_path->exists())
 
458
                        old_path->move(RETAIN(new_path));
 
459
                tab->myDatabase->dropTable(RETAIN(tab));
 
460
                
 
461
                /* Add the table to the temp delete list if we are not recovering... */
 
462
                tab->prepareToDelete();
 
463
 
 
464
                backtopool_(tab_pool);  // The will unlock and close the table pool freeing all tables in it.
 
465
                pop_(tab);                              // Returning the pool will have released this. (YUK!)
 
466
                release_(old_path);
 
467
                release_(new_path);
 
468
 
 
469
 
 
470
                                
 
471
end_try:
 
472
                rtc = false;    
 
473
        }
 
474
        catch_(a);
 
475
        cont_(a);
 
476
        return rtc;
 
477
}
 
478
 
 
479
//---------------
 
480
int32_t MSEngine::dropTable(const char *db_name, const char *tab_name, PBMSResultPtr result)
 
481
{
 
482
        CSThread        *self;
 
483
        int                     err = MS_OK;
 
484
 
 
485
        if ((err = enterConnectionNoThd(&self, result)))
 
486
                return err;
 
487
 
 
488
        inner_();
 
489
        if (try_dropTable(self, db_name, tab_name))
 
490
                err = exceptionToResult(&self->myException, result);
 
491
 
 
492
        outer_();
 
493
        exitConnection();
 
494
        return err;
 
495
}
 
496
 
 
497
//---------------
 
498
static void completeDeleteTable(UnDoInfoPtr info, bool ok)
 
499
{
 
500
        // TO DO: figure out a way to undo the delete.
 
501
        cs_free(info);
 
502
        if (!ok) 
 
503
                CSException::throwException(CS_CONTEXT, MS_ERR_NOT_IMPLEMENTED, "Cannot undo delete table.");
 
504
}
 
505
 
 
506
//---------------
 
507
bool MSEngine::renameTable(const char *from_db_name, const char *from_table, const char *to_db_name, const char *to_table)
 
508
{
 
509
        MSOpenTable             *otab;
 
510
        CSPath                  *from_path;
 
511
        CSPath                  *to_path;
 
512
        MSOpenTablePool *tab_pool;
 
513
        MSTable                 *tab;
 
514
 
 
515
        enter_();
 
516
        
 
517
        if (strcmp(to_db_name, from_db_name) != 0) {
 
518
                CSException::throwException(CS_CONTEXT, MS_ERR_NOT_IMPLEMENTED, "Cannot rename tables containing BLOBs across databases (yet). Sorry!");
 
519
        }
 
520
        
 
521
        otab = openTable(from_db_name, from_table, false);
 
522
        if (!otab)
 
523
                return_(false);
 
524
                
 
525
        frompool_(otab);
 
526
 
 
527
        if (otab->getDB()->isRecovering()) 
 
528
                CSException::throwException(CS_CONTEXT, MS_ERR_RECOVERY_IN_PROGRESS, "Cannot rename tables during repository recovery.");
 
529
 
 
530
        from_path = otab->getDBTable()->getTableFile();
 
531
        push_(from_path);
 
532
 
 
533
        to_path = otab->getDBTable()->getTableFile(to_table, false);
 
534
 
 
535
        // Rearrage the object stack to pop the otab object
 
536
        pop_(from_path);
 
537
        pop_(otab);
 
538
 
 
539
        push_(to_path);
 
540
        push_(from_path);
 
541
        frompool_(otab);
 
542
 
 
543
        otab->openForReading();
 
544
        tab = otab->getDBTable();
 
545
        tab->retain();
 
546
        pop_(otab);
 
547
        push_(tab);
 
548
        
 
549
        tab_pool = MSTableList::lockTablePoolForDeletion(otab);
 
550
        frompool_(tab_pool);
 
551
 
 
552
        from_path->move(RETAIN(to_path));
 
553
        tab->myDatabase->renameTable(tab, to_table);
 
554
 
 
555
        backtopool_(tab_pool);  // The will unlock and close the table pool freeing all tables in it.
 
556
        pop_(tab);                              // Returning the pool will have released this. (YUK!)
 
557
        release_(from_path);
 
558
        release_(to_path);
 
559
        
 
560
        return_(true);
 
561
}
 
562
 
 
563
//---------------
 
564
bool MSEngine::try_renameTable(CSThread *self, const char *from_db_name, const char *from_table, const char *to_db_name, const char *to_table)
 
565
{
 
566
        volatile bool rtc = true;
 
567
        try_(a) {
 
568
                UnDoInfoPtr undo_info = (UnDoInfoPtr) cs_malloc(sizeof(UnDoInfoRec));
 
569
                push_ptr_(undo_info);
 
570
 
 
571
                undo_info->udo_WasRename = true;
 
572
                if (renameTable(from_db_name, from_table, to_db_name, to_table)) {              
 
573
                        undo_info->udo_fromDatabaseName = CSString::newString(from_db_name);
 
574
                        push_(undo_info->udo_fromDatabaseName);
 
575
 
 
576
                        undo_info->udo_toDatabaseName = CSString::newString(to_db_name);
 
577
                        push_(undo_info->udo_toDatabaseName);
 
578
 
 
579
                        undo_info->udo_OldName = CSString::newString(from_table);
 
580
                        push_(undo_info->udo_OldName);
 
581
 
 
582
                        undo_info->udo_NewName = CSString::newString(to_table);
 
583
                        
 
584
                        pop_(undo_info->udo_OldName);
 
585
                        pop_(undo_info->udo_toDatabaseName);
 
586
                        pop_(undo_info->udo_fromDatabaseName);
 
587
                } else {
 
588
                        undo_info->udo_fromDatabaseName = undo_info->udo_toDatabaseName = undo_info->udo_OldName = undo_info->udo_NewName = NULL;
 
589
                }
 
590
                self->myInfo = undo_info;
 
591
                pop_(undo_info);
 
592
                rtc = false;                    
 
593
        }
 
594
        catch_(a);
 
595
        cont_(a);
 
596
        return rtc;
 
597
}
 
598
 
 
599
//---------------
 
600
int32_t MSEngine::renameTable(const char *from_db_name, const char *from_table, const char *to_db_name, const char *to_table, PBMSResultPtr result)
 
601
{
 
602
        CSThread        *self;
 
603
        int err = MS_OK;
 
604
 
 
605
        if ((err = enterConnectionNoThd(&self, result)))
 
606
                return err;
 
607
 
 
608
        inner_();
 
609
        if (try_renameTable(self, from_db_name, from_table, to_db_name, to_table))
 
610
                err = exceptionToResult(&self->myException, result);
 
611
 
 
612
        outer_();
 
613
        exitConnection();
 
614
        return err;
 
615
}
 
616
 
 
617
//---------------
 
618
void MSEngine::completeRenameTable(UnDoInfoPtr info, bool ok)
 
619
{
 
620
        // Swap the paths around here to revers the rename.
 
621
        CSString                *from_db_name= info->udo_toDatabaseName;
 
622
        CSString                *to_db_name= info->udo_fromDatabaseName;
 
623
        CSString                *from_table= info->udo_NewName;
 
624
        CSString                *to_table= info->udo_OldName;
 
625
        
 
626
        enter_();
 
627
        
 
628
        cs_free(info);
 
629
        if (from_db_name) {
 
630
                push_(from_db_name);
 
631
                push_(from_table);
 
632
                push_(to_db_name);
 
633
                push_(to_table);
 
634
                if (!ok) 
 
635
                        renameTable(from_db_name->getCString(), from_table->getCString(), to_db_name->getCString(), to_table->getCString());
 
636
                        
 
637
                release_(to_table);
 
638
                release_(to_db_name);
 
639
                release_(from_table);
 
640
                release_(from_db_name);
 
641
        }
 
642
        exit_();
 
643
}
 
644
 
 
645
//---------------
 
646
static bool try_CompleteTransaction(CSThread *self, bool ok)
 
647
{
 
648
        volatile bool rtc = true;
 
649
        try_(a) {
 
650
                if (ok)
 
651
                        MSTransactionManager::commit();
 
652
                else if (self->myIsAutoCommit)
 
653
                        MSTransactionManager::rollback();
 
654
                else
 
655
                        MSTransactionManager::rollbackToPosition(self->myStartStmt); // Rollback the last logical statement.
 
656
                rtc = false;
 
657
        }
 
658
        catch_(a)
 
659
        cont_(a);
 
660
        
 
661
        return rtc;
 
662
}
 
663
 
 
664
//---------------
 
665
void MSEngine::callCompleted(bool ok)
 
666
{
 
667
        CSThread        *self;
 
668
        PBMSResultRec   result;
 
669
        
 
670
        if (enterConnectionNoThd(&self, &result))
 
671
                return ;
 
672
 
 
673
        if (self->myInfo) {
 
674
                UnDoInfoPtr info = (UnDoInfoPtr) self->myInfo;
 
675
                if (info->udo_WasRename) 
 
676
                        completeRenameTable(info, ok);
 
677
                else 
 
678
                        completeDeleteTable(info, ok);
 
679
 
 
680
                
 
681
                self->myInfo = NULL;
 
682
        } else if (self->myTID && (self->myIsAutoCommit || !ok)) {
 
683
                inner_();
 
684
                if (try_CompleteTransaction(self, ok)) {
 
685
                        self->logException();
 
686
                }
 
687
                outer_();
 
688
        }
 
689
        
 
690
        self->myStartStmt = self->myStmtCount;
 
691
}
 
692
 
 
693
//---------------
 
694
MSOpenTable *MSEngine::openTable(const char *db_name, const char *tab_name, bool create)
 
695
{
 
696
        MSOpenTable             *otab = NULL;
 
697
        uint32_t db_id, tab_id;
 
698
        enter_();
 
699
        
 
700
        if ( MSDatabase::convertTableAndDatabaseToIDs(db_name, tab_name, &db_id, &tab_id, create))  
 
701
                otab = MSTableList::getOpenTableByID(db_id, tab_id);
 
702
                
 
703
        return_(otab);
 
704
}
 
705
 
 
706
//---------------
 
707
bool MSEngine::couldBeURL(const char *blob_url, size_t length)
 
708
{
 
709
        MSBlobURLRec blob;
 
710
        return PBMSBlobURLTools::couldBeURL(blob_url, length, &blob);
 
711
}
 
712
 
 
713
//---------------
 
714
int MSEngine::exceptionToResult(CSException *e, PBMSResultPtr result)
 
715
{
 
716
        const char *context, *trace;
 
717
 
 
718
        result->mr_code = e->getErrorCode();
 
719
        cs_strcpy(MS_RESULT_MESSAGE_SIZE, result->mr_message, e->getMessage());
 
720
        context = e->getContext();
 
721
        trace = e->getStackTrace();
 
722
        if (context && *context) {
 
723
                cs_strcpy(MS_RESULT_STACK_SIZE, result->mr_stack, context);
 
724
                if (trace && *trace)
 
725
                        cs_strcat(MS_RESULT_STACK_SIZE, result->mr_stack, "\n");
 
726
        }
 
727
        else
 
728
                *result->mr_stack = 0;
 
729
        if (trace && *trace)
 
730
                cs_strcat(MS_RESULT_STACK_SIZE, result->mr_stack, trace);
 
731
        return MS_ERR_ENGINE;
 
732
}
 
733
 
 
734
//---------------
 
735
int MSEngine::errorResult(const char *func, const char *file, int line, int err, const char *message, PBMSResultPtr result)
 
736
{
 
737
        CSException e;
 
738
                
 
739
        e.initException(func, file, line, err, message);
 
740
        return exceptionToResult(&e, result);
 
741
}
 
742
 
 
743
//---------------
 
744
int MSEngine::osErrorResult(const char *func, const char *file, int line, int err, PBMSResultPtr result)
 
745
{
 
746
        CSException e;
 
747
                
 
748
        e.initOSError(func, file, line, err);
 
749
        return MSEngine::exceptionToResult(&e, result);
 
750
}
 
751
 
 
752
//---------------
 
753
int MSEngine::enterConnection(THD *thd, CSThread **r_self, PBMSResultPtr result, bool doCreate)
 
754
{
 
755
        CSThread        *self = NULL;
 
756
 
 
757
#ifndef DRIZZLED
 
758
        // In drizzle there is no 1:1 relationship between pthreads and sessions
 
759
        // so we must always get it from the session handle NOT the current pthread.
 
760
        self = CSThread::getSelf();
 
761
#endif
 
762
        if (!self) {    
 
763
                if (thd) {
 
764
                        if (!(self = pbms_getMySelf(thd))) {
 
765
                                if (!doCreate)
 
766
                                        return MS_ERR_NOT_FOUND;
 
767
                                        
 
768
                                if (!(self = CSThread::newCSThread()))
 
769
                                        return osErrorResult(CS_CONTEXT, ENOMEM, result);
 
770
                                if (!CSThread::attach(self))
 
771
                                        return MSEngine::exceptionToResult(&self->myException, result);
 
772
                                pbms_setMySelf(thd, self);
 
773
                        } else {
 
774
                                if (!CSThread::setSelf(self))
 
775
                                        return MSEngine::exceptionToResult(&self->myException, result);
 
776
                        }
 
777
                } else {
 
778
                        if (!doCreate)
 
779
                                return MS_ERR_NOT_FOUND;
 
780
                                
 
781
                        if (!(self = CSThread::newCSThread()))
 
782
                                return osErrorResult(CS_CONTEXT, ENOMEM, result);
 
783
                        if (!CSThread::attach(self))
 
784
                                return MSEngine::exceptionToResult(&self->myException, result);
 
785
                }
 
786
        }
 
787
 
 
788
        *r_self = self;
 
789
        return MS_OK;
 
790
}
 
791
 
 
792
//---------------
 
793
int MSEngine::enterConnectionNoThd(CSThread **r_self, PBMSResultPtr result)
 
794
{
 
795
        return enterConnection(current_thd, r_self, result, true);
 
796
}
 
797
 
 
798
//---------------
 
799
void MSEngine::exitConnection()
 
800
{
 
801
        THD                     *thd = (THD *) current_thd;
 
802
        CSThread        *self;
 
803
 
 
804
        self = CSThread::getSelf();
 
805
        if (self && self->pbms_api_owner)
 
806
                return;
 
807
 
 
808
 
 
809
        if (thd)
 
810
                CSThread::setSelf(NULL);
 
811
        else {
 
812
                self = CSThread::getSelf();
 
813
                CSThread::detach(self);
 
814
        }
 
815
}
 
816
 
 
817
//---------------
 
818
void MSEngine::closeConnection(THD* thd)
 
819
{
 
820
        CSThread        *self;
 
821
 
 
822
        self = CSThread::getSelf();
 
823
        if (self && self->pbms_api_owner)
 
824
                return;
 
825
 
 
826
        if (thd) {
 
827
                if ((self = pbms_getMySelf(thd))) {
 
828
                        pbms_setMySelf(thd, NULL);
 
829
                        CSThread::setSelf(self);
 
830
                        CSThread::detach(self);
 
831
                }
 
832
        }
 
833
        else {
 
834
                self = CSThread::getSelf();
 
835
                CSThread::detach(self);
 
836
        }
 
837
}
 
838
 
 
839
 
 
840
 
 
841