"Fossies" - the Fresh Open Source Software Archive  

Source code changes of the file "src/jrd/cch.cpp" between
Firebird-3.0.2.32703-0.tar.bz2 and Firebird-3.0.4.33054-0.tar.bz2

About: Firebird is a relational database offering many ANSI SQL standard features.

cch.cpp  (Firebird-3.0.2.32703-0.tar.bz2):cch.cpp  (Firebird-3.0.4.33054-0.tar.bz2)
skipping to change at line 184 skipping to change at line 184
fb_assert(bcb->bcb_dirty_count > 0); fb_assert(bcb->bcb_dirty_count > 0);
bcb->bcb_dirty_count--; bcb->bcb_dirty_count--;
QUE_DELETE(bdb->bdb_dirty); QUE_DELETE(bdb->bdb_dirty);
QUE_INIT(bdb->bdb_dirty); QUE_INIT(bdb->bdb_dirty);
} }
static void flushDirty(thread_db* tdbb, SLONG transaction_mask, const bool sys_o nly); static void flushDirty(thread_db* tdbb, SLONG transaction_mask, const bool sys_o nly);
static void flushAll(thread_db* tdbb, USHORT flush_flag); static void flushAll(thread_db* tdbb, USHORT flush_flag);
static void flushPages(thread_db* tdbb, USHORT flush_flag, BufferDesc** begin, F B_SIZE_T count);
static void recentlyUsed(BufferDesc* bdb); static void recentlyUsed(BufferDesc* bdb);
static void requeueRecentlyUsed(BufferControl* bcb); static void requeueRecentlyUsed(BufferControl* bcb);
const ULONG MIN_BUFFER_SEGMENT = 65536; const ULONG MIN_BUFFER_SEGMENT = 65536;
// Given pointer a field in the block, find the block // Given pointer a field in the block, find the block
#define BLOCK(fld_ptr, type, fld) (type*)((SCHAR*) fld_ptr - offsetof(type, fld) ) #define BLOCK(fld_ptr, type, fld) (type*)((SCHAR*) fld_ptr - offsetof(type, fld) )
skipping to change at line 264 skipping to change at line 265
// Assert any page locks that have been requested, but not assert ed // Assert any page locks that have been requested, but not assert ed
dbb->dbb_ast_flags |= DBB_assert_locks; dbb->dbb_ast_flags |= DBB_assert_locks;
BufferControl* bcb = dbb->dbb_bcb; BufferControl* bcb = dbb->dbb_bcb;
if (bcb) if (bcb)
{ {
SyncLockGuard bcbSync(&bcb->bcb_syncObject, SYNC_EXCLUSIV E, "CCH_down_grade_dbb"); SyncLockGuard bcbSync(&bcb->bcb_syncObject, SYNC_EXCLUSIV E, "CCH_down_grade_dbb");
bcb->bcb_flags &= ~BCB_exclusive; bcb->bcb_flags &= ~BCB_exclusive;
if (bcb->bcb_count) bool done = (bcb->bcb_count == 0);
while (!done)
{ {
done = true;
const bcb_repeat* const head = bcb->bcb_rpt;
const bcb_repeat* tail = bcb->bcb_rpt; const bcb_repeat* tail = bcb->bcb_rpt;
fb_assert(tail); // once I 've got here with NULL. AP. fb_assert(tail); // once I 've got here with NULL. AP.
for (const bcb_repeat* const end = tail + bcb->bc b_count; tail < end; ++tail) for (const bcb_repeat* const end = tail + bcb->bc b_count; tail < end; ++tail)
PAGE_LOCK_ASSERT(tdbb, bcb, tail->bcb_bdb {
->bdb_lock); BufferDesc* bdb = tail->bcb_bdb;
// Acquire EX latch to avoid races with L
CK_release (called by CCH_release)
// or LCK_lock (by lock_buffer) in main t
hread. Take extra care to avoid
// deadlock with CCH_handoff. See CORE-54
36.
Sync sync(&bdb->bdb_syncPage, FB_FUNCTION
);
while (!sync.lockConditional(SYNC_EXCLUSI
VE))
{
SyncUnlockGuard bcbUnlock(bcbSync
);
Thread::sleep(1);
}
if (head != bcb->bcb_rpt)
{
// expand_buffers or CCH_fini was
called, consider to start all over again
done = (bcb->bcb_count == 0);
break;
}
PAGE_LOCK_ASSERT(tdbb, bcb, bdb->bdb_lock
);
}
} }
} }
// Down grade the lock on the database itself // Down grade the lock on the database itself
if (lock->lck_physical == LCK_EX) if (lock->lck_physical == LCK_EX)
LCK_convert(tdbb, lock, LCK_PW, LCK_WAIT); // This l ets waiting cache manager in first LCK_convert(tdbb, lock, LCK_PW, LCK_WAIT); // This l ets waiting cache manager in first
else if (lock->lck_physical == LCK_PW) else if (lock->lck_physical == LCK_PW)
LCK_convert(tdbb, lock, LCK_SW, LCK_WAIT); LCK_convert(tdbb, lock, LCK_SW, LCK_WAIT);
else else
skipping to change at line 1687 skipping to change at line 1714
Database* const dbb = tdbb->getDatabase(); Database* const dbb = tdbb->getDatabase();
BackupManager* const bm = dbb->dbb_backup_manager; BackupManager* const bm = dbb->dbb_backup_manager;
// Temporary pages don't write to delta and need no SCN // Temporary pages don't write to delta and need no SCN
PageSpace* pageSpace = dbb->dbb_page_manager.findPageSpace(bdb->bdb_page. getPageSpaceID()); PageSpace* pageSpace = dbb->dbb_page_manager.findPageSpace(bdb->bdb_page. getPageSpaceID());
fb_assert(pageSpace); fb_assert(pageSpace);
if (pageSpace->isTemporary()) if (pageSpace->isTemporary())
return true; return true;
// Take backup state lock // Take backup state lock
const AtomicCounter::counter_type oldFlags = bdb->bdb_flags.exchangeBitOr if (!(tdbb->tdbb_flags & TDBB_backup_write_locked))
(BDB_nbak_state_lock);
if (!(oldFlags & BDB_nbak_state_lock))
{ {
NBAK_TRACE(("lock state for dirty page %d:%06d", const AtomicCounter::counter_type oldFlags = bdb->bdb_flags.excha
bdb->bdb_page.getPageSpaceID(), bdb->bdb_page.getPageNum( ngeBitOr(BDB_nbak_state_lock);
))); if (!(oldFlags & BDB_nbak_state_lock))
{
NBAK_TRACE(("lock state for dirty page %d:%06d",
bdb->bdb_page.getPageSpaceID(), bdb->bdb_page.get
PageNum()));
bm->lockStateRead(tdbb, LCK_WAIT); bm->lockStateRead(tdbb, LCK_WAIT);
}
} }
else
fb_assert(bdb->bdb_page == HEADER_PAGE_NUMBER);
if (bdb->bdb_page != HEADER_PAGE_NUMBER) if (bdb->bdb_page != HEADER_PAGE_NUMBER)
{ {
// SCN of header page is adjusted in nbak.cpp // SCN of header page is adjusted in nbak.cpp
if (bdb->bdb_buffer->pag_scn != bm->getCurrentSCN()) if (bdb->bdb_buffer->pag_scn != bm->getCurrentSCN())
{ {
bdb->bdb_buffer->pag_scn = bm->getCurrentSCN(); // Set SC N for the page bdb->bdb_buffer->pag_scn = bm->getCurrentSCN(); // Set SC N for the page
// At PAG_set_page_scn() below we could dirty SCN page an d thus acquire // At PAG_set_page_scn() below we could dirty SCN page an d thus acquire
// nbackup state lock recursively. Since RWLock allows it , we are safe. // nbackup state lock recursively. Since RWLock allows it , we are safe.
skipping to change at line 1796 skipping to change at line 1828
if (window->win_flags & WIN_large_scan && window->win_flags & WIN_garbage _collect) if (window->win_flags & WIN_large_scan && window->win_flags & WIN_garbage _collect)
{ {
bdb->bdb_flags |= BDB_garbage_collect; bdb->bdb_flags |= BDB_garbage_collect;
window->win_flags &= ~WIN_garbage_collect; window->win_flags &= ~WIN_garbage_collect;
} }
const bool mustWrite = (bdb->bdb_flags & BDB_must_write) || const bool mustWrite = (bdb->bdb_flags & BDB_must_write) ||
bcb->bcb_database->dbb_backup_manager->databaseFlushInProgress(); bcb->bcb_database->dbb_backup_manager->databaseFlushInProgress();
// if (bdb->bdb_writers == 1 || bdb->bdb_use_count == 1) if (bdb->bdb_writers == 1 || bdb->bdb_use_count == 1 ||
if (bdb->bdb_writers == 1 ||
(bdb->bdb_writers == 0 && mustWrite)) (bdb->bdb_writers == 0 && mustWrite))
{ {
const bool marked = bdb->bdb_flags & BDB_marked; const bool marked = bdb->bdb_flags & BDB_marked;
bdb->bdb_flags &= ~(BDB_writer | BDB_marked | BDB_faked); bdb->bdb_flags &= ~(BDB_writer | BDB_marked | BDB_faked);
if (marked) if (marked)
bdb->unLockIO(tdbb); bdb->unLockIO(tdbb);
if (mustWrite) if (mustWrite)
{ {
skipping to change at line 2079 skipping to change at line 2110
if (bdb->ourIOLock()) if (bdb->ourIOLock())
{ {
bdb->unLockIO(tdbb); bdb->unLockIO(tdbb);
} }
else else
{ {
if (bdb->ourExclusiveLock()) if (bdb->ourExclusiveLock())
bdb->bdb_flags &= ~(BDB_writer | BDB_fake d | BDB_must_write); bdb->bdb_flags &= ~(BDB_writer | BDB_fake d | BDB_must_write);
bdb->release(tdbb, false); bdb->release(tdbb, true);
} }
} }
} }
/*** /***
bcb_repeat* tail = bcb->bcb_rpt; bcb_repeat* tail = bcb->bcb_rpt;
for (const bcb_repeat* const end = tail + bcb->bcb_count; tail < end; tai l++) for (const bcb_repeat* const end = tail + bcb->bcb_count; tail < end; tai l++)
{ {
BufferDesc* bdb = tail->bcb_bdb; BufferDesc* bdb = tail->bcb_bdb;
if (!bdb->bdb_use_count) { if (!bdb->bdb_use_count) {
skipping to change at line 2435 skipping to change at line 2466
iscDbLogStatus(dbb->dbb_filename.c_str(), tdbb->tdbb_stat us_vector); iscDbLogStatus(dbb->dbb_filename.c_str(), tdbb->tdbb_stat us_vector);
} }
catch (const Firebird::Exception&) catch (const Firebird::Exception&)
{ {
return -1; return -1;
} // no-op } // no-op
return 0; return 0;
} }
// Used in qsort below
extern "C" {
static int cmpBdbs(const void* a, const void* b)
{
const BufferDesc* bdbA = *(BufferDesc**) a;
const BufferDesc* bdbB = *(BufferDesc**) b;
if (bdbA->bdb_page > bdbB->bdb_page)
return 1;
if (bdbA->bdb_page < bdbB->bdb_page)
return -1;
return 0;
}
} // extern C
// Remove cleared precedence blocks from high precedence queue // Remove cleared precedence blocks from high precedence queue
static void purgePrecedence(BufferControl* bcb, BufferDesc* bdb) static void purgePrecedence(BufferControl* bcb, BufferDesc* bdb)
{ {
Sync precSync(&bcb->bcb_syncPrecedence, "purgePrecedence"); Sync precSync(&bcb->bcb_syncPrecedence, "purgePrecedence");
precSync.lock(SYNC_EXCLUSIVE); precSync.lock(SYNC_EXCLUSIVE);
QUE que_prec = bdb->bdb_higher.que_forward, next_prec; QUE que_prec = bdb->bdb_higher.que_forward, next_prec;
for (; que_prec != &bdb->bdb_higher; que_prec = next_prec) for (; que_prec != &bdb->bdb_higher; que_prec = next_prec)
{ {
next_prec = que_prec->que_forward; next_prec = que_prec->que_forward;
skipping to change at line 2474 skipping to change at line 2488
if (precedence->pre_flags & PRE_cleared) if (precedence->pre_flags & PRE_cleared)
{ {
QUE_DELETE(precedence->pre_higher); QUE_DELETE(precedence->pre_higher);
QUE_DELETE(precedence->pre_lower); QUE_DELETE(precedence->pre_lower);
precedence->pre_hi = (BufferDesc*) bcb->bcb_free; precedence->pre_hi = (BufferDesc*) bcb->bcb_free;
bcb->bcb_free = precedence; bcb->bcb_free = precedence;
} }
} }
} }
// Write pages modified by given or system transaction to disk. First sort all // Collect pages modified by given or system transaction and write it to disk.
// corresponding pages by their numbers to make writes physically ordered and // See also comments in flushPages.
// thus faster. At every iteration of while loop write pages which have no high
// precedence pages to ensure order preserved. If after some iteration there are
// no such pages (i.e. all of not written yet pages have high precedence pages)
// then write them all at last iteration (of course write_buffer will also check
// for precedence before write)
static void flushDirty(thread_db* tdbb, SLONG transaction_mask, const bool sys_o nly) static void flushDirty(thread_db* tdbb, SLONG transaction_mask, const bool sys_o nly)
{ {
SET_TDBB(tdbb); SET_TDBB(tdbb);
FbStatusVector* const status = tdbb->tdbb_status_vector;
Database* dbb = tdbb->getDatabase(); Database* dbb = tdbb->getDatabase();
BufferControl* bcb = dbb->dbb_bcb; BufferControl* bcb = dbb->dbb_bcb;
Firebird::HalfStaticArray<BufferDesc*, 1024> flush; Firebird::HalfStaticArray<BufferDesc*, 1024> flush;
{ // dirtySync scope { // dirtySync scope
Sync dirtySync(&bcb->bcb_syncDirtyBdbs, "flushDirty"); Sync dirtySync(&bcb->bcb_syncDirtyBdbs, "flushDirty");
dirtySync.lock(SYNC_EXCLUSIVE); dirtySync.lock(SYNC_EXCLUSIVE);
QUE que_inst = bcb->bcb_dirty.que_forward, next; QUE que_inst = bcb->bcb_dirty.que_forward, next;
for (; que_inst != &bcb->bcb_dirty; que_inst = next) for (; que_inst != &bcb->bcb_dirty; que_inst = next)
skipping to change at line 2516 skipping to change at line 2523
if ((transaction_mask & bdb->bdb_transactions) || if ((transaction_mask & bdb->bdb_transactions) ||
(bdb->bdb_flags & BDB_system_dirty) || (bdb->bdb_flags & BDB_system_dirty) ||
(!transaction_mask && !sys_only) || (!transaction_mask && !sys_only) ||
(!bdb->bdb_transactions)) (!bdb->bdb_transactions))
{ {
flush.add(bdb); flush.add(bdb);
} }
} }
} }
qsort(flush.begin(), flush.getCount(), sizeof(BufferDesc*), cmpBdbs); flushPages(tdbb, FLUSH_TRAN, flush.begin(), flush.getCount());
bool writeAll = false;
while (flush.getCount())
{
BufferDesc** ptr = flush.begin();
const size_t cnt = flush.getCount();
while (ptr < flush.end())
{
BufferDesc* bdb = *ptr;
bdb->addRef(tdbb, SYNC_SHARED);
if (!writeAll)
purgePrecedence(bcb, bdb);
if (writeAll || QUE_EMPTY(bdb->bdb_higher))
{
const PageNumber page = bdb->bdb_page;
if (!write_buffer(tdbb, bdb, page, false, status,
true))
CCH_unwind(tdbb, true);
// re-post the lock only if it was really written
bdb->release(tdbb, !(bdb->bdb_flags & BDB_dirty))
;
flush.remove(ptr);
}
else
{
bdb->release(tdbb, false);
ptr++;
}
}
if (cnt == flush.getCount())
writeAll = true;
}
} }
// Write pages modified by garbage collector or all dirty pages or release page // Collect pages modified by garbage collector or all dirty pages or release pag
// locks - depending of flush_flag. See also comments in flushDirty e
// locks - depending of flush_flag, and write it to disk.
// See also comments in flushPages.
static void flushAll(thread_db* tdbb, USHORT flush_flag) static void flushAll(thread_db* tdbb, USHORT flush_flag)
{ {
SET_TDBB(tdbb); SET_TDBB(tdbb);
Database* dbb = tdbb->getDatabase(); Database* dbb = tdbb->getDatabase();
BufferControl* bcb = dbb->dbb_bcb; BufferControl* bcb = dbb->dbb_bcb;
FbStatusVector* status = tdbb->tdbb_status_vector;
Firebird::HalfStaticArray<BufferDesc*, 1024> flush(bcb->bcb_dirty_count); Firebird::HalfStaticArray<BufferDesc*, 1024> flush(bcb->bcb_dirty_count);
const bool all_flag = (flush_flag & FLUSH_ALL) != 0; const bool all_flag = (flush_flag & FLUSH_ALL) != 0;
const bool sweep_flag = (flush_flag & FLUSH_SWEEP) != 0; const bool sweep_flag = (flush_flag & FLUSH_SWEEP) != 0;
const bool release_flag = (flush_flag & FLUSH_RLSE) != 0; const bool release_flag = (flush_flag & FLUSH_RLSE) != 0;
const bool write_thru = release_flag; const bool write_thru = release_flag;
for (ULONG i = 0; i < bcb->bcb_count; i++) for (ULONG i = 0; i < bcb->bcb_count; i++)
{ {
BufferDesc* bdb = bcb->bcb_rpt[i].bcb_bdb; BufferDesc* bdb = bcb->bcb_rpt[i].bcb_bdb;
skipping to change at line 2601 skipping to change at line 2570
bdb->addRef(tdbb, SYNC_EXCLUSIVE); bdb->addRef(tdbb, SYNC_EXCLUSIVE);
if (bdb->bdb_use_count > 1) if (bdb->bdb_use_count > 1)
BUGCHECK(210); // msg 210 page in use during flu sh BUGCHECK(210); // msg 210 page in use during flu sh
PAGE_LOCK_RELEASE(tdbb, bcb, bdb->bdb_lock); PAGE_LOCK_RELEASE(tdbb, bcb, bdb->bdb_lock);
bdb->release(tdbb, false); bdb->release(tdbb, false);
} }
} }
qsort(flush.begin(), flush.getCount(), sizeof(BufferDesc*), cmpBdbs); flushPages(tdbb, flush_flag, flush.begin(), flush.getCount());
}
// Used in qsort below
extern "C" {
static int cmpBdbs(const void* a, const void* b)
{
const BufferDesc* bdbA = *(BufferDesc**)a;
const BufferDesc* bdbB = *(BufferDesc**)b;
if (bdbA->bdb_page > bdbB->bdb_page)
return 1;
if (bdbA->bdb_page < bdbB->bdb_page)
return -1;
return 0;
}
} // extern C
// Write array of pages to disk in efficient order.
// First, sort pages by their numbers to make writes physically ordered and
// thus faster. At every iteration of while loop write pages which have no high
// precedence pages to ensure order preserved. If after some iteration there are
// no such pages (i.e. all of not written yet pages have high precedence pages)
// then write them all at last iteration (of course write_buffer will also check
// for precedence before write).
static void flushPages(thread_db* tdbb, USHORT flush_flag, BufferDesc** begin, F
B_SIZE_T count)
{
FbStatusVector* const status = tdbb->tdbb_status_vector;
const bool all_flag = (flush_flag & FLUSH_ALL) != 0;
const bool release_flag = (flush_flag & FLUSH_RLSE) != 0;
const bool write_thru = release_flag;
qsort(begin, count, sizeof(BufferDesc*), cmpBdbs);
MarkIterator<BufferDesc*> iter(begin, count);
FB_SIZE_T written = 0;
bool writeAll = false; bool writeAll = false;
while (flush.getCount())
while (!iter.isEmpty())
{ {
BufferDesc** ptr = flush.begin(); bool found = false;
const size_t cnt = flush.getCount(); for (; !iter.isEof(); ++iter)
while (ptr < flush.end())
{ {
BufferDesc* bdb = *ptr; BufferDesc* bdb = *iter;
fb_assert(bdb);
if (!bdb)
continue;
bdb->addRef(tdbb, release_flag ? SYNC_EXCLUSIVE : SYNC_SH ARED); bdb->addRef(tdbb, release_flag ? SYNC_EXCLUSIVE : SYNC_SH ARED);
BufferControl* bcb = bdb->bdb_bcb;
if (!writeAll) if (!writeAll)
purgePrecedence(bcb, bdb); purgePrecedence(bcb, bdb);
if (writeAll || QUE_EMPTY(bdb->bdb_higher)) if (writeAll || QUE_EMPTY(bdb->bdb_higher))
{ {
if (release_flag) if (release_flag)
{ {
if (bdb->bdb_use_count > 1) if (bdb->bdb_use_count > 1)
BUGCHECK(210); // msg 210 page i n use during flush BUGCHECK(210); // msg 210 page i n use during flush
} }
if (bdb->bdb_flags & (BDB_db_dirty | BDB_dirty)) if (!all_flag || bdb->bdb_flags & (BDB_db_dirty | BDB_dirty))
{ {
if (!write_buffer(tdbb, bdb, bdb->bdb_pag e, write_thru, status, true)) if (!write_buffer(tdbb, bdb, bdb->bdb_pag e, write_thru, status, true))
CCH_unwind(tdbb, true); CCH_unwind(tdbb, true);
} }
// release lock before losing control over bdb, i t prevents // release lock before losing control over bdb, i t prevents
// concurrent operations on released lock // concurrent operations on released lock
if (release_flag) if (release_flag)
PAGE_LOCK_RELEASE(tdbb, bcb, bdb->bdb_loc k); PAGE_LOCK_RELEASE(tdbb, bcb, bdb->bdb_loc k);
bdb->release(tdbb, !release_flag && !(bdb->bdb_fl ags & BDB_dirty)); bdb->release(tdbb, !release_flag && !(bdb->bdb_fl ags & BDB_dirty));
flush.remove(ptr);
iter.mark();
found = true;
written++;
} }
else else
{ {
bdb->release(tdbb, false); bdb->release(tdbb, false);
ptr++;
} }
} }
if (cnt == flush.getCount()) if (!found)
writeAll = true; writeAll = true;
iter.rewind();
} }
fb_assert(count == written);
} }
#ifdef CACHE_READER #ifdef CACHE_READER
void BufferControl::cache_reader(BufferControl* bcb) void BufferControl::cache_reader(BufferControl* bcb)
{ {
/************************************** /**************************************
* *
* c a c h e _ r e a d e r * c a c h e _ r e a d e r
* *
************************************** **************************************
skipping to change at line 3257 skipping to change at line 3273
continue; continue;
} }
BufferDesc* blocking_bdb = precedence->pre_hi; BufferDesc* blocking_bdb = precedence->pre_hi;
if (blocking_bdb->bdb_flags & BDB_dirty) if (blocking_bdb->bdb_flags & BDB_dirty)
{ {
found = true; found = true;
syncPrec.unlock(); syncPrec.unlock();
down_grade(tdbb, blocking_bdb, high + 1); down_grade(tdbb, blocking_bdb, high + 1);
if (blocking_bdb->bdb_flags & BDB_dirty && !(prec edence->pre_flags & PRE_cleared)) if ((blocking_bdb->bdb_flags & BDB_dirty) && !(pr ecedence->pre_flags & PRE_cleared))
in_use = true; in_use = true;
if (blocking_bdb->bdb_flags & BDB_not_valid) if (blocking_bdb->bdb_flags & BDB_not_valid)
{ {
invalid = true; invalid = true;
in_use = false; in_use = false;
que_inst = bdb->bdb_higher.que_forward; que_inst = bdb->bdb_higher.que_forward;
} }
break; break;
skipping to change at line 3530 skipping to change at line 3546
if (!latchOk) if (!latchOk)
return lsTimeout; // go out return lsTimeout; // go out
if (bdb->bdb_page == page) if (bdb->bdb_page == page)
{ {
//bdb->bdb_flags &= ~(BDB_faked | BDB_prefetch); //bdb->bdb_flags &= ~(BDB_faked | BDB_prefetch);
return lsOk; return lsOk;
} }
bdb->release(tdbb, false); bdb->release(tdbb, true);
} }
return lsPageChanged; // try again return lsPageChanged; // try again
} }
static BufferDesc* get_buffer(thread_db* tdbb, const PageNumber page, SyncType s yncType, int wait) static BufferDesc* get_buffer(thread_db* tdbb, const PageNumber page, SyncType s yncType, int wait)
{ {
/************************************** /**************************************
* *
* g e t _ b u f f e r * g e t _ b u f f e r
* *
skipping to change at line 5093 skipping to change at line 5109
if (bdb_writers) if (bdb_writers)
{ {
if (--bdb_writers == 0) if (--bdb_writers == 0)
bdb_exclusive = NULL; bdb_exclusive = NULL;
bdb_syncPage.unlock(NULL, SYNC_EXCLUSIVE); bdb_syncPage.unlock(NULL, SYNC_EXCLUSIVE);
} }
else else
bdb_syncPage.unlock(NULL, SYNC_SHARED); bdb_syncPage.unlock(NULL, SYNC_SHARED);
if (repost && !bdb_use_count && (bdb_ast_flags & BDB_blocking)) if (repost && !isLocked() && (bdb_ast_flags & BDB_blocking))
{ {
PAGE_LOCK_RE_POST(tdbb, bdb_bcb, bdb_lock); PAGE_LOCK_RE_POST(tdbb, bdb_bcb, bdb_lock);
} }
} }
void BufferDesc::lockIO(thread_db* tdbb) void BufferDesc::lockIO(thread_db* tdbb)
{ {
bdb_syncIO.lock(NULL, SYNC_EXCLUSIVE, FB_FUNCTION); bdb_syncIO.lock(NULL, SYNC_EXCLUSIVE, FB_FUNCTION);
fb_assert(!bdb_io_locks && bdb_io != tdbb || bdb_io_locks && bdb_io == td bb); fb_assert(!bdb_io_locks && bdb_io != tdbb || bdb_io_locks && bdb_io == td bb);
 End of changes. 31 change blocks. 
96 lines changed or deleted 119 lines changed or added

Home  |  About  |  Features  |  All  |  Newest  |  Dox  |  Diffs  |  RSS Feeds  |  Screenshots  |  Comments  |  Imprint  |  Privacy  |  HTTP(S)