-// find and add the next available latch entry
-// to the queue
-
-BTERR bt_txnavaillatch (BtDb *bt)
-{
-BtLatchSet *latch;
-uint startattempt;
-uint cnt, entry;
-uint hashidx;
-BtPage page;
-
- // find and reuse previous entry on victim
-
- startattempt = bt->mgr->latchvictim;
-
- while( 1 ) {
-#ifdef unix
- entry = __sync_fetch_and_add(&bt->mgr->latchvictim, 1);
-#else
- entry = _InterlockedIncrement (&bt->mgr->latchvictim) - 1;
-#endif
- // skip entry if it has outstanding pins
-
- entry %= bt->mgr->latchtotal;
-
- if( !entry )
- continue;
-
- // only go around one time before
- // flushing redo recovery buffer,
- // and the buffer pool to free up entries.
-
- if( bt->mgr->redopages )
- if( bt->mgr->latchvictim - startattempt > bt->mgr->latchtotal ) {
- if( bt_mutextry (bt->mgr->dump) ) {
- if( bt_dumpredo (bt->mgr) )
- return bt->mgr->err;
- bt_flushlsn (bt->mgr, bt->thread_no);
- // synchronize the various threads running into this condition
- // so that only one thread does the dump and flush
- } else
- bt_mutexlock(bt->mgr->dump);
-
- startattempt = bt->mgr->latchvictim;
- bt_releasemutex(bt->mgr->dump);
- }
-
- latch = bt->mgr->latchsets + entry;
-
- if( latch->avail )
- continue;
-
- bt_mutexlock(latch->modify);
-
- // skip if already an available entry
-
- if( latch->avail ) {
- bt_releasemutex(latch->modify);
- continue;
- }
-
- // skip this entry if it is pinned
- // if the CLOCK bit is set
- // reset it to zero.
-
- if( latch->pin ) {
- latch->pin &= ~CLOCK_bit;
- bt_releasemutex(latch->modify);
- continue;
- }
-
- page = (BtPage)(((uid)entry << bt->mgr->page_bits) + bt->mgr->pagepool);
-
- // if dirty page has lsn >= last redo recovery buffer
- // then hold page in the buffer pool until next redo
- // recovery buffer is being written to disk.
-
- if( latch->dirty )
- if( page->lsn >= bt->mgr->flushlsn ) {
- bt_releasemutex(latch->modify);
- continue;
- }
-
- // entry is now available
-#ifdef unix
- __sync_fetch_and_add (&bt->mgr->available, 1);
-#else
- _InterlockedIncrement(&bt->mgr->available);
-#endif
- latch->avail = 1;
- bt_releasemutex(latch->modify);
- return 0;
- }
-}
-
-// release available latch requests
-
-void bt_txnavailrelease (BtDb *bt, uint count)
-{
-#ifdef unix
- __sync_fetch_and_add(bt->mgr->availlock, -count);
-#else
- _InterlockedAdd(bt->mgr->availlock, -count);
-#endif
-}
-
-// promote page of keys from first btree
-// into main btree
-
-BTERR bt_txnavailmain (BtDb *bt)
-{
-BtLatchSet *latch;
-uint entry;
-
- while( 1 ) {
-#ifdef unix
- entry = __sync_fetch_and_add(&bt->mgr->latchvictim, 1);
-#else
- entry = _InterlockedIncrement (&bt->mgr->latchvictim) - 1;
-#endif
- // skip entry if it has outstanding pins
-
- entry %= bt->mgr->latchtotal;
-
- if( !entry )
- continue;
-
- latch = bt->mgr->latchsets + entry;
-
- if( latch->avail )
- continue;
-
- bt_mutexlock(latch->modify);
-
- // skip if already an available entry
-
- if( latch->avail ) {
- bt_releasemutex(latch->modify);
- continue;
- }
-
- // skip this entry if it is pinned
- // if the CLOCK bit is set
- // reset it to zero.
-
- if( latch->pin ) {
- latch->pin &= ~CLOCK_bit;
- bt_releasemutex(latch->modify);
- continue;
- }
-
- }
-}
-
-// commit available pool entries
-// find available entries as required
-
-BTERR bt_txnavailrequest (BtDb *bt, uint count)
-{
-#ifdef unix
- __sync_fetch_and_add(bt->mgr->availlock, count);
-#else
- _InterlockedAdd(bt->mgr->availlock, count);
-#endif
-
- // find another available pool entry
-
- while( *bt->mgr->availlock > bt->mgr->available )
- if( bt->mgr->redopages )
- bt_txnavaillatch (bt);
- else
- if( bt_txnavailmain (bt) )
- return bt->mgr->err;
-}
-