Esempio n. 1
0
void signalHandler(int signalId)
	{
	switch(signalId)
		{
		case SIGHUP:
			/* Restart server: */
			{
			Threads::MutexCond::Lock shutdownLock(shutdownCond);
			shutdown=false;
			shutdownCond.broadcast();
			}
			break;
		
		case SIGINT:
		case SIGTERM:
			/* Shut down server: */
			{
			Threads::MutexCond::Lock shutdownLock(shutdownCond);
			shutdown=true;
			shutdownCond.broadcast();
			}
			break;
		}
	return;
	}
Esempio n. 2
0
WiredTigerSession* WiredTigerSessionCache::getSession() {
    boost::shared_lock<boost::shared_mutex> shutdownLock(_shutdownLock);

    // We should never be able to get here after _shuttingDown is set, because no new
    // operations should be allowed to start.
    invariant(!_shuttingDown.loadRelaxed());

    // Set the high water mark if we need to
    if (_sessionsOut.fetchAndAdd(1) > _highWaterMark.load()) {
        _highWaterMark.store(_sessionsOut.load());
    }

    if (!_sessions.empty()) {
        stdx::lock_guard<SpinLock> lock(_cacheLock);
        if (!_sessions.empty()) {
            // Get the most recently used session so that if we discard sessions, we're
            // discarding older ones
            WiredTigerSession* cachedSession = _sessions.back();
            _sessions.pop_back();
            sessionsInCache.fetchAndSubtract(1);
            return cachedSession;
        }
    }

    // Outside of the cache partition lock, but on release will be put back on the cache
    return new WiredTigerSession(_conn, _epoch);
}
Esempio n. 3
0
void WiredTigerSessionCache::releaseSession(WiredTigerSession* session) {
    invariant(session);
    invariant(session->cursorsOut() == 0);

    boost::shared_lock<boost::shared_mutex> shutdownLock(_shutdownLock);
    if (_shuttingDown.loadRelaxed()) {
        // Leak the session in order to avoid race condition with clean shutdown, where the
        // storage engine is ripped from underneath transactions, which are not "active"
        // (i.e., do not have any locks), but are just about to delete the recovery unit.
        // See SERVER-16031 for more information.
        return;
    }

    // This checks that we are only caching idle sessions and not something which might hold
    // locks or otherwise prevent truncation.
    {
        WT_SESSION* ss = session->getSession();
        uint64_t range;
        invariantWTOK(ss->transaction_pinned_range(ss, &range));
        invariant(range == 0);
    }

    _sessionsOut.fetchAndSubtract(1);

    bool returnedToCache = false;
    invariant(session->_getEpoch() <= _epoch);

    // Only return sessions until we hit the maximum number of sessions we have ever seen demand
    // for concurrently. We also want to immediately delete any session that is from a
    // non-current epoch.
    if (session->_getEpoch() == _epoch && sessionsInCache.load() < _highWaterMark.load()) {
        returnedToCache = true;
        stdx::lock_guard<SpinLock> lock(_cacheLock);
        _sessions.push_back(session);
    }

    if (returnedToCache) {
        sessionsInCache.fetchAndAdd(1);
    } else {
        delete session;
    }

    if (_engine && _engine->haveDropsQueued()) {
        _engine->dropAllQueued();
    }

    if (_engine && _engine->haveDropsQueued()) {
        _engine->dropAllQueued();
    }
}
Esempio n. 4
0
void MessageEndpoint::Shutdown()
{
	{
		Lock shutdownLock(&m_isShutdownMutex);
		m_isShutDown = true;
	}

	//Shut down each MessageQueue
	std::vector<uint32_t> serials = m_queues.GetUsedSerials();
	for(uint i = 0; i < serials.size(); i++)
	{
		MessageQueue *queue = m_queues.GetByOurSerial(serials[i]);
		if(queue != NULL)
		{
			queue->Shutdown();
		}
	}

	pthread_cond_signal(&m_callbackWakeupCondition);
}
Esempio n. 5
0
//blocking call
Message *MessageEndpoint::PopMessage(Ticket &ticket, int timeout)
{
	Message *ret;

	MessageQueue *queue = m_queues.GetByOurSerial(ticket.m_ourSerialNum);
	if(queue == NULL)
	{
		//Tried to read from a queue, but it didn't exist. We must have closed it, and then tried reading.
		//	This is a protocol error
		return new ErrorMessage(ERROR_PROTOCOL_MISTAKE);
	}

	//TODO: This is not quite right. We should keep returning valid messages as long as
	//	we have them. We should ask the MessageQueue for a new message (maybe peek?)
	//	and only return a shutdown message if one doesn't exist there.

	//If we're shut down, then return a shutdown message
	{
		Lock shutdownLock(&m_isShutdownMutex);
		if(m_isShutDown)
		{
			return new ErrorMessage(ERROR_SOCKET_CLOSED);
		}
	}

	ret = queue->PopMessage(timeout);

	if(ret->m_messageType == ERROR_MESSAGE)
	{
		ErrorMessage *error = (ErrorMessage*)ret;
		if(error->m_errorType == ERROR_TIMEOUT)
		{
			m_consecutiveTimeouts++;
			//TODO: deal with timeouts
		}
	}

	return ret;
}
Esempio n. 6
0
GlobalRWLock::~GlobalRWLock()
{
	if (cachedLock)
		shutdownLock();
}
Esempio n. 7
0
bool MessageEndpoint::PushMessage(Message *message)
{
	uint32_t ourSerial;
	bool isNewCallback = false;

	if(message == NULL)
	{
		return false;
	}

	{
		Lock shutdownLock(&m_isShutdownMutex);
		if(m_isShutDown)
		{
			message->DeleteContents();
			delete message;
			return false;
		}
	}

	//The other endpoint must always provide a valid "our" serial number, ignore if they don't
	if(message->m_ourSerialNumber == 0)
	{
		message->DeleteContents();
		delete message;
		return false;
	}

	//If this is a new conversation from the endpoint (new callback conversation)
	if(message->m_theirSerialNumber == 0)
	{
		isNewCallback = true;
		//Look up to see if there's a MessageQueue for this serial
		MessageQueue *queue = m_queues.GetByTheirSerial(message->m_ourSerialNumber);

		//If this is a brand new callback message
		if(queue == NULL)
		{
			ourSerial = GetNextOurSerialNum();
			m_queues.AddQueue(ourSerial, message->m_ourSerialNumber);

			queue = m_queues.GetByOurSerial(ourSerial);
			//It's possible to have a race condition that would delete this MessageQueue before we could access it
			if(queue == NULL)
			{
				message->DeleteContents();
				delete message;
				return false;
			}
		}
		if(queue->PushMessage(message))
		{
			if(isNewCallback)
			{
				{
					Lock lock(&m_availableCBsMutex);
					m_availableCBs.push(ourSerial);
				}
				pthread_cond_signal(&m_callbackWakeupCondition);
			}
			return true;
		}
		else
		{
			return false;
		}
	}

	//If we got here, the message should be for an existing conversation
	//	(IE: Both serials should be valid)

	MessageQueue *queue = m_queues.GetByOurSerial(message->m_theirSerialNumber);
	if(queue == NULL)
	{
		//If there wasn't a MessageQueue for this serial number, then this message must be late or in error
		message->DeleteContents();
		delete message;
		return false;
	}

	//Update the MessageQueue to have the received "their" serial. It might not have it yet.
	m_queues.AddQueue(message->m_theirSerialNumber, message->m_ourSerialNumber);
	return queue->PushMessage(message);
}