예제 #1
0
void BusClient::ScheduleShutdown()
{
	MojLogTrace(m_log);
	// Reply to the "run" message now that we're done
	if (m_launchedAsService && m_msg.get()) {
		const Configurator::ConfigCollection& ok = Configurator::ConfigureOk();
		const Configurator::ConfigCollection& failed = Configurator::ConfigureFailure();

		if (m_wrongAplication) {
			MojString response;
			response.appendFormat("Aplication or service doesn't exist");
			m_wrongAplication = false;
			m_msg->replyError(MojErrInternal, response.data());

		} else if (!failed.empty()) {
			MojString response;
			response.appendFormat("Partial configuration - %zu ok, %zu failed", ok.size(), failed.size());
			m_msg->replyError(MojErrInternal, response.data());
		} else {
			MojObject response;
			response.putInt("configured", ok.size());
			m_msg->replySuccess(response);
		}
		m_msg.reset();
	}

	if (!m_pending.empty()) {
		MojLogDebug(m_log, "%d pending service calls to handle remaining", m_pending.size());

		// still more pending work
		m_configuratorsCompleted = 0;
		m_configurators.clear();
		Configurator::ResetConfigStats();

		const PendingWork &pending = m_pending.back();
		(pending.instance->*(pending.callback))(pending.msg.get(), pending.payload);

		m_pending.pop_back();
		return;
	}

	MojLogDebug(m_log, "No more pending service calls to handle - scheduling shutdown");

	// Schedule an event to shutdown once the stack is unwound.
	if (m_timerTimeout == 0) {
		// this is to work around around a race condition where the LSCall is delivered
		// after we shutdown causing us to start back up - give some time for the LSCall
		// to get delivered.  NOV-114626.  This needs a proper fix within ls2 (can't be
		// worked around anywhere else).
		m_timerTimeout = g_timeout_add_full(G_PRIORITY_DEFAULT_IDLE, /* timer priority */
		    500, /* timeout in ms */
		    &BusClient::ShutdownCallback, // callback
		    this, /* callback data */
		    NULL /*destroy notify callback*/
		);
	}
	//g_idle_add(&BusClient::ShutdownCallback, this);

	m_shuttingDown = true;
}
예제 #2
0
MojErr MojDb::dump(const MojChar* path, MojUInt32& countOut, bool incDel, MojDbReqRef req, bool backup,
		MojUInt32 maxBytes, const MojObject* incrementalKey, MojObject* backupResponse)
{
	MojAssert(path);
	MojLogTrace(s_log);

	MojErr err = beginReq(req);
	MojErrCheck(err);

	if (!req->admin()) {
		MojLogError(s_log, _T("access denied: '%s' cannot dump db to path: '%s'"), req->domain().data(), path);
		MojErrThrow(MojErrDbAccessDenied);
	}

	MojFile file;
	err = file.open(path, MOJ_O_WRONLY | MOJ_O_CREAT | MOJ_O_TRUNC, MOJ_S_IRUSR | MOJ_S_IWUSR);
	MojErrCheck(err);

	// write out kinds first, then existing objects, then deleted objects
	MojSize bytesWritten = 0;
	MojSize totalwarns = 0;
	MojSize newwarns = 0;
	MojDbQuery objQuery;
	MojVector<MojObject> kindVec;
	MojObject revParam = -1;
	MojObject delRevParam = -1;

	// if we were given an incremental key, pull out the revs now
	if (incrementalKey) {
		incrementalKey->get(MojDbServiceDefs::RevKey, revParam);
		incrementalKey->get(MojDbServiceDefs::DeletedRevKey, delRevParam);
	}

	err = m_kindEngine.getKinds(kindVec);
	MojErrCheck(err);

	// write kinds - if incremental, only write the kinds that have changed since the respective revs
	MojString countStr;
	for (MojVector<MojObject>::ConstIterator i = kindVec.begin(); i != kindVec.end(); ++i) {
		if (backup) {
			bool backupKind = false;
			i->get(MojDbKind::SyncKey, backupKind);
			if (!backupKind)
				continue;
			MojString id;
			err = i->getRequired(MojDbServiceDefs::IdKey, id);
			MojErrCheck(err);
			MojDbQuery countQuery;
			err = countQuery.from(id);
			MojErrCheck(err);
			MojDbCursor cursor;
			err = find(countQuery, cursor, req);
			MojErrCheck(err);
			MojUInt32 count = 0;
			err = cursor.count(count);
			MojErrCheck(err);
			if (count > 0) {
				if (i != kindVec.begin()) {
					err = countStr.appendFormat(_T(", "));
					MojErrCheck(err);
				}
				err = countStr.appendFormat("%s=%u", id.data(), count);
				MojErrCheck(err);
			}
		}
		bool deleted = false;
		i->get(DelKey, deleted);
		MojObject kindRev;
		err = i->getRequired(RevKey, kindRev);
		MojErrCheck(err);
		if ((deleted && kindRev > delRevParam) || (!deleted && kindRev > revParam)) {
			err = dumpObj(file, (*i), bytesWritten, maxBytes);
			MojErrCheck(err);
			countOut++;
		}
	}

	// dump all the non-deleted objects
	err = dumpImpl(file, backup, false, revParam, delRevParam, true, countOut, req, backupResponse, MojDbServiceDefs::RevKey, bytesWritten, newwarns, maxBytes);
	MojErrCheck(err);
	totalwarns += newwarns;
	// If we're supposed to include deleted objects, dump the deleted objects now.
	// There's a chance that we may have run out of space in our backup.  If that's the case,
	// we don't want to try to dump deleted objects - we can detect this by looking for the HasMoreKey
	if (incDel && backupResponse && !backupResponse->contains(MojDbServiceDefs::HasMoreKey)) {
		err = dumpImpl(file, backup, true, revParam, delRevParam, false, countOut, req, backupResponse, MojDbServiceDefs::DeletedRevKey, bytesWritten, newwarns, maxBytes);
		MojErrCheck(err);
	}
	totalwarns += newwarns;

	// Add the Full and Version keys
	if (backup && backupResponse) {
		bool incremental = (incrementalKey != NULL);
		err = backupResponse->putBool(MojDbServiceDefs::FullKey, !incremental);
		MojErrCheck(err);
		err = backupResponse->put(MojDbServiceDefs::VersionKey, DatabaseVersion);
		MojErrCheck(err);
		err = backupResponse->put(MojDbServiceDefs::WarningsKey, (MojInt32)totalwarns);
		MojErrCheck(err);
		MojString description;
		err = description.format(_T("incremental=%u"), countOut);
		MojErrCheck(err);
		if (!countStr.empty()) {
			err = description.appendFormat(_T(", %s"), countStr.data());
			MojErrCheck(err);
		}
		err = backupResponse->put(_T("description"), description);
		MojErrCheck(err);
	}

	err = req->end();
	MojErrCheck(err);

	return MojErrNone;
}