Beispiel #1
0
void PowerTray::monitorLid()
{
    bool do_suspend = false;
    QStringList lids;
    lids << "/proc/acpi/button/lid/LID/state" << "/proc/acpi/button/lid/LID0/state";
    for (int i = 0; i < lids.size(); ++i)
    {
        QFile lid(lids.at(i));
        if (lid.exists())
        {
            if (lid.open(QIODevice::ReadOnly))
            {
                QString line;
                QTextStream textStream(&lid);
                line = textStream.readAll().simplified();
                if (line == "state: closed")
                {
                    do_suspend = true;
                }
                lid.close();
            }
        }
    }

    if (do_suspend)
    {
        QDBusConnection conn = QDBusConnection::systemBus();
        QDBusInterface computer("org.freedesktop.Hal","/org/freedesktop/Hal/devices/computer","org.freedesktop.Hal.Device.SystemPowerManagement",conn);
        computer.call("Suspend",1);
    }

    QTimer::singleShot(1000,this,SLOT(monitorLid())); // loop
}
Beispiel #2
0
/******************************************************************************************
* @brief	sendAlarm
*
* purpose:	send a trap and log the process information
*
******************************************************************************************/
void ServerMonitor::sendAlarm(string alarmItem, ALARMS alarmID, int action, float sensorValue)
{
	ServerMonitor serverMonitor;
	Oam oam;

	//Log this event 
	LoggingID lid(SERVER_MONITOR_LOG_ID);
	MessageLog ml(lid);
	Message msg;
	Message::Args args;
	args.add(alarmItem);
	args.add(", sensor value out-of-range: ");
	args.add(sensorValue);

	// get current server name
	string moduleName;
	oamModuleInfo_t st;
	try {
		st = oam.getModuleInfo();
		moduleName = boost::get<0>(st);
	}
	catch (...) {
		moduleName = "Unknown Server";
	}

	// check if there is an active alarm above the reporting theshold 
	// that needs to be cleared
	serverMonitor.checkAlarm(alarmItem, alarmID);

	// check if Alarm is already active, don't resend
	if ( !( oam.checkActiveAlarm(alarmID, moduleName, alarmItem)) ) {

		SNMPManager alarmMgr;
		// send alarm
		alarmMgr.sendAlarmReport(alarmItem.c_str(), alarmID, action);

		args.add(", Alarm set: ");
		args.add(alarmID);
	}

	// output log
	msg.format(args);
	ml.logWarningMessage(msg);

	return;
}
Beispiel #3
0
/******************************************************************************************
* @brief	clearAlarm
*
* purpose:	clear Alarm that was previously set
*
******************************************************************************************/
void ServerMonitor::clearAlarm(string alarmItem, ALARMS alarmID)
{
	SNMPManager alarmMgr;
	alarmMgr.sendAlarmReport(alarmItem.c_str(), alarmID, CLEAR);

	//Log this event 
	LoggingID lid(SERVER_MONITOR_LOG_ID);
	MessageLog ml(lid);
	Message msg;
	Message::Args args;
	args.add(alarmItem);
	args.add(" alarm #");
	args.add(alarmID);
	args.add("cleared");
	msg.format(args);
	ml.logWarningMessage(msg);
}
Beispiel #4
0
Chunk::Chunk(uint32_t id, const void * buffer, size_t len, bool skipcrc) :
    _id(id),
    _nextOffset(0),
    _lastSerial(static_cast<uint64_t>(-1l)),
    _format(ChunkFormat::deserialize(buffer, len, skipcrc))
{
    vespalib::nbostream &os = getData();
    while (os.size() > sizeof(_lastSerial)) {
        uint32_t sz(0);
        uint32_t lid(0);
        ssize_t oldRp(os.rp());
        os >> lid >> sz;
        os.adjustReadPos(sz);
        _lids.push_back(Entry(lid, sz, oldRp));
    }
    os >> _lastSerial;
}
Beispiel #5
0
Controller::ledid Controller::getPortPinFromString(const QString& channel) const {
    Controller::ledid lid(-1,0);
    if (channel.size()<3) {
        qWarning() << m_plugin->pluginid() << "getPortPinFromChannel failed. Right syntax: e.g. A:0 or 2:7" << channel;
        return lid;
    }

    char port = channel[0].toAscii();
    lid.pin = channel[2].toAscii()-'0';

    switch (port) {
    case 'A':
    case '0':
        lid.port = 0;
        break;
    case 'B':
    case '1':
        lid.port = 1;
        break;
    case 'C':
    case '2':
        lid.port = 2;
        break;
    case 'D':
    case '3':
        lid.port = 3;
        break;
    case 'E':
    case '4':
        lid.port = 4;
        break;
    case 'F':
    case '5':
        lid.port = 5;
        break;
    default:
        lid.port = 250;
    }

    if (lid.port == 250 || lid.pin >= 8) {
        qWarning() << m_plugin->pluginid() << "getPortPinFromChannel failed. Port range (A-F) or Pin range (0-7) wrong!" << channel;
    }

    return lid;
}
Beispiel #6
0
/******************************************************************************************
* @brief	sendResourceAlarm
*
* purpose:	send a trap and log the process information
*
******************************************************************************************/
bool ServerMonitor::sendResourceAlarm(string alarmItem, ALARMS alarmID, int action, int usage)
{
	ServerMonitor serverMonitor;
	Oam oam;

	//Log this event 
	LoggingID lid(SERVER_MONITOR_LOG_ID);
	MessageLog ml(lid);
	Message msg;
	Message::Args args;
	args.add(alarmItem);
	args.add(" usage at percentage of ");
	args.add(usage);

	// get current module name
	string moduleName;
	oamModuleInfo_t st;
	try {
		st = oam.getModuleInfo();
		moduleName = boost::get<0>(st);
	}
	catch (...) {
		moduleName = "Unknown Server";
	}

	// check if there is an active alarm above the reporting theshold 
	// that needs to be cleared

	if (alarmItem == "CPU")
		serverMonitor.checkCPUAlarm(alarmItem, alarmID);
	else if (alarmItem == "Local Disk" || alarmItem == "External")
			serverMonitor.checkDiskAlarm(alarmItem, alarmID);
	else if (alarmItem == "Local Memory")
			serverMonitor.checkMemoryAlarm(alarmItem, alarmID);
	else if (alarmItem == "Local Swap")
			serverMonitor.checkSwapAlarm(alarmItem, alarmID);

	// don't issue an alarm on thge dbroots is already issued by this or another server
	if ( alarmItem.find(startup::StartUp::installDir() + "/data") == 0 ) {
		// check if Alarm is already active from any module, don't resend
		if ( !( oam.checkActiveAlarm(alarmID, "*", alarmItem)) ) {
	
			SNMPManager alarmMgr;
			// send alarm
			alarmMgr.sendAlarmReport(alarmItem.c_str(), alarmID, action);
	
			args.add(", Alarm set: ");
			args.add(alarmID);
			msg.format(args);
			ml.logInfoMessage(msg);
			return true;
		}
		else
			return false;
	}
	else
	{
		// check if Alarm is already active from this module, don't resend
		if ( !( oam.checkActiveAlarm(alarmID, moduleName, alarmItem)) ) {
	
			SNMPManager alarmMgr;
			// send alarm
			alarmMgr.sendAlarmReport(alarmItem.c_str(), alarmID, action);
	
			args.add(", Alarm set: ");
			args.add(alarmID);
			msg.format(args);
			ml.logInfoMessage(msg);
			return true;
		}
		else
			return false;
	}

	return true;
}
Beispiel #7
0
 //! Returns true if the GID passed in belongs to the calling processor in this map, otherwise returns false.
 bool  myGID( size_type GID ) const
 {
     return( lid( GID )!=invalid_size_type_value );
 }
Beispiel #8
0
//------------------------------------------------------------------------------
// Main entry point to this program
//------------------------------------------------------------------------------
int main(int argc, char** argv)
{
	int c;
	bool clearLockOnly = false;
	bool rollbackOnly  = false;
	uint32_t tableOID  = 0;

	while ((c = getopt(argc, argv, "hlr:")) != EOF)
	{
		switch (c)
		{
			case 'l':
				clearLockOnly = true;
				break;
//Only allow '-r' option for development/debugging
#if 1
			case 'r': // hidden option to rollback specified table w/o a lock
				rollbackOnly  = true;
				tableOID      = ::strtoull(optarg, 0, 10);
				break;
#endif
			case 'h':
			case '?':
			default:
				usage();
				return (c == 'h' ? 0 : 1);
				break;
		}
	}

	if ((argc - optind) != 1 )
	{
		usage();
		return 1;
	}

	// Get the table lock ID specified by the user
	uint64_t lockID = ::strtoull(argv[optind], 0, 10);

	// If user specified both clearlock and rollback then we need to do both
	if (clearLockOnly && rollbackOnly)
	{
		clearLockOnly = false;
		rollbackOnly  = false;
	}

	//--------------------------------------------------------------------------
	// Verify that BRM is up and in a read/write state
	//--------------------------------------------------------------------------
	BRM::DBRM brm;
	int brmRc = brm.isReadWrite();
	if (brmRc != BRM::ERR_OK)
	{
		std::string brmErrMsg;
		BRM::errString(brmRc, brmErrMsg);
		std::cout << "BRM error: " << brmErrMsg << std::endl;
		std::cout << "Table lock " << lockID << " is not cleared." << std::endl;
		return 1;
	}

	if (brm.getSystemReady() < 1)
	{
		std::cout << "System is not ready.  Verify that EryDB "
			"is up and ready before running this program" << std::endl;
		return 1;
	}

	//--------------------------------------------------------------------------
	//@Bug 3711 Check whether the table is locked; does the table lock exist.
	//--------------------------------------------------------------------------
	execplan::erydbSystemCatalog::TableName tblName;
	BRM::TableLockInfo tInfo;
	std::string task;
	std::vector<uint32_t> pmList;
	int rc;
	const std::string taskSysCat("getting system catalog information");
	try {
		if (rollbackOnly)
		{
			tInfo.id             = lockID;
			tInfo.tableOID       = tableOID;
			tInfo.ownerPID       = 0;
			tInfo.ownerSessionID = 1;
			tInfo.state          = BRM::LOADING;

			// Construct PM list using all PMs, since we don't have a table
			// lock with the list of applicable DBRoots.
			task = "constructing total PM list";
			rc = constructPMList( pmList );
			if (rc != 0)
			{
				return 1;
			}
		}
		else
		{
			task = "getting table lock";
   			bool lockExists = brm.getTableLockInfo( lockID, &tInfo );
   			if (!lockExists)
			{
				std::cout << "Table lock " << lockID << " does not exist." <<
					std::endl;
				return 1;
			}

			// Construct PM list based on list of affected DBRoots
			task = "mapping DBRoots to PMs";
			rc = constructPMList( tInfo.dbrootList, pmList );
			if (rc != 0)
			{
				return 1;
			}
		}

		uint32_t sessionID = 1;
		task = taskSysCat;
		boost::shared_ptr<execplan::erydbSystemCatalog> systemCatalogPtr =
			execplan::erydbSystemCatalog::makeerydbSystemCatalog(
				sessionID );
		systemCatalogPtr->identity(execplan::erydbSystemCatalog::EC);
		tblName = systemCatalogPtr->tableName( tInfo.tableOID );
	}
	catch (std::exception& ex)
	{
		std::cout << "Error " << task << ".  " << ex.what() << std::endl;
		if (clearLockOnly && (task == taskSysCat))
		{
			tblName.schema= "[unknown name]";
			tblName.table.clear();
			std::cout << "Will still try to clear table lock." << std::endl;
		}
		else
		{
			std::cout << "Table lock " << lockID << " is not cleared." <<
				std::endl;
			return 1;
		}
	}
	catch (...)
	{
		std::cout << "Error " << task << ".  " << std::endl;
		if (clearLockOnly && (task == taskSysCat))
		{
			tblName.schema= "[unknown name]";
			tblName.table.clear();
			std::cout << "Will still try to clear table lock." << std::endl;
		}
		else
		{
			std::cout << "Table lock " << lockID << " is not cleared." <<
				std::endl;
			return 1;
		}
	}

	logInitStatus( tblName.toString(), lockID );
	if (rollbackOnly)
	{
		std::cout << "Rolling back table " << tblName.toString() <<
			std::endl << std::endl;
	}
	else if (clearLockOnly)
	{
		std::cout << "Clearing table lock " << lockID <<
			" for table " << tblName.toString() << std::endl << std::endl;
	}
	else
	{
		std::cout << "Rolling back and clearing table lock for table " <<
			tblName.toString() << "; table lock " << lockID <<
			std::endl << std::endl;
	}

	//--------------------------------------------------------------------------
	// Perform bulk rollback
	//--------------------------------------------------------------------------
	std::string errMsg;
	if (!clearLockOnly)
	{
		std::vector<boost::shared_ptr<messageqcpp::MessageQueueClient> >
			msgQueClts;
		rc = createMsgQueClts(pmList, msgQueClts, errMsg);
		if (rc != 0)
		{
			logFinalStatus( tblName.toString(), lockID, errMsg );
			std::cout << errMsg << std::endl;
			std::cout << "Table lock " << lockID << " for table " <<
				tblName.toString() << " is not cleared." << std::endl;
			return rc;
		}

		rc = execBulkRollbackReq( msgQueClts, pmList,
			&brm, tInfo, tblName.toString(), rollbackOnly, errMsg );
		if (rc != 0)
		{
			logFinalStatus( tblName.toString(), lockID, errMsg );
			std::cout << "Rollback error: " << errMsg << std::endl;
			std::cout << "Table lock " << lockID << " for table " <<
				tblName.toString() << " is not cleared." << std::endl;
			return rc;
		}

		//----------------------------------------------------------------------
		// Change the state of the table lock to cleanup state.
		// We ignore the return stateChange flag.
		//----------------------------------------------------------------------
		if (!rollbackOnly)
		{
			try {
				brm.changeState( tInfo.id, BRM::CLEANUP );
			}
			catch (std::exception& ex)
			{
				std::ostringstream oss;
				oss << "Error changing state.  " << ex.what();
				logFinalStatus( tblName.toString(), lockID, oss.str() );
				std::cout << oss.str() << std::endl;
				std::cout << "Table lock " << lockID << " is not cleared." <<
					std::endl;
				return 1;
			}
			catch (...)
			{
				std::ostringstream oss;
				oss << "Error changing state.  " << std::endl;
				logFinalStatus( tblName.toString(), lockID, oss.str() );
				std::cout << oss.str() << std::endl;
				std::cout << "Table lock " << lockID << " is not cleared." <<
					std::endl;
				return 1;
			}
		}

		//----------------------------------------------------------------------
		// Delete the meta data files
		//----------------------------------------------------------------------
		rc = execFileCleanupReq( msgQueClts, pmList,
			&brm, tInfo, tblName.toString(), errMsg );
		if (rc != 0)
		{
			//@Bug 4517. Release tablelock if remove meta files failed
			const std::string APPLNAME("cleartablelock command");
			const int SUBSYSTEM_ID = 19; // writeengine?
			const int COMP_MSG_NUM = logging::M0089;
			logging::Message::Args msgArgs;
			logging::Message logMsg( COMP_MSG_NUM );
			msgArgs.add( APPLNAME );
			msgArgs.add( tblName.toString() );
			msgArgs.add( lockID );
			msgArgs.add( errMsg );
			logMsg.format( msgArgs );
			logging::LoggingID  lid( SUBSYSTEM_ID );
			logging::MessageLog ml( lid );
			ml.logWarningMessage( logMsg );
			
			std::cout << "File cleanup error: " << errMsg << std::endl;
		}
	} // end of: if (!clearLockOnly)

	//--------------------------------------------------------------------------
	// Finally, release the actual table lock
	//--------------------------------------------------------------------------
	std::cout << std::endl;
	if (rollbackOnly)
	{
		logFinalStatus( tblName.toString(), lockID, std::string() );
		std::cout << "Bulk Rollback Only for table " << tblName.toString() <<
			" completed successfully." << std::endl;
	}
	else
	{
		try {
			brm.releaseTableLock( lockID ); // ignore boolean return value
		}
		catch (std::exception& ex)
		{
			logFinalStatus( tblName.toString(), lockID, ex.what() );
			std::cout << "Error releasing table lock " << lockID <<
				" for table " << tblName.toString() << std::endl;
			std::cout << ex.what() << std::endl;
			return 1;
		}
		catch (...)
		{
			std::string unknownErr("Unknown exception");
			logFinalStatus( tblName.toString(), lockID, unknownErr );
			std::cout << "Error releasing table lock " << lockID <<
				" for table " << tblName.toString() << std::endl;
			std::cout << unknownErr << std::endl;
			return 1;
		}

		logFinalStatus( tblName.toString(), lockID, std::string() );
		std::cout << "Table lock " << lockID << " for table " <<
			tblName.toString() << " is cleared." << std::endl;
	}
	
	return 0;
}
Beispiel #9
0
rc_t bt_cursor_t::_advance_one_slot(btree_page_h &p, bool &eof)
{
    w_assert1(p.is_fixed());
    w_assert1(_slot <= p.nrecs());

    if(_forward) {
        ++_slot;
    } else {
        --_slot;
    }
    eof = false;

    // keep following the next page.
    // because we might see empty pages to skip consecutively!
    while (true) {
        bool time2move = _forward ? (_slot >= p.nrecs()) : _slot < 0;

        if (time2move) {
            //  Move to right(left) sibling
            bool reached_end = _forward ? p.is_fence_high_supremum() : p.is_fence_low_infimum();
            if (reached_end) {
                eof = true;
                return RCOK;
            }
            // now, use fence keys to tell where the neighboring page exists
            w_keystr_t neighboring_fence;
            btree_impl::traverse_mode_t traverse_mode;
            bool only_low_fence_exact_match = false;
            if (_forward) {
                p.copy_fence_high_key(neighboring_fence);
                traverse_mode = btree_impl::t_fence_low_match;
                int d = _upper.compare(neighboring_fence);
                if (d < 0 || (d == 0 && !_upper_inclusive)) {
                    eof = true;
                    return RCOK;
                }
                if (d == 0 && _upper_inclusive) {
                    // we will check the next page, but the only
                    // possible matching is an entry with
                    // the low-fence..
                    only_low_fence_exact_match = true;
                }
            } else {
                // if we are going backwards, the current page had
                // low = [current-fence-low], high = [current-fence-high]
                // and the previous page should have
                // low = [?], high = [current-fence-low].
                p.copy_fence_low_key(neighboring_fence);
                // let's find a page which has this value as high-fence
                traverse_mode = btree_impl::t_fence_high_match;
                int d = _lower.compare(neighboring_fence);
                if (d >= 0) {
                    eof = true;
                    return RCOK;
                }
            }
            p.unfix();

            // take lock for the fence key
            if (_needs_lock) {
                lockid_t lid (_store, (const unsigned char*) neighboring_fence.buffer_as_keystr(), neighboring_fence.get_length_as_keystr());
                okvl_mode lock_mode;
                if (only_low_fence_exact_match) {
                    lock_mode = _ex_lock ? ALL_X_GAP_N: ALL_S_GAP_N;
                } else {
                    lock_mode = _ex_lock ? ALL_X_GAP_X : ALL_S_GAP_S;
                }
                // we can unconditionally request lock because we already released latch
                W_DO(ss_m::lm->lock(lid.hash(), lock_mode, true, true, true));
            }

            // TODO this part should check if we find an exact match of fence keys.
            // because we unlatch above, it's possible to not find exact match.
            // in that case, we should change the traverse_mode to fence_contains and continue
            W_DO(btree_impl::_ux_traverse(_store, neighboring_fence, traverse_mode, LATCH_SH, p));
            _slot = _forward ? 0 : p.nrecs() - 1;
            _set_current_page(p);
            continue;
        }

        // take lock on the next key.
        // NOTE: until we get locks, we aren't sure the key really becomes
        // the next key. So, we use the temporary variable _tmp_next_key_buf.
        const okvl_mode *mode = NULL;
        {
            p.get_key(_slot, _tmp_next_key_buf);
            if (_forward) {
                int d = _tmp_next_key_buf.compare(_upper);
                if (d < 0) {
                    mode = _ex_lock ? &ALL_X_GAP_X : &ALL_S_GAP_S;
                } else if (d == 0 && _upper_inclusive) {
                    mode = _ex_lock ? &ALL_X_GAP_N : &ALL_S_GAP_N;
                } else {
                    eof = true;
                    mode = &ALL_N_GAP_N;
                }
            } else {
                int d = _tmp_next_key_buf.compare(_lower);
                if (d > 0) {
                    mode = _ex_lock ? &ALL_X_GAP_X : &ALL_S_GAP_S;
                } else if (d == 0 && _lower_inclusive) {
                    mode = _ex_lock ? &ALL_X_GAP_X : &ALL_S_GAP_S;
                } else {
                    eof = true;
                    mode = _ex_lock ? &ALL_N_GAP_X : &ALL_N_GAP_S;
                }
            }
        }
        if (_needs_lock && !mode->is_empty()) {
            rc_t rc = btree_impl::_ux_lock_key (_store, p, _tmp_next_key_buf,
                    LATCH_SH, *mode, false);
            if (rc.is_error()) {
                if (rc.err_num() == eLOCKRETRY) {
                    W_DO(_check_page_update(p));
                    continue;
                } else {
                    return rc;
                }
            }
        }
        // okay, now we are sure the _tmp_next_key_buf is the key we want to use
        _key = _tmp_next_key_buf;
        return RCOK; // found a record! (or eof)
    }
    return RCOK;
}
Beispiel #10
0
rc_t
btree_impl::_ux_lock_key(
    const StoreID&      store,
    btree_page_h&      leaf,
    const void*        keystr,
    size_t             keylen,
    latch_mode_t       latch_mode,
    const okvl_mode&   lock_mode,
    bool               check_only
    )
{
    // Callers:
    // 1. Top level _ux_lock_key() - I/U/D and search operations, lock conflict is possible
    // 2. _ux_lock_range() - lock conflict is possible
    //
    // Lock conflict:
    // 1. Deadlock - the asking lock is held by another transaction currently, and the
    //                      current transaction is holding other locks already, failed
    // 2. Timeout -  the asking lock is held by another transaction currently, but the
    //                     current transaction does not hold other locks, okay to retry

    // For restart operation using lock re-acquisition:
    // 1. On_demand or mixed UNDO - when lock conflict. it triggers UNDO transaction rollback
    //                                                 this is a blocking operation, meaning the other concurrent
    //                                                 transactions asking for the same lock are blocked, no deadlock
    // 2. Traditional UNDO - original behavior, either deadlock error or timeout and retry

    lockid_t lid (store, (const unsigned char*) keystr, keylen);
    // first, try conditionally. we utilize the inserted lock entry even if it fails
    RawLock* entry = nullptr;

    // The lock request does the following:
    // If the lock() failed to acquire lock (trying to acquire lock while holding the latch) and
    // if the transaction doesn't have any other locks, because 'condition' is true, lock()
    // returns immediatelly with eCONDLOCKTIMEOUT which indicates it failed to
    // acquire lock but no deadlock worry and the lock entry has been created already.
    // In this case caller (this function) releases latch and try again using retry_lock()
    // which is a blocking operation, this is because it is safe to forever retry without
    // risking deadlock
    // If the lock() returns eDEADLOCK, it means lock acquisition failed and
    // the current transaction already held other locks, it is not safe to retry (will cause
    // further deadlocks) therefore caller must abort the current transaction
    rc_t lock_rc = lm->lock(lid.hash(), lock_mode, true /*check */, false /* wait */,
            !check_only /* acquire */, smthread_t::xct(),timeout_t::WAIT_IMMEDIATE, &entry);

    if (!lock_rc.is_error()) {
        // lucky! we got it immediately. just return.
        return RCOK;
    } else {
        // if it caused deadlock and it was chosen to be victim, give up! (not retry)
        if (lock_rc.err_num() == eDEADLOCK)
        {
            // The user transaction will abort and rollback itself upon deadlock detection.
            // Because Express does not have a deadlock monitor and policy to determine
            // which transaction to rollback during a deadlock (should abort the cheaper
            // transaction), the user transaction which detects deadlock will be aborted.
            w_assert1(entry == nullptr);
            return lock_rc;
        }

        // couldn't immediately get it. then we unlatch the page and wait.
        w_assert1(lock_rc.err_num() == eCONDLOCKTIMEOUT);
        w_assert1(entry != nullptr);

        // we release the latch here. However, we increment the pin count before that
        // to prevent the page from being evicted.
        pin_for_refix_holder pin_holder(leaf.pin_for_refix()); // automatically releases the pin
        lsn_t prelsn = leaf.get_page_lsn(); // to check if it's modified after this unlatch
        leaf.unfix();
        // then, we try it unconditionally (this will block)
        W_DO(lm->retry_lock(&entry, !check_only /* acquire */));
        // now we got the lock.. but it might be changed because we unlatched.
        w_rc_t refix_rc = leaf.refix_direct(pin_holder._idx, latch_mode);
        if (refix_rc.is_error() || leaf.get_page_lsn() != prelsn)
        {
            // release acquired lock
            if (entry != nullptr) {
                w_assert1(!check_only);
                lm->unlock(entry);
            } else {
                w_assert1(check_only);
            }
            if (refix_rc.is_error())
            {
                return refix_rc;
            }
            else
            {
                w_assert1(leaf.get_page_lsn() != prelsn); // unluckily, it's the case
                return RC(eLOCKRETRY); // retry!
            }
        }
        return RCOK;
    }
}
Beispiel #11
0
void chkpt_t::acquire_lock(logrec_t& r)
{
    w_assert1(is_xct_active(r.tid()));
    w_assert1(!r.is_single_sys_xct());
    w_assert1(!r.is_multi_page());
    w_assert1(!r.is_cpsn());
    w_assert1(r.is_page_update());

    switch (r.type())
    {
        case logrec_t::t_btree_insert:
        case logrec_t::t_btree_insert_nonghost:
            {
                btree_insert_t* dp = (btree_insert_t*) r.data();

                w_keystr_t key;
                key.construct_from_keystr(dp->data, dp->klen);

                okvl_mode mode = btree_impl::create_part_okvl(okvl_mode::X, key);
                lockid_t lid (r.stid(), (const unsigned char*) key.buffer_as_keystr(),
                        key.get_length_as_keystr());

                add_lock(r.tid(), mode, lid.hash());
            }
            break;
        case logrec_t::t_btree_update:
            {
                btree_update_t* dp = (btree_update_t*) r.data();

                w_keystr_t key;
                key.construct_from_keystr(dp->_data, dp->_klen);

                okvl_mode mode = btree_impl::create_part_okvl(okvl_mode::X, key);
                lockid_t lid (r.stid(), (const unsigned char*) key.buffer_as_keystr(),
                        key.get_length_as_keystr());

                add_lock(r.tid(), mode, lid.hash());
            }
            break;
        case logrec_t::t_btree_overwrite:
            {
                btree_overwrite_t* dp = (btree_overwrite_t*) r.data();

                w_keystr_t key;
                key.construct_from_keystr(dp->_data, dp->_klen);

                okvl_mode mode = btree_impl::create_part_okvl(okvl_mode::X, key);
                lockid_t lid (r.stid(), (const unsigned char*) key.buffer_as_keystr(),
                        key.get_length_as_keystr());

                add_lock(r.tid(), mode, lid.hash());
            }
            break;
        case logrec_t::t_btree_ghost_mark:
            {
                btree_ghost_t* dp = (btree_ghost_t*) r.data();
                for (size_t i = 0; i < dp->cnt; ++i) {
                    w_keystr_t key (dp->get_key(i));

                    okvl_mode mode = btree_impl::create_part_okvl(okvl_mode::X, key);
                    lockid_t lid (r.stid(), (const unsigned char*) key.buffer_as_keystr(),
                            key.get_length_as_keystr());

                    add_lock(r.tid(), mode, lid.hash());
                }
            }
            break;
        case logrec_t::t_btree_ghost_reserve:
            {
                btree_ghost_reserve_t* dp = (btree_ghost_reserve_t*) r.data();

                w_keystr_t key;
                key.construct_from_keystr(dp->data, dp->klen);

                okvl_mode mode = btree_impl::create_part_okvl(okvl_mode::X, key);
                lockid_t lid (r.stid(), (const unsigned char*) key.buffer_as_keystr(),
                        key.get_length_as_keystr());

                add_lock(r.tid(), mode, lid.hash());
            }
            break;
        default:
            w_assert0(r.type() == logrec_t::t_page_img_format);
            break;
    }

    return;
}