~drizzle-trunk/drizzle/development

« back to all changes in this revision

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

  • Committer: Mark Atwood
  • Date: 2011-12-20 02:32:53 UTC
  • mfrom: (2469.1.1 drizzle-build)
  • Revision ID: me@mark.atwood.name-20111220023253-bvu0kr14kwsdvz7g
mergeĀ lp:~brianaker/drizzle/deprecate-pbms

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