| 3367 | |
| 3368 | |
| 3369 | static void down_grade(thread_db* tdbb, BufferDesc* bdb, int high) |
| 3370 | { |
| 3371 | /************************************** |
| 3372 | * |
| 3373 | * d o w n _ g r a d e |
| 3374 | * |
| 3375 | ************************************** |
| 3376 | * |
| 3377 | * Functional description |
| 3378 | * A lock on a page is blocking another process. If possible, downgrade |
| 3379 | * the lock on the buffer. This may be called from either AST or |
| 3380 | * regular level. Return true if the down grade was successful. If the |
| 3381 | * down grade was deferred for any reason, return false. |
| 3382 | * |
| 3383 | **************************************/ |
| 3384 | SET_TDBB(tdbb); |
| 3385 | |
| 3386 | const bool oldBlocking = (bdb->bdb_ast_flags.exchangeBitOr(BDB_blocking) & BDB_blocking); |
| 3387 | Lock* lock = bdb->bdb_lock; |
| 3388 | Database* dbb = tdbb->getDatabase(); |
| 3389 | BufferControl* bcb = bdb->bdb_bcb; |
| 3390 | |
| 3391 | if (dbb->dbb_flags & DBB_bugcheck) |
| 3392 | { |
| 3393 | PAGE_LOCK_RELEASE(tdbb, bcb, lock); |
| 3394 | bdb->bdb_ast_flags &= ~BDB_blocking; |
| 3395 | |
| 3396 | clear_dirty_flag_and_nbak_state(tdbb, bdb); |
| 3397 | return; // true; |
| 3398 | } |
| 3399 | |
| 3400 | // If the BufferDesc is in use and, being written or already |
| 3401 | // downgraded to read, mark it as blocking and exit. |
| 3402 | |
| 3403 | bool justWrite = false; |
| 3404 | |
| 3405 | if (bdb->isLocked() || !bdb->addRefConditional(tdbb, SYNC_EXCLUSIVE)) |
| 3406 | { |
| 3407 | if (!high) |
| 3408 | return; // false; |
| 3409 | |
| 3410 | // hvlad: buffer is in use and we can't downgrade its lock. But if this |
| 3411 | // buffer blocks some lower precedence buffer, it is enough to just write |
| 3412 | // our (high) buffer to clear precedence and thus allow blocked (low) |
| 3413 | // buffer to be downgraded. IO lock guarantees that there is no buffer |
| 3414 | // modification in progress currently and it is safe to write it right now. |
| 3415 | // No need to mark our buffer as blocking nor to change state of our lock. |
| 3416 | |
| 3417 | bdb->lockIO(tdbb); |
| 3418 | if (!(bdb->bdb_flags & BDB_dirty)) |
| 3419 | { |
| 3420 | bdb->unLockIO(tdbb); |
| 3421 | return; // true |
| 3422 | } |
| 3423 | |
| 3424 | if (!oldBlocking) |
| 3425 | bdb->bdb_ast_flags &= ~BDB_blocking; |
| 3426 |
no test coverage detected