Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 54 additions & 0 deletions src/dsql/DdlNodes.epp
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,8 @@
#include "../common/StatusArg.h"
#include "../auth/SecureRemotePassword/Message.h"
#include "../jrd/Mapping.h"
#include "../jrd/btr_proto.h"
#include "../jrd/lck_proto.h"

namespace Jrd {

Expand Down Expand Up @@ -110,6 +112,7 @@ static void updateRdbFields(const TypeClause* type,
SSHORT& fieldPrecisionNull, SSHORT& fieldPrecision,
SSHORT& collationIdNull, SSHORT& collationId,
SSHORT& segmentLengthNull, SSHORT& segmentLength);
static int blocking_ast_index(void* ast_object);

static const char* const CHECK_CONSTRAINT_EXCEPTION = "check_constraint";

Expand Down Expand Up @@ -9794,6 +9797,35 @@ bool DropIndexNode::checkPermission(thread_db* tdbb, jrd_tra* transaction)
return true;
}

static int blocking_ast_index(void* ast_object)
{
/**************************************
*
* b l o c k i n g _ a s t _ i n d e x
*
**************************************
*
* Functional description
* Someone is trying to get lock on index.
* If index is not on deletion, relese the lock.
*
**************************************/
IndexLock* const index = static_cast<IndexLock*>(ast_object);
try
{
if (!index->idl_deletion && index->idl_lock)
{
Database* const dbb = index->idl_lock->lck_dbb;
AsyncContextHolder tdbb(dbb, FB_FUNCTION, index->idl_lock);
LCK_release(tdbb, index->idl_lock);
}
}
catch (const Exception&)
{} // no-op

return 0;
}

void DropIndexNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch, jrd_tra* transaction)
{
// run all statements under savepoint control
Expand All @@ -9802,6 +9834,28 @@ void DropIndexNode::execute(thread_db* tdbb, DsqlCompilerScratch* dsqlScratch, j
AutoCacheRequest request(tdbb, drq_e_indices, DYN_REQUESTS);
bool found = false;

Jrd::IndexStatus idx_state;
SLONG idx_id;
SLONG rel_id;

// Need to create lock on index. This lock guarantees
// that index which are deleted and should not be used in future queries
idx_id = MET_lookup_index_name(tdbb, name, &rel_id, &idx_state);

if (idx_id != -1)
{
jrd_rel* relation = MET_lookup_relation_id(tdbb, rel_id, true);
IndexLock* index = CMP_get_index_lock(tdbb, relation, idx_id);
if (index)
{
// mark the index to deletion stage and get exclusive lock on it
index->idl_lock->lck_ast = blocking_ast_index;
index->idl_lock->lck_object = index;
index->idl_deletion = true;
LCK_lock(tdbb, index->idl_lock, LCK_EX, LCK_WAIT);
}
}

FOR(REQUEST_HANDLE request TRANSACTION_HANDLE transaction)
IDX IN RDB$INDICES
WITH IDX.RDB$INDEX_NAME EQ name.c_str()
Expand Down
15 changes: 14 additions & 1 deletion src/jrd/btr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@
#include "../jrd/mov_proto.h"
#include "../jrd/pag_proto.h"
#include "../jrd/tra_proto.h"
#include "../jrd/cmp_proto.h"

using namespace Jrd;
using namespace Ods;
Expand Down Expand Up @@ -478,7 +479,6 @@ bool BTR_delete_index(thread_db* tdbb, WIN* window, USHORT id)
return tree_exists;
}


bool BTR_description(thread_db* tdbb, jrd_rel* relation, index_root_page* root, index_desc* idx,
USHORT id)
{
Expand All @@ -503,6 +503,19 @@ bool BTR_description(thread_db* tdbb, jrd_rel* relation, index_root_page* root,
if (irt_desc->getRoot() == 0)
return false;

IndexLock* index = CMP_get_index_lock(tdbb, relation, id);
if (index)
{
// try to get lock on the index, if it's unsuccessful, then
// the index already locked on deletion stage
if(!LCK_lock(tdbb, index->idl_lock, LCK_SR, LCK_NO_WAIT))
{
// clean status vector after trying lock
fb_utils::init_status(tdbb->tdbb_status_vector);
return false;
}
}

idx->idx_id = id;
idx->idx_root = irt_desc->getRoot();
idx->idx_count = irt_desc->irt_keys;
Expand Down
20 changes: 20 additions & 0 deletions src/jrd/dfw.epp
Original file line number Diff line number Diff line change
Expand Up @@ -1294,6 +1294,26 @@ void DFW_delete_deferred( jrd_tra* transaction, SavNumber sav_number)
for (DfwHash::iterator i(h->hash); i.hasData();)
{
DeferredWork* work(i);
// If the index deleting was rolled back,
// We need to deque the index lock from lock manager
if (work->dfw_type == dfw_delete_index ||
work->dfw_type == dfw_delete_expression_index)
{
DeferredWork* w = work;
const DeferredWork* arg = w->findArg(dfw_arg_index_name);
fb_assert(arg);
fb_assert(arg->dfw_id > 0);
const USHORT id = arg->dfw_id - 1;

Jrd::thread_db* tdbb = JRD_get_thread_data();
jrd_rel* relation = MET_lookup_relation_id(tdbb, w->dfw_id, false);

IndexLock* index = CMP_get_index_lock(tdbb, relation, id);

// mark index as non deleted and make it shared
index->idl_deletion = false;
LCK_lock(tdbb, index->idl_lock, LCK_SR, LCK_WAIT);
}
++i;
delete work;
}
Expand Down
2 changes: 2 additions & 0 deletions src/jrd/lck.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,8 @@ static bool internal_enqueue(thread_db*, CheckStatusWrapper*, Lock*, USHORT, SSH
static SLONG get_owner_handle(thread_db* tdbb, enum lck_t lock_type);
static lck_owner_t get_owner_type(enum lck_t lock_type);

static Firebird::GlobalPtr<Firebird::Array<Jrd::Lock*> > index_locks;

#ifdef DEBUG_LCK
namespace
{
Expand Down
1 change: 0 additions & 1 deletion src/jrd/lck_proto.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,6 @@ void LCK_release(Jrd::thread_db*, Jrd::Lock*);
void LCK_re_post(Jrd::thread_db*, Jrd::Lock*);
void LCK_write_data(Jrd::thread_db*, Jrd::Lock*, SINT64);


class AutoLock
{
public:
Expand Down
1 change: 1 addition & 0 deletions src/jrd/req.h
Original file line number Diff line number Diff line change
Expand Up @@ -324,6 +324,7 @@ class IndexLock : public pool_alloc<type_idl>
jrd_rel* idl_relation; // Parent relation
USHORT idl_id; // Index id
USHORT idl_count; // Use count
bool idl_deletion; // Deletion stage
};

} //namespace Jrd
Expand Down