VOID CMutexRWLock::WaitToRead() { BOOL bWait = FALSE; { CSpinLock locallock(m_cs); if(m_nActive > 0) ++m_nActive; else if(m_nActive == 0) { if(m_mtx.try_lock_shared()) { ++m_nReadCount; ++m_nActive; } else bWait = TRUE; } else if(!IsOwner()) bWait = TRUE; } if(bWait) { m_mtx.lock_shared(); CSpinLock locallock(m_cs); { ++m_nReadCount; ++m_nActive; } } }
PIDFile::~PIDFile() { if (IsOwner()) { Remove(); } }
// release write lock on a tuple. // one example usage of this method is when a tuple is acquired, but operation // (insert,update,delete) can't proceed, the executor needs to yield the // ownership before return false to upper layer. // It should not be called if the tuple is in the write set as commit and abort // will release the write lock anyway. void TimestampOrderingTransactionManager::YieldOwnership( UNUSED_ATTRIBUTE TransactionContext *const current_txn, const storage::TileGroupHeader *const tile_group_header, const oid_t &tuple_id) { PL_ASSERT(IsOwner(current_txn, tile_group_header, tuple_id)); tile_group_header->SetTransactionId(tuple_id, INITIAL_TXN_ID); }
bool PessimisticTxnManager::AcquireOwnership( const storage::TileGroupHeader *const tile_group_header, const oid_t &tile_group_id, const oid_t &tuple_id) { LOG_TRACE("AcquireOwnership"); assert(IsOwner(tile_group_header, tuple_id) == false); // acquire write lock. // No writer, release read lock that is acquired before // Must success ReleaseReadLock(tile_group_header, tuple_id); pessimistic_released_rdlock[tile_group_id].insert(tuple_id); // Try get write lock auto current_txn_id = current_txn->GetTransactionId(); bool res = tile_group_header->SetAtomicTransactionId(tuple_id, PACK_TXNID(current_txn_id, 0)); if (res) { return true; } else { LOG_INFO("Fail to acquire write lock. Set txn failure."); // SetTransactionResult(Result::RESULT_FAILURE); return false; } }
VOID CRWLock::WaitToRead() { BOOL bWait = FALSE; { CCriSecLock locallock(m_cs); if(m_nActive > 0) ++m_nActive; else if(m_nActive == 0) { if(m_nWaitingWriters == 0) ++m_nActive; else { ++m_nWaitingReaders; bWait = TRUE; } } else { if(!IsOwner()) { ++m_nWaitingReaders; bWait = TRUE; } } } if(bWait) { m_smRead.Wait(); } }
VOID CRWLock::WaitToWrite() { BOOL bWait = FALSE; { CCriSecLock locallock(m_cs); if(m_nActive > 0) { ++m_nWaitingWriters; bWait = TRUE; } else if(m_nActive == 0) { --m_nActive; SetOwner(); } else { if(IsOwner()) --m_nActive; else { ++m_nWaitingWriters; bWait = TRUE; } } } if(bWait) { m_smWrite.Wait(); SetOwner(); } }
void StackAsArray::Purge () { if (IsOwner ()) { for (unsigned int i = 0; i < count; ++i) { delete array [i]; #ifdef DPRINT fprintf(stderr, " delete array[%d]@ count =%d\n", i, count); #endif } } #ifdef DPRINT fprintf(stderr, " Stack.Purge() is called & IsOwner() == %d\n", IsOwner()); #endif count = 0; }
/** * Remove * * After calling Create this function can be used to remove the pid file * If the PIDFile is invalid and is not currently owner by the process * calling Remove will call abort. */ void PIDFile::Remove() { if (IsOwner() == false) abort(); //Your not the owner if (unlink(m_filename.c_str()) < 0) abort(); //We should be the owner of this file m_IsOwner = false; }
void StackAsArray::Purge () { if (IsOwner ()) { for (unsigned int i = 0; i < count; ++i) { delete array [i]; } } count = 0; }
VOID CMutexRWLock::WriteDone() { ASSERT(IsOwner()); ASSERT(m_nActive < 0); CSpinLock locallock(m_cs); if(++m_nActive == 0) { DetachOwner(); m_mtx.unlock(); } }
void OpenScatterTable::Purge () { for (unsigned int i = 0; i < length; ++i) { if (array [i].state == Entry::occupied) { if (IsOwner ()) delete array [i].object; array [i] = Entry (); } } count = 0; }
VOID CRWLock::ReadDone() { CCriSecLock locallock(m_cs); ASSERT(m_nActive != 0); if(m_nActive > 0) { if(--m_nActive == 0) Done(); } else ASSERT(IsOwner()); }
void BagAsLinkedList::Purge () { if (IsOwner ()) { ListElement<Object*> const* ptr; for (ptr = list.Head (); ptr != 0; ptr = ptr->Next ()) { delete ptr->Datum (); } } list.Purge (); count = 0; }
VOID CRWLock::WriteDone() { CCriSecLock locallock(m_cs); ASSERT(m_nActive < 0); if(++m_nActive == 0) { DetachOwner(); Done(); } else ASSERT(IsOwner()); }
bool PessimisticTxnManager::PerformRead(const oid_t &tile_group_id, const oid_t &tuple_id) { LOG_TRACE("Perform read"); auto &manager = catalog::Manager::GetInstance(); auto tile_group = manager.GetTileGroup(tile_group_id); auto tile_group_header = tile_group->GetHeader(); auto &rw_set = current_txn->GetRWSet(); auto tuple_map = rw_set.find(tile_group_id); if (tuple_map != rw_set.end()) { if (tuple_map->second.find(tuple_id) != tuple_map->second.end()) { // It was already accessed, don't acquire read lock again return true; } } if (IsOwner(tile_group_header, tuple_id)) { return true; } // Try to acquire read lock. auto old_txn_id = tile_group_header->GetTransactionId(tuple_id); // No one is holding the write lock if (EXTRACT_TXNID(old_txn_id) == INITIAL_TXN_ID) { LOG_TRACE("No one holding the lock"); while (true) { LOG_TRACE("Current read count is %lu", EXTRACT_READ_COUNT(old_txn_id)); auto new_read_count = EXTRACT_READ_COUNT(old_txn_id) + 1; // Try add read count auto new_txn_id = PACK_TXNID(INITIAL_TXN_ID, new_read_count); LOG_TRACE("New txn id %lx", new_txn_id); txn_id_t real_txn_id = tile_group_header->SetAtomicTransactionId( tuple_id, old_txn_id, new_txn_id); if (real_txn_id != old_txn_id) { // See if there's writer if (EXTRACT_TXNID(real_txn_id) != INITIAL_TXN_ID) return false; } else { break; } } } else { // SetTransactionResult(RESULT_FAILURE); return false; } current_txn->RecordRead(tile_group_id, tuple_id); return true; }
void COXRollup::ReleaseRecipient(const CWnd* pRCRequesting, BOOL bCallNotifyFunction) { // do this only when he is the current owner of the message dispatch system if (IsOwner(pRCRequesting)) { TRACE1("[RU]Released the owner of the mds. Handle : %ld\n", m_hWndMR); // if he chose to do some cleanup, do it if (bCallNotifyFunction) OnRecipientRelease(); m_hWndMR = NULL; } // else do nothing (somebody else has registered as current user }
void Delete() { if (IsOwner()) { if (IsArray()) { m_bits &= POINTER_MASK; delete [] m_ptr; } else { m_bits &= POINTER_MASK; delete m_ptr; } } m_ptr = 0; }
VOID CSEMRWLock::ReadDone() { ASSERT(m_nActive != 0); INT iFlag = 0; if(m_nActive > 0) { CSpinLock locallock(m_cs); if(--m_nActive == 0) iFlag = Done(); } else ASSERT(IsOwner()); Notify(iFlag); }
VOID CSEMRWLock::WriteDone() { ASSERT(IsOwner()); ASSERT(m_nActive < 0); INT iFlag = 0; { CSpinLock locallock(m_cs); if(++m_nActive == 0) { DetachOwner(); iFlag = Done(); } } Notify(iFlag); }
VOID CMutexRWLock::ReadDone() { ASSERT(m_nActive != 0); if(m_nActive > 0) { ASSERT(m_nReadCount > 0); CSpinLock locallock(m_cs); if(--m_nActive == 0) { for(; m_nReadCount > 0; --m_nReadCount) m_mtx.unlock_shared(); } } else ASSERT(IsOwner()); }
Bool_t KVUniqueNameList::checkObjInList(TObject* obj) { // Return kTRUE if 'obj' can be added to list. // If fReplace==kFALSE, there must be no object in the list with // same name as obj->GetName(). // If fReplace==kTRUE the previous object is removed from the list. // If IsOwner()==kTRUE the previous object is removed AND deleted. // In the latter two cases the new object can always be added (returns kTRUE) TObject* old_obj = FindObject(obj->GetName()); if(!old_obj) return kTRUE; else { if(fReplace){ Remove(old_obj); if(IsOwner()) delete old_obj; return kTRUE; } } return kFALSE; }
VOID CRWLock::WriteDone() { CSEM* pSem = nullptr; LONG lCount = 0; { CSpinLock locallock(m_cs); ASSERT(m_nActive < 0); if(++m_nActive == 0) { DetachOwner(); Done(&pSem, lCount); } else ASSERT(IsOwner()); } if(pSem != nullptr) pSem->Release(lCount); }
VOID CRWLock::ReadDone() { CSEM* pSem = nullptr; LONG lCount = 0; { CSpinLock locallock(m_cs); ASSERT(m_nActive != 0); if(m_nActive > 0) { if(--m_nActive == 0) Done(&pSem, lCount); } else ASSERT(IsOwner()); } if(pSem != nullptr) pSem->Release(lCount); }
VOID CMutexRWLock::WaitToWrite() { BOOL bWait = FALSE; { CSpinLock locallock(m_cs); if(m_nActive > 0) bWait = TRUE; else if(m_nActive == 0) { if(m_mtx.try_lock()) { SetOwner(); --m_nActive; } else bWait = TRUE; } else { if(IsOwner()) --m_nActive; else bWait = TRUE; } } if(bWait) { m_mtx.lock(); SetOwner(); --m_nActive; } }
// transaction. // this function is called by update/delete executors. bool EagerWriteTxnManager::IsOwnable( const storage::TileGroupHeader *const tile_group_header, const oid_t &tuple_id) { auto tuple_txn_id = tile_group_header->GetTransactionId(tuple_id); auto tuple_end_cid = tile_group_header->GetEndCommitId(tuple_id); LOG_INFO("IsOwnable txnid: %lx end_cid: %lx", tuple_txn_id, tuple_end_cid); return tuple_txn_id == INITIAL_TXN_ID && tuple_end_cid == MAX_CID; } bool EagerWriteTxnManager::AcquireOwnership( const storage::TileGroupHeader *const tile_group_header, const oid_t &tile_group_id __attribute__((unused)), const oid_t &tuple_id) { LOG_INFO("AcquireOwnership"); assert(IsOwner(tile_group_header, tuple_id) == false); // Try to get write lock auto current_tid = current_txn->GetTransactionId(); auto old_tid = INITIAL_TXN_ID; GetEwReaderLock(tile_group_header, tuple_id); old_tid = tile_group_header->SetAtomicTransactionId(tuple_id, old_tid, current_tid); // Check if we successfully get the write lock bool res = (old_tid == INITIAL_TXN_ID); if (!res) { LOG_INFO("Fail to acquire write lock. Set txn failure."); ReleaseEwReaderLock(tile_group_header, tuple_id);
/** * Create * * Create a new PIDFile using the filename that was specified in the constructor. * The function will return true if it was capable of creating a pid file. * The function will fail if the pid file already exists and has an active owner * An active owner is checked by comaring the current process exe filename with * the process who's pid is in the existing pid file */ bool PIDFile::Create() { int fd = open(m_filename.c_str(), O_CREAT | O_EXCL | O_RDWR, S_IRUSR | S_IWUSR | S_IRGRP); FILE *file = NULL; int tpid = -1; int ret = 0; if (IsOwner()) abort(); //Error with caller attempting to create pidfile twice if (fd < 0) { switch(errno) { case EEXIST: //Lets see if we can fix fd file = fopen(m_filename.c_str(), "r"); if (!file) return false; ret = fscanf(file, "%d", &tpid); fclose(file); if (ret != 1) //Issue here is that we have an unparsable pid file. Should we remove it? return false; do { std::string self; std::string pidexe; if (GetOwnExePath(&self) == false) return false; if (GetPIDExePath(tpid, &pidexe) == true) { if (self == pidexe) return false; //The pid in the file matchs us and is a valid process } if (unlink(m_filename.c_str()) < 0) //Not "us" just overwrite it abort(); fd = open(m_filename.c_str(), O_CREAT | O_EXCL | O_RDWR, S_IRUSR | S_IWUSR | S_IRGRP); if (fd < 0) return false; } while(0); break; default: return false; } } FILE *fp = fdopen(fd, "w"); if (!fp) abort(); //Should never happen fprintf(fp, "%d\n", getpid()); fclose(fp); m_IsOwner = true; return true; }
// transaction. // this function is called by update/delete executors. bool EagerWriteTxnManager::IsOwnable( const storage::TileGroupHeader *const tile_group_header, const oid_t &tuple_id) { auto tuple_txn_id = tile_group_header->GetTransactionId(tuple_id); auto tuple_end_cid = tile_group_header->GetEndCommitId(tuple_id); LOG_TRACE("IsOwnable txnid: %lx end_cid: %lx", tuple_txn_id, tuple_end_cid); return tuple_txn_id == INITIAL_TXN_ID && tuple_end_cid == MAX_CID; } bool EagerWriteTxnManager::AcquireOwnership( const storage::TileGroupHeader *const tile_group_header, const oid_t &tile_group_id UNUSED_ATTRIBUTE, const oid_t &tuple_id) { LOG_TRACE("AcquireOwnership"); PL_ASSERT(IsOwner(tile_group_header, tuple_id) == false); // Try to get write lock auto current_tid = current_txn->GetTransactionId(); auto old_tid = INITIAL_TXN_ID; GetEwReaderLock(tile_group_header, tuple_id); old_tid = tile_group_header->SetAtomicTransactionId(tuple_id, old_tid, current_tid); // Check if we successfully get the write lock bool res = (old_tid == INITIAL_TXN_ID); if (!res) { LOG_TRACE("Fail to acquire write lock. Set txn failure."); ReleaseEwReaderLock(tile_group_header, tuple_id);
bool Matrix<T>::Viewing() const { return !IsOwner( viewType_ ); }
bool Matrix<T>::Owner() const { return IsOwner( viewType_ ); }
bool TimestampOrderingTransactionManager::PerformRead( TransactionContext *const current_txn, const ItemPointer &read_location, bool acquire_ownership) { ItemPointer location = read_location; ////////////////////////////////////////////////////////// //// handle READ_ONLY ////////////////////////////////////////////////////////// if (current_txn->GetIsolationLevel() == IsolationLevelType::READ_ONLY) { // do not update read set for read-only transactions. return true; } // end READ ONLY ////////////////////////////////////////////////////////// //// handle SNAPSHOT ////////////////////////////////////////////////////////// // TODO: what if we want to read a version that we write? else if (current_txn->GetIsolationLevel() == IsolationLevelType::SNAPSHOT) { oid_t tile_group_id = location.block; oid_t tuple_id = location.offset; LOG_TRACE("PerformRead (%u, %u)\n", location.block, location.offset); auto &manager = catalog::Manager::GetInstance(); auto tile_group_header = manager.GetTileGroup(tile_group_id)->GetHeader(); // Check if it's select for update before we check the ownership // and modify the last reader cid if (acquire_ownership == true) { // get the latest version of this tuple. location = *(tile_group_header->GetIndirection(location.offset)); tile_group_id = location.block; tuple_id = location.offset; tile_group_header = manager.GetTileGroup(tile_group_id)->GetHeader(); if (IsOwner(current_txn, tile_group_header, tuple_id) == false) { // Acquire ownership if we haven't if (IsOwnable(current_txn, tile_group_header, tuple_id) == false) { // Cannot own return false; } if (AcquireOwnership(current_txn, tile_group_header, tuple_id) == false) { // Cannot acquire ownership return false; } // Record RWType::READ_OWN current_txn->RecordReadOwn(location); } // if we have already owned the version. PL_ASSERT(IsOwner(current_txn, tile_group_header, tuple_id) == true); // Increment table read op stats if (static_cast<StatsType>(settings::SettingsManager::GetInt(settings::SettingId::stats_mode)) != StatsType::INVALID) { stats::BackendStatsContext::GetInstance()->IncrementTableReads( location.block); } return true; } else { // if it's not select for update, then update read set and return true. current_txn->RecordRead(location); // Increment table read op stats if (static_cast<StatsType>(settings::SettingsManager::GetInt(settings::SettingId::stats_mode)) != StatsType::INVALID) { stats::BackendStatsContext::GetInstance()->IncrementTableReads( location.block); } return true; } } // end SNAPSHOT ////////////////////////////////////////////////////////// //// handle READ_COMMITTED ////////////////////////////////////////////////////////// else if (current_txn->GetIsolationLevel() == IsolationLevelType::READ_COMMITTED) { oid_t tile_group_id = location.block; oid_t tuple_id = location.offset; LOG_TRACE("PerformRead (%u, %u)\n", location.block, location.offset); auto &manager = catalog::Manager::GetInstance(); auto tile_group_header = manager.GetTileGroup(tile_group_id)->GetHeader(); // Check if it's select for update before we check the ownership. if (acquire_ownership == true) { // acquire ownership. if (IsOwner(current_txn, tile_group_header, tuple_id) == false) { // Acquire ownership if we haven't if (IsOwnable(current_txn, tile_group_header, tuple_id) == false) { // Cannot own return false; } if (AcquireOwnership(current_txn, tile_group_header, tuple_id) == false) { // Cannot acquire ownership return false; } // Record RWType::READ_OWN current_txn->RecordReadOwn(location); } // if we have already owned the version. PL_ASSERT(IsOwner(current_txn, tile_group_header, tuple_id) == true); // Increment table read op stats if (static_cast<StatsType>(settings::SettingsManager::GetInt(settings::SettingId::stats_mode)) != StatsType::INVALID) { stats::BackendStatsContext::GetInstance()->IncrementTableReads( location.block); } return true; } else { // a transaction can never read an uncommitted version. if (IsOwner(current_txn, tile_group_header, tuple_id) == false) { if (IsOwned(current_txn, tile_group_header, tuple_id) == false) { current_txn->RecordRead(location); // Increment table read op stats if (static_cast<StatsType>(settings::SettingsManager::GetInt(settings::SettingId::stats_mode)) != StatsType::INVALID) { stats::BackendStatsContext::GetInstance()->IncrementTableReads( location.block); } return true; } else { // if the tuple has been owned by some concurrent transactions, // then read fails. LOG_TRACE("Transaction read failed"); return false; } } else { // this version must already be in the read/write set. // so no need to update read set. // current_txn->RecordRead(location); // Increment table read op stats if (static_cast<StatsType>(settings::SettingsManager::GetInt(settings::SettingId::stats_mode)) != StatsType::INVALID) { stats::BackendStatsContext::GetInstance()->IncrementTableReads( location.block); } return true; } } } // end READ_COMMITTED ////////////////////////////////////////////////////////// //// handle SERIALIZABLE and REPEATABLE_READS ////////////////////////////////////////////////////////// else { PL_ASSERT(current_txn->GetIsolationLevel() == IsolationLevelType::SERIALIZABLE || current_txn->GetIsolationLevel() == IsolationLevelType::REPEATABLE_READS); oid_t tile_group_id = location.block; oid_t tuple_id = location.offset; LOG_TRACE("PerformRead (%u, %u)\n", location.block, location.offset); auto &manager = catalog::Manager::GetInstance(); auto tile_group_header = manager.GetTileGroup(tile_group_id)->GetHeader(); // Check if it's select for update before we check the ownership // and modify the last reader cid. if (acquire_ownership == true) { // acquire ownership. if (IsOwner(current_txn, tile_group_header, tuple_id) == false) { // Acquire ownership if we haven't if (IsOwnable(current_txn, tile_group_header, tuple_id) == false) { // Cannot own return false; } if (AcquireOwnership(current_txn, tile_group_header, tuple_id) == false) { // Cannot acquire ownership return false; } // Record RWType::READ_OWN current_txn->RecordReadOwn(location); // now we have already obtained the ownership. // then attempt to set last reader cid. UNUSED_ATTRIBUTE bool ret = SetLastReaderCommitId( tile_group_header, tuple_id, current_txn->GetCommitId(), true); PL_ASSERT(ret == true); // there's no need to maintain read set for timestamp ordering protocol. // T/O does not check the read set during commit phase. } // if we have already owned the version. PL_ASSERT(IsOwner(current_txn, tile_group_header, tuple_id) == true); PL_ASSERT(GetLastReaderCommitId(tile_group_header, tuple_id) == current_txn->GetCommitId() || GetLastReaderCommitId(tile_group_header, tuple_id) == 0); // Increment table read op stats if (static_cast<StatsType>(settings::SettingsManager::GetInt(settings::SettingId::stats_mode)) != StatsType::INVALID) { stats::BackendStatsContext::GetInstance()->IncrementTableReads( location.block); } return true; } else { if (IsOwner(current_txn, tile_group_header, tuple_id) == false) { // if the current transaction does not own this tuple, // then attempt to set last reader cid. if (SetLastReaderCommitId(tile_group_header, tuple_id, current_txn->GetCommitId(), false) == true) { // update read set. current_txn->RecordRead(location); // Increment table read op stats if (static_cast<StatsType>(settings::SettingsManager::GetInt(settings::SettingId::stats_mode)) != StatsType::INVALID) { stats::BackendStatsContext::GetInstance()->IncrementTableReads( location.block); } return true; } else { // if the tuple has been owned by some concurrent transactions, // then read fails. LOG_TRACE("Transaction read failed"); return false; } } else { // if the current transaction has already owned this tuple, // then perform read directly. PL_ASSERT(GetLastReaderCommitId(tile_group_header, tuple_id) == current_txn->GetCommitId() || GetLastReaderCommitId(tile_group_header, tuple_id) == 0); // this version must already be in the read/write set. // so no need to update read set. // current_txn->RecordRead(location); // Increment table read op stats if (static_cast<StatsType>(settings::SettingsManager::GetInt(settings::SettingId::stats_mode)) != StatsType::INVALID) { stats::BackendStatsContext::GetInstance()->IncrementTableReads( location.block); } return true; } } } // end SERIALIZABLE || REPEATABLE_READS }