Fix for MOT DDLs in a transaction

This commit is contained in:
Vinoth
2020-08-26 11:11:36 +08:00
parent ed27420caa
commit 23d7a6d34d
10 changed files with 290 additions and 269 deletions

View File

@ -31,7 +31,7 @@
namespace MOT {
IMPLEMENT_CLASS_LOGGER(Index, Storage);
std::atomic<uint32_t> Index::m_indexCounter(0);
std::atomic<uint32_t> MOT::Index::m_indexCounter(0);
uint64_t Index::GetSize() const
{
@ -497,4 +497,14 @@ Index* Index::CloneEmpty()
return clonedIndex;
}
MOTIndexArr::MOTIndexArr(MOT::Table* table)
{
m_numIndexes = 0;
m_table = table;
errno_t erc = memset_s(m_indexArr, MAX_NUM_INDEXES * sizeof(MOT::Index*), 0, MAX_NUM_INDEXES * sizeof(MOT::Index*));
securec_check(erc, "\0", "\0");
erc = memset_s(m_origIx, MAX_NUM_INDEXES * sizeof(uint16_t), 0, MAX_NUM_INDEXES * sizeof(uint16_t));
securec_check(erc, "\0", "\0");
}
} // namespace MOT

View File

@ -96,6 +96,9 @@ public:
m_unique = isUnique;
m_indexId = m_indexCounter.fetch_add(1, std::memory_order_relaxed);
if (m_indexExtId == 0) {
m_indexExtId = m_indexId;
}
if (m_keyLength > MAX_KEY_SIZE)
return RC_INDEX_EXCEEDS_MAX_SIZE;
@ -717,6 +720,57 @@ protected:
DECLARE_CLASS_LOGGER()
};
/**
* @class MOTIndexArr
* @brief This class contains a temporary copy of index array of the table.
*/
class MOTIndexArr {
public:
explicit MOTIndexArr(MOT::Table* table);
MOT::Index* GetIndex(uint16_t ix)
{
if (likely(ix < m_numIndexes)) {
return m_indexArr[ix];
}
return nullptr;
}
uint16_t GetIndexIx(uint16_t ix)
{
if (likely(ix < m_numIndexes)) {
return m_origIx[ix];
}
return MAX_NUM_INDEXES;
}
void Add(uint16_t ix, MOT::Index* index)
{
if (likely(m_numIndexes < MAX_NUM_INDEXES)) {
m_indexArr[m_numIndexes] = index;
m_origIx[m_numIndexes] = ix;
m_numIndexes++;
}
}
uint16_t GetNumIndexes()
{
return m_numIndexes;
}
MOT::Table* GetTable()
{
return m_table;
}
private:
MOT::Index* m_indexArr[MAX_NUM_INDEXES];
MOT::Table* m_table;
uint16_t m_origIx[MAX_NUM_INDEXES];
uint16_t m_numIndexes;
};
} // namespace MOT
#endif /* INDEX_H */

View File

@ -138,7 +138,7 @@ void Table::ClearThreadMemoryCache()
}
}
void Table::IncIndexColumnUsage(Index* index)
void Table::IncIndexColumnUsage(MOT::Index* index)
{
int16_t const* index_cols = index->GetColumnKeyFields();
for (int16_t i = 0; i < index->GetNumFields(); i++) {
@ -149,7 +149,7 @@ void Table::IncIndexColumnUsage(Index* index)
}
}
void Table::DecIndexColumnUsage(Index* index)
void Table::DecIndexColumnUsage(MOT::Index* index)
{
int16_t const* index_cols = index->GetColumnKeyFields();
for (int16_t i = 0; i < index->GetNumFields(); i++) {
@ -179,7 +179,7 @@ bool Table::IsTableEmpty(uint32_t tid)
return res;
}
void Table::SetPrimaryIndex(Index* index)
void Table::SetPrimaryIndex(MOT::Index* index)
{
if (index != nullptr) {
index->SetTable(this);
@ -188,11 +188,11 @@ void Table::SetPrimaryIndex(Index* index)
m_indexes[0] = index;
}
bool Table::UpdatePrimaryIndex(Index* index, TxnManager* txn, uint32_t tid)
bool Table::UpdatePrimaryIndex(MOT::Index* index, TxnManager* txn, uint32_t tid)
{
if (this->m_primaryIndex) {
if (txn == nullptr) {
if (DeletePrimaryIndex(this->m_primaryIndex) != RC_OK) {
if (DeleteIndex(this->m_primaryIndex) != RC_OK) {
return false;
}
} else {
@ -212,15 +212,16 @@ bool Table::UpdatePrimaryIndex(Index* index, TxnManager* txn, uint32_t tid)
return true;
}
RC Table::DeletePrimaryIndex(MOT::Index* index)
RC Table::DeleteIndex(MOT::Index* index)
{
GcManager::ClearIndexElements(index->GetIndexId());
DecIndexColumnUsage(index);
delete index;
return RC::RC_OK;
}
bool Table::AddSecondaryIndex(const string& indexName, Index* index, TxnManager* txn, uint32_t tid)
bool Table::AddSecondaryIndex(const string& indexName, MOT::Index* index, TxnManager* txn, uint32_t tid)
{
// OA: Should we check for duplicate indices with same name?
// first create secondary index data
@ -247,7 +248,7 @@ bool Table::AddSecondaryIndex(const string& indexName, Index* index, TxnManager*
return true;
}
bool Table::CreateSecondaryIndexDataNonTransactional(Index* index, uint32_t tid)
bool Table::CreateSecondaryIndexDataNonTransactional(MOT::Index* index, uint32_t tid)
{
MaxKey key;
bool ret = true;
@ -286,7 +287,7 @@ bool Table::CreateSecondaryIndexDataNonTransactional(Index* index, uint32_t tid)
}
return ret;
}
bool Table::CreateSecondaryIndexData(Index* index, TxnManager* txn)
bool Table::CreateSecondaryIndexData(MOT::Index* index, TxnManager* txn)
{
RC status = RC_OK;
bool error = false;
@ -459,6 +460,7 @@ RC Table::InsertRow(Row* row, TxnManager* txn)
key = txn->GetTxnKey(ix);
if (key == nullptr) {
DestroyRow(row);
MOT_REPORT_ERROR(MOT_ERROR_OOM, "Insert Row", "Failed to create primary key");
return RC_MEMORY_ALLOCATION_ERROR;
}
@ -485,6 +487,7 @@ RC Table::InsertRow(Row* row, TxnManager* txn)
MOTCurrTxn->DestroyTxnKey(cleanupKeys[j]);
}
}
DestroyRow(row);
MOTCurrTxn->Rollback();
return RC_MEMORY_ALLOCATION_ERROR;
}
@ -560,7 +563,7 @@ Row* Table::RemoveKeyFromIndex(Row* row, Sentinel* sentinel, uint64_t tid, GcMan
{
MaxKey key;
Row* OutputRow = nullptr;
Index* ix = sentinel->GetIndex();
MOT::Index* ix = sentinel->GetIndex();
Sentinel* currSentinel = nullptr;
MOT_ASSERT(sentinel != nullptr);
RC rc = sentinel->RefCountUpdate(DEC, tid);
@ -832,12 +835,13 @@ char* Table::DesrializeMeta(char* dataIn, CommonColumnMeta& meta)
return dataIn;
}
size_t Table::SerializeItemSize(Index* index)
size_t Table::SerializeItemSize(MOT::Index* index)
{
size_t ret = SerializableSTR::SerializeSize(index->m_name) +
SerializablePOD<uint32_t>::SerializeSize(index->m_keyLength) +
SerializablePOD<IndexOrder>::SerializeSize(index->m_indexOrder) +
SerializablePOD<IndexingMethod>::SerializeSize(index->m_indexingMethod) +
SerializablePOD<uint64_t>::SerializeSize(index->m_indexExtId) +
SerializablePOD<bool>::SerializeSize(index->GetUnique()) +
SerializablePOD<int16_t>::SerializeSize(index->m_numKeyFields) +
SerializablePOD<uint32_t>::SerializeSize(index->m_numTableFields) +
@ -847,7 +851,7 @@ size_t Table::SerializeItemSize(Index* index)
return ret;
}
char* Table::SerializeItem(char* dataOut, Index* index)
char* Table::SerializeItem(char* dataOut, MOT::Index* index)
{
if (!index || !dataOut) {
return nullptr;
@ -860,6 +864,7 @@ char* Table::SerializeItem(char* dataOut, Index* index)
dataOut = SerializablePOD<uint32_t>::Serialize(dataOut, keyLength);
dataOut = SerializablePOD<IndexOrder>::Serialize(dataOut, index->m_indexOrder);
dataOut = SerializablePOD<IndexingMethod>::Serialize(dataOut, index->m_indexingMethod);
dataOut = SerializablePOD<uint64_t>::Serialize(dataOut, index->m_indexExtId);
dataOut = SerializablePOD<bool>::Serialize(dataOut, index->GetUnique());
dataOut = SerializablePOD<int16_t>::Serialize(dataOut, index->m_numKeyFields);
dataOut = SerializablePOD<uint32_t>::Serialize(dataOut, index->m_numTableFields);
@ -869,24 +874,21 @@ char* Table::SerializeItem(char* dataOut, Index* index)
return dataOut;
}
RC Table::RemoveSecondaryIndex(char* name, TxnManager* txn)
RC Table::RemoveSecondaryIndex(MOT::Index* index, TxnManager* txn)
{
int rmIx = -1;
std::string ixName(name);
Index* index = nullptr;
RC res = RC_OK;
do {
SecondaryIndexMap::iterator itr = m_secondaryIndexes.find(ixName);
SecondaryIndexMap::iterator itr = m_secondaryIndexes.find(index->GetName());
if (MOT_EXPECT_TRUE(itr != m_secondaryIndexes.end())) {
index = itr->second;
MOT_LOG_DEBUG("logging drop index operation (tableId %u), index name: %s index id = %d \n",
GetTableId(),
index->GetName().c_str(),
index->GetIndexId());
m_secondaryIndexes.erase(itr);
} else {
if (m_numIndexes > 0 && (strcmp(m_indexes[0]->GetName().c_str(), name) == 0)) {
MOT_LOG_INFO("Trying to remove primary index %s, not supported", name);
if (m_numIndexes > 0 && (strcmp(m_indexes[0]->GetName().c_str(), index->GetName().c_str()) == 0)) {
MOT_LOG_INFO("Trying to remove primary index %s, not supported", index->GetName().c_str());
break;
}
@ -926,6 +928,7 @@ char* Table::DesrializeMeta(char* dataIn, CommonIndexMeta& meta)
dataIn = SerializablePOD<uint32_t>::Deserialize(dataIn, meta.m_keyLength);
dataIn = SerializablePOD<IndexOrder>::Deserialize(dataIn, meta.m_indexOrder);
dataIn = SerializablePOD<IndexingMethod>::Deserialize(dataIn, meta.m_indexingMethod);
dataIn = SerializablePOD<uint64_t>::Deserialize(dataIn, meta.m_indexExtId);
dataIn = SerializablePOD<bool>::Deserialize(dataIn, meta.m_unique);
dataIn = SerializablePOD<int16_t>::Deserialize(dataIn, meta.m_numKeyFields);
dataIn = SerializablePOD<uint32_t>::Deserialize(dataIn, meta.m_numTableFields);
@ -936,11 +939,11 @@ char* Table::DesrializeMeta(char* dataIn, CommonIndexMeta& meta)
return dataIn;
}
RC Table::CreateIndexFromMeta(
CommonIndexMeta& meta, bool primary, uint32_t tid, bool addToTable /* = true */, Index** outIndex /* = nullptr */)
RC Table::CreateIndexFromMeta(CommonIndexMeta& meta, bool primary, uint32_t tid, bool addToTable /* = true */,
MOT::Index** outIndex /* = nullptr */)
{
IndexTreeFlavor flavor = DEFAULT_TREE_FLAVOR;
Index* ix = nullptr;
MOT::Index* ix = nullptr;
MOT_LOG_DEBUG("%s: %s (%s)", __func__, meta.m_name.c_str(), primary ? "primary" : "secondary");
if (meta.m_indexingMethod == IndexingMethod::INDEXING_METHOD_TREE) {
@ -973,6 +976,7 @@ RC Table::CreateIndexFromMeta(
ix->SetFakePrimary(meta.m_fake);
ix->SetNumIndexFields(meta.m_numKeyFields);
ix->SetTable(this);
ix->SetExtId(meta.m_indexExtId);
if (ix->IndexInit(meta.m_keyLength, meta.m_unique, meta.m_name, nullptr) != RC_OK) {
MOT_REPORT_ERROR(MOT_ERROR_INTERNAL, "Create Index from meta-data", "Failed to initialize index");
delete ix;
@ -1139,7 +1143,7 @@ RC Table::DropImpl()
MOT_LOG_DEBUG("DropImpl numIndexes = %d \n", m_numIndexes);
for (int i = m_numIndexes - 1; i >= 0; i--) {
if (m_indexes[i] != nullptr) {
Index* index = m_indexes[i];
MOT::Index* index = m_indexes[i];
// first remove index from table metadata to prevent it's usage
m_indexes[i] = nullptr;
GcManager::ClearIndexElements(index->GetIndexId());

View File

@ -63,7 +63,7 @@ class alignas(CL_SIZE) Table : public Serializable {
// allow privileged access
friend TxnManager;
friend TxnInsertAction;
friend Index;
friend MOT::Index;
friend RecoveryManager;
friend TxnDDLAccess;
@ -148,7 +148,7 @@ public:
* @brief Retrieves the primary index of the table.
* @return The index object.
*/
inline Index* GetPrimaryIndex() const
inline MOT::Index* GetPrimaryIndex() const
{
return m_primaryIndex;
}
@ -158,9 +158,9 @@ public:
* @param indexName The name of the index to retrieve.
* @return The secondary index with indicating whether it has unique keys or not.
*/
inline Index* GetSecondaryIndex(const string& indexName)
inline MOT::Index* GetSecondaryIndex(const string& indexName)
{
Index* result = nullptr;
MOT::Index* result = nullptr;
SecondaryIndexMap::iterator itr = m_secondaryIndexes.find(indexName);
if (MOT_EXPECT_TRUE(itr != m_secondaryIndexes.end())) {
result = itr->second;
@ -168,12 +168,12 @@ public:
return result;
}
inline Index* GetSecondaryIndex(uint16_t ix) const
inline MOT::Index* GetSecondaryIndex(uint16_t ix) const
{
return (Index*)m_indexes[ix];
return (MOT::Index*)m_indexes[ix];
}
inline Index* GetIndex(uint16_t ix) const
inline MOT::Index* GetIndex(uint16_t ix) const
{
return m_indexes[ix];
}
@ -182,7 +182,7 @@ public:
* @brief Sets the primary index for the table.
* @param index The index to set.
*/
void SetPrimaryIndex(Index* index);
void SetPrimaryIndex(MOT::Index* index);
/**
* @brief Sets the primary index for the table (replaces previously created fake primary.
@ -190,7 +190,7 @@ public:
* @param txn The current transaction.
* @param tid Current thread id
*/
bool UpdatePrimaryIndex(Index* index, TxnManager* txn, uint32_t tid);
bool UpdatePrimaryIndex(MOT::Index* index, TxnManager* txn, uint32_t tid);
/**
* @brief Adds a secondary index to the table.
@ -200,7 +200,7 @@ public:
* @param tid The identifier of the requesting process/thread.
* @return Boolean value denoting success or failure.
*/
bool AddSecondaryIndex(const string& indexName, Index* index, TxnManager* txn, uint32_t tid);
bool AddSecondaryIndex(const string& indexName, MOT::Index* index, TxnManager* txn, uint32_t tid);
/**
* @brief Index a table using a secondary index.
@ -216,14 +216,55 @@ public:
* @param txn The txn manager object.
* @return RC value denoting the operation's completion status.
*/
RC RemoveSecondaryIndex(char* name, TxnManager* txn);
RC RemoveSecondaryIndex(MOT::Index* index, TxnManager* txn);
/**
* @brief Deletes a primary index.
* @brief Remove Index from table meta data.
* @param index The index to use.
* @return void.
*/
void RemoveSecondaryIndexFromMetaData(MOT::Index* index) {
if (!index->IsPrimaryKey()) {
uint16_t rmIx = 0;
for (uint16_t i = 1; i < m_numIndexes; i++) {
if (m_indexes[i] == index) {
rmIx = i;
break;
}
}
// prevent removing primary by mistake
if (rmIx > 0) {
m_numIndexes--;
for (uint16_t i = rmIx; i < m_numIndexes; i++) {
m_indexes[i] = m_indexes[i + 1];
}
m_secondaryIndexes[index->GetName()] = nullptr;
m_indexes[m_numIndexes] = nullptr;
}
}
}
/**
* @brief Add Index to table meta data.
* @param index The index to use.
* @return void.
*/
void AddSecondaryIndexToMetaData(MOT::Index* index) {
if (!index->IsPrimaryKey()) {
m_secondaryIndexes[index->GetName()] = index;
m_indexes[m_numIndexes] = index;
++m_numIndexes;
}
}
/**
* @brief Deletes an index.
* @param the index to remove.
* @return RC value denoting the operation's completion status.
*/
RC DeletePrimaryIndex(MOT::Index* index);
RC DeleteIndex(MOT::Index* index);
/**
* @brief Checks if table contains data.
@ -262,13 +303,13 @@ public:
* @brief Increases the column usage on an index.
* @param index The index to perform on.
*/
void IncIndexColumnUsage(Index* index);
void IncIndexColumnUsage(MOT::Index* index);
/**
* @brief Deccreases the column usage on an index.
* @param index The index to perform on.
*/
void DecIndexColumnUsage(Index* index);
void DecIndexColumnUsage(MOT::Index* index);
/**
* @brief Retrieves an iterator to the first row in the primary index.
@ -288,7 +329,7 @@ public:
* @param result The resulting row (indirected through sItem object).
* @return Result code denoting success or failure reason.
*/
inline RC QuerySecondaryIndex(const Index* index, Key const* const& key, void*& result)
inline RC QuerySecondaryIndex(const MOT::Index* index, Key const* const& key, void*& result)
{
RC rc = RC_OK;
@ -312,7 +353,7 @@ public:
* @param pid The identifier of the requesting process/thread.
* @return Result code denoting success or failure reason.
*/
inline RC QuerySecondaryIndex(const Index* index, Key const* const& key, bool matchKey, IndexIterator*& result,
inline RC QuerySecondaryIndex(const MOT::Index* index, Key const* const& key, bool matchKey, IndexIterator*& result,
bool forwardDirection, uint32_t pid)
{
RC rc = RC_OK;
@ -356,7 +397,7 @@ public:
* @param pid The logical identifier of the requesting thread.
* @return Return code denoting success or failure reason.
*/
inline RC FindRowByIndexId(Index* index, Key const* const& key, Sentinel*& result, const uint32_t& pid)
inline RC FindRowByIndexId(MOT::Index* index, Key const* const& key, Sentinel*& result, const uint32_t& pid)
{
RC rc = RC_ERROR;
@ -473,7 +514,7 @@ public:
* @param index The secondary index.
* @return The secondary index key length.
*/
uint16_t GetLengthSecondaryKey(Index* index) const
uint16_t GetLengthSecondaryKey(MOT::Index* index) const
{
return index->GetKeyLength();
}
@ -519,7 +560,7 @@ public:
* @param tid The logical identifier of the requesting thread.
* @return Status of the operation.
*/
bool CreateSecondaryIndexDataNonTransactional(Index* index, uint32_t tid);
bool CreateSecondaryIndexDataNonTransactional(MOT::Index* index, uint32_t tid);
/**
* @brief Inserts a new row into transactional storage.
@ -787,7 +828,7 @@ private:
// we have only index-organized-tables (IOT) so this is the pointer to the index
// representing the table
/** @var The primary index holding all rows. */
Index* m_primaryIndex;
MOT::Index* m_primaryIndex;
/** @var Number of fields in the table schema. */
uint32_t m_fieldCnt;
@ -807,7 +848,7 @@ private:
Column** m_columns = NULL;
/** @var Secondary index array. */
Index** m_indexes = NULL;
MOT::Index** m_indexes = NULL;
/** @var Current table unique identifier. */
uint32_t m_tableId = tableCounter++;
@ -817,7 +858,7 @@ private:
uint64_t m_tableExId;
/** @typedef Secondary index map (indexed by index name). */
typedef std::map<string, Index*> SecondaryIndexMap;
typedef std::map<string, MOT::Index*> SecondaryIndexMap;
/** @var Secondary index map accessed by name. */
SecondaryIndexMap m_secondaryIndexes;
@ -880,6 +921,8 @@ public:
IndexingMethod m_indexingMethod;
uint64_t m_indexExtId;
int16_t m_numKeyFields;
uint32_t m_numTableFields;

View File

@ -611,7 +611,7 @@ void RecoveryManager::FreeRedoSegment(LogSegment* segment)
bool RecoveryManager::ApplyRedoLog(uint64_t redoLsn, char* data, size_t len)
{
if (redoLsn < m_lsn) {
if (redoLsn <= m_lsn) {
// ignore old redo records which are prior to our checkpoint LSN
MOT_LOG_DEBUG("ApplyRedoLog - ignoring old redo record. Checkpoint LSN: %lu, redo LSN: %lu", m_lsn, redoLsn);
return true;

View File

@ -522,6 +522,7 @@ void RecoveryManager::InsertRow(uint64_t tableId, uint64_t exId, char* keyData,
MOTCurrTxn->DestroyTxnKey(cleanupKeys[j]);
}
}
table->DestroyRow(row);
MOTCurrTxn->Rollback();
return;
}
@ -541,7 +542,6 @@ void RecoveryManager::InsertRow(uint64_t tableId, uint64_t exId, char* keyData,
status = RC_OK;
} else if (status == RC_MEMORY_ALLOCATION_ERROR) {
MOT_REPORT_ERROR(MOT_ERROR_OOM, "Recovery Manager Insert Row", "failed to insert row");
table->DestroyRow(row);
}
}

View File

@ -62,7 +62,7 @@ InsItem* TxnManager::GetNextInsertItem(Index* index)
return m_accessMgr->GetInsertMgr()->GetInsertItem(index);
}
Key* TxnManager::GetTxnKey(Index* index)
Key* TxnManager::GetTxnKey(MOT::Index* index)
{
int size = index->GetAlignedKeyLength() + sizeof(Key);
void* buf = MemSessionAlloc(size);
@ -429,7 +429,7 @@ void TxnManager::UndoInserts()
for (const auto& ra_pair : OrderedSet) {
Access* ac = ra_pair.second;
if (ac->m_type == AccessType::INS) {
Index* index_ = ac->GetSentinel()->GetIndex();
MOT::Index* index_ = ac->GetSentinel()->GetIndex();
// Row is local and was not inserted in the commit
if (index_->GetIndexOrder() == IndexOrder::INDEX_ORDER_PRIMARY) {
// Release local row to the GC!!!!!
@ -448,7 +448,7 @@ RC TxnManager::RollbackInsert(Access* ac)
Sentinel* outputSen = nullptr;
RC rc;
Sentinel* sentinel = ac->GetSentinel();
Index* index_ = sentinel->GetIndex();
MOT::Index* index_ = sentinel->GetIndex();
MOT_ASSERT(sentinel != nullptr);
rc = sentinel->RefCountUpdate(DEC, GetThdId());
@ -498,8 +498,8 @@ void TxnManager::RollbackDDLs()
// rollback DDLs in reverse order (avoid rolling back parent object before rolling back child)
for (int i = m_txnDdlAccess->Size() - 1; i >= 0; i--) {
Index* index = nullptr;
Index** indexes = nullptr;
MOT::Index* index = nullptr;
MOTIndexArr* indexArr = nullptr;
Table* table = nullptr;
TxnDDLAccess::DDLAccess* ddl_access = m_txnDdlAccess->Get(i);
switch (ddl_access->GetDDLAccessType()) {
@ -516,23 +516,28 @@ void TxnManager::RollbackDDLs()
MOT_LOG_INFO("Rollback of drop table %s", table->GetLongTableName().c_str());
break;
case DDL_ACCESS_TRUNCATE_TABLE:
indexes = (Index**)ddl_access->GetEntry();
table = indexes[0]->GetTable();
MOT_LOG_INFO("Rollback of truncate table %s", table->GetLongTableName().c_str());
table->WrLock();
for (int idx = 0; idx < table->GetNumIndexes(); idx++) {
index = table->m_indexes[idx];
table->m_indexes[idx] = indexes[idx];
if (idx == 0)
table->m_primaryIndex = indexes[idx];
else
table->m_secondaryIndexes[indexes[idx]->GetName()] = indexes[idx];
GcManager::ClearIndexElements(index->GetIndexId());
index->Truncate(true);
delete index;
indexArr = (MOTIndexArr*)ddl_access->GetEntry();
if (indexArr->GetNumIndexes() > 0) {
MOT_ASSERT(indexArr->GetNumIndexes() == table->GetNumIndexes());
table = indexArr->GetTable();
MOT_LOG_INFO("Rollback of truncate table %s", table->GetLongTableName().c_str());
table->WrLock();
for (int idx = 0; idx < indexArr->GetNumIndexes(); idx++) {
uint16_t oldIx = indexArr->GetIndexIx(idx);
MOT::Index* oldIndex = indexArr->GetIndex(idx);
index = table->m_indexes[oldIx];
table->m_indexes[oldIx] = oldIndex;
if (idx == 0)
table->m_primaryIndex = oldIndex;
else
table->m_secondaryIndexes[oldIndex->GetName()] = oldIndex;
GcManager::ClearIndexElements(index->GetIndexId());
index->Truncate(true);
delete index;
}
table->Unlock();
}
table->Unlock();
delete[] indexes;
delete indexArr;
break;
case DDL_ACCESS_CREATE_INDEX:
index = (Index*)ddl_access->GetEntry();
@ -543,10 +548,9 @@ void TxnManager::RollbackDDLs()
table->WrLock();
if (index->IsPrimaryKey()) {
table->SetPrimaryIndex(nullptr);
GcManager::ClearIndexElements(index->GetIndexId());
table->DeletePrimaryIndex(index);
table->DeleteIndex(index);
} else {
table->RemoveSecondaryIndex((char*)index->GetName().c_str(), this);
table->RemoveSecondaryIndex(index, this);
}
table->Unlock();
break;
@ -556,11 +560,13 @@ void TxnManager::RollbackDDLs()
MOT_LOG_INFO("Rollback of drop index %s for table %s",
index->GetName().c_str(),
table->GetLongTableName().c_str());
table->WrLock();
if (index->IsPrimaryKey()) {
table->WrLock();
table->SetPrimaryIndex(index);
table->Unlock();
} else {
table->AddSecondaryIndexToMetaData(index);
}
table->Unlock();
break;
default:
break;
@ -574,8 +580,8 @@ void TxnManager::WriteDDLChanges()
if (m_txnDdlAccess->Size() == 0)
return;
Index* index = nullptr;
Index** indexes = nullptr;
MOT::Index* index = nullptr;
MOTIndexArr* indexArr = nullptr;
Table* table = nullptr;
for (uint16_t i = 0; i < m_txnDdlAccess->Size(); i++) {
TxnDDLAccess::DDLAccess* ddl_access = m_txnDdlAccess->Get(i);
@ -587,18 +593,20 @@ void TxnManager::WriteDDLChanges()
GetTableManager()->DropTable((Table*)ddl_access->GetEntry(), m_sessionContext);
break;
case DDL_ACCESS_TRUNCATE_TABLE:
indexes = (Index**)ddl_access->GetEntry();
table = indexes[0]->GetTable();
table->WrLock();
table->m_rowCount = 0;
for (int i = 0; i < table->GetNumIndexes(); i++) {
index = indexes[i];
GcManager::ClearIndexElements(index->GetIndexId());
index->Truncate(true);
delete index;
indexArr = (MOTIndexArr*)ddl_access->GetEntry();
if (indexArr->GetNumIndexes() > 0) {
table = indexArr->GetTable();
table->WrLock();
table->m_rowCount = 0;
for (int i = 0; i < indexArr->GetNumIndexes(); i++) {
index = indexArr->GetIndex(i);
GcManager::ClearIndexElements(index->GetIndexId());
index->Truncate(true);
delete index;
}
table->Unlock();
}
table->Unlock();
delete[] indexes;
delete indexArr;
break;
case DDL_ACCESS_CREATE_INDEX:
index = (Index*)ddl_access->GetEntry();
@ -616,11 +624,8 @@ void TxnManager::WriteDDLChanges()
table->WrLock();
if (index->IsPrimaryKey()) {
table->SetPrimaryIndex(nullptr);
GcManager::ClearIndexElements(index->GetIndexId());
table->DeletePrimaryIndex(index);
} else {
table->RemoveSecondaryIndex((char*)index->GetName().c_str(), this);
}
table->DeleteIndex(index);
table->Unlock();
break;
default:
@ -886,7 +891,7 @@ RC TxnInsertAction::ExecuteOptimisticInsert(Row* row)
while (currentItem != EndCursor()) {
isInserted = true;
isMappedToCache = false;
bool res = reinterpret_cast<Index*>(currentItem->m_index)
bool res = reinterpret_cast<MOT::Index*>(currentItem->m_index)
->IndexInsert(pIndexInsertResult, currentItem->m_key, m_manager->GetThdId(), rc);
if (unlikely(rc == RC_MEMORY_ALLOCATION_ERROR)) {
ReportError(rc);
@ -953,7 +958,7 @@ end:
if (isInserted == true) {
if (isMappedToCache == false) {
RC rc = pIndexInsertResult->RefCountUpdate(DEC, m_manager->GetThdId());
Index* index_ = pIndexInsertResult->GetIndex();
MOT::Index* index_ = pIndexInsertResult->GetIndex();
if (rc == RC::RC_INDEX_DELETE) {
// Memory reclamation need to release the key from the primary sentinel back to the pool
MOT_ASSERT(pIndexInsertResult->GetCounter() == 0);
@ -1022,6 +1027,8 @@ Table* TxnManager::GetTableByExternalId(uint64_t id)
switch (ddl_access->GetDDLAccessType()) {
case DDL_ACCESS_CREATE_TABLE:
return (Table*)ddl_access->GetEntry();
case DDL_ACCESS_TRUNCATE_TABLE:
return ((MOTIndexArr*)ddl_access->GetEntry())->GetTable();
case DDL_ACCESS_DROP_TABLE:
return nullptr;
default:
@ -1034,19 +1041,7 @@ Table* TxnManager::GetTableByExternalId(uint64_t id)
Index* TxnManager::GetIndexByExternalId(uint64_t table_id, uint64_t index_id)
{
TxnDDLAccess::DDLAccess* ddl_access = m_txnDdlAccess->GetByOid(index_id);
if (ddl_access != nullptr) {
switch (ddl_access->GetDDLAccessType()) {
case DDL_ACCESS_CREATE_INDEX:
return (Index*)ddl_access->GetEntry();
case DDL_ACCESS_DROP_INDEX:
return nullptr;
default:
break;
}
}
Table* table = GetTableManager()->GetTableByExternal(table_id);
Table* table = GetTableByExternalId(table_id);
if (table == nullptr) {
return nullptr;
} else {
@ -1054,38 +1049,6 @@ Index* TxnManager::GetIndexByExternalId(uint64_t table_id, uint64_t index_id)
}
}
Index* TxnManager::GetIndex(uint64_t table_id, uint16_t position)
{
TxnDDLAccess::DDLAccess* ddl_access = m_txnDdlAccess->GetByOid(table_id);
Table* table = GetTableByExternalId(table_id);
return GetIndex(table, position);
}
Index* TxnManager::GetIndex(Table* table, uint16_t position)
{
MOT_ASSERT(table != nullptr);
Index* index = table->GetIndex(position);
MOT_ASSERT(index != nullptr);
TxnDDLAccess::DDLAccess* ddl_access = m_txnDdlAccess->GetByOid(index->GetExtId());
if (ddl_access != nullptr) {
switch (ddl_access->GetDDLAccessType()) {
case DDL_ACCESS_CREATE_INDEX:
return index;
case DDL_ACCESS_DROP_INDEX:
return nullptr;
default:
// should print error, the only index operation which are supported
// are create and drop
return nullptr;
}
} else {
if (index->GetIsCommited())
return index;
else
return nullptr;
}
}
RC TxnManager::CreateTable(Table* table)
{
TxnDDLAccess::DDLAccess* ddl_access =
@ -1104,15 +1067,11 @@ RC TxnManager::DropTable(Table* table)
RC res = RC_OK;
// we allocate all memory before action takes place, so that if memory allocation fails, we can report error safely
TxnDDLAccess::DDLAccess* new_ddl_access = nullptr;
TxnDDLAccess::DDLAccess* ddl_access = m_txnDdlAccess->GetByOid(table->GetTableExId());
if ((ddl_access == nullptr) || (ddl_access->GetDDLAccessType() == DDL_ACCESS_TRUNCATE_TABLE)) {
new_ddl_access =
new (std::nothrow) TxnDDLAccess::DDLAccess(table->GetTableExId(), DDL_ACCESS_DROP_TABLE, (void*)table);
if (new_ddl_access == nullptr) {
MOT_REPORT_ERROR(MOT_ERROR_OOM, "Drop Table", "Failed to allocate DDL Access object");
return RC_MEMORY_ALLOCATION_ERROR;
}
TxnDDLAccess::DDLAccess* new_ddl_access =
new (std::nothrow) TxnDDLAccess::DDLAccess(table->GetTableExId(), DDL_ACCESS_DROP_TABLE, (void*)table);
if (new_ddl_access == nullptr) {
MOT_REPORT_ERROR(MOT_ERROR_OOM, "Drop Table", "Failed to allocate DDL Access object");
return RC_MEMORY_ALLOCATION_ERROR;
}
if (!m_isLightSession) {
@ -1132,48 +1091,7 @@ RC TxnManager::DropTable(Table* table)
}
}
if (ddl_access != nullptr) {
if (ddl_access->GetDDLAccessType() == DDL_ACCESS_CREATE_TABLE) {
// this table was created in this transaction, can delete it from the ddl_access
m_txnDdlAccess->EraseByOid(table->GetTableExId());
// check for create and drop index ddls
for (uint16_t i = 0; i < table->GetNumIndexes(); i++) {
m_txnDdlAccess->EraseByOid(table->GetIndex(i)->GetExtId());
}
// erase drop fake primary index if exists
TxnDDLAccess::DDLAccess* iddl = m_txnDdlAccess->GetByOid(table->GetTableExId() + 1);
if (iddl != nullptr) {
MOT::Index* ix = (MOT::Index*)iddl->GetEntry();
GcManager::ClearIndexElements(ix->GetIndexId());
table->DeletePrimaryIndex(ix);
}
table->DropImpl();
RemoveTableFromStat(table);
delete table;
} else if (ddl_access->GetDDLAccessType() == DDL_ACCESS_TRUNCATE_TABLE) {
Index** indexes = (Index**)ddl_access->GetEntry();
table->WrLock();
for (int i = 0; i < table->GetNumIndexes(); i++) {
Index* newIndex = table->m_indexes[i];
Index* oldIndex = indexes[i];
table->m_indexes[i] = oldIndex;
if (i != 0)
table->m_secondaryIndexes[oldIndex->GetName()] = oldIndex;
else
table->m_primaryIndex = oldIndex;
// need to check if need to release memory in a different way? GC?
// assumption is the we deleted all rows
delete newIndex;
}
table->Unlock();
delete[] indexes;
m_txnDdlAccess->EraseByOid(table->GetTableExId());
m_txnDdlAccess->Add(new_ddl_access);
}
} else {
m_txnDdlAccess->Add(new_ddl_access);
}
m_txnDdlAccess->Add(new_ddl_access);
return RC_OK;
}
@ -1182,32 +1100,28 @@ RC TxnManager::TruncateTable(Table* table)
RC res = RC_OK;
if (m_isLightSession) // really?
return res;
TxnDDLAccess::DDLAccess* ddl_access = m_txnDdlAccess->GetByOid(table->GetTableExId());
if (ddl_access != nullptr) {
// must be create table or truncate table
MOT_ASSERT(ddl_access->GetDDLAccessType() == DDL_ACCESS_CREATE_TABLE ||
ddl_access->GetDDLAccessType() == DDL_ACCESS_TRUNCATE_TABLE);
// this is a table that we created or truncated before, should remove all the rows
// belonging to this table from the access and continue
TxnOrderedSet_t& access_row_set = m_accessMgr->GetOrderedRowSet();
TxnOrderedSet_t::iterator it = access_row_set.begin();
while (it != access_row_set.end()) {
Access* ac = it->second;
if (ac->GetTxnRow()->GetTable() == table) {
if (ac->m_type == INS)
RollbackInsert(ac);
it = access_row_set.erase(it);
// need to perform index clean-up!
m_accessMgr->PubReleaseAccess(ac);
} else {
it++;
}
TxnOrderedSet_t& access_row_set = m_accessMgr->GetOrderedRowSet();
TxnOrderedSet_t::iterator it = access_row_set.begin();
while (it != access_row_set.end()) {
Access* ac = it->second;
if (ac->GetTxnRow()->GetTable() == table) {
if (ac->m_type == INS)
RollbackInsert(ac);
it = access_row_set.erase(it);
// need to perform index clean-up!
m_accessMgr->PubReleaseAccess(ac);
} else {
it++;
}
} else {
Index** indexes = nullptr;
indexes = new (std::nothrow) Index*[MAX_NUM_INDEXES];
if (indexes == nullptr) {
// print error, clould not allocate memory
}
TxnDDLAccess::DDLAccess* ddl_access = m_txnDdlAccess->GetByOid(table->GetTableExId());
if (ddl_access == nullptr) {
MOTIndexArr* indexesArr = nullptr;
indexesArr = new (std::nothrow) MOTIndexArr(table);
if (indexesArr == nullptr) {
// print error, could not allocate memory
MOT_REPORT_ERROR(MOT_ERROR_OOM,
"Truncate Table",
"Failed to allocate memory for %u index objects",
@ -1216,36 +1130,39 @@ RC TxnManager::TruncateTable(Table* table)
}
// allocate DDL before work and fail immediately if required
ddl_access = new (std::nothrow)
TxnDDLAccess::DDLAccess(table->GetTableExId(), DDL_ACCESS_TRUNCATE_TABLE, (void*)indexes);
TxnDDLAccess::DDLAccess(table->GetTableExId(), DDL_ACCESS_TRUNCATE_TABLE, (void*)indexesArr);
if (ddl_access == nullptr) {
MOT_REPORT_ERROR(MOT_ERROR_OOM, "Truncate Table", "Failed to allocate memory for DDL Access object");
delete[] indexes;
delete indexesArr;
return RC_MEMORY_ALLOCATION_ERROR;
}
for (int i = 0; i < table->GetNumIndexes(); i++) {
Index* index_copy = table->GetIndex(i)->CloneEmpty();
for (uint16_t i = 0; i < table->GetNumIndexes(); i++) {
MOT::Index* index = table->GetIndex(i);
MOT::Index* index_copy = index->CloneEmpty();
if (index_copy == nullptr) {
// print error, clould not allocate memory for index
// print error, could not allocate memory for index
MOT_REPORT_ERROR(MOT_ERROR_OOM,
"Truncate Table",
"Failed to clone empty index %s",
table->GetIndex(i)->GetName().c_str());
for (int j = 0; j < i; j++) {
index->GetName().c_str());
for (uint16_t j = 0; j < indexesArr->GetNumIndexes(); j++) {
// cleanup of previous created indexes copy
Index* newIndex = table->m_indexes[j];
Index* oldIndex = indexes[j];
table->m_indexes[j] = oldIndex;
if (j != 0) // is secondary
MOT::Index* oldIndex = indexesArr->GetIndex(j);
uint16_t oldIx = indexesArr->GetIndexIx(j);
MOT::Index* newIndex = table->m_indexes[oldIx];
table->m_indexes[oldIx] = oldIndex;
if (oldIx != 0) // is secondary
table->m_secondaryIndexes[oldIndex->GetName()] = oldIndex;
else // is primary
table->m_primaryIndex = oldIndex;
delete newIndex;
}
delete ddl_access;
delete indexesArr;
return RC_MEMORY_ALLOCATION_ERROR;
}
indexes[i] = table->GetIndex(i);
indexesArr->Add(i, index);
table->m_indexes[i] = index_copy;
if (i != 0) // is secondary
table->m_secondaryIndexes[index_copy->GetName()] = index_copy;
@ -1258,7 +1175,7 @@ RC TxnManager::TruncateTable(Table* table)
return res;
}
RC TxnManager::CreateIndex(Table* table, Index* index, bool is_primary)
RC TxnManager::CreateIndex(Table* table, MOT::Index* index, bool is_primary)
{
// allocate DDL before work and fail immediately if required
@ -1314,42 +1231,35 @@ RC TxnManager::CreateIndex(Table* table, Index* index, bool is_primary)
RC TxnManager::DropIndex(MOT::Index* index)
{
// allocate DDL before work and fail immediately if required
TxnDDLAccess::DDLAccess* new_ddl_access = nullptr;
TxnDDLAccess::DDLAccess* ddl_access = m_txnDdlAccess->GetByOid(index->GetExtId());
if (ddl_access == nullptr) {
new_ddl_access =
new (std::nothrow) TxnDDLAccess::DDLAccess(index->GetExtId(), DDL_ACCESS_DROP_INDEX, (void*)index);
if (new_ddl_access == nullptr) {
MOT_REPORT_ERROR(MOT_ERROR_OOM, "Drop Index", "Failed to allocate DDL Access object");
return RC_MEMORY_ALLOCATION_ERROR;
}
TxnDDLAccess::DDLAccess* new_ddl_access =
new (std::nothrow) TxnDDLAccess::DDLAccess(index->GetExtId(), DDL_ACCESS_DROP_INDEX, (void*)index);
if (new_ddl_access == nullptr) {
MOT_REPORT_ERROR(MOT_ERROR_OOM, "Drop Index", "Failed to allocate DDL Access object");
return RC_MEMORY_ALLOCATION_ERROR;
}
RC res = RC_OK;
Table* table = index->GetTable();
if (!index->IsPrimaryKey()) {
RollbackSecondaryIndexInsert(index);
}
if (ddl_access != nullptr) {
// this index was created in this transaction, can delete it from the ddl_access
// table->removeSecondaryIndex also performs releases the object
m_txnDdlAccess->EraseByOid(index->GetExtId());
if (index->IsPrimaryKey()) {
res = table->DeletePrimaryIndex(index);
} else {
res = table->RemoveSecondaryIndex((char*)index->GetName().c_str(), this);
}
if (res != RC_OK) {
// print Error
MOT_REPORT_ERROR(MOT_ERROR_INTERNAL, "Drop Index", "Failed to remove secondary index");
return res;
}
} else {
m_txnDdlAccess->Add(new_ddl_access);
if (!m_isLightSession && !index->IsPrimaryKey()) {
TxnOrderedSet_t& access_row_set = m_accessMgr->GetOrderedRowSet();
TxnOrderedSet_t::iterator it = access_row_set.begin();
while (it != access_row_set.end()) {
Access* ac = it->second;
if (ac->GetSentinel()->GetIndex() == index) {
if (ac->m_type == INS)
RollbackInsert(ac);
it = access_row_set.erase(it);
// need to perform index clean-up!
m_accessMgr->PubReleaseAccess(ac);
} else {
it++;
}
}
}
table->RemoveSecondaryIndexFromMetaData(index);
m_txnDdlAccess->Add(new_ddl_access);
return res;
}

View File

@ -515,8 +515,6 @@ private:
public:
Table* GetTableByExternalId(uint64_t id);
Index* GetIndexByExternalId(uint64_t table_id, uint64_t index_id);
Index* GetIndex(uint64_t table_id, uint16_t position);
Index* GetIndex(Table* table, uint16_t position);
RC CreateTable(Table* table);
RC DropTable(Table* table);
RC CreateIndex(Table* table, Index* index, bool is_primary);
@ -591,7 +589,7 @@ public:
bool m_isLightSession;
/** @var In case of unique violation this will be set to a violating index */
Index* m_errIx;
MOT::Index* m_errIx;
/** @var In case of error this will contain the exact error code */
RC m_err;

View File

@ -96,9 +96,14 @@ TxnDDLAccess::DDLAccess* TxnDDLAccess::Get(uint16_t index)
TxnDDLAccess::DDLAccess* TxnDDLAccess::GetByOid(uint64_t oid)
{
for (int i = 0; i < m_size; i++)
if (m_accessList[i]->GetOid() == oid)
if (m_size == 0) {
return nullptr;
}
for (int i = m_size - 1; i >= 0; i--) {
if (m_accessList[i]->GetOid() == oid) {
return m_accessList[i];
}
}
return nullptr;
}

View File

@ -1170,12 +1170,10 @@ bool MOTAdaptor::SetMatchingExpr(
MOTFdwStateSt* state, MatchIndexArr* marr, int16_t colId, KEY_OPER op, Expr* expr, Expr* parent, bool set_local)
{
bool res = false;
MOT::TxnManager* txn = GetSafeTxn();
uint16_t numIx = state->m_table->GetNumIndexes();
for (uint16_t i = 0; i < numIx; i++) {
// MOT::Index *ix = state->table->getIndex(i);
MOT::Index* ix = txn->GetIndex(state->m_table, i);
MOT::Index *ix = state->m_table->GetIndex(i);
if (ix != nullptr && ix->IsFieldPresent(colId)) {
if (marr->m_idx[i] == nullptr) {
marr->m_idx[i] = (MatchIndex*)palloc0(sizeof(MatchIndex));
@ -1211,7 +1209,6 @@ inline int32_t MOTAdaptor::AddParam(List** params, Expr* expr)
MatchIndex* MOTAdaptor::GetBestMatchIndex(MOTFdwStateSt* festate, MatchIndexArr* marr, int numClauses, bool setLocal)
{
MOT::TxnManager* txn = GetSafeTxn();
MatchIndex* best = nullptr;
double bestCost = INT_MAX;
uint16_t numIx = festate->m_table->GetNumIndexes();
@ -1282,7 +1279,7 @@ MatchIndex* MOTAdaptor::GetBestMatchIndex(MOTFdwStateSt* festate, MatchIndexArr*
}
if (best != nullptr && best->m_ix != nullptr) {
for (uint16_t i = 0; i < numIx; i++) {
if (best->m_ix == txn->GetIndex(festate->m_table, i)) {
if (best->m_ix == festate->m_table->GetIndex(i)) {
best->m_ixPosition = i;
break;
}
@ -2030,7 +2027,7 @@ uint64_t MOTAdaptor::GetTableIndexSize(uint64_t tabId, uint64_t ixId)
}
if (ixId > 0) {
ix = txn->GetIndexByExternalId(tabId, ixId);
ix = tab->GetIndexByExtId(ixId);
if (ix == nullptr) {
ereport(ERROR,
(errmodule(MOD_MM),
@ -2893,7 +2890,7 @@ void MatchIndex::Deserialize(ListCell* cell, uint64_t exTableID)
m_ixPosition = (int32_t)((Const*)lfirst(cell))->constvalue;
MOT::Table* table = txn->GetTableByExternalId(exTableID);
if (table != nullptr) {
m_ix = txn->GetIndex(table, m_ixPosition);
m_ix = table->GetIndex(m_ixPosition);
}
cell = lnext(cell);