void GlobalRWLock::blockingAstHandler(thread_db* tdbb) { SET_TDBB(tdbb); COS_TRACE(("(%p)->blockingAst enter", this)); COS_TRACE(("(%p)->blockingAst readers(%d), blocking(%d), pendingWriters(%d), currentWriter(%d), lck_physical(%d)", this, readers, blocking, pendingWriters, currentWriter, cachedLock->lck_physical)); if (!pendingLock && !currentWriter && !readers) { COS_TRACE(("(%p)->Downgrade lock", this)); LCK_downgrade(tdbb, cachedLock); fb_assert(!blocking); if (cachedLock->lck_physical < LCK_read) invalidate(tdbb); } else if (!pendingLock && !currentWriter && readers && cachedLock->lck_physical > LCK_read) { COS_TRACE(("(%p)->Convert lock to SR ", this)); if (!LCK_convert(tdbb, cachedLock, LCK_read, LCK_NO_WAIT)) { COS_TRACE(("(%p)->Set blocking", this)); blocking = true; } } else { COS_TRACE(("(%p)->Set blocking", this)); blocking = true; } }
SLONG Database::SharedCounter::generate(thread_db* tdbb, ULONG space, ULONG prefetch) { fb_assert(space < TOTAL_ITEMS); ValueCache* const counter = &m_counters[space]; if (m_localOnly) { SLONG result = 0; while ( !(result = (SLONG) ++counter->curVal) ) ; return result; } Database* const dbb = tdbb->getDatabase(); SyncLockGuard guard(&dbb->dbb_sh_counter_sync, SYNC_EXCLUSIVE, "Database::SharedCounter::generate"); if (!counter->lock) { Lock* const lock = FB_NEW_RPT(*dbb->dbb_permanent, 0) Lock(tdbb, sizeof(SLONG), LCK_shared_counter); counter->lock = lock; lock->lck_key.lck_long = space; LCK_lock(tdbb, lock, LCK_PW, LCK_WAIT); } SLONG result = (SLONG) ++counter->curVal; if (result > counter->maxVal) { LCK_convert(tdbb, counter->lock, LCK_PW, LCK_WAIT); result = LCK_read_data(tdbb, counter->lock); // zero IDs are somewhat special, so let's better skip them if (!result) result = 1; counter->curVal = result; counter->maxVal = result + prefetch - 1; LCK_write_data(tdbb, counter->lock, counter->maxVal + 1); LCK_convert(tdbb, counter->lock, LCK_SR, LCK_WAIT); } return result; }
SLONG Database::SharedCounter::generate(thread_db* tdbb, ULONG space, ULONG prefetch) { fb_assert(space < TOTAL_ITEMS); ValueCache* const counter = &m_counters[space]; Database* const dbb = tdbb->getDatabase(); if (!counter->lock) { Lock* const lock = FB_NEW_RPT(*dbb->dbb_permanent, sizeof(SLONG)) Lock(); counter->lock = lock; lock->lck_type = LCK_shared_counter; lock->lck_owner_handle = LCK_get_owner_handle(tdbb, lock->lck_type); lock->lck_parent = dbb->dbb_lock; lock->lck_length = sizeof(SLONG); lock->lck_key.lck_long = space; lock->lck_dbb = dbb; lock->lck_ast = blockingAst; lock->lck_object = counter; LCK_lock(tdbb, lock, LCK_PW, LCK_WAIT); counter->curVal = 1; counter->maxVal = 0; } if (counter->curVal > counter->maxVal) { LCK_convert(tdbb, counter->lock, LCK_PW, LCK_WAIT); counter->curVal = LCK_read_data(tdbb, counter->lock); if (!counter->curVal) { // zero IDs are somewhat special, so let's better skip them counter->curVal = 1; } counter->maxVal = counter->curVal + prefetch - 1; LCK_write_data(tdbb, counter->lock, counter->maxVal + 1); } return counter->curVal++; }
void CryptoManager::changeCryptState(thread_db* tdbb, const Firebird::string& plugName) { if (plugName.length() > 31) { (Arg::Gds(isc_cp_name_too_long) << Arg::Num(31)).raise(); } bool newCryptState = plugName.hasData(); { // window scope Header hdr(tdbb, LCK_write); // Check header page for flags if (hdr->hdr_flags & Ods::hdr_crypt_process) { (Arg::Gds(isc_cp_process_active)).raise(); } bool headerCryptState = hdr->hdr_flags & Ods::hdr_encrypted; if (headerCryptState == newCryptState) { (Arg::Gds(isc_cp_already_crypted)).raise(); } fb_assert(stateLock); // Take exclusive stateLock bool ret = needLock ? LCK_lock(tdbb, stateLock, LCK_PW, LCK_WAIT) : LCK_convert(tdbb, stateLock, LCK_PW, LCK_WAIT); if (!ret) { fb_assert(tdbb->tdbb_status_vector[1]); ERR_punt(); } fb_utils::init_status(tdbb->tdbb_status_vector); needLock = false; // Load plugin if (newCryptState) { loadPlugin(plugName.c_str()); } crypt = newCryptState; // Write modified header page Ods::header_page* header = hdr.write(); if (crypt) { header->hdr_flags |= Ods::hdr_encrypted; plugName.copyTo(header->hdr_crypt_plugin, sizeof header->hdr_crypt_plugin); } else { header->hdr_flags &= ~Ods::hdr_encrypted; } header->hdr_flags |= Ods::hdr_crypt_process; process = true; } // Trigger lock on ChangeCryptState if (!LCK_convert(tdbb, stateLock, LCK_EX, LCK_WAIT)) { ERR_punt(); } if (!LCK_convert(tdbb, stateLock, LCK_SR, LCK_WAIT)) { ERR_punt(); } fb_utils::init_status(tdbb->tdbb_status_vector); // Now we may set hdr_crypt_page for crypt thread { // window scope Header hdr(tdbb, LCK_write); Ods::header_page* header = hdr.write(); header->hdr_crypt_page = 1; } startCryptThread(tdbb); }