Skip to content

Commit

Permalink
Add test for Lock.
Browse files Browse the repository at this point in the history
  • Loading branch information
asfernandes committed Nov 19, 2022
1 parent e97e064 commit 8228caa
Show file tree
Hide file tree
Showing 3 changed files with 136 additions and 1 deletion.
1 change: 1 addition & 0 deletions src/jrd/lck.cpp
Expand Up @@ -586,6 +586,7 @@ static lck_owner_t get_owner_type(enum lck_t lock_type)
case LCK_repl_tables:
case LCK_dsql_statement_cache:
case LCK_profiler_listener:
case LCK_test_attachment:
owner_type = LCK_OWNER_attachment;
break;

Expand Down
3 changes: 2 additions & 1 deletion src/jrd/lck.h
Expand Up @@ -76,7 +76,8 @@ enum lck_t {
LCK_repl_state, // Replication state lock
LCK_repl_tables, // Replication set lock
LCK_dsql_statement_cache, // DSQL statement cache lock
LCK_profiler_listener // Remote profiler listener
LCK_profiler_listener, // Remote profiler listener
LCK_test_attachment
};

// Lock owner types
Expand Down
133 changes: 133 additions & 0 deletions src/jrd/tests/LockTest.cpp
@@ -0,0 +1,133 @@
#include "firebird.h"
#include "boost/test/unit_test.hpp"
#include "../jrd/jrd.h"
#include "../jrd/EngineInterface.h"
#include "../common/StatusHolder.h"
#include "../common/classes/auto.h"
#include "../common/classes/RefCounted.h"
#include "../jrd/lck_proto.h"
#include <thread>

using namespace Firebird;
using namespace Jrd;

BOOST_AUTO_TEST_SUITE(EngineSuite)
BOOST_AUTO_TEST_SUITE(LockSuite)


BOOST_AUTO_TEST_SUITE(LockTests)

BOOST_AUTO_TEST_CASE(LockTest)
{
struct ThreadInfo
{
unsigned threadNum;
Lock* lock;
};

const auto blockingAst = [](void* astObject) -> int
{
auto threadInfo = (ThreadInfo*) astObject;

try
{
const auto dbb = threadInfo->lock->lck_dbb;
AsyncContextHolder tdbb(dbb, FB_FUNCTION, threadInfo->lock);

LCK_release(tdbb, threadInfo->lock);
}
catch (const Exception&)
{
}

return 0;
};

const auto filename = "/tmp/test1.fdb";

LocalStatus initLocalStatus;
CheckStatusWrapper initStatusWrapper(&initLocalStatus);

RefPtr<JProvider> provider(FB_NEW JProvider(nullptr));

auto initAttachment = makeNoIncRef(provider->createDatabase(&initStatusWrapper, filename, 0, nullptr));
initLocalStatus.check();

std::vector<std::thread> threads;
std::atomic_int counter(0);
constexpr unsigned THREAD_COUNT = 128;
constexpr unsigned ITER_COUNT = 2048;

for (unsigned threadNum = 0; threadNum < THREAD_COUNT; ++threadNum)
{
threads.push_back(std::thread([&, threadNum]() {
LocalStatus localStatus;
CheckStatusWrapper statusWrapper(&localStatus);

AutoPtr<Lock> lock; // 1!
ThreadInfo threadInfo;

auto attachment = makeNoIncRef(provider->attachDatabase(&statusWrapper, filename, 0, nullptr));
localStatus.check();

{ // scope
threadInfo.threadNum = threadNum;

const auto level = threadInfo.threadNum % 2 == 0 ? LCK_EX : LCK_SR;

EngineContextHolder tdbb(&statusWrapper, attachment.getPtr(), FB_FUNCTION);

///AutoPtr<Lock> lock; // 2!

lock.reset(FB_NEW_RPT(attachment->getPool(), 0) Lock(tdbb, 0,
LCK_test_attachment, &threadInfo, blockingAst));

threadInfo.lock = lock.get();

for (unsigned i = 0; i < ITER_COUNT; ++i)
{
if (level == LCK_SR)
{
if (lock->lck_logical == LCK_none)
LCK_lock(tdbb, lock, level, LCK_WAIT);
}
else
{
auto locked = LCK_lock(tdbb, lock, level, LCK_WAIT);
if (locked)
LCK_release(tdbb, lock);
}

++counter;

EngineCheckout checkout(tdbb, __FUNCTION__);
}

if (lock->lck_logical != LCK_none)
LCK_release(tdbb, lock);
}

attachment->detach(&statusWrapper);
localStatus.check();
}));
}

for (auto& thread : threads)
thread.join();

BOOST_CHECK(counter == THREAD_COUNT * ITER_COUNT);

initAttachment->dropDatabase(&initStatusWrapper);
initLocalStatus.check();

initAttachment = nullptr;

provider->shutdown(&initStatusWrapper, 0, fb_shutrsn_app_stopped);
initLocalStatus.check();
}

BOOST_AUTO_TEST_SUITE_END() // LockTests


BOOST_AUTO_TEST_SUITE_END() // LockSuite
BOOST_AUTO_TEST_SUITE_END() // EngineSuite

0 comments on commit 8228caa

Please sign in to comment.