1
/* Copyright (c) 2008 PrimeBase Technologies GmbH, Germany
3
* PrimeBase Media Stream for MySQL
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.
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.
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19
* Original author: Paul McCullagh
20
* Continued development: Barry Leslie
26
* Media Stream Tables.
29
#include "cslib/CSConfig.h"
31
#include "cslib/CSGlobal.h"
32
#include "cslib/CSLog.h"
33
#include "cslib/CSStrUtil.h"
34
#include "cslib/CSPath.h"
36
#include "open_table_ms.h"
38
#include "connection_handler_ms.h"
39
#include "engine_ms.h"
40
#include "transaction_ms.h"
41
#include "parameters_ms.h"
44
* ---------------------------------------------------------------
48
MSOpenTable::MSOpenTable():
57
myWriteRepoFile(NULL),
67
MSOpenTable::~MSOpenTable()
72
void MSOpenTable::close()
76
myTableFile->release();
81
myTempLogFile->release();
95
void MSOpenTable::returnToPool()
97
MSTableList::releaseTable(this);
100
void MSOpenTable::createBlob(PBMSBlobURLPtr bh, uint64_t blob_size, char *metadata, uint16_t metadata_size, CSInputStream *stream, CloudKeyPtr cloud_key, Md5Digest *checksum)
102
uint64_t repo_offset;
103
uint64_t blob_id = 0;
111
Md5Digest my_checksum;
112
CloudKeyRec cloud_key_rec;
115
CLOBBER_PROTECT(cloud_key);
116
CLOBBER_PROTECT(checksum);
119
checksum = &my_checksum;
121
if (stream) push_(stream);
124
auth_code = random();
125
repo_size = myWriteRepo->getRepoFileSize();
126
temp_time = myWriteRepo->myLastTempTime;
129
head_size = myWriteRepo->getDefaultHeaderSize(metadata_size);
130
if (getDB()->myBlobType == MS_STANDARD_STORAGE) {
132
repo_offset = myWriteRepo->receiveBlob(this, head_size, blob_size, checksum, stream);
134
ASSERT(getDB()->myBlobType == MS_CLOUD_STORAGE);
135
CloudDB *cloud = getDB()->myBlobCloud;
138
CSException::throwException(CS_CONTEXT, CS_ERR_GENERIC_ERROR, "Creating cloud BLOB without cloud.");
140
repo_offset = repo_size + head_size;
141
memset(checksum, 0, sizeof(Md5Digest)); // The checksum is only for local storage.
143
// If there is a stream then the data has not been sent to the cloud yet.
145
cloud_key = &cloud_key_rec;
146
cloud->cl_getNewKey(cloud_key);
148
cloud->cl_putData(cloud_key, stream, blob_size);
153
repo_id = myWriteRepo->myRepoID;
155
getDB()->queueForDeletion(this, MS_TL_REPO_REF, repo_id, repo_offset, auth_code, &log_id, &log_offset, &temp_time);
156
formatRepoURL(bh, repo_id, repo_offset, auth_code, blob_size);
159
blob_id = getDBTable()->createBlobHandle(this, myWriteRepo->myRepoID, repo_offset, blob_size, head_size, auth_code);
160
getDB()->queueForDeletion(this, MS_TL_BLOB_REF, getDBTable()->myTableID, blob_id, auth_code, &log_id, &log_offset, &temp_time);
161
formatBlobURL(bh, blob_id, auth_code, blob_size, 0);
164
myWriteRepo->writeBlobHead(this, repo_offset, myWriteRepo->myRepoDefRefSize, head_size, blob_size, checksum, metadata, metadata_size, blob_id, auth_code, log_id, log_offset, getDB()->myBlobType, cloud_key);
168
// In the event of an error reset the repository size to its original size.
169
myWriteRepo->setRepoFileSize(this, repo_size);
176
// BLOBs created with this method are always created as standard local BLOBs. (No cloud storage)
177
void MSOpenTable::createBlob(PBMSBlobIDPtr blob_id, uint64_t blob_size, char *metadata, uint16_t metadata_size)
180
uint64_t repo_offset;
191
auth_code = random();
193
repo_size = myWriteRepo->getRepoFileSize();
195
head_size = myWriteRepo->getDefaultHeaderSize(metadata_size);
197
repo_offset = myWriteRepo->receiveBlob(this, head_size, blob_size);
198
repo_id = myWriteRepo->myRepoID;
199
temp_time = myWriteRepo->myLastTempTime;
200
getDB()->queueForDeletion(this, MS_TL_REPO_REF, repo_id, repo_offset, auth_code, &log_id, &log_offset, &temp_time);
201
myWriteRepo->myLastTempTime = temp_time;
202
myWriteRepo->writeBlobHead(this, repo_offset, myWriteRepo->myRepoDefRefSize, head_size, blob_size, NULL, metadata, metadata_size, 0, auth_code, log_id, log_offset, MS_STANDARD_STORAGE, NULL);
203
// myWriteRepo->setRepoFileSize(this, repo_offset + head_size + blob_size);This is now set by writeBlobHead()
205
blob_id->bi_db_id = getDB()->myDatabaseID;
206
blob_id->bi_blob_id = repo_offset;
207
blob_id->bi_tab_id = repo_id;
208
blob_id->bi_auth_code = auth_code;
209
blob_id->bi_blob_size = blob_size;
210
blob_id->bi_blob_type = MS_URL_TYPE_REPO;
211
blob_id->bi_blob_ref_id = 0;
216
// BLOBs created with this method are always created as standard local BLOBs. (No cloud storage)
217
myWriteRepo->setRepoFileSize(this, repo_size);
224
void MSOpenTable::sendRepoBlob(uint64_t blob_id, uint64_t req_offset, uint64_t req_size, uint32_t auth_code, bool info_only, CSHTTPOutputStream *stream)
230
MSRepoFile *repo_file;
234
getDBTable()->readBlobHandle(this, blob_id, &auth_code, &repo_id, &offset, &size, &head_size, true);
235
repo_file = getDB()->getRepoFileFromPool(repo_id, false);
236
frompool_(repo_file);
237
//repo_file->sendBlob(this, offset, head_size, size, stream);
238
repo_file->sendBlob(this, offset, req_offset, req_size, 0, false, info_only, stream);
239
backtopool_(repo_file);
243
void MSOpenTable::freeReference(uint64_t blob_id, uint64_t blob_ref_id)
249
MSRepoFile *repo_file;
250
uint32_t auth_code = 0;
255
getDBTable()->readBlobHandle(this, blob_id, &auth_code, &repo_id, &offset, &blob_size, &head_size, true);
256
repo_file = getDB()->getRepoFileFromPool(repo_id, false);
258
frompool_(repo_file);
259
repo_file->releaseBlob(this, offset, head_size, getDBTable()->myTableID, blob_id, blob_ref_id, auth_code);
260
backtopool_(repo_file);
265
void MSOpenTable::commitReference(uint64_t blob_id, uint64_t blob_ref_id)
271
MSRepoFile *repo_file;
272
uint32_t auth_code = 0;
277
getDBTable()->readBlobHandle(this, blob_id, &auth_code, &repo_id, &offset, &blob_size, &head_size, true);
278
repo_file = getDB()->getRepoFileFromPool(repo_id, false);
280
frompool_(repo_file);
281
repo_file->commitBlob(this, offset, head_size, getDBTable()->myTableID, blob_id, blob_ref_id, auth_code);
282
backtopool_(repo_file);
287
void MSOpenTable::useBlob(int type, uint32_t db_id, uint32_t tab_id, uint64_t blob_id, uint32_t auth_code, uint16_t col_index, uint64_t blob_size, uint64_t blob_ref_id, PBMSBlobURLPtr ret_blob_url)
289
MSRepoFile *repo_file= NULL;
291
CSInputStream *stream;
295
uint64_t repo_offset;
302
if (!blob_db->isRecovering()) {
303
// During recovery the only thing that needs to be done is to
304
// reset the database ID which is done when the URL is created.
305
// Create the URL using the table ID passed in not the one from
306
// the table associated with this object.
309
if (type == MS_URL_TYPE_REPO) { // There is no table reference associated with this BLOB yet.
314
if (blob_db->myDatabaseID == db_id)
315
repo_file = blob_db->getRepoFileFromPool(tab_id, false);
318
blob_db = MSDatabase::getDatabase(db_id);
320
repo_file = blob_db->getRepoFileFromPool(tab_id, false);
322
blob_db = repo_file->myRepo->myRepoDatabase;
325
frompool_(repo_file);
326
repo_file->read(&blob, blob_id, MS_MIN_BLOB_HEAD_SIZE, MS_MIN_BLOB_HEAD_SIZE);
328
repo_offset = blob_id;
329
blob_size = CS_GET_DISK_6(blob.rb_blob_data_size_6);
330
head_size = CS_GET_DISK_2(blob.rb_head_size_2);
332
ac = CS_GET_DISK_4(blob.rb_auth_code_4);
334
CSException::throwException(CS_CONTEXT, MS_ERR_AUTH_FAILED, "Invalid BLOB identifier");
335
status = CS_GET_DISK_1(blob.rb_status_1);
336
if ( ! IN_USE_BLOB_STATUS(status))
337
CSException::throwException(CS_CONTEXT, MS_ERR_NOT_FOUND, "BLOB has already been deleted");
340
// Create a table reference to the BLOB:
342
blob_id = getDBTable()->createBlobHandle(this, tab_id, blob_id, blob_size, head_size, auth_code);
343
state = MS_UB_NEW_HANDLE;
347
getDB()->openWriteRepo(this);
349
// If either databases are using cloud storage then this is
350
// not supported yet.
351
if (getDB()->myBlobCloud || myWriteRepo->myRepoDatabase->myBlobCloud)
352
CSException::throwException(CS_CONTEXT, CS_ERR_GENERIC_ERROR, "Copying cloud BLOB between databases is not supported.");
354
stream = repo_file->getInputStream(repo_offset);
356
repo_offset = myWriteRepo->copyBlob(this, head_size + blob_size, stream);
359
// Create a table reference to the BLOB:
360
repo_id = myWriteRepo->myRepoID;
361
blob_id = getDBTable()->createBlobHandle(this, myWriteRepo->myRepoID, repo_offset, blob_size, head_size, auth_code);
362
state = MS_UB_NEW_BLOB;
364
backtopool_(repo_file);
368
if (blob_db->myDatabaseID == db_id && getDBTable()->myTableID == tab_id) {
369
getDBTable()->readBlobHandle(this, blob_id, &auth_code, &repo_id, &repo_offset, &blob_size, &head_size, true);
371
state = MS_UB_SAME_TAB;
374
MSOpenTable *blob_otab;
376
blob_otab = MSTableList::getOpenTableByID(db_id, tab_id);
377
frompool_(blob_otab);
378
blob_otab->getDBTable()->readBlobHandle(blob_otab, blob_id, &auth_code, &repo_id, &repo_offset, &blob_size, &head_size, true);
379
if (blob_db->myDatabaseID == db_id) {
380
blob_id = getDBTable()->findBlobHandle(this, repo_id, repo_offset, blob_size, head_size, auth_code);
382
blob_id = getDBTable()->createBlobHandle(this, repo_id, repo_offset, blob_size, head_size, auth_code);
383
state = MS_UB_NEW_HANDLE;
387
// If either databases are using cloud storage then this is
388
// not supported yet.
389
if (blob_db->myBlobCloud || myWriteRepo->myRepoDatabase->myBlobCloud)
390
CSException::throwException(CS_CONTEXT, CS_ERR_GENERIC_ERROR, "Copying cloud BLOB between databases is not supported.");
392
// NOTE: For each BLOB reference copied from one database to another a new
393
// BLOB will be created. This can result in multiple copies fo the same BLOB
394
// in the destination database. One way around this would be to redisign things
395
// so that there is one BLOB repository shared across all databases.
396
blob_db->openWriteRepo(this);
398
stream = repo_file->getInputStream(repo_offset);
401
repo_offset = myWriteRepo->copyBlob(this, head_size + blob_size, stream);
405
repo_id = myWriteRepo->myRepoID;
406
blob_id = getDBTable()->createBlobHandle(this, myWriteRepo->myRepoID, repo_offset, blob_size, head_size, auth_code);
407
state = MS_UB_NEW_BLOB;
409
backtopool_(blob_otab);
414
blob_ref_id = blob_db->newBlobRefId();
416
// Always use the table ID of this table because regardless of
417
// where the BLOB ref came from it is being inserted into this table.
418
tab_id = getDBTable()->myTableID;
420
// Add the BLOB reference to the repository.
421
repo_file = blob_db->getRepoFileFromPool(repo_id, false);
422
frompool_(repo_file);
423
repo_file->referenceBlob(this, repo_offset, head_size, tab_id, blob_id, blob_ref_id, auth_code, col_index);
424
backtopool_(repo_file);
426
MSTransactionManager::referenceBLOB(getDB()->myDatabaseID, tab_id, blob_id, blob_ref_id);
430
formatBlobURL(ret_blob_url, blob_id, auth_code, blob_size, tab_id, blob_ref_id);
435
void MSOpenTable::releaseReference(uint64_t blob_id, uint64_t blob_ref_id)
439
MSTransactionManager::dereferenceBLOB(getDB()->myDatabaseID, getDBTable()->myTableID, blob_id, blob_ref_id);
444
void MSOpenTable::checkBlob(CSStringBuffer *buffer, uint64_t blob_id, uint32_t auth_code, uint32_t temp_log_id, uint32_t temp_log_offset)
450
MSRepoFile *repo_file;
454
if (getDBTable()->readBlobHandle(this, blob_id, &auth_code, &repo_id, &offset, &size, &head_size, false)) {
455
if ((repo_file = getDB()->getRepoFileFromPool(repo_id, true))) {
456
frompool_(repo_file);
457
repo_file->checkBlob(buffer, offset, auth_code, temp_log_id, temp_log_offset);
458
backtopool_(repo_file);
461
getDBTable()->freeBlobHandle(this, blob_id, repo_id, offset, auth_code);
466
bool MSOpenTable::deleteReferences(uint32_t temp_log_id, uint32_t temp_log_offset, bool *must_quit)
468
MSTableHeadRec tab_head;
470
MSTableBlobRec tab_blob;
472
uint64_t repo_offset;
475
MSRepoFile *repo_file = NULL;
480
if (myTableFile->read(&tab_head, 0, offsetof(MSTableHeadRec, th_reserved_4), 0) < offsetof(MSTableHeadRec, th_reserved_4))
481
/* Nothing to read, delete it ... */
483
if (CS_GET_DISK_4(tab_head.th_temp_log_id_4) != temp_log_id ||
484
CS_GET_DISK_4(tab_head.th_temp_log_offset_4) != temp_log_offset) {
485
/* Wrong delete reference (ignore): */
490
blob_id = CS_GET_DISK_2(tab_head.th_head_size_2);
491
while (blob_id + sizeof(MSTableBlobRec) <= getDBTable()->getTableFileSize()) {
493
/* Bit of a waste of work, but we must quit! */
497
if (myTableFile->read(&tab_blob, blob_id, sizeof(MSTableBlobRec), 0) < sizeof(MSTableBlobRec))
499
repo_id = CS_GET_DISK_3(tab_blob.tb_repo_id_3);
500
repo_offset = CS_GET_DISK_6(tab_blob.tb_offset_6);
501
head_size = CS_GET_DISK_2(tab_blob.tb_header_size_2);
502
auth_code = CS_GET_DISK_4(tab_blob.tb_auth_code_4);
503
if (repo_file && repo_file->myRepo->myRepoID != repo_id) {
504
backtopool_(repo_file);
508
repo_file = getDB()->getRepoFileFromPool(repo_id, true);
510
frompool_(repo_file);
513
repo_file->freeTableReference(this, repo_offset, head_size, getDBTable()->myTableID, blob_id, auth_code);
515
blob_id += sizeof(MSTableBlobRec);
519
backtopool_(repo_file);
525
void MSOpenTable::openForReading()
527
if (!myTableFile && !isNotATable)
528
myTableFile = getDBTable()->openTableFile();
531
void MSOpenTable::openForWriting()
533
if (myTableFile && myWriteRepo && myWriteRepoFile)
537
if (!myWriteRepo || !myWriteRepoFile)
538
getDB()->openWriteRepo(this);
542
void MSOpenTable::closeForWriting()
544
if (myWriteRepoFile) {
545
myWriteRepoFile->myRepo->syncHead(myWriteRepoFile);
546
myWriteRepoFile->release();
547
myWriteRepoFile = NULL;
550
myWriteRepo->unlockRepo(REPO_WRITE);
551
#ifndef MS_COMPACTOR_POLLS
552
if (myWriteRepo->getGarbageLevel() >= PBMSParameters::getGarbageThreshold()) {
553
if (myWriteRepo->myRepoDatabase->myCompactorThread)
554
myWriteRepo->myRepoDatabase->myCompactorThread->wakeup();
557
myWriteRepo->release();
562
uint32_t MSOpenTable::getTableID()
564
return myPool->myPoolTable->myTableID;
567
MSTable *MSOpenTable::getDBTable()
569
return myPool->myPoolTable;
572
MSDatabase *MSOpenTable::getDB()
574
return myPool->myPoolDB;
577
void MSOpenTable::formatBlobURL(PBMSBlobURLPtr blob_url, uint64_t blob_id, uint32_t auth_code, uint64_t blob_size, uint32_t tab_id, uint64_t blob_ref_id)
581
blob.bu_type = MS_URL_TYPE_BLOB;
582
blob.bu_db_id = getDB()->myDatabaseID;
583
blob.bu_tab_id = tab_id;
584
blob.bu_blob_id = blob_id;
585
blob.bu_auth_code = auth_code;
586
blob.bu_server_id = PBMSParameters::getServerID();
587
blob.bu_blob_size = blob_size;
588
blob.bu_blob_ref_id = blob_ref_id;
590
PBMSBlobURLTools::buildBlobURL(&blob, blob_url);
593
void MSOpenTable::formatBlobURL(PBMSBlobURLPtr blob_url, uint64_t blob_id, uint32_t auth_code, uint64_t blob_size, uint64_t blob_ref_id)
595
formatBlobURL(blob_url, blob_id, auth_code, blob_size, getDBTable()->myTableID, blob_ref_id);
597
void MSOpenTable::formatRepoURL(PBMSBlobURLPtr blob_url, uint32_t log_id, uint64_t log_offset, uint32_t auth_code, uint64_t blob_size)
601
blob.bu_type = MS_URL_TYPE_REPO;
602
blob.bu_db_id = getDB()->myDatabaseID;
603
blob.bu_tab_id = log_id;
604
blob.bu_blob_id = log_offset;
605
blob.bu_auth_code = auth_code;
606
blob.bu_server_id = PBMSParameters::getServerID();
607
blob.bu_blob_size = blob_size;
608
blob.bu_blob_ref_id = 0;
610
PBMSBlobURLTools::buildBlobURL(&blob, blob_url);
613
MSOpenTable *MSOpenTable::newOpenTable(MSOpenTablePool *pool)
617
if (!(otab = new MSOpenTable()))
618
CSException::throwOSError(CS_CONTEXT, ENOMEM);
619
if ((otab->myPool = pool))
620
otab->isNotATable = pool->myPoolTable == NULL;
622
otab->isNotATable = false;
628
* ---------------------------------------------------------------
632
MSOpenTablePool::MSOpenTablePool():
641
MSOpenTablePool::~MSOpenTablePool()
644
removeOpenTablesNotInUse();
645
/* With this, I also delete those that are in use!: */
648
myPoolTable->release();
654
void MSOpenTablePool::check()
656
MSOpenTable *otab, *ptab;
659
if ((otab = (MSOpenTable *) iPoolTables.getBack())) {
668
ptab = ptab->nextTable;
676
otab = (MSOpenTable *) otab->getNextLink();
685
* This returns the table referenced. So it is safe from the pool being
688
MSOpenTable *MSOpenTablePool::getPoolTable()
692
if ((otab = iTablePool)) {
693
iTablePool = otab->nextTable;
694
otab->nextTable = NULL;
695
ASSERT(!otab->inUse);
702
void MSOpenTablePool::returnOpenTable(MSOpenTable *otab)
705
otab->nextTable = iTablePool;
710
* Add a table to the pool, but do not release it!
712
void MSOpenTablePool::addOpenTable(MSOpenTable *otab)
714
iPoolTables.addFront(otab);
717
void MSOpenTablePool::removeOpenTable(MSOpenTable *otab)
720
iPoolTables.remove(otab);
723
void MSOpenTablePool::removeOpenTablesNotInUse()
725
MSOpenTable *otab, *curr_otab;
728
/* Remove all tables that are not in use: */
729
if ((otab = (MSOpenTable *) iPoolTables.getBack())) {
732
otab = (MSOpenTable *) otab->getNextLink();
733
if (!curr_otab->inUse)
734
iPoolTables.remove(curr_otab);
739
void MSOpenTablePool::returnToPool()
741
MSTableList::removeTablePool(this);
744
MSOpenTablePool *MSOpenTablePool::newPool(uint32_t db_id, uint32_t tab_id)
746
MSOpenTablePool *pool;
749
if (!(pool = new MSOpenTablePool())) {
750
CSException::throwOSError(CS_CONTEXT, ENOMEM);
753
pool->myPoolDB = MSDatabase::getDatabase(db_id);
754
pool->myPoolTableID = tab_id;
756
pool->myPoolTable = pool->myPoolDB->getTable(tab_id, false);
762
* ---------------------------------------------------------------
766
CSSyncOrderedList *MSTableList::gPoolListByID;
768
MSTableList::MSTableList()
772
MSTableList::~MSTableList()
776
void MSTableList::startUp()
778
new_(gPoolListByID, CSSyncOrderedList);
781
void MSTableList::shutDown()
784
gPoolListByID->clear();
785
gPoolListByID->release();
786
gPoolListByID = NULL;
790
class MSTableKey : public CSOrderKey {
792
uint32_t myKeyDatabaseID;
793
uint32_t myKeyTableID;
795
MSTableKey(): myKeyDatabaseID(0), myKeyTableID(0){ }
797
virtual ~MSTableKey() {
800
int compareKey(CSObject *key) {return CSObject::compareKey(key);}
801
virtual int compareKey(CSOrderKey *x) {
802
MSTableKey *key = (MSTableKey *) x;
805
if (myKeyDatabaseID < key->myKeyDatabaseID)
807
else if (myKeyDatabaseID > key->myKeyDatabaseID)
811
if (myKeyTableID < key->myKeyTableID)
813
else if (myKeyTableID > key->myKeyTableID)
820
static MSTableKey *newTableKey(uint32_t db_id, uint32_t tab_id)
824
if (!(key = new MSTableKey())) {
825
CSException::throwOSError(CS_CONTEXT, ENOMEM);
827
key->myKeyDatabaseID = db_id;
828
key->myKeyTableID = tab_id;
833
MSOpenTable *MSTableList::getOpenTableByID(uint32_t db_id, uint32_t tab_id)
835
MSOpenTablePool *pool;
836
MSOpenTable *otab = NULL;
840
lock_(gPoolListByID);
841
key.myKeyDatabaseID = db_id;
842
key.myKeyTableID = tab_id;
843
pool = (MSOpenTablePool *) gPoolListByID->find(&key);
846
pool = MSOpenTablePool::newPool(db_id, tab_id);
847
key_ptr = MSTableKey::newTableKey(db_id, tab_id);
848
gPoolListByID->add(key_ptr, pool);
850
if (!(otab = pool->getPoolTable())) {
851
otab = MSOpenTable::newOpenTable(pool);
852
pool->addOpenTable(otab);
855
unlock_(gPoolListByID);
859
MSOpenTable *MSTableList::getOpenTableForDB(uint32_t db_id)
861
return(MSTableList::getOpenTableByID(db_id, 0));
865
void MSTableList::releaseTable(MSOpenTable *otab)
867
MSOpenTablePool *pool;
870
lock_(gPoolListByID);
872
if ((pool = otab->myPool)) {
873
if (pool->isRemovingTP) {
874
pool->removeOpenTable(otab);
875
gPoolListByID->wakeup();
878
pool->returnOpenTable(otab);
881
unlock_(gPoolListByID);
885
bool MSTableList::removeTablePoolIfEmpty(MSOpenTablePool *pool)
888
if (pool->getSize() == 0) {
891
key.myKeyDatabaseID = pool->myPoolDB->myDatabaseID;
892
key.myKeyTableID = pool->myPoolTableID;
893
gPoolListByID->remove(&key);
894
/* TODO: Remove the table from the database, if it does not exist
902
void MSTableList::removeTablePool(MSOpenTablePool *pool)
905
lock_(gPoolListByID);
907
pool->isRemovingTP = true;
908
pool->removeOpenTablesNotInUse();
909
if (removeTablePoolIfEmpty(pool))
913
* Wait for the tables that are in use to be
916
gPoolListByID->wait();
918
unlock_(gPoolListByID);
923
* Close the pool associated with this open table.
925
void MSTableList::removeTablePool(MSOpenTable *otab)
927
MSOpenTablePool *pool;
930
key.myKeyDatabaseID = otab->getDB()->myDatabaseID;
931
key.myKeyTableID = otab->getTableID();
935
lock_(gPoolListByID);
937
if (!(pool = (MSOpenTablePool *) gPoolListByID->find(&key)))
939
pool->isRemovingTP = true;
940
pool->removeOpenTablesNotInUse();
941
if (removeTablePoolIfEmpty(pool))
944
* Wait for the tables that are in use to be
947
gPoolListByID->wait();
949
unlock_(gPoolListByID);
954
void MSTableList::removeDatabaseTables(MSDatabase *database)
956
MSOpenTablePool *pool;
964
lock_(gPoolListByID);
966
while ((pool = (MSOpenTablePool *) gPoolListByID->itemAt(idx))) {
967
if (pool->myPoolDB == database) {
972
unlock_(gPoolListByID);
975
removeTablePool(pool);
983
// lockTablePoolForDeletion() is only called to lock a pool for a table which is about to be removed.
984
// When the pool is returned then it will be removed from the global pool list.
985
MSOpenTablePool *MSTableList::lockTablePoolForDeletion(uint32_t db_id, uint32_t tab_id, CSString *db_name, CSString *tab_name)
987
MSOpenTablePool *pool;
996
key.myKeyDatabaseID = db_id;
997
key.myKeyTableID = tab_id;
999
lock_(gPoolListByID);
1002
if (!(pool = (MSOpenTablePool *) gPoolListByID->find(&key))) {
1003
char buffer[CS_EXC_MESSAGE_SIZE];
1005
cs_strcpy(CS_EXC_MESSAGE_SIZE, buffer, "Table is temporarily not available: ");
1006
cs_strcat(CS_EXC_MESSAGE_SIZE, buffer, db_name->getCString());
1008
cs_strcat(CS_EXC_MESSAGE_SIZE, buffer, ".");
1009
cs_strcat(CS_EXC_MESSAGE_SIZE, buffer, tab_name->getCString());
1011
CSException::throwException(CS_CONTEXT, MS_ERR_TABLE_LOCKED, buffer);
1013
pool->isRemovingTP = true;
1014
pool->removeOpenTablesNotInUse();
1015
if (pool->getSize() == 0) {
1016
// pool->retain(); Do not do this. The return to pool will free this by removing it from the list.
1020
* Wait for the tables that are in use to be
1023
gPoolListByID->wait();
1025
unlock_(gPoolListByID);
1034
MSOpenTablePool *MSTableList::lockTablePoolForDeletion(MSTable *tab)
1036
CSString *tab_name = NULL, *db_name;
1037
uint32_t db_id, tab_id;
1041
db_name = tab->myDatabase->myDatabaseName;
1044
tab_name = tab->myTableName;
1047
db_id = tab->myDatabase->myDatabaseID;
1048
tab_id = tab->myTableID;
1052
return_( lockTablePoolForDeletion(db_id, tab_id, db_name, tab_name));
1055
MSOpenTablePool *MSTableList::lockTablePoolForDeletion(MSOpenTable *otab)
1057
CSString *tab_name = NULL, *db_name;
1058
uint32_t db_id, tab_id;
1063
tab = otab->getDBTable();
1065
tab_name = tab->myTableName;
1069
db_name = otab->getDB()->myDatabaseName;
1072
db_id = otab->getDB()->myDatabaseID;
1073
tab_id = otab->getTableID();
1075
otab->returnToPool();
1077
return_( lockTablePoolForDeletion(db_id, tab_id, db_name, tab_name));