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 |